<?php

/**
 * @file
 * Tests for the Metatag module to ensure image handling doesn't break.
 */

/**
 * Tests for the Metatag module to ensure image handling doesn't break.
 */
class MetatagCoreImageTest extends MetatagTestHelper {

  /**
   * {@inheritdoc}
   */
  public static function getInfo() {
    return array(
      'name' => 'Metatag core tests for images',
      'description' => 'Test Metatag integration with image files.',
      'group' => 'Metatag',
      'dependencies' => array('ctools', 'token', 'devel_generate'),
    );
  }

  /**
   * {@inheritdoc}
   */
  function setUp(array $modules = array()) {
    // Needs the OpenGraph submodule because of testNodeFieldValueMultiple().
    $modules[] = 'metatag_opengraph';

    // Need image handling.
    $modules[] = 'image';

    // Need the Devel Generate image generator.
    $modules[] = 'devel_generate';

    parent::setUp($modules);
  }

  /**
   * Confirm that an image can be added to a global configuration using the
   * image's absolute URL.
   */
  function testConfigAbsoluteURL() {
    // Generate a test image.
    $image_uri = $this->generateImage();
    $this->verbose($image_uri);

    // Work out the web-accessible URL for this image.
    $image_url = file_create_url($image_uri);

    // Update the global config to add an image meta tag.
    $config = metatag_config_load('global');
    $config->config['image_src']['value'] = $image_url;
    metatag_config_save($config);

    // Dump out the current config, to aid with debugging.
    $this->verbose($config);

    // Load the front page.
    $this->drupalGet('<front>');
    $this->assertResponse(200);

    // Confirm that the image_src meta tag has the expected values.
    $xpath = $this->xpath("//link[@rel='image_src']");
    $this->assertEqual(count($xpath), 1, 'One image_src meta tag found.');
    $this->assertEqual($xpath[0]['href'], $image_url, 'The image_src meta tag with an absolute URL is being output correctly.');

    // Confirm the file could be loaded.
    $this->drupalGet($xpath[0]['href']);
    $this->assertResponse(200, "The image_src meta tag's value could be loaded.");
  }

  /**
   * Confirm that an image can be added to a global configuration using the
   * image's relative URL.
   */
  function testConfigDrupalRelativeURL() {
    // Generate a test image.
    $image_uri = $this->generateImage();
    $this->verbose($image_uri);

    // Work out the web-accessible URL for this image.
    $image_url = file_create_url($image_uri);

    // Extract the relative URL version of the absolute URL.
    $url_length = strlen($GLOBALS['base_url']);

    // Need to increase the length by 1 as the base_url does not include a
    // trailing slash.
    $relative_url = substr($image_url, $url_length + 1);

    // Update the global config to add an image meta tag.
    $config = metatag_config_load('global');
    $config->config['image_src']['value'] = $relative_url;
    metatag_config_save($config);

    // Dump out the current config, to aid with debugging.
    $this->verbose($config);

    // Load the front page.
    $this->drupalGet('<front>');
    $this->assertResponse(200);

    // Confirm that the image_src meta tag has the expected values.
    $xpath = $this->xpath("//link[@rel='image_src']");
    $this->assertEqual(count($xpath), 1, 'One image_src meta tag found.');
    $this->assertEqual((string) $xpath[0]['href'], $image_url);
    // , 'The image_src meta tag with a URL relative to the Drupal root is being output as an absolute URL.');
    // Confirm the file could be loaded.
    $this->drupalGet($xpath[0]['href']);
    $this->assertResponse(200, "The image_src meta tag's value could be loaded.");
  }

  /**
   * Confirm that an image can be added to a global configuration using the
   * image's relative URL.
   */
  function testConfigRelativeURL() {
    // Generate a test image.
    $image_uri = $this->generateImage();
    $this->verbose($image_uri);

    // Work out the web-accessible URL for this image.
    $image_url = file_create_url($image_uri);

    // Extract the relative URL version of the absolute URL.
    $url_length = drupal_strlen($GLOBALS['base_url']);

    // Need to increase the length by 1 as the base_url does not include a
    // trailing slash.
    $relative_url = drupal_substr($image_url, $url_length + 1);

    // Update the global config to add an image meta tag.
    $config = metatag_config_load('global');
    $config->config['image_src']['value'] = $relative_url;
    metatag_config_save($config);

    // Dump out the current config, to aid with debugging.
    $this->verbose($config);

    // Load the front page.
    $this->drupalGet('<front>');
    $this->assertResponse(200);

    // Confirm that the image_src meta tag has the expected values.
    $xpath = $this->xpath("//link[@rel='image_src']");
    $this->assertEqual(count($xpath), 1, 'One image_src meta tag found.');
    $this->assertEqual((string) $xpath[0]['href'], $image_url);
    // , 'The image_src meta tag with an internal URI is being output as an absolute URL.');
    // Confirm the file could be loaded.
    $this->drupalGet($xpath[0]['href']);
    $this->assertResponse(200, "The image_src meta tag's value could be loaded.");
  }

  /**
   * Confirm that an image can be added to a global configuration using the
   * image's protocol-relative URL.
   */
  function testConfigProtocolRelativeURL() {
    // Generate a test image.
    $image_uri = $this->generateImage();
    $this->verbose($image_uri);

    // Work out the web-accessible URL for this image.
    $image_url = file_create_url($image_uri);

    // Make the URL protocol-relative.
    $relative_url = str_replace('http://', '//', $image_url);

    // Update the global config to add an image meta tag.
    $config = metatag_config_load('global');
    $config->config['image_src']['value'] = $relative_url;
    metatag_config_save($config);

    // Dump out the current config, to aid with debugging.
    $this->verbose($config);

    // Load the front page.
    $this->drupalGet('<front>');
    $this->assertResponse(200);

    // Confirm that the image_src meta tag has the expected values.
    $xpath = $this->xpath("//link[@rel='image_src']");
    $this->assertEqual(count($xpath), 1, 'One image_src meta tag found.');
    $this->assertEqual($xpath[0]['href'], $relative_url, 'The image_src meta tag with a protocol-relative URL is being output correctly.');
    $this->assertNotEqual($xpath[0]['href'], $image_url, 'The image_src meta tag does not contain the absolute URL.');
  }

  /**
   * Confirm that an image can be added to a global configuration using the
   * image's internal URI.
   */
  function testConfigInternalURL() {
    // Generate a test image.
    $image_uri = $this->generateImage();
    $this->verbose($image_uri);

    // Work out the web-accessible URL for this image.
    $image_url = file_create_url($image_uri);

    // Confirm the file could be loaded.
    $this->drupalGet($image_url);
    $this->assertResponse(200, 'The image could be loaded.');

    // Update the global config to add an image meta tag.
    $config = metatag_config_load('global');
    $config->config['image_src']['value'] = $image_uri;
    metatag_config_save($config);

    // Dump out the current config, to aid with debugging.
    $this->verbose($config);

    // Load the front page.
    $this->drupalGet('<front>');
    $this->assertResponse(200);

    // Confirm that the image URL can be found in the raw HTML.
    $this->assertRaw($image_url, 'Found the image URL in the raw HTML.');

    // Confirm that the image_src meta tag has the expected values.
    $xpath = $this->xpath("//link[@rel='image_src']");
    $this->assertEqual(count($xpath), 1, 'One image_src meta tag found.');
    $this->assertEqual($xpath[0]['href'], $image_url, 'The image_src meta tag with an internal URI is being output correctly.');

    // Confirm the file could be loaded.
    $this->drupalGet($xpath[0]['href']);
    $this->assertResponse(200, "The image_src meta tag's value could be loaded.");
  }

  /**
   * Confirm that an image with a space in its URL will be handled properly.
   */
  function testConfigImageWithSpaceInURL() {
    // Generate a test image.
    $image_uri = $this->generateImage();
    $this->verbose($image_uri);

    // Rename the file so it has a space in the filename.
    $image_uri = file_unmanaged_move($image_uri, str_replace('_', ' ', $image_uri));
    $this->verbose($image_uri);

    // Work out the web-accessible URL for this image.
    $image_url = file_create_url($image_uri);

    // Confirm the file could be loaded.
    $this->drupalGet($image_url);
    $this->assertResponse(200, 'The image could be loaded.');

    // After processing the image's URL will have "%20" instead of spaces.
    $image_url_friendly = str_replace(' ', '%20', $image_url);

    // Confirm the file's friendly URL could be loaded.
    $this->drupalGet($image_url_friendly);
    $this->assertResponse(200, 'The friendly image could be loaded.');

    // Update the global config to add an image meta tag.
    $config = metatag_config_load('global');
    $config->config['image_src']['value'] = $image_uri;
    metatag_config_save($config);

    // Dump out the current config, to aid with debugging.
    $this->verbose($config);

    // Load the front page.
    $this->drupalGet('<front>');
    $this->assertResponse(200);

    // Confirm that the image's friendly URL can be found in the raw HTML.
    $this->assertRaw($image_url_friendly, 'Found the friendly image URL in the raw HTML.');

    // Confirm that the image_src meta tag has the expected values.
    $xpath = $this->xpath("//link[@rel='image_src']");
    $this->assertEqual(count($xpath), 1, 'One image_src meta tag found.');
    $this->assertEqual($xpath[0]['href'], $image_url_friendly, 'The image had its spaces replaces with "%20".');

    // Confirm the file could be loaded.
    $this->drupalGet($xpath[0]['href']);
    $this->assertResponse(200, "The image_src meta tag's value could be loaded.");
  }

  /**
   * Confirm that a default value on an image field will be output correctly.
   */
  function testNodeFieldDefault() {
    // Generate a test image file object.
    $image = $this->generateImageFile();
    $image_url = file_create_url($image->uri);

    // Dump out the file object, to aid with debugging.
    $this->verbose($image);

    // Update the article-image default settings to use the new image field.
    $entity_type = 'node';
    $bundle = 'article';
    $field_name = 'field_image';
    $instance = field_info_instance($entity_type, $field_name, $bundle);
    $instance['settings']['default_image'] = $image->fid;
    field_update_instance($instance);

    // Create an example node.
    $args = array(
      'type' => 'article',
    );
    $node = $this->drupalCreateNode($args);

    // Update the config.
    $config = metatag_config_load('node');
    $config->config['image_src']['value'] = '[node:field_image]';
    metatag_config_save($config);

    // Load the node page.
    $this->drupalGet('node/' . $node->nid);
    $this->assertResponse(200);

    // Confirm that the image_src meta tag has the expected values.
    $xpath = $this->xpath("//link[@rel='image_src']");
    $this->assertEqual(count($xpath), 1, 'One image_src meta tag found.');
    $this->assertEqual($xpath[0]['href'], $image_url, "The image_src meta tag was found with the field's default image.");

    // Confirm the file could be loaded.
    $this->drupalGet($xpath[0]['href']);
    $this->assertResponse(200, "The image_src meta tag's value could be loaded.");
  }

  /**
   * Confirm that a file on an image field will be output correctly.
   */
  function testNodeFieldValue() {
    // Update the 'content' config to use the field_image field as the
    // image_src meta tag.
    $config = metatag_config_load('node');
    $config->config['image_src']['value'] = '[node:field_image]';
    metatag_config_save($config);

    // Generate a test image file object.
    $image = $this->generateImageFile();
    $image_url = file_create_url($image->uri);

    // Dump out the file object, to aid with debugging.
    $this->verbose($image);

    // Create an example node.
    $args = array(
      'type' => 'article',
      'field_image' => array(
        LANGUAGE_NONE => array(
          array('fid' => $image->fid),
        ),
      ),
    );
    $node = $this->drupalCreateNode($args);

    // Forcibly reload the node, to avoid working with a cached version.
    $node = node_load($node->nid, NULL, TRUE);
    $this->verbose($node, 'Node');

    // Load the node page.
    $this->drupalGet('node/' . $node->nid);
    $this->assertResponse(200);

    // Confirm that the image_src meta tag has the expected values.
    $xpath = $this->xpath("//link[@rel='image_src']");
    $this->assertEqual(count($xpath), 1, 'One image_src meta tag found.');
    $this->assertEqual($xpath[0]['href'], $image_url, "The image_src meta tag was found with the node's image field's value.");

    // Confirm the file could be loaded.
    $this->drupalGet($xpath[0]['href']);
    $this->assertResponse(200, "The image_src meta tag's value could be loaded.");
  }

  /**
   * Confirm that when using a file field that allows multiple values, only the
   * first item will be used when outputting a single meta tag.
   */
  function testNodeFieldValueNotMultiple() {
    // Update the 'content' config to use the field_image field as the
    // image_src meta tag.
    $config = metatag_config_load('node');
    $config->config['image_src']['value'] = '[node:field_image]';
    metatag_config_save($config);

    // Update the image field to allow unlimited items.
    $field_name = 'field_image';
    $field = field_info_field($field_name);
    $field['cardinality'] = FIELD_CARDINALITY_UNLIMITED;
    field_update_field($field);

    // Generate a test image file object.
    $image1 = $this->generateImageFile();
    $image1_url = file_create_url($image1->uri);
    $image2 = $this->generateImageFile();
    $image2_url = file_create_url($image2->uri);

    // Dump out the file objects, to aid with debugging.
    $this->verbose($image1, 'Image #1');
    $this->verbose($image2, 'Image #2');

    // Create an example node.
    $args = array(
      'type' => 'article',
      'field_image' => array(
        LANGUAGE_NONE => array(
          array('fid' => $image1->fid),
          array('fid' => $image2->fid),
        ),
      ),
    );
    $node = $this->drupalCreateNode($args);

    // Forcibly reload the node, to avoid working with a cached version.
    $node = node_load($node->nid, NULL, TRUE);
    $this->verbose($node, 'Node');

    // Load the node page.
    $this->drupalGet('node/' . $node->nid);
    $this->assertResponse(200);

    // Confirm that the image_src meta tag has the expected values.
    $xpath = $this->xpath("//link[@rel='image_src']");
    $this->assertEqual(count($xpath), 1, 'Only one image_src meta tag found.');
    $this->assertEqual($xpath[0]['href'], $image1_url, "The image_src meta tag was found with the node's image field's first value.");
    $this->assertNotEqual($xpath[0]['href'], $image2_url, "The image_src meta tag does not contain the node's image field's second value.");

    // Confirm the file could be loaded.
    $this->drupalGet($xpath[0]['href']);
    $this->assertResponse(200, "The image_src meta tag's value could be loaded.");
  }

  /**
   * Confirm that when using a file field that allows multiple values, that
   * multiple images can be used and then it will result in multiple meta tags.
   */
  function testNodeFieldValueMultiple() {
    // Update the 'content' config to use the field_image field as the
    // image_src meta tag.
    $config = metatag_config_load('node');
    $config->config['og:image']['value'] = '[node:field_image]';
    metatag_config_save($config);

    // Update the image field to allow unlimited items.
    $field_name = 'field_image';
    $field = field_info_field($field_name);
    $field['cardinality'] = FIELD_CARDINALITY_UNLIMITED;
    field_update_field($field);

    // Generate a test image file object.
    $image1 = $this->generateImageFile();
    $image1_url = file_create_url($image1->uri);
    $image2 = $this->generateImageFile();
    $image2_url = file_create_url($image2->uri);

    // Dump out the file objects, to aid with debugging.
    $this->verbose($image1, 'Image #1');
    $this->verbose($image2, 'Image #2');

    // Create an example node.
    $args = array(
      'type' => 'article',
      'field_image' => array(
        LANGUAGE_NONE => array(
          array('fid' => $image1->fid),
          array('fid' => $image2->fid),
        ),
      ),
    );
    $node = $this->drupalCreateNode($args);

    // Forcibly reload the node, to avoid working with a cached version.
    $node = node_load($node->nid, NULL, TRUE);
    $this->verbose($node, 'Node');

    // Load the node page.
    $this->drupalGet('node/' . $node->nid);
    $this->assertResponse(200);

    // Confirm that the og:image meta tags have the expected values.
    $xpath = $this->xpath("//meta[@property='og:image']");
    $this->assertEqual(count($xpath), 2, 'Two og:image meta tags were found.');
    $this->assertEqual($xpath[0]['content'], $image1_url, "The first og:image meta tag has the correct image.");
    $this->assertEqual($xpath[1]['content'], $image2_url, "The second og:image meta tag has the correct image.");

    // Confirm the file could be loaded.
    $this->drupalGet($xpath[0]['content']);
    $this->assertResponse(200, "The first og:image meta tag's value could be loaded.");
    $this->drupalGet($xpath[1]['content']);
    $this->assertResponse(200, "The second og:image meta tag's value could be loaded.");
  }

}
