Drupal PHP Cross Reference Content Management Systems

Source: /modules/image/image.field.inc - 642 lines - 21008 bytes - Summary - Text - Print

   1  <?php
   2  
   3  /**
   4   * @file
   5   * Implement an image field, based on the file module's file field.
   6   */
   7  
   8  /**
   9   * Implements hook_field_info().
  10   */
  11  function image_field_info() {
  12    return array(
  13      'image' => array(
  14        'label' => t('Image'),
  15        'description' => t('This field stores the ID of an image file as an integer value.'),
  16        'settings' => array(
  17          'uri_scheme' => variable_get('file_default_scheme', 'public'),
  18          'default_image' => 0,
  19        ),
  20        'instance_settings' => array(
  21          'file_extensions' => 'png gif jpg jpeg',
  22          'file_directory' => '',
  23          'max_filesize' => '',
  24          'alt_field' => 0,
  25          'title_field' => 0,
  26          'max_resolution' => '',
  27          'min_resolution' => '',
  28          'default_image' => 0,
  29        ),
  30        'default_widget' => 'image_image',
  31        'default_formatter' => 'image',
  32      ),
  33    );
  34  }
  35  
  36  /**
  37   * Implements hook_field_settings_form().
  38   */
  39  function image_field_settings_form($field, $instance) {
  40    $defaults = field_info_field_settings($field['type']);
  41    $settings = array_merge($defaults, $field['settings']);
  42  
  43    $scheme_options = array();
  44    foreach (file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE) as $scheme => $stream_wrapper) {
  45      $scheme_options[$scheme] = $stream_wrapper['name'];
  46    }
  47    $form['uri_scheme'] = array(
  48      '#type' => 'radios',
  49      '#title' => t('Upload destination'),
  50      '#options' => $scheme_options,
  51      '#default_value' => $settings['uri_scheme'],
  52      '#description' => t('Select where the final files should be stored. Private file storage has significantly more overhead than public files, but allows restricted access to files within this field.'),
  53    );
  54  
  55    // When the user sets the scheme on the UI, even for the first time, it's
  56    // updating a field because fields are created on the "Manage fields"
  57    // page. So image_field_update_field() can handle this change.
  58    $form['default_image'] = array(
  59      '#title' => t('Default image'),
  60      '#type' => 'managed_file',
  61      '#description' => t('If no image is uploaded, this image will be shown on display.'),
  62      '#default_value' => $field['settings']['default_image'],
  63      '#upload_location' => $settings['uri_scheme'] . '://default_images/',
  64    );
  65  
  66    return $form;
  67  }
  68  
  69  /**
  70   * Implements hook_field_instance_settings_form().
  71   */
  72  function image_field_instance_settings_form($field, $instance) {
  73    $settings = $instance['settings'];
  74  
  75    // Use the file field instance settings form as a basis.
  76    $form = file_field_instance_settings_form($field, $instance);
  77  
  78    // Add maximum and minimum resolution settings.
  79    $max_resolution = explode('x', $settings['max_resolution']) + array('', '');
  80    $form['max_resolution'] = array(
  81      '#type' => 'item',
  82      '#title' => t('Maximum image resolution'),
  83      '#element_validate' => array('_image_field_resolution_validate'),
  84      '#weight' => 4.1,
  85      '#field_prefix' => '<div class="container-inline">',
  86      '#field_suffix' => '</div>',
  87      '#description' => t('The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Leave blank for no restriction. If a larger image is uploaded, it will be resized to reflect the given width and height. Resizing images on upload will cause the loss of <a href="http://en.wikipedia.org/wiki/Exchangeable_image_file_format">EXIF data</a> in the image.'),
  88    );
  89    $form['max_resolution']['x'] = array(
  90      '#type' => 'textfield',
  91      '#title' => t('Maximum width'),
  92      '#title_display' => 'invisible',
  93      '#default_value' => $max_resolution[0],
  94      '#size' => 5,
  95      '#maxlength' => 5,
  96      '#field_suffix' => ' x ',
  97    );
  98    $form['max_resolution']['y'] = array(
  99      '#type' => 'textfield',
 100      '#title' => t('Maximum height'),
 101      '#title_display' => 'invisible',
 102      '#default_value' => $max_resolution[1],
 103      '#size' => 5,
 104      '#maxlength' => 5,
 105      '#field_suffix' => ' ' . t('pixels'),
 106    );
 107  
 108    $min_resolution = explode('x', $settings['min_resolution']) + array('', '');
 109    $form['min_resolution'] = array(
 110      '#type' => 'item',
 111      '#title' => t('Minimum image resolution'),
 112      '#element_validate' => array('_image_field_resolution_validate'),
 113      '#weight' => 4.2,
 114      '#field_prefix' => '<div class="container-inline">',
 115      '#field_suffix' => '</div>',
 116      '#description' => t('The minimum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Leave blank for no restriction. If a smaller image is uploaded, it will be rejected.'),
 117    );
 118    $form['min_resolution']['x'] = array(
 119      '#type' => 'textfield',
 120      '#title' => t('Minimum width'),
 121      '#title_display' => 'invisible',
 122      '#default_value' => $min_resolution[0],
 123      '#size' => 5,
 124      '#maxlength' => 5,
 125      '#field_suffix' => ' x ',
 126    );
 127    $form['min_resolution']['y'] = array(
 128      '#type' => 'textfield',
 129      '#title' => t('Minimum height'),
 130      '#title_display' => 'invisible',
 131      '#default_value' => $min_resolution[1],
 132      '#size' => 5,
 133      '#maxlength' => 5,
 134      '#field_suffix' => ' ' . t('pixels'),
 135    );
 136  
 137    // Remove the description option.
 138    unset($form['description_field']);
 139  
 140    // Add title and alt configuration options.
 141    $form['alt_field'] = array(
 142      '#type' => 'checkbox',
 143      '#title' => t('Enable <em>Alt</em> field'),
 144      '#default_value' => $settings['alt_field'],
 145      '#description' => t('The alt attribute may be used by search engines, screen readers, and when the image cannot be loaded.'),
 146      '#weight' => 10,
 147    );
 148    $form['title_field'] = array(
 149      '#type' => 'checkbox',
 150      '#title' => t('Enable <em>Title</em> field'),
 151      '#default_value' => $settings['title_field'],
 152      '#description' => t('The title attribute is used as a tooltip when the mouse hovers over the image.'),
 153      '#weight' => 11,
 154    );
 155  
 156    // Add the default image to the instance.
 157    $form['default_image'] = array(
 158      '#title' => t('Default image'),
 159      '#type' => 'managed_file',
 160      '#description' => t("If no image is uploaded, this image will be shown on display and will override the field's default image."),
 161      '#default_value' => $settings['default_image'],
 162      '#upload_location' => $field['settings']['uri_scheme'] . '://default_images/',
 163    );
 164  
 165    return $form;
 166  }
 167  
 168  /**
 169   * Element validate function for resolution fields.
 170   */
 171  function _image_field_resolution_validate($element, &$form_state) {
 172    if (!empty($element['x']['#value']) || !empty($element['y']['#value'])) {
 173      foreach (array('x', 'y') as $dimension) {
 174        $value = $element[$dimension]['#value'];
 175        if (!is_numeric($value)) {
 176          form_error($element[$dimension], t('Height and width values must be numeric.'));
 177          return;
 178        }
 179        if (intval($value) == 0) {
 180          form_error($element[$dimension], t('Both a height and width value must be specified in the !name field.', array('!name' => $element['#title'])));
 181          return;
 182        }
 183      }
 184      form_set_value($element, intval($element['x']['#value']) . 'x' . intval($element['y']['#value']), $form_state);
 185    }
 186    else {
 187      form_set_value($element, '', $form_state);
 188    }
 189  }
 190  
 191  /**
 192   * Implements hook_field_load().
 193   */
 194  function image_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
 195    file_field_load($entity_type, $entities, $field, $instances, $langcode, $items, $age);
 196  }
 197  
 198  /**
 199   * Implements hook_field_prepare_view().
 200   */
 201  function image_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) {
 202    // If there are no files specified at all, use the default.
 203    foreach ($entities as $id => $entity) {
 204      if (empty($items[$id])) {
 205        $fid = 0;
 206        // Use the default for the instance if one is available.
 207        if (!empty($instances[$id]['settings']['default_image'])) {
 208          $fid = $instances[$id]['settings']['default_image'];
 209        }
 210        // Otherwise, use the default for the field.
 211        elseif (!empty($field['settings']['default_image'])) {
 212          $fid = $field['settings']['default_image'];
 213        }
 214  
 215        // Add the default image if one is found.
 216        if ($fid && ($file = file_load($fid))) {
 217          $items[$id][0] = (array) $file + array(
 218            'is_default' => TRUE,
 219            'alt' => '',
 220            'title' => '',
 221          );
 222        }
 223      }
 224    }
 225  }
 226  
 227  /**
 228   * Implements hook_field_presave().
 229   */
 230  function image_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
 231    file_field_presave($entity_type, $entity, $field, $instance, $langcode, $items);
 232  
 233    // Determine the dimensions if necessary.
 234    foreach ($items as &$item) {
 235      if (!isset($item['width']) || !isset($item['height'])) {
 236        $info = image_get_info(file_load($item['fid'])->uri);
 237  
 238        if (is_array($info)) {
 239          $item['width'] = $info['width'];
 240          $item['height'] = $info['height'];
 241        }
 242      }
 243    }
 244  }
 245  
 246  /**
 247   * Implements hook_field_insert().
 248   */
 249  function image_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
 250    file_field_insert($entity_type, $entity, $field, $instance, $langcode, $items);
 251  }
 252  
 253  /**
 254   * Implements hook_field_update().
 255   */
 256  function image_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
 257    file_field_update($entity_type, $entity, $field, $instance, $langcode, $items);
 258  }
 259  
 260  /**
 261   * Implements hook_field_delete().
 262   */
 263  function image_field_delete($entity_type, $entity, $field, $instance, $langcode, &$items) {
 264    file_field_delete($entity_type, $entity, $field, $instance, $langcode, $items);
 265  }
 266  
 267  /**
 268   * Implements hook_field_delete_revision().
 269   */
 270  function image_field_delete_revision($entity_type, $entity, $field, $instance, $langcode, &$items) {
 271    file_field_delete_revision($entity_type, $entity, $field, $instance, $langcode, $items);
 272  }
 273  
 274  /**
 275   * Implements hook_field_is_empty().
 276   */
 277  function image_field_is_empty($item, $field) {
 278    return file_field_is_empty($item, $field);
 279  }
 280  
 281  /**
 282   * Implements hook_field_widget_info().
 283   */
 284  function image_field_widget_info() {
 285    return array(
 286      'image_image' => array(
 287        'label' => t('Image'),
 288        'field types' => array('image'),
 289        'settings' => array(
 290          'progress_indicator' => 'throbber',
 291          'preview_image_style' => 'thumbnail',
 292        ),
 293        'behaviors' => array(
 294          'multiple values' => FIELD_BEHAVIOR_CUSTOM,
 295          'default value' => FIELD_BEHAVIOR_NONE,
 296        ),
 297      ),
 298    );
 299  }
 300  
 301  /**
 302   * Implements hook_field_widget_settings_form().
 303   */
 304  function image_field_widget_settings_form($field, $instance) {
 305    $widget = $instance['widget'];
 306    $settings = $widget['settings'];
 307  
 308    // Use the file widget settings form.
 309    $form = file_field_widget_settings_form($field, $instance);
 310  
 311    $form['preview_image_style'] = array(
 312      '#title' => t('Preview image style'),
 313      '#type' => 'select',
 314      '#options' => image_style_options(FALSE),
 315      '#empty_option' => '<' . t('no preview') . '>',
 316      '#default_value' => $settings['preview_image_style'],
 317      '#description' => t('The preview image will be shown while editing the content.'),
 318      '#weight' => 15,
 319    );
 320  
 321    return $form;
 322  }
 323  
 324  /**
 325   * Implements hook_field_widget_form().
 326   */
 327  function image_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
 328  
 329    // Add display_field setting to field because file_field_widget_form() assumes it is set.
 330    $field['settings']['display_field'] = 0;
 331  
 332    $elements = file_field_widget_form($form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
 333    $settings = $instance['settings'];
 334  
 335    foreach (element_children($elements) as $delta) {
 336      // Add upload resolution validation.
 337      if ($settings['max_resolution'] || $settings['min_resolution']) {
 338        $elements[$delta]['#upload_validators']['file_validate_image_resolution'] = array($settings['max_resolution'], $settings['min_resolution']);
 339      }
 340  
 341      // If not using custom extension validation, ensure this is an image.
 342      $supported_extensions = array('png', 'gif', 'jpg', 'jpeg');
 343      $extensions = isset($elements[$delta]['#upload_validators']['file_validate_extensions'][0]) ? $elements[$delta]['#upload_validators']['file_validate_extensions'][0] : implode(' ', $supported_extensions);
 344      $extensions = array_intersect(explode(' ', $extensions), $supported_extensions);
 345      $elements[$delta]['#upload_validators']['file_validate_extensions'][0] = implode(' ', $extensions);
 346  
 347      // Add all extra functionality provided by the image widget.
 348      $elements[$delta]['#process'][] = 'image_field_widget_process';
 349    }
 350  
 351    if ($field['cardinality'] == 1) {
 352      // If there's only one field, return it as delta 0.
 353      if (empty($elements[0]['#default_value']['fid'])) {
 354        $elements[0]['#description'] = theme('file_upload_help', array('description' => $instance['description'], 'upload_validators' => $elements[0]['#upload_validators']));
 355      }
 356    }
 357    else {
 358      $elements['#file_upload_description'] = theme('file_upload_help', array('upload_validators' => $elements[0]['#upload_validators']));
 359    }
 360    return $elements;
 361  }
 362  
 363  /**
 364   * An element #process callback for the image_image field type.
 365   *
 366   * Expands the image_image type to include the alt and title fields.
 367   */
 368  function image_field_widget_process($element, &$form_state, $form) {
 369    $item = $element['#value'];
 370    $item['fid'] = $element['fid']['#value'];
 371  
 372    $instance = field_widget_instance($element, $form_state);
 373  
 374    $settings = $instance['settings'];
 375    $widget_settings = $instance['widget']['settings'];
 376  
 377    $element['#theme'] = 'image_widget';
 378    $element['#attached']['css'][] = drupal_get_path('module', 'image') . '/image.css';
 379  
 380    // Add the image preview.
 381    if ($element['#file'] && $widget_settings['preview_image_style']) {
 382      $variables = array(
 383        'style_name' => $widget_settings['preview_image_style'],
 384        'path' => $element['#file']->uri,
 385      );
 386  
 387      // Determine image dimensions.
 388      if (isset($element['#value']['width']) && isset($element['#value']['height'])) {
 389        $variables['width'] = $element['#value']['width'];
 390        $variables['height'] = $element['#value']['height'];
 391      }
 392      else {
 393        $info = image_get_info($element['#file']->uri);
 394  
 395        if (is_array($info)) {
 396          $variables['width'] = $info['width'];
 397          $variables['height'] = $info['height'];
 398        }
 399        else {
 400          $variables['width'] = $variables['height'] = NULL;
 401        }
 402      }
 403  
 404      $element['preview'] = array(
 405        '#type' => 'markup',
 406        '#markup' => theme('image_style', $variables),
 407      );
 408  
 409      // Store the dimensions in the form so the file doesn't have to be accessed
 410      // again. This is important for remote files.
 411      $element['width'] = array(
 412        '#type' => 'hidden',
 413        '#value' => $variables['width'],
 414      );
 415      $element['height'] = array(
 416        '#type' => 'hidden',
 417        '#value' => $variables['height'],
 418      );
 419    }
 420  
 421    // Add the additional alt and title fields.
 422    $element['alt'] = array(
 423      '#title' => t('Alternate text'),
 424      '#type' => 'textfield',
 425      '#default_value' => isset($item['alt']) ? $item['alt'] : '',
 426      '#description' => t('This text will be used by screen readers, search engines, or when the image cannot be loaded.'),
 427      // @see http://www.gawds.org/show.php?contentid=28
 428      '#maxlength' => 512,
 429      '#weight' => -2,
 430      '#access' => (bool) $item['fid'] && $settings['alt_field'],
 431    );
 432    $element['title'] = array(
 433      '#type' => 'textfield',
 434      '#title' => t('Title'),
 435      '#default_value' => isset($item['title']) ? $item['title'] : '',
 436      '#description' => t('The title is used as a tool tip when the user hovers the mouse over the image.'),
 437      '#maxlength' => 1024,
 438      '#weight' => -1,
 439      '#access' => (bool) $item['fid'] && $settings['title_field'],
 440    );
 441  
 442    return $element;
 443  }
 444  
 445  /**
 446   * Returns HTML for an image field widget.
 447   *
 448   * @param $variables
 449   *   An associative array containing:
 450   *   - element: A render element representing the image field widget.
 451   *
 452   * @ingroup themeable
 453   */
 454  function theme_image_widget($variables) {
 455    $element = $variables['element'];
 456    $output = '';
 457    $output .= '<div class="image-widget form-managed-file clearfix">';
 458  
 459    if (isset($element['preview'])) {
 460      $output .= '<div class="image-preview">';
 461      $output .= drupal_render($element['preview']);
 462      $output .= '</div>';
 463    }
 464  
 465    $output .= '<div class="image-widget-data">';
 466    if ($element['fid']['#value'] != 0) {
 467      $element['filename']['#markup'] .= ' <span class="file-size">(' . format_size($element['#file']->filesize) . ')</span> ';
 468    }
 469    $output .= drupal_render_children($element);
 470    $output .= '</div>';
 471    $output .= '</div>';
 472  
 473    return $output;
 474  }
 475  
 476  /**
 477   * Implements hook_field_formatter_info().
 478   */
 479  function image_field_formatter_info() {
 480    $formatters = array(
 481      'image' => array(
 482        'label' => t('Image'),
 483        'field types' => array('image'),
 484        'settings' => array('image_style' => '', 'image_link' => ''),
 485      ),
 486    );
 487  
 488    return $formatters;
 489  }
 490  
 491  /**
 492   * Implements hook_field_formatter_settings_form().
 493   */
 494  function image_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
 495    $display = $instance['display'][$view_mode];
 496    $settings = $display['settings'];
 497  
 498    $image_styles = image_style_options(FALSE);
 499    $element['image_style'] = array(
 500      '#title' => t('Image style'),
 501      '#type' => 'select',
 502      '#default_value' => $settings['image_style'],
 503      '#empty_option' => t('None (original image)'),
 504      '#options' => $image_styles,
 505    );
 506  
 507    $link_types = array(
 508      'content' => t('Content'),
 509      'file' => t('File'),
 510    );
 511    $element['image_link'] = array(
 512      '#title' => t('Link image to'),
 513      '#type' => 'select',
 514      '#default_value' => $settings['image_link'],
 515      '#empty_option' => t('Nothing'),
 516      '#options' => $link_types,
 517    );
 518  
 519    return $element;
 520  }
 521  
 522  /**
 523   * Implements hook_field_formatter_settings_summary().
 524   */
 525  function image_field_formatter_settings_summary($field, $instance, $view_mode) {
 526    $display = $instance['display'][$view_mode];
 527    $settings = $display['settings'];
 528  
 529    $summary = array();
 530  
 531    $image_styles = image_style_options(FALSE);
 532    // Unset possible 'No defined styles' option.
 533    unset($image_styles['']);
 534    // Styles could be lost because of enabled/disabled modules that defines
 535    // their styles in code.
 536    if (isset($image_styles[$settings['image_style']])) {
 537      $summary[] = t('Image style: @style', array('@style' => $image_styles[$settings['image_style']]));
 538    }
 539    else {
 540      $summary[] = t('Original image');
 541    }
 542  
 543    $link_types = array(
 544      'content' => t('Linked to content'),
 545      'file' => t('Linked to file'),
 546    );
 547    // Display this setting only if image is linked.
 548    if (isset($link_types[$settings['image_link']])) {
 549      $summary[] = $link_types[$settings['image_link']];
 550    }
 551  
 552    return implode('<br />', $summary);
 553  }
 554  
 555  /**
 556   * Implements hook_field_formatter_view().
 557   */
 558  function image_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
 559    $element = array();
 560  
 561    // Check if the formatter involves a link.
 562    if ($display['settings']['image_link'] == 'content') {
 563      $uri = entity_uri($entity_type, $entity);
 564    }
 565    elseif ($display['settings']['image_link'] == 'file') {
 566      $link_file = TRUE;
 567    }
 568  
 569    foreach ($items as $delta => $item) {
 570      if (isset($link_file)) {
 571        $uri = array(
 572          'path' => file_create_url($item['uri']),
 573          'options' => array(),
 574        );
 575      }
 576      $element[$delta] = array(
 577        '#theme' => 'image_formatter',
 578        '#item' => $item,
 579        '#image_style' => $display['settings']['image_style'],
 580        '#path' => isset($uri) ? $uri : '',
 581      );
 582    }
 583  
 584    return $element;
 585  }
 586  
 587  /**
 588   * Returns HTML for an image field formatter.
 589   *
 590   * @param $variables
 591   *   An associative array containing:
 592   *   - item: Associative array of image data, which may include "uri", "alt",
 593   *     "width", "height", "title" and "attributes".
 594   *   - image_style: An optional image style.
 595   *   - path: An array containing the link 'path' and link 'options'.
 596   *
 597   * @ingroup themeable
 598   */
 599  function theme_image_formatter($variables) {
 600    $item = $variables['item'];
 601    $image = array(
 602      'path' => $item['uri'],
 603    );
 604  
 605    if (array_key_exists('alt', $item)) {
 606      $image['alt'] = $item['alt'];
 607    }
 608  
 609    if (isset($item['attributes'])) {
 610      $image['attributes'] = $item['attributes'];
 611    }
 612  
 613    if (isset($item['width']) && isset($item['height'])) {
 614      $image['width'] = $item['width'];
 615      $image['height'] = $item['height'];
 616    }
 617  
 618    // Do not output an empty 'title' attribute.
 619    if (isset($item['title']) && drupal_strlen($item['title']) > 0) {
 620      $image['title'] = $item['title'];
 621    }
 622  
 623    if ($variables['image_style']) {
 624      $image['style_name'] = $variables['image_style'];
 625      $output = theme('image_style', $image);
 626    }
 627    else {
 628      $output = theme('image', $image);
 629    }
 630  
 631    // The link path and link options are both optional, but for the options to be
 632    // processed, the link path must at least be an empty string.
 633    if (isset($variables['path']['path'])) {
 634      $path = $variables['path']['path'];
 635      $options = isset($variables['path']['options']) ? $variables['path']['options'] : array();
 636      // When displaying an image inside a link, the html option must be TRUE.
 637      $options['html'] = TRUE;
 638      $output = l($output, $path, $options);
 639    }
 640  
 641    return $output;
 642  }

title

Description

title

Description

title

Description

title

title

Body