uri) && isset($file->metadata)) { $svg_dimensions = svg_image_get_dimensions($file->uri); if ($svg_dimensions) { $file->metadata['width'] = $svg_dimensions['width']; $file->metadata['height'] = $svg_dimensions['height']; } } } /** * Implements hook_field_attach_presave(). * * When saving a entity, this hook is called to make any adjustments to the * entire entity's fields before attempting to write to the database. When * Image module encounters an SVG image, it sets the height and width values * to be empty strings, which would cause a database constraint error when * a string is inserted into an integer column. * * This implementation loops through all fields attached to an entity, finds * those that are an image field, then sets the width and height values within * that field. These changes are made by reference, so they are in the $entity * object when Field module saves to the database. */ function svg_image_field_attach_presave($entity_type, $entity) { // Get information about which fields are on this type of entity. list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); $bundle_field_info = field_info_instances($entity_type, $bundle); // Loop through each of the fields and find those that are image fields. foreach ($bundle_field_info as $field_name => $instance_info) { $field_info = field_info_field($field_name); if ($field_info['type'] === 'image') { // The language should normally be LANGUAGE_NONE for an image field, but // check the language property just to be certain. $langcode = LANGUAGE_NONE; if (isset($entity->language) && isset($entity->{$field_name}[$entity->language])) { $langcode = $entity->language; } if (!isset($entity->{$field_name}[$langcode])) { continue; } // Update the field values (by reference) for SVG images. $field_values = &$entity->{$field_name}[$langcode]; foreach ($field_values as $delta => $field_value) { if (!isset($field_value['fid'])) { continue; } $file = file_load($field_value['fid']); if ($file && svg_image_is_svg($file->uri)) { // Set width/height as a safety measure. Savable NULL is better than // the not savable empty string. $field_values[$delta]['width'] = NULL; $field_values[$delta]['height'] = NULL; if ($svg_dimensions = svg_image_get_dimensions($file->uri)) { $field_values[$delta]['width'] = $svg_dimensions['width']; $field_values[$delta]['height'] = $svg_dimensions['height']; } } } } } } /** * Implements hook_file_url_alter(). * * Prevent image_style_url() from using a different URL for SVG images. Because * image styles cannot operate on SVGs, set the URL back to the original image. * This affects theme_image_style(), which normally would point to a new image. */ function svg_image_file_url_alter(&$url) { // If this is an SVG image in the styles directory... if (strpos($url, '/styles/') && strpos($url, '.svg')) { // Remove the styles directory portions and use the original image URL. $url = preg_replace('!/styles/.*?/.*?/!', '/', $url); } } /** * Get an SVG image's defined dimensions. * * @param string $uri * The URI or path to an SVG image. * * @return array|FALSE * An array containing the keys "width" and "height" as integer values. If the * image is an SVG but no set dimensions are available, these keys will have * NULL values. If the image is not an SVG, FALSE will be return. */ function svg_image_get_dimensions($uri) { // Safety check. if (!svg_image_is_svg($uri)) { return FALSE; } // Return cached dimensions if already retrieved once this request. $cached_images = &drupal_static(__FUNCTION__, array()); if (isset($cached_images[$uri])) { return $cached_images[$uri]; } $svg_dimensions = array( 'width' => NULL, 'height' => NULL, ); $file_contents = file_get_contents($uri); if ($file_contents) { $svg = simplexml_load_string($file_contents); foreach ($svg->attributes() as $attribute => $value) { if ($attribute === 'width' || $attribute === 'height') { $svg_dimensions[$attribute] = (integer) $value; } } } // Save values to static cache. $cached_images[$uri] = $svg_dimensions; return $svg_dimensions; } /** * Determine if a file URI is an SVG image based on its file extension. * * @param string $uri * A path or URI to an image. * @return bool * TRUE if the image is an SVG. FALSE if it is not. */ function svg_image_is_svg($uri) { $mimetype = file_get_mimetype($uri); return $mimetype === 'image/svg+xml'; }