diff --git a/src/Tests/TokenFieldUiTest.php b/src/Tests/TokenFieldUiTest.php index 37c80f4..37c4a10 100644 --- a/src/Tests/TokenFieldUiTest.php +++ b/src/Tests/TokenFieldUiTest.php @@ -3,6 +3,9 @@ namespace Drupal\token\Tests; use Drupal\node\Entity\NodeType; +use Drupal\node\Entity\Node; +use Drupal\file\Entity\File; +use Drupal\image\Entity\ImageStyle; /** * Tests field ui. @@ -60,6 +63,28 @@ class TokenFieldUiTest extends TokenTestBase { 'entity_type' => 'node', 'bundle' => 'article', ))->save(); + entity_create('field_storage_config', array( + 'field_name' => 'field_image_2', + 'entity_type' => 'node', + 'type' => 'image', + ))->save(); + entity_create('field_config', array( + 'field_name' => 'field_image_2', + 'label' => 'Image 2', + 'entity_type' => 'node', + 'bundle' => 'article', + ))->save(); + entity_create('field_storage_config', array( + 'field_name' => 'multivalued_field_image', + 'entity_type' => 'node', + 'type' => 'image', + ))->save(); + entity_create('field_config', array( + 'field_name' => 'multivalued_field_image', + 'label' => 'Multivalued field image', + 'entity_type' => 'node', + 'bundle' => 'article', + ))->save(); entity_get_form_display('node', 'article', 'default') ->setComponent('field_body', [ @@ -94,4 +119,147 @@ class TokenFieldUiTest extends TokenTestBase { $this->drupalGet('node/add/article'); $this->assertText('The site is called Drupal.'); } + + /** + * Test that tokens are correctly provided and replaced for the image fields. + */ + public function testImageFieldTokens() { + // Generate 2 different test images. + file_unmanaged_copy(\Drupal::root() . '/core/misc/druplicon.png', 'public://example1.png'); + file_unmanaged_copy(\Drupal::root() . '/core/misc/loading.gif', 'public://example2.gif'); + + // Resize the test images so that they will be scaled down during token + // replacement. + $image1 = \Drupal::service('image.factory')->get('public://example1.png'); + $image1->resize(500, 500); + $image1->save(); + $image2 = \Drupal::service('image.factory')->get('public://example2.gif'); + $image2->resize(500, 500); + $image2->save(); + + /** @var \Drupal\file\Entity\File $image1 */ + $image1 = File::create(['uri' => 'public://example1.png']); + $image1->save(); + /** @var \Drupal\file\Entity\File $image2 */ + $image2 = File::create(['uri' => 'public://example2.gif']); + $image2->save(); + + $node = Node::create([ + 'title' => 'Test node title', + 'type' => 'article', + 'field_image' => [ + [ + 'target_id' => $image1->id(), + ], + ], + 'field_image_2' => [ + [ + 'target_id' => $image2->id(), + ], + ], + 'multivalued_field_image' => [ + ['target_id' => $image1->id()], + ['target_id' => $image2->id()], + ], + ]); + $node->save(); + + // Obtain the file size and dimension of the images that will be scaled + // down during token replacement by applying the styles here. + $style_thumbnail = ImageStyle::load('thumbnail'); + $style_thumbnail->createDerivative('public://example1.png', 'public://styles/thumbnail/public/example1-test.png'); + $style_medium = ImageStyle::load('medium'); + $style_medium->createDerivative('public://example1.png', 'public://styles/medium/public/example1-test.png'); + $style_medium->createDerivative('public://example2.gif', 'public://styles/medium/public/example2-test.gif'); + $style_large = ImageStyle::load('large'); + $style_large->createDerivative('public://example1.png', 'public://styles/large/public/example1-test.png'); + $style_large->createDerivative('public://example2.gif', 'public://styles/large/public/example2-test.gif'); + + $tokens = [ + // field_image + 'field_image:thumbnail:mimetype' => 'image/png', + 'field_image:medium:mimetype' => 'image/png', + 'field_image:large:mimetype' => 'image/png', + 'field_image:thumbnail:filesize' => '6909', + 'field_image:medium:filesize' => '26745', + 'field_image:large:filesize' => '90402', + 'field_image:thumbnail:height' => '100', + 'field_image:medium:height' => '220', + 'field_image:large:height' => '480', + 'field_image:thumbnail:width' => '100', + 'field_image:medium:width' => '220', + 'field_image:large:width' => '480', + 'field_image:thumbnail:uri' => 'public://styles/thumbnail/public/example1.png', + 'field_image:medium:uri' => 'public://styles/medium/public/example1.png', + 'field_image:large:uri' => 'public://styles/large/public/example1.png', + 'field_image:thumbnail:url' => $style_thumbnail->buildUrl('public://example1.png'), + 'field_image:medium:url' => $style_medium->buildUrl('public://example1.png'), + 'field_image:large:url' => $style_large->buildUrl('public://example1.png'), + 'field_image:thumbnail' => $style_thumbnail->buildUrl('public://example1.png'), + 'field_image:medium' => $style_medium->buildUrl('public://example1.png'), + 'field_image:large' => $style_large->buildUrl('public://example1.png'), + // field_image_2 + 'field_image_2:thumbnail:mimetype' => 'image/gif', + 'field_image_2:medium:mimetype' => 'image/gif', + 'field_image_2:large:mimetype' => 'image/gif', + 'field_image_2:thumbnail:filesize' => '3797', + 'field_image_2:medium:filesize' => '13562', + 'field_image_2:large:filesize' => '56314', + 'field_image_2:thumbnail:height' => '100', + 'field_image_2:medium:height' => '220', + 'field_image_2:large:height' => '480', + 'field_image_2:thumbnail:width' => '100', + 'field_image_2:medium:width' => '220', + 'field_image_2:large:width' => '480', + 'field_image_2:thumbnail:uri' => 'public://styles/thumbnail/public/example2.gif', + 'field_image_2:medium:uri' => 'public://styles/medium/public/example2.gif', + 'field_image_2:large:uri' => 'public://styles/large/public/example2.gif', + 'field_image_2:thumbnail:url' => $style_thumbnail->buildUrl('public://example2.gif'), + 'field_image_2:medium:url' => $style_medium->buildUrl('public://example2.gif'), + 'field_image_2:large:url' => $style_large->buildUrl('public://example2.gif'), + 'field_image_2:thumbnail' => $style_thumbnail->buildUrl('public://example2.gif'), + 'field_image_2:medium' => $style_medium->buildUrl('public://example2.gif'), + 'field_image_2:large' => $style_large->buildUrl('public://example2.gif'), + // multivalued_field_image:0, test for thumbnail image style only. + 'multivalued_field_image:0:thumbnail:mimetype' => 'image/png', + 'multivalued_field_image:0:thumbnail:filesize' => '6909', + 'multivalued_field_image:0:thumbnail:height' => '100', + 'multivalued_field_image:0:thumbnail:width' => '100', + 'multivalued_field_image:0:thumbnail:uri' => 'public://styles/thumbnail/public/example1.png', + 'multivalued_field_image:0:thumbnail:url' => $style_thumbnail->buildUrl('public://example1.png'), + 'multivalued_field_image:0:thumbnail' => $style_thumbnail->buildUrl('public://example1.png'), + // multivalued_field_image:1, test for medium image style only. + 'multivalued_field_image:1:medium:mimetype' => 'image/gif', + 'multivalued_field_image:1:medium:filesize' => '13562', + 'multivalued_field_image:1:medium:height' => '220', + 'multivalued_field_image:1:medium:width' => '220', + 'multivalued_field_image:1:medium:uri' => 'public://styles/medium/public/example2.gif', + 'multivalued_field_image:1:medium:url' => $style_medium->buildUrl('public://example2.gif'), + 'multivalued_field_image:1:medium' => $style_medium->buildUrl('public://example2.gif'), + ]; + $this->assertTokens('node', ['node' => $node], $tokens); + + /** @var \Drupal\token\Token $token_service */ + $token_service = \Drupal::service('token'); + + // Test one of the image style's token info for cardinality 1 image field. + $token_info = $token_service->getTokenInfo('node-field_image', 'thumbnail'); + $this->assertEqual('Thumbnail (100×100)', $token_info['name']); + $this->assertEqual('Represents the image in the given image style.', $token_info['description']); + + // Test one of the image style's token info for a multivalued image field. + $token_info = $token_service->getTokenInfo('node-multivalued_field_image', 'medium'); + $this->assertEqual('Medium (220×220)', $token_info['name']); + $this->assertEqual('Represents the image in the given image style.', $token_info['description']); + + // Test few of the image styles' properties token info. + $token_info = $token_service->getTokenInfo('image_with_image_style', 'mimetype'); + $this->assertEqual('MIME type', $token_info['name']); + $this->assertEqual('The MIME type (image/png, image/bmp, etc.) of the image.', $token_info['description']); + + $token_info = $token_service->getTokenInfo('image_with_image_style', 'filesize'); + $this->assertEqual('File size', $token_info['name']); + $this->assertEqual('The file size of the image.', $token_info['description']); + } + } diff --git a/token.tokens.inc b/token.tokens.inc index 5b39039..2670560 100644 --- a/token.tokens.inc +++ b/token.tokens.inc @@ -22,6 +22,7 @@ use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Drupal\Core\TypedData\PrimitiveInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Entity\ContentEntityTypeInterface; +use Drupal\image\Entity\ImageStyle; /** * Implements hook_token_info_alter(). @@ -382,6 +383,42 @@ function token_token_info() { 'dynamic' => TRUE, ); + // Define image_with_image_style token type. + if (\Drupal::moduleHandler()->moduleExists('image')) { + $info['types']['image_with_image_style'] = [ + 'name' => t('Image with image style'), + 'needs-data' => 'image_with_image_style', + 'module' => 'token', + 'nested' => TRUE, + ]; + + // Provide tokens for the ImageStyle attributes. + $info['tokens']['image_with_image_style']['mimetype'] = [ + 'name' => t('MIME type'), + 'description' => t('The MIME type (image/png, image/bmp, etc.) of the image.'), + ]; + $info['tokens']['image_with_image_style']['filesize'] = [ + 'name' => t('File size'), + 'description' => t('The file size of the image.'), + ]; + $info['tokens']['image_with_image_style']['height'] = [ + 'name' => t('Height'), + 'description' => t('The height the image, in pixels.'), + ]; + $info['tokens']['image_with_image_style']['width'] = [ + 'name' => t('Width'), + 'description' => t('The width of the image, in pixels.'), + ]; + $info['tokens']['image_with_image_style']['uri'] = [ + 'name' => t('URI'), + 'description' => t('The URI to the image.'), + ]; + $info['tokens']['image_with_image_style']['url'] = [ + 'name' => t('URL'), + 'description' => t('The URL to the image.'), + ]; + } + return $info; } @@ -1286,6 +1323,17 @@ function field_token_info_alter(&$info) { ]; } } + // Provide image_with_image_style tokens for image fields. + if ($field->getType() == 'image') { + $image_styles = image_style_options(FALSE); + foreach ($image_styles as $style => $description) { + $info['tokens'][$field_token_name][$style] = [ + 'name' => $description, + 'description' => t('Represents the image in the given image style.'), + 'type' => 'image_with_image_style', + ]; + } + } } } } @@ -1460,6 +1508,51 @@ function field_tokens($type, $tokens, array $data = array(), array $options = ar $replacements[$original] = $entity->label(); } } + elseif (($field_item->getFieldDefinition()->getType() == 'image') && ($style = ImageStyle::load($property_name))) { + // Handle [node:field_name:image_style:property] tokens and multivalued + // [node:field_name:delta:image_style:property] tokens. If the token is + // of the form [node:field_name:image_style], provide the URL as a + // replacement. + $property_name = isset($parts[1]) ? $parts[1] : 'url'; + $entity = $field_item->entity; + $original_uri = $entity->getFileUri(); + + // Only generate the image derivative if needed. + if ($property_name === 'width' || $property_name === 'height') { + $dimensions = [ + 'width' => $field_item->width, + 'height' => $field_item->height, + ]; + $style->transformDimensions($dimensions, $original_uri); + $replacements[$original] = $dimensions[$property_name]; + } + elseif ($property_name === 'uri') { + $replacements[$original] = $style->buildUri($original_uri); + } + elseif ($property_name === 'url') { + $replacements[$original] = $style->buildUrl($original_uri); + } + else { + // Generate the image derivative, if it doesn't already exist. + $derivative_uri = $style->buildUri($original_uri); + $derivative_exists = TRUE; + if (!file_exists($derivative_uri)) { + $derivative_exists = $style->createDerivative($original_uri, $derivative_uri); + } + if ($derivative_exists) { + $image = \Drupal::service('image.factory')->get($derivative_uri); + // Provide the replacement. + switch ($property_name) { + case 'mimetype': + $replacements[$original] = $image->getMimeType(); + break; + case 'filesize' : + $replacements[$original] = $image->getFileSize(); + break; + } + } + } + } else { $replacements[$original] = $field_item->$property_name; }