diff --git a/config/schema/google_vision.schema.yml b/config/schema/google_vision.schema.yml
index 76f0c1a..07850ab 100644
--- a/config/schema/google_vision.schema.yml
+++ b/config/schema/google_vision.schema.yml
@@ -24,3 +24,6 @@ field.field.*.*.*.third_party.google_vision:
emotion_detect:
type: boolean
label: 'Emotion Detection'
+ google_vision:
+ type: boolean
+ label: 'Google Vision'
diff --git a/google_vision.module b/google_vision.module
index 859a724..551e03b 100644
--- a/google_vision.module
+++ b/google_vision.module
@@ -10,7 +10,7 @@ use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
-
+use Drupal\taxonomy\Entity\Vocabulary;
/**
* Implements hook_entity_presave().
*/
@@ -35,7 +35,7 @@ function google_vision_entity_presave(EntityInterface $entity) {
//Use a new taxonomy vocabulary to group the objects by their dominant color.
$new_vid = "dominant_color";
$name = "Dominant Color";
- $vocabularies = \Drupal\taxonomy\Entity\Vocabulary::loadMultiple();
+ $vocabularies = Vocabulary::loadMultiple();
// Create a vocabulary if not already present.
if (!isset($vocabularies[$new_vid])) {
$vocabulary = \Drupal\taxonomy\Entity\Vocabulary::create(array(
@@ -45,7 +45,9 @@ function google_vision_entity_presave(EntityInterface $entity) {
));
$vocabulary->save();
}
- google_vision_file_entity_dominant_color($entity, $field, $new_vid);
+ if (!empty($field->getSettings()['handler_settings']['target_bundles']['dominant_color'])) {
+ google_vision_file_entity_dominant_color($entity, $field, $new_vid);
+ }
}
}
}
diff --git a/google_vision.services.yml b/google_vision.services.yml
index be39f19..91ddb31 100644
--- a/google_vision.services.yml
+++ b/google_vision.services.yml
@@ -1,4 +1,4 @@
services:
google_vision.api:
class: Drupal\google_vision\GoogleVisionAPI
- arguments: ['@config.factory', '@http_client']
\ No newline at end of file
+ arguments: ['@config.factory', '@http_client']
diff --git a/src/Controller/SimilarContentController.php b/src/Controller/SimilarContentController.php
index 9006afe..e16df87 100644
--- a/src/Controller/SimilarContentController.php
+++ b/src/Controller/SimilarContentController.php
@@ -9,21 +9,38 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Render\BareHtmlPageRendererInterface;
use Drupal\Core\Url;
use Drupal\Core\Entity\EntityInterface;
+use Drupal\taxonomy\Entity\Term;
+use Drupal\Core\Database\Connection;
/**
-* Returns the related content based on dominant color of the images.
-*/
+ * Returns the related content based on dominant color of the images.
+ */
class SimilarContentController extends ControllerBase {
/**
+ * Database Service Object.
+ *
+ * @var \Drupal\Core\Database\Connection
+ */
+ protected $connection;
+
+ /**
+ * Constructs a SimilarContentController object.
+ */
+ public function __construct(Connection $connection) {
+ $this->connection = $connection;
+ }
+
+ /**
* Get the file title.
*/
public function getFileTitle($fid) {
- $query = \Drupal::database()->select('file_managed', 'fm');
+ $query = $this->connection->select('file_managed', 'fm');
$query->fields('fm', ['filename']);
$query->condition('fm.fid', $fid);
$title = $query->execute()->fetchField();
return $title;
}
+
/**
* Returns the list of image links which share the same dominant color.
*/
@@ -33,41 +50,56 @@ class SimilarContentController extends ControllerBase {
//Get an array of just term ids.
$query = \Drupal::entityQuery('taxonomy_term');
- $query->condition('vid', "dominant_color");
+ $query->condition('vid', 'dominant_color');
$tids = $query->execute();
- $terms = \Drupal\taxonomy\Entity\Term::loadMultiple($tids);
+ $terms = Term::loadMultiple($tids);
$term_id = array_keys($terms);
// Get the list of dominant colors per file.
$dominant_color = [];
foreach ($term_id as $key => $value) {
- $query = \Drupal::database()->select('file__field_labels', 'ffl');
+ $query = $this->connection->select('file__field_labels', 'ffl');
$query->fields('ffl', ['field_labels_target_id']);
$query->condition('ffl.entity_id', $file_id);
$query->condition('ffl.field_labels_target_id', $value);
$dominant_color[] = $query->execute()->fetchField();
}
+ $build = array();
+
+ if (!empty($dominant_color)) {
//Get all the file ids which have one or more dominant colors in common with $dominant_color.
- $query = \Drupal::database()->select('file__field_labels', 'ffl');
- $query->fields('ffl', ['entity_id', 'field_labels_target_id']);
- $query->condition('field_labels_target_id', $dominant_color, 'IN');
- $files = $query->execute()->fetchAllKeyed();
+ $query = $this->connection->select('file__field_labels', 'ffl');
+ $query->fields('ffl', ['entity_id', 'field_labels_target_id']);
+ $query->condition('field_labels_target_id', $dominant_color, 'IN');
+ $files = $query->execute()->fetchAllKeyed();
- $build = array();
- $build['#prefix'] = '
';
- $build['#suffix'] = '
';
+ $build['#prefix'] = '';
+ $build['#suffix'] = '
';
- foreach ($files as $key => $value) {
- $build[$key] = [
+ foreach ($files as $key => $value) {
+ $build[$key] = [
'#prefix' => '',
'#type' => 'link',
'#title' => $this->getFileTitle($key),
'#url' => Url::fromRoute('entity.file.canonical', ['file' => $key]),
'#suffix' => '',
+ ];
+ }
+ }
+ else {
+ $build = [
+ '#markup' => t('No items found.'),
];
}
return $build;
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container) {
+ return new static($container->get('database'));
+ }
}
diff --git a/src/Tests/SimilarContentsTest.php b/src/Tests/SimilarContentsTest.php
new file mode 100644
index 0000000..1e6070d
--- /dev/null
+++ b/src/Tests/SimilarContentsTest.php
@@ -0,0 +1,205 @@
+adminUser = $this->drupalCreateUser([
+ 'administer google vision',
+ 'administer files',
+ 'edit any image files',
+ 'create files',
+ 'administer file types',
+ 'administer file fields',
+ 'administer taxonomy',
+ ]);
+ $this->drupalLogin($this->adminUser);
+ //Check whether the API key is set.
+ $this->drupalGet(Url::fromRoute('google_vision.settings'));
+ $this->assertNotNull('api_key', 'The api key is set');
+ }
+
+ /**
+ * Uploads an image file and saves it.
+ *
+ * @param integer $count
+ * The index for the image file.
+ *
+ * @return integer
+ * The file id of the newly created image file.
+ */
+ public function uploadImageFile($count) {
+ $images = $this->drupalGetTestFiles('image');
+ $edit = [
+ 'files[upload]' => \Drupal::service('file_system')->realpath($images[$count]->uri),
+ ];
+ $this->drupalPostForm('file/add', $edit, t('Next'));
+ $this->drupalPostForm(NULL, array(), t('Next'));
+ $this->drupalPostForm(NULL, array(), t('Save'));
+ return (int) db_query('SELECT MAX(fid) FROM {file_managed}')->fetchField();
+ }
+
+ /**
+ * Creates a new field for referencing taxonomy vocabulary.
+ *
+ * @param \Drupal\taxonomy\Entity\Vocabulary $vocabulary.
+ * The vocabulary.
+ */
+ public function createEntityReferenceField($vocabulary) {
+ $entity_type = 'taxonomy_term';
+ $field_name = 'field_labels';
+ $field_storage = FieldStorageConfig::create(array(
+ 'field_name' => $field_name,
+ 'entity_type' => 'file',
+ 'translatable' => FALSE,
+ 'settings' => array(
+ 'target_type' => $entity_type,
+ ),
+ 'type' => 'entity_reference',
+ 'cardinality' => 1,
+ ));
+ $field_storage->save();
+ $field = FieldConfig::create(array(
+ 'field_storage' => $field_storage,
+ 'entity_type' => 'file',
+ 'bundle' => 'image',
+ 'settings' => array(
+ 'handler' => 'default',
+ 'handler_settings' => array(
+ // Restrict selection of terms to a single vocabulary.
+ 'target_bundles' => array(
+ $vocabulary->id() => $vocabulary->id(),
+ ),
+ ),
+ ),
+ ));
+ $field->save();
+ }
+
+ /**
+ * Creates and returns a new vocabulary.
+ *
+ * @param string $name.
+ * The name for the created vocabulary.
+ *
+ * @param string $vid.
+ * The vocabulary id.
+ *
+ * @return \Drupal\taxonomy\Entity\Vocabulary $vocabulary.
+ * The vocabulary.
+ */
+ function createTaxonomyVocabulary($name, $vid) {
+ $vocabulary = Vocabulary::create([
+ 'name' => $name,
+ 'description' => t('Stores the dominant color of the images.'),
+ 'vid' => $vid,
+ 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
+ ]);
+ $vocabulary->save();
+ return $vocabulary;
+ }
+
+ /**
+ * Test to ensure that the Similar Contents contains the related images.
+ */
+ public function testSimilarContents() {
+ $name = 'Dominant Color';
+ $vid = 'dominant_color';
+ $count = 0;
+ $vocabulary = $this->createTaxonomyVocabulary($name, $vid);
+ //Check whether the vocabulary is created.
+ $this->drupalGet(Url::fromRoute('entity.taxonomy_vocabulary.collection'));
+ $this->assertResponse(200);
+ //Create a taxonomy reference field.
+ $this->createEntityReferenceField($vocabulary);
+ $edit = [
+ 'google_vision' => 1,
+ 'settings[handler_settings][auto_create]' => 1,
+ ];
+ $this->drupalPostForm('admin/structure/file-types/manage/image/edit/fields/file.image.field_labels', $edit, t('Save settings'));
+ //Ensure that the Dominant Color option is selected.
+ $this->drupalGet('admin/structure/file-types/manage/image/edit/fields/file.image.field_labels');
+ // Upload an image file.
+ $file_id = $this->uploadImageFile($count);
+
+ //Create multiple images to be displayed in the similar contents link.
+ for ($count=1; $count < 3; $count++) {
+ $id[$count] = $this->uploadImageFile($count);
+ }
+ $this->drupalGet('file/' . $file_id . '/similarcontent');
+ $this->assertResponse(200);
+ $this->assertNoText('No items found.', 'Similar Contents are displayed.');
+ }
+
+ /**
+ * Test to ensure that no similar images are present.
+ */
+ public function testNoSimilarContents() {
+ $name = 'Labels';
+ $vid = 'other_labels';
+ $count = 0;
+ $vocabulary = $this->createTaxonomyVocabulary($name, $vid);
+ //Check whether the vocabulary is created.
+ $this->drupalGet(Url::fromRoute('entity.taxonomy_vocabulary.collection'));
+ $this->assertResponse(200);
+ //Create a taxonomy reference field.
+ $this->createEntityReferenceField($vocabulary);
+ $edit = [
+ 'google_vision' => 1,
+ 'settings[handler_settings][auto_create]' => 1,
+ ];
+ $this->drupalPostForm('admin/structure/file-types/manage/image/edit/fields/file.image.field_labels', $edit, t('Save settings'));
+ //Ensure that the Dominant Color option is not selected.
+ $this->drupalGet('admin/structure/file-types/manage/image/edit/fields/file.image.field_labels');
+ // Upload an image file.
+ $file_id = $this->uploadImageFile($count);
+
+ //Create multiple images to be displayed in the similar contents link.
+ for ($count=1; $count < 3; $count++) {
+ $id[$count] = $this->uploadImageFile($count);
+ }
+ $this->drupalGet('file/' . $file_id . '/similarcontent');
+ $this->assertResponse(200);
+ $this->assertText('No items found.', 'No items found message is displayed.');
+ }
+}
diff --git a/tests/modules/google_vision_test/src/GoogleVisionAPIFake.php b/tests/modules/google_vision_test/src/GoogleVisionAPIFake.php
index c35f123..e426967 100644
--- a/tests/modules/google_vision_test/src/GoogleVisionAPIFake.php
+++ b/tests/modules/google_vision_test/src/GoogleVisionAPIFake.php
@@ -49,6 +49,31 @@ class GoogleVisionAPIFake extends GoogleVisionAPI {
}
/**
+ * Function to retrieve labels for given image.
+ *
+ * @param string $filepath .
+ *
+ * @return Array|bool.
+ */
+ public function labelDetection($filepath) {
+ if (!$this->apiKey) {
+ return FALSE;
+ }
+ $response = [
+ 'responses' => [
+ '0' => [
+ 'labelAnnotations' => [
+ '0' => [
+ 'description' => 'Sample Image',
+ ],
+ ],
+ ],
+ ],
+ ];
+ return $response;
+ }
+
+ /**
* Function to return the response showing the image contains explicit content.
*
* @param string $filepath .
@@ -73,4 +98,37 @@ class GoogleVisionAPIFake extends GoogleVisionAPI {
);
return $response;
}
+
+ /**
+ * Function to retrieve image attributes for given image.
+ *
+ * @param string $filepath .
+ *
+ * @return Array|bool.
+ */
+ public function imageAttributesDetection($filepath) {
+ if (!$this->apiKey) {
+ return FALSE;
+ }
+ $response = [
+ 'responses' => [
+ '0' => [
+ 'imagePropertiesAnnotation' => [
+ 'dominantColors' => [
+ 'colors' => [
+ '0' => [
+ 'color' => [
+ 'red' => 124,
+ 'blue' => 159,
+ 'green' => 20,
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ ];
+ return $response;
+ }
}