You are here

image_attach.module in Image 6

File

contrib/image_attach/image_attach.module
View source
<?php

/**
 * @file image_attach.module
 */
define('IMAGE_ATTACH_HIDDEN', 'hidden');

/**
 * Implementation of hook_menu()
 */
function image_attach_menu() {
  $items['image_attach'] = array(
    'title' => 'Image attachment view',
    'page callback' => 'image_attach_view_image',
    'access arguments' => array(
      'access content',
    ),
    'type' => MENU_CALLBACK,
  );
  $items['admin/settings/image/image_attach'] = array(
    'title' => 'Image attach',
    'description' => 'Enable image attach for content.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'image_attach_admin_settings',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
}

/**
 * Implementation of hook_perm()
 */
function image_attach_perm() {
  return array(
    'attach images',
  );
}
function image_attach_admin_settings() {
  $form['image_attach_existing'] = array(
    '#type' => 'radios',
    '#title' => t('Attach existing images'),
    '#default_value' => variable_get('image_attach_existing', 1),
    '#options' => array(
      0 => t('Disabled'),
      1 => t('Enabled'),
    ),
    '#description' => t('When enabled, will allow existing image nodes to be attached instead of uploading new images.'),
  );
  return system_settings_form($form);
}

/**
 * Implementation of hook_block().
 */
function image_attach_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
      $blocks[0] = array(
        'info' => t('Attached images'),
        'weight' => 0,
        'visibility' => 1,
        'pages' => 'node/*',
      );
      return $blocks;
    case 'view':
      if ($delta == 0) {
        if (arg(0) == 'node' && is_numeric(arg(1))) {
          $node = node_load(arg(1));
          if (isset($node->iids)) {
            $output['subject'] = t('Attached images');
            foreach ($node->iids as $iid) {
              $image = node_load($iid);
              if (node_access('view', $image)) {
                $image_nodes[] = $image;
              }
            }
            $output['content'] = theme('image_attach_attached_images_block', $node->nid, $image_nodes);
            return $output;
          }
        }
      }
      break;
    case 'configure':
      if ($delta == 0) {
        $image_sizes = array();
        foreach (image_get_sizes() as $key => $size) {
          $image_sizes[$key] = $size['label'];
        }
        $form['image_attach_block_0_size'] = array(
          '#type' => 'select',
          '#title' => t('Image size'),
          '#default_value' => variable_get('image_attach_block_0_size', IMAGE_THUMBNAIL),
          '#options' => $image_sizes,
          '#description' => t('This determines the size of the image that appears in the block.'),
        );
        return $form;
      }
      break;
    case 'save':
      if ($delta == 0) {
        variable_set('image_attach_block_0_size', $edit['image_attach_block_0_size']);
      }
      break;
  }
}

/**
 * Implementation of hook_form_FORM_ID_alter().
 *
 * Add settings to the content type settings form.
 */
function image_attach_form_node_type_form_alter(&$form, $form_state) {
  if ($form['#node_type']->type != 'image') {
    _image_check_settings();
    $image_sizes = array(
      IMAGE_ATTACH_HIDDEN => t('<Hidden>'),
    );
    foreach (image_get_sizes() as $key => $size) {
      $image_sizes[$key] = $size['label'];
    }
    $form['image_attach'] = array(
      '#type' => 'fieldset',
      '#title' => t('Image Attach settings'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $form['image_attach']['image_attach'] = array(
      '#type' => 'radios',
      '#title' => t('Attach images'),
      '#default_value' => variable_get('image_attach_' . $form['#node_type']->type, 0),
      '#options' => array(
        0 => t('Disabled'),
        1 => t('Enabled'),
      ),
      '#description' => t('Should this node allows users to upload an image?'),
    );
    $form['image_attach']['image_attach_maximum'] = array(
      '#type' => 'select',
      '#title' => t('Maximum number of images'),
      '#default_value' => variable_get('image_attach_maximum_' . $form['#node_type']->type, 0),
      '#options' => array(
        0 => t('Unlimited'),
      ) + drupal_map_assoc(range(1, 10)),
      '#description' => t('The maximum number of images that may be attached to nodes of this type.'),
    );
    $form['image_attach']['image_attach_size_teaser'] = array(
      '#type' => 'select',
      '#title' => t('Teaser image size'),
      '#default_value' => variable_get('image_attach_size_teaser_' . $form['#node_type']->type, IMAGE_THUMBNAIL),
      '#options' => $image_sizes,
      '#description' => t("This determines the size of the image that appears when the node is displayed as a teaser. 'Hidden' will not show the image."),
    );

    // Hide the weight if CCK is doing the weight for us.
    if (!module_exists('content')) {
      $form['image_attach']['image_attach_weight_teaser'] = array(
        '#type' => 'weight',
        '#title' => t('Teaser image weight'),
        '#default_value' => variable_get('image_attach_weight_teaser_' . $form['#node_type']->type, 0),
        '#description' => t('This value determines the order of the image when displayed in the teaser.'),
      );
    }
    $form['image_attach']['image_attach_size_body'] = array(
      '#type' => 'select',
      '#title' => t('Full node image size'),
      '#default_value' => variable_get('image_attach_size_body_' . $form['#node_type']->type, IMAGE_THUMBNAIL),
      '#options' => $image_sizes,
      '#description' => t("This determines the size of the image that appears when the full node is displayed. 'Hidden' will not show the image."),
    );
    if (!module_exists('content')) {
      $form['image_attach']['image_attach_weight_body'] = array(
        '#type' => 'weight',
        '#title' => t('Full node image weight'),
        '#default_value' => variable_get('image_attach_weight_body_' . $form['#node_type']->type, 0),
        '#description' => t('This value determines the order of the image when displayed in the body.'),
      );
    }
    if (module_exists('content')) {
      $link = l(t('Manage fields'), $_GET['q'] . '/fields');
      $form['image_attach']['#description'] = t('Since you installed CCK module, you can change the image weight in the !link page.', array(
        '!link' => $link,
      ));
    }
  }
}

/**
 * Implementation of hook_form_alter().
 */
function image_attach_form_alter(&$form, $form_state, $form_id) {

  // Node edit form.
  if (isset($form['type']['#value']) && $form['type']['#value'] != 'image') {
    $type = $form['type']['#value'];

    // If enabled adjust the form.
    if ($form_id == $type . '_node_form' && variable_get('image_attach_' . $type, 0)) {
      $node = $form['#node'];
      _image_check_settings();
      $value = !empty($node->new_image) ? '#value' : '#default_value';
      $form['#attributes'] = array(
        "enctype" => "multipart/form-data",
      );

      // Add a custom submit handler so we can handle image creation on-the-fly
      $form['#validate'][] = 'image_attach_validate';

      // Add a custom submit handler so we can clean up the selection box items.
      $form['#submit'][] = 'image_attach_node_form_submit';

      // Check permissions and settings
      $may_attach = user_access('attach images');
      $may_attach_existing = variable_get('image_attach_existing', 1);
      $may_upload = user_access('create images');
      $has_existing_images = !empty($node->iids);
      $maximum_images = variable_get('image_attach_maximum_' . $type, 0);

      // Display the image attach form only if user can attach images, AND
      // it is allowed to attach existing images or the user is allowed to create new images
      if ($may_attach && ($may_attach_existing || $may_upload)) {
        $form['image_attach'] = array(
          '#type' => 'fieldset',
          '#title' => t('Attached images'),
          '#collapsible' => TRUE,
          '#collapsed' => empty($node->iids),
        );
        if ($maximum_images) {
          $form['image_attach']['#description'] = format_plural($maximum_images, 'You may attach 1 image.', 'You may attach up to @count images.');
        }
        if ($has_existing_images) {
          $form['image_attach']['image_thumbnail']['#theme'] = 'image_attach_form_thumbnails';
          $form['image_attach']['image_thumbnail']['#tree'] = TRUE;
          $weight = 0;
          foreach ($node->iids as $iid) {
            $image = node_load($iid);
            $form['image_attach']['image_thumbnail'][$iid] = array(
              'id' => array(
                '#type' => 'hidden',
                '#value' => $iid,
              ),
              'image' => array(
                '#type' => 'markup',
                '#value' => image_display($image, 'thumbnail'),
              ),
              'delete' => array(
                '#type' => 'checkbox',
              ),
              'title' => array(
                '#type' => 'markup',
                '#value' => check_plain($image->title),
              ),
              'weight' => array(
                '#type' => 'weight',
                '#title' => t('Weight'),
                '#delta' => count($node->iids),
                '#default_value' => isset($form_state['values']['image_thumbnail'][$iid]) ? $form_state['values']['image_thumbnail'][$iid]['weight'] : $weight++,
              ),
            );
          }
        }

        // Only show selection box of image nodes if the user may attach some,
        // or if there are existings ones that may be removed.
        if ($may_attach_existing || $has_existing_images) {
          $form['image_attach']['iids'] = array(
            '#type' => 'select',
            $value => empty($node->iids) ? NULL : $node->iids,
            '#multiple' => TRUE,
            '#size' => 6,
          );

          // User may attach already existing images: show a selection box containing all images.
          if ($may_attach_existing) {
            $form['image_attach']['iids']['#title'] = t('Existing images');
            $form['image_attach']['iids']['#options'] = _image_attach_get_image_nodes();
            if ($may_upload) {
              $form['image_attach']['iids']['#description'] = t('Choose existing images if you do not upload a new one.');
            }
            else {
              $form['image_attach']['iids']['#description'] = t('Choose existing images to attach.');
            }
          }
          else {
            $form['image_attach']['iids']['#title'] = t('Attached images');
            $form['image_attach']['iids']['#options'] = _image_attach_get_image_nodes($node->iids);
            $form['image_attach']['iids']['#description'] = t('You can remove a previously attached image by unselecting it.');
          }
        }

        // User may create images, add upload form elements.
        if ($may_upload) {
          $form['image_attach']['image'] = array(
            '#type' => 'file',
            '#size' => 40,
            '#title' => t('Upload image'),
          );
          $form['image_attach']['image_title'] = array(
            '#type' => 'textfield',
            '#title' => t('Image title'),
            $value => '',
            '#description' => t('The title the image will be shown with. Leave blank to use the filename.'),
          );

          // Provide an additional submit button, which adds an image and redirects
          // the user to the node edit form.
          $form['image_attach']['image_attach_multiple'] = array(
            '#type' => 'submit',
            '#value' => t('Upload'),
            '#validate' => array(
              'image_attach_validate',
            ),
            '#submit' => array(
              'image_attach_image_add_submit',
            ),
          );
        }
      }
    }
  }
}

/**
 * Get image weights and return an iid array ordered by weight.
 *
 * This private function is called by submit handlers to discover how the user
 * has ordered their images.
 * It returns an array with identical keys and values (just like the ordinary
 * iid array).
 *
 * @param $raw_weight_data
 *   An array of iids and weights from the drag-to-reorder table, derived from
 *   either the $form_state object or the $node object.
 * @param $select_box_array
 *   The array of existing images that the user wants to include. This may be
 *   different to the iids passed in $raw_weight_data.
 *
 * @return
 *   A weight-sorted (from lightest to heaviest) array of iids, with identical
 *   keys and (integer) values.
 */
function _image_attach_set_image_weight($raw_weight_data, $select_box_array) {

  // Build up an array of iids => weights.
  $weights = array();
  foreach ($select_box_array as $iid) {

    // Check the delete box has not been ticked.
    if ($raw_weight_data[$iid]['delete'] !== 1) {

      // If the image exists in the drag-to-reorder array, get its weight, otherwise, assign it the heaviest weight possible.
      $weights[$iid] = isset($raw_weight_data[$iid]['weight']) ? $raw_weight_data[$iid]['weight'] : count($select_box_array);
    }
  }

  // Sort the iids array by weight.
  asort($weights);

  // Take the keys to make the return array.
  $items = drupal_map_assoc(array_keys($weights));
  return $items;
}

/**
 * Save attached image nids and rebuild form.
 *
 * This submit function adds the new images and returns to the
 * node edit form directly afterwards, without creating the new node yet.
 */
function image_attach_image_add_submit(&$form, &$form_state) {

  // Rebuild the attached image data.
  if (isset($form_state['values']['iids'])) {
    db_query("DELETE FROM {image_attach} WHERE nid = %d", $form['nid']['#value']);

    // Sort the $form_state['values']['iids'] array by weight.
    if (count($form_state['values']['image_thumbnail'])) {
      $form_state['values']['iids'] = _image_attach_set_image_weight($form_state['values']['image_thumbnail'], $form_state['values']['iids']);
    }
    if (count($form_state['values']['iids'])) {
      $weight = 0;
      foreach ($form_state['values']['iids'] as $iid) {
        db_query("INSERT INTO {image_attach} (nid, iid, weight) VALUES (%d, %d, %d)", $form['nid']['#value'], $iid, $weight++);
      }
    }
  }

  // Convert taxonomy format from Preview to Object.
  if (module_exists('taxonomy') && !empty($form_state['values']['taxonomy'])) {
    $temp_node = new stdClass();
    $temp_node->taxonomy = $form_state['values']['taxonomy'];
    $form_state['values']['taxonomy'] = taxonomy_preview_terms($temp_node);
    unset($temp_node);
  }

  // Rebuild the node edit form.
  node_form_submit_build_node($form, $form_state);
}

/**
 * Image attach validation handler for node edit form.
 *
 * Check that the number of images has not exceeded the maximum.
 * Capture node form submission and immediately create an image if one has been
 * uploaded.
 * Note that the new image nodes are created even on preview. Taking several
 * attempts may create trash.
 */
function image_attach_validate(&$form, &$form_state) {

  // Test for whether a file is being uploaded cribbed from file_save_upload().
  $uploading_new_image = isset($_FILES['files']) && $_FILES['files']['name']['image'] && is_uploaded_file($_FILES['files']['tmp_name']['image']);

  // Validate the number of attached images. Filter out the 'None' with array_filter.
  if ($maximum_images = variable_get('image_attach_maximum_' . $form['#node']->type, 0)) {
    if (is_array($form_state['values']['iids'])) {
      $num_images = count(array_filter($form_state['values']['iids']));
    }
    else {
      $num_images = 0;
    }
    $node_type_label = node_get_types('name', $form['#node']->type);
    if ($num_images >= $maximum_images && $uploading_new_image) {

      // This error will be set when attempting to upload a new image.
      // The number already selected may be equal to the maximum, in which case
      // the error is just to alert the user that their upload has not been performed, and allow
      // them to unselect an image and proceed to upload the new one.
      form_set_error('iids', t('There are @count_images images already attached. A new image cannot be uploaded until one or more attached images are unselected.', array(
        '@count_images' => format_plural($num_images, '1 image', '@count images'),
        '@maximum' => $maximum_images,
        '%type' => $node_type_label,
      )));
    }
    elseif ($num_images > $maximum_images) {
      form_set_error('iids', t('You have selected @count_images but the maximum for a %type is @maximum.', array(
        '@count_images' => format_plural($num_images, '1 image', '@count images'),
        '@maximum' => $maximum_images,
        '%type' => $node_type_label,
      )));
    }
  }

  // Validate and save the uploaded image, providing that there are no errors set.
  if (!count(form_get_errors())) {
    $validators = array(
      'file_validate_is_image' => array(),
    );
    if ($file = file_save_upload('image', $validators)) {
      $image_title = $_POST['image_title'] ? $_POST['image_title'] : basename($file->filepath);

      // Initialize an image properly.
      $image = image_create_node_from($file->filepath, $image_title, '');
      if ($image && !form_get_errors()) {
        drupal_set_message(t("Created new image to attach to this node. !image_link", array(
          '!image_link' => l($image_title, 'node/' . $image->nid),
        )));

        // Append image nid to array of images.
        $form_state['values']['iids'][$image->nid] = $image->nid;
      }
    }
    else {

      // Only raise error if user clicked specific Upload button.
      if ($uploading_new_image) {
        form_set_error('image_attach', t('Invalid or missing image file for upload and attach.'));
      }
    }
  }
}

/**
 * Extra submit handler for node forms.
 */
function image_attach_node_form_submit(&$form, &$form_state) {

  // Clear the 0 key in the iids array that arises from selecting the 'None'
  // option. We do this here so image_attach_nodeapi() gets clean data.
  if (isset($form_state['values']['iids'][0])) {
    unset($form_state['values']['iids'][0]);
  }
}

/**
 * Implementation of hook_nodeapi().
 */
function image_attach_nodeapi(&$node, $op, $teaser, $page) {

  // Make sure that if an image is deleted it is detached from any nodes.
  if ($node->type == 'image') {
    switch ($op) {
      case 'delete':
        db_query("DELETE FROM {image_attach} WHERE iid = %d", $node->nid);
    }
    return;
  }
  else {
    if (variable_get('image_attach_' . $node->type, 0) == 0) {
      return;
    }
  }
  switch ($op) {
    case 'insert':
    case 'update':
      db_query("DELETE FROM {image_attach} WHERE nid = %d", $node->nid);
      if (!empty($node->iids)) {
        if (!empty($node->image_thumbnail)) {

          // Form submitted, order iids according to drag-to-reorder table.
          $node->iids = _image_attach_set_image_weight($node->image_thumbnail, $node->iids);
        }
        $weight = 0;
        foreach ($node->iids as $iid) {
          db_query("INSERT INTO {image_attach} (nid, iid, weight) VALUES (%d, %d, %d)", $node->nid, $iid, $weight++);
        }
      }
      break;
    case 'delete':
      db_query("DELETE FROM {image_attach} WHERE nid = %d", $node->nid);
      break;
    case 'load':
      $res = db_query("SELECT iid FROM {image_attach} WHERE nid = %d ORDER BY weight", $node->nid);
      $iids = array();
      while ($iid = db_fetch_array($res)) {
        $iids[] = $iid['iid'];
      }
      return array(
        'iids' => $iids,
      );

    // Pass the body and teaser objects to the theme again to add the images.
    case 'view':
      if (!empty($node->iids)) {
        $node->image_attach = _image_attach_node_load_attached($node->iids, $teaser);
        $teaser_or_body = $teaser ? 'teaser' : 'body';
        $img_size = variable_get('image_attach_size_' . $teaser_or_body . '_' . $node->type, IMAGE_THUMBNAIL);

        // Don't show anything if the attached images are set to hidden.
        if ($img_size == IMAGE_ATTACH_HIDDEN) {
          return;
        }

        // Set weight, either from CCK or our own settings. Cribbed from signup!
        if (module_exists('content')) {

          // Due to a bug in CCK (http://drupal.org/node/363456), we need
          // to call this function twice to ensure we get the real value.
          // The bug is present when you first enable the setting to
          // display in the node instead of a separate tab, or when you
          // first upgrade to the version that contains this code.
          content_extra_field_weight($node->type, 'image_attach');
          $weight = content_extra_field_weight($node->type, 'image_attach');
        }
        else {
          $weight = variable_get("image_attach_weight_{$teaser_or_body}_{$node->type}", 0);
        }
        $node->content['image_attach'] = array(
          '#weight' => $weight,
          '#value' => theme('image_attach_attached_images_node', $node->nid, $node->image_attach, $img_size, $teaser),
        );
      }
      break;
    case 'rss item':
      $ret = array();
      if (!empty($node->iids) && ($image = node_load($node->iids[0]))) {
        $info = image_get_info(file_create_path($image->images[IMAGE_PREVIEW]));
        $ret[] = array(
          'key' => 'enclosure',
          'attributes' => array(
            'url' => url("image/view/{$node->iids[0]}/" . IMAGE_PREVIEW, array(
              'absolute' => TRUE,
            )),
            'length' => $info['file_size'],
            'type' => $info['mime_type'],
          ),
        );
      }
      return $ret;
  }
}

/**
 * Helper function for hook_nodeapi: view op.
 * Loads all the required attached image nodes.
 *
 * @param $attached_nids
 *  An array of node ids.
 * @param $teaser
 *  If true, only load the first of the node ids.
 *
 * @return
 *  An numerical array of node objects.
 */
function _image_attach_node_load_attached($attached_nids, $teaser = FALSE) {
  if ($teaser) {

    // For the teaser we only want the first image from $attached_nids.
    // During normal node viewing the array is zero-keyed but during edit
    // preview it is keyed by iid. Therefore using array_shift() will return the
    // first image for either of these situations.
    $attached_nids = array(
      array_shift($attached_nids),
    );
  }
  foreach ($attached_nids as $nid) {
    $nodes[] = node_load($nid);
  }
  return $nodes;
}

/**
 * Fetch an array of all candidate referenced nodes, for use in presenting the
 * selection form to the user.
 *
 * @param $nids
 *  A list of nids to filter on. If not passed, all image nids are returned.
 */
function _image_attach_get_image_nodes($nids = array()) {
  $placeholder = '';

  // If $nids was passed, build placeholders to put in the query
  if (count($nids)) {
    $placeholder = 'AND n.nid IN (' . implode(', ', array_fill(0, sizeof($nids), '%d')) . ') ';
  }
  $rows = array(
    0 => t('- None -'),
  );
  $result = db_query(db_rewrite_sql("SELECT n.nid, n.title, n.sticky FROM {node} n WHERE n.status = 1 AND n.type = 'image' " . $placeholder . "ORDER BY n.sticky DESC, n.title ASC"), $nids);
  while ($node = db_fetch_object($result)) {
    $rows[$node->nid] = $node->title;
  }
  return $rows;
}

/**
 * Views 2 API handler
 */
function image_attach_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'image_attach'),
  );
}

/**
 * Implementation of hook_theme() registry.
 */
function image_attach_theme() {
  return array(
    'image_attach_attached_images' => array(
      'arguments' => array(
        'nid' => 0,
        'image_nodes' => array(),
        'options' => array(),
      ),
    ),
    'image_attach_attached_images_node' => array(
      'arguments' => array(
        'node' => new stdClass(),
        'image_nodes' => array(),
        'img_size' => IMAGE_THUMBNAIL,
        'teaser' => FALSE,
      ),
    ),
    'image_attach_attached_images_block' => array(
      'arguments' => array(
        'nid' => 0,
        'image_nodes' => array(),
      ),
    ),
    'image_attach_form_thumbnails' => array(
      'arguments' => array(
        'form' => NULL,
      ),
    ),
  );
}

/**
 * Theme image thumbnails in editing ui to a drag-to-reorder table
 *
 * @param $form
 *  The $form object
 */
function theme_image_attach_form_thumbnails($form) {
  drupal_add_tabledrag('image-attach-thumbnails-draggable-table', 'order', 'sibling', 'weight');
  $header = array(
    t('Attached images'),
    t('Remove'),
    t('Title'),
    t('Weight'),
  );
  foreach (element_children($form) as $key) {
    $element =& $form[$key];
    $element['weight']['#attributes']['class'] = 'weight';
    $row = array();
    $row[] = drupal_render($element['image']);
    $row[] = drupal_render($element['delete']);
    $row[] = drupal_render($element['title']);
    $row[] = drupal_render($element['weight']) . drupal_render($element['id']);
    $rows[] = array(
      'data' => $row,
      'class' => 'draggable',
    );
  }
  $output = theme('table', $header, $rows, array(
    'id' => 'image-attach-thumbnails-draggable-table',
  ));
  $output .= drupal_render($form);
  return $output;
}

/**
 * Theme attached images shown in nodes.
 *
 * @param $nid
 *  The attaching node's id.
 * @param $image_nodes
 *   The node objects of the images to theme.
 * @param $img_size
 *   The size at which to show images.
 * @param $teaser
 *   Whether the $node is being shown as a teaser or not.
 *
 * Override this in template.php to include a case statement if you want
 * different node types to appear differently.
 * If you have additional image sizes you defined in image.module, you can
 * use them by theming this function as well.
 */
function theme_image_attach_attached_images_node($nid, $image_nodes, $img_size, $teaser = FALSE) {
  drupal_add_css(drupal_get_path('module', 'image_attach') . '/image_attach.css');
  $options = array(
    'size' => $img_size,
    'link' => $teaser ? 'node' : 'image',
    'attributes' => array(
      'class' => 'image-attach-' . ($teaser ? 'teaser' : 'body'),
    ),
  );

  // We take the images in reverse order because they are floated to the right,
  // and we want the apparent left to right order to be correct.
  $output = theme('image_attach_attached_images', $nid, array_reverse($image_nodes), $options);

  // Wrap output of potentially multiple images in a DIV.
  if ($output && !$teaser) {
    $output = '<div class="all-attached-images">' . $output . '</div>';
  }
  return $output;
}

/**
 * Theme the attached images block.
 *
 * @param $nid
 *  The attaching node's id.
 * @param $image_nodes
 *  The attached image nodes.
 */
function theme_image_attach_attached_images_block($nid, $image_nodes = array()) {

  // Only return block content if there are images.
  if (is_array($image_nodes) && count($image_nodes)) {
    $options = array(
      'size' => variable_get('image_attach_block_0_size', IMAGE_THUMBNAIL),
      'link' => 'image',
    );
    $output = theme('image_attach_attached_images', $nid, $image_nodes, $options);
    $output = '<div class="all-attached-images">' . $output . '</div>';
    return $output;
  }
}

/**
 * Generic theme function for any set of attached images.
 *
 * @param $nid
 *  The id of the attaching node.
 * @param $image_nodes
 *  The fully loaded image nodes to theme. These do not need to be checked for
 *  access: that happens in this function.
 * @param $options
 *  An associative array of options, with the following keys:
 *    - 'size' (default IMAGE_THUMBNAIL)
 *      The name of the image derivative size at which to show the images,
 *      eg 'thumbnail'.
 *    - 'link' (default 'image')
 *      Whether and where the images should be linked. This should be one of:
 *        - 'image': link to the image node. Default.
 *        - 'node': link to the attaching node.
 *        - 'none': no link.
 *    - 'attributes'
 *      Extra attributes for the div around each image.
 */
function theme_image_attach_attached_images($nid, $image_nodes = array(), $options = array()) {

  // Merge in defaults.
  $options += array(
    'size' => IMAGE_THUMBNAIL,
    'link' => 'image',
    'attributes' => array(),
  );
  $img_size = $options['size'];
  $link_destination = $options['link'];

  // Link images to the attaching node.
  if ($link_destination == 'node') {
    $link_path = "node/{$nid}";
  }
  $output = '';
  foreach ($image_nodes as $image) {
    if (!node_access('view', $image)) {

      // If the image is restricted, don't show it as an attachment.
      continue;
    }

    // Link images to the image node.
    if ($link_destination == 'image') {
      $link_path = "node/{$image->nid}";
    }

    // Get a fresh copy of the attributes for each image node.
    $div_attributes = $options['attributes'];

    // Create CSS classes, beginning with those passed in to the function.
    $classes = array();
    if (isset($div_attributes['class'])) {
      $classes[] = $div_attributes['class'];
    }

    // replace with base class in DIV

    //$classes[] = 'image-attach-' . $teaser_or_body;
    $classes[] = 'image-attach-node-' . $image->nid;
    if (!$image->status) {
      $classes[] = 'image-unpublished';
    }
    $div_attributes['class'] = implode(' ', $classes);

    // Add the width as inline CSS.
    $info = image_get_info(file_create_path($image->images[$img_size]));
    if (!isset($div_attributes['style'])) {
      $div_attributes['style'] = '';
    }
    $div_attributes['style'] .= 'width: ' . $info['width'] . 'px;';
    $output .= '<div' . drupal_attributes($div_attributes) . '>';
    $image_img = image_display($image, $img_size);
    if (isset($link_path)) {
      $output .= l($image_img, $link_path, array(
        'html' => TRUE,
      ));
    }
    else {
      $output .= $image_img;
    }
    $output .= "</div>\n";
  }
  return $output;
}

/**
 * Implementation of hook_content_extra_fields().
 */
function image_attach_content_extra_fields($type_name) {
  if (variable_get('image_attach_' . $type_name, 0)) {
    $extra['image_attach'] = array(
      'label' => t('Attached images'),
      'description' => t('Image Attach module form.'),
      'weight' => 0,
    );
    return $extra;
  }
}

Functions

Namesort descending Description
image_attach_admin_settings
image_attach_block Implementation of hook_block().
image_attach_content_extra_fields Implementation of hook_content_extra_fields().
image_attach_form_alter Implementation of hook_form_alter().
image_attach_form_node_type_form_alter Implementation of hook_form_FORM_ID_alter().
image_attach_image_add_submit Save attached image nids and rebuild form.
image_attach_menu Implementation of hook_menu()
image_attach_nodeapi Implementation of hook_nodeapi().
image_attach_node_form_submit Extra submit handler for node forms.
image_attach_perm Implementation of hook_perm()
image_attach_theme Implementation of hook_theme() registry.
image_attach_validate Image attach validation handler for node edit form.
image_attach_views_api Views 2 API handler
theme_image_attach_attached_images Generic theme function for any set of attached images.
theme_image_attach_attached_images_block Theme the attached images block.
theme_image_attach_attached_images_node Theme attached images shown in nodes.
theme_image_attach_form_thumbnails Theme image thumbnails in editing ui to a drag-to-reorder table
_image_attach_get_image_nodes Fetch an array of all candidate referenced nodes, for use in presenting the selection form to the user.
_image_attach_node_load_attached Helper function for hook_nodeapi: view op. Loads all the required attached image nodes.
_image_attach_set_image_weight Get image weights and return an iid array ordered by weight.

Constants