Commit c561cc92 authored by Arpit Jalan's avatar Arpit Jalan Committed by Naveen Valecha
Browse files

Issue #2759031 by ajalan065, eugene.ilyin, naveenvalecha, penyaskito:...

Issue #2759031 by ajalan065, eugene.ilyin, naveenvalecha, penyaskito: Implement the Face Detection feature of the Google Cloud Vision API
parent ee40d362
Loading
Loading
Loading
Loading
+187 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\google_vision\Tests;

use Drupal\Core\Url;
use Drupal\field\Entity\FieldConfig;
use Drupal\simpletest\WebTestBase;
use Drupal\field\Entity\FieldStorageConfig;

/**
 * Base class for Google Vision API tests.
 */
abstract class GoogleVisionTestBase extends WebTestBase {

  /**
   * {@inheritdoc}
   */
  public static $modules = [
    'google_vision',
    'google_vision_test',
    'image',
    'field_ui',
    'field',
  ];

  /**
   * Retrieves the entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  protected $entityTypeManager;

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();

    $this->entityTypeManager = $this->container->get('entity_type.manager');
  }

  /**
   * Create a new image field.
   *
   * @param string $name
   *   The name of the new field (all lowercase), exclude the "field_" prefix.
   * @param string $entity_type
   *   The entity type that this field will be added to.
   * @param string $type_name
   *   The node type that this field will be added to.
   * @param array $storage_settings
   *   A list of field storage settings that will be added to the defaults.
   * @param array $field_settings
   *   A list of instance settings that will be added to the instance defaults.
   * @param array $widget_settings
   *   Widget settings to be added to the widget defaults.
   * @param array $formatter_settings
   *   Formatter settings to be added to the formatter defaults.
   * @param string $description
   *   A description for the field.
   */
  public function createImageField($name, $entity_type, $type_name, $storage_settings = [], $field_settings = [], $widget_settings = [], $formatter_settings = [], $description = '') {
    FieldStorageConfig::create([
      'field_name' => $name,
      'entity_type' => $entity_type,
      'type' => 'image',
      'settings' => $storage_settings,
      'cardinality' => 1,
    ])->save();

    $field_config = FieldConfig::create([
      'field_name' => $name,
      'label' => $name,
      'entity_type' => $entity_type,
      'bundle' => $type_name,
      'settings' => $field_settings,
      'description' => $description,
    ])->addConstraint('UserEmotion');
    $field_config->save();

    $form_display = $this->entityTypeManager
      ->getStorage('entity_form_display')
      ->load($entity_type . '.' . $type_name . '.' . 'default');
    if (!$form_display) {
      $values = [
        'targetEntityType' => $entity_type,
        'bundle' => $type_name,
        'mode' => 'default',
        'status' => TRUE,
      ];
      $form_display = $this->entityTypeManager
        ->getStorage('entity_form_display')
        ->create($values);
    }
    $form_display->setComponent($name, [
      'type' => 'image_image',
      'settings' => $widget_settings,
    ])->save();

    $display = $this->entityTypeManager
      ->getStorage('entity_view_display')
      ->load($entity_type . '.' . $type_name . '.' . 'default');

    if (!$display) {
      $values = [
        'targetEntityType' => $entity_type,
        'bundle' => $type_name,
        'mode' => 'default',
        'status' => TRUE,
      ];
      $display = $this->entityTypeManager
        ->getStorage('entity_view_display')
        ->create($values);
    }
    $display->setComponent($name, [
      'type' => 'image',
      'settings' => $formatter_settings,
    ])->save();

    return $field_config;
  }

  /**
   * Get the field id of the image field formed.
   *
   * @param string $entity_type.
   *  The entity type the field will be added to.
   * @param string $type.
   *  The node type the field will be added to.
   * @return string $field_id.
   *  The field id of the created field.
   */
  public function getImageFieldId($entity_type, $type) {
    // Create an image field and add an field to the custom content type.
    $storage_settings['default_image'] = [
      'uuid' => 1,
      'alt' => '',
      'title' => '',
      'width' => 0,
      'height' => 0,
    ];
    $field_settings['default_image'] = [
      'uuid' => 1,
      'alt' => '',
      'title' => '',
      'width' => 0,
      'height' => 0,
    ];
    $widget_settings = [
      'preview_image_style' => 'medium',
    ];
    $field = $this->createImageField('images', $entity_type, $type, $storage_settings, $field_settings, $widget_settings);

    // Get the field id and return it.
    $field_id = $field->id();
    return $field_id;
  }

  /**
   * Creates a user with profile picture attached.
   *
   * @return string $edit['name'].
   *  The user name of the newly created user.
   */
  public function createUserWithProfilePicture() {
    //Get an image.
    $images = $this->drupalGetTestFiles('image');
    $user = 'user1';
    $pass = 'password1';
    $edit = [
      'mail' => 'user@user.com',
      'name' => $user,
      'pass[pass1]' => $pass,
      'pass[pass2]' => $pass,
      'files[images_0]' => \Drupal::service('file_system')->realpath($images[0]->uri),
    ];
    $this->drupalPostForm(Url::fromRoute('user.admin_create'), $edit, t('Create new account'));
    $re_edit = [
      'pass[pass1]' => $pass,
      'pass[pass2]' => $pass,
      'images[0][alt]' => $this->randomMachineName(),
    ];
    $this->drupalPostForm(NULL, $re_edit, t('Create new account'));

    return $edit['name'];
  }
}
+72 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\google_vision\Tests;

/**
 * Tests to verify that the Emotion Detection feature works correctly.
 *
 * @group google_vision
 */
class UserEmotionTest extends GoogleVisionTestBase {

  /**
   * {@inheritdoc}
   */
  public static $modules = ['user'];

  /**
   * A user with permission to create content and upload images.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $adminUser;

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();

    // Creates administrative user.
    $this->adminUser = $this->drupalCreateUser([
      'administer google vision',
      'administer account settings',
      'administer user fields',
      'administer users',
    ]);
    $this->drupalLogin($this->adminUser);
  }

  /**
   * Test to ensure that the user emotion is not detected when Emotion
   * Detection is disabled.
   */
  public function testNoUserEmotionDetection() {
    // Create an image field for the user picture and get its id.
    $field_id = $this->getImageFieldId('user', 'user');
    // Ensuring that the Emotion Detection feature is disabled.
    $this->drupalGet('admin/config/people/accounts/fields/' . $field_id);
    $username = $this->createUserWithProfilePicture();
    $this->assertNoText('Please upload a photo where you are smiling and happy');
    $this->assertText("Created a new user account for $username. No email has been sent");
  }

  /**
   * Test to ensure that user emotion is detected when Emotion Detection is
   * enabled.
   */
  public function testUserEmotionDetection() {
    // Create an image field for the user picture and get its id.
    $field_id = $this->getImageFieldId('user', 'user');
    // Enabling the Emotion Detection feature.
    $edit = [
      'emotion_detect' => 1,
    ];
    $this->drupalPostForm('admin/config/people/accounts/fields/' . $field_id, $edit, t('Save settings'));
    // Ensuring that the Emotion Detection feature is enabled.
    $this->drupalGet('admin/config/people/accounts/fields/' . $field_id);
    $username = $this->createUserWithProfilePicture();
    $this->assertText('Please upload a photo where you are smiling and happy');
    $this->assertText("Created a new user account for $username. No email has been sent");
  }
}
+28 −0
Original line number Diff line number Diff line
@@ -205,4 +205,32 @@ class GoogleVisionAPIFake extends GoogleVisionAPI {
    ];
    return $response;
  }

  /**
   * Function to fetch faces from a given image.
   *
   * @param string $filepath .
   *
   * @return Array|bool.
   */
  public function faceDetection($filepath) {
    if (!$this->apiKey) {
      return FALSE;
    }
    $response = [
      'responses' => [
        '0' => [
          'faceAnnotations' => [
            '0' => [
              'joyLikelihood' => 'UNLIKELY',
              'sorrowLikelihood' => 'VERY_LIKELY',
              'angerLikelihood' => 'LIKELY',
              'surpriseLikelihood' => 'POSSIBLE',
            ],
          ],
        ],
      ],
    ];
    return $response;
  }
}