<?php
// $Id: image_attach.module,v 1.37 2008/02/12 21:11:43 drewish Exp $

/**
 * @file image_attach.module
 */

define('IMAGE_ATTACH_HIDDEN', 'hidden');

/**
 * Implementation of hook_help().
 */
function image_attach_help($path, $arg) {
  switch ($path) {
    case 'admin/settings/modules#description':
      return t('Allows easy attaching of image nodes to other content types.');
  }
}

/**
 * Implementation of hook_menu()
 */
function image_attach_menu() {
  $items = array();

  $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_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_NORMAL_ITEM,
  );
  return $items;
}


function image_attach_admin_settings() {
  $form = array();

  $form['image_attach_existing'] = array(
    '#type' => 'radios',
    '#title' => t('Attach existing images'),
    '#default_value' => variable_get('image_attach_existing', 1),
    '#options' => array(0 => 'Disabled', 1 => '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'),
        'status'     => TRUE,
        '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->iid) && $node->iid) {
            $image = node_load($node->iid);
            if (node_access('view', $image)) {
              $img = image_display($image, variable_get('image_attach_block_0_size', IMAGE_THUMBNAIL));
              return array(
                'subject' => t('Attached Images'),
                'content' => l($img, "node/$node->iid", array('html' => TRUE)),
              );
            }
          }
        }
      }
      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_alter()
 */
function image_attach_form_alter(&$form, $form_state, $form_id) {
  // Content type settings form.
  if ($form_id == 'node_type_form' && $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_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.")
    );
    $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.")
    );
    $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."),
    );
  }
  // Node edit form.
  else if (isset($form['type']) && $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");

      $form['image_attach'] = array(
        '#type' => 'fieldset',
        '#title' => t('Attached Images'),
        '#collapsible' => TRUE,
        '#collapsed' => empty($node->iid),
      );
      if (!empty($node->iid)) {
        $image = node_load($node->iid);
        $form['image_attach']['image_thumbnail'] = array(
          '#type' => 'item',
          '#title' => t('Thumbnail'),
          '#value' => image_display($image, 'thumbnail')
        );
      }
      if (variable_get('image_attach_existing', 1) && user_access('access content')) {
        $form['image_attach']['iid'] = array(
          '#type' => 'select',
          '#title' => t('Existing Image'),
          '#options' => _image_attach_get_image_nodes(),
          $value => empty($node->iid) ? NULL : $node->iid,
          '#description' => t('Choose an image already existing on the server if you do not upload a new one.')
        );
        $form['image_attach'][] = array(
          '#type' => 'item',
          '#value' => t('-or-'),
          '#attributes' => array('class' => 'either-choice')
        );
      }
      else {
        $form['image_attach']['iid'] = array(
          '#type' => 'hidden',
          $value => empty($node->iid) ? NULL : $node->iid,
        );
      }
      $form['image_attach']['image'] = array(
        '#type' => 'file',
        '#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.')
      );
    }
  }
}

/**
 * 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 'prepare':
	  $validators = array(
	    'file_validate_is_image' => array(),
	  );
      if (file_save_upload('image', $validators)) {
        $image->title = $_POST['image_title'];
        $image->uid = $node->uid;
        $image->name = $node->name;
        $image->created = $node->created;
        $image->type = 'image';
        // Set the node's defaults... (copied this from node and comment.module)
        $node_options = variable_get('node_options_image', array('status', 'promote'));
        $image->status = in_array('status', $node_options);
        $image->promote = in_array('promote', $node_options);
        if (module_exists('comment')) {
          $image->comment = variable_get('comment_image', COMMENT_NODE_READ_WRITE);
        }
        image_prepare($image, 'image');
        if ($image->images) {
          if (empty($image->title)) {
            $image->title = basename($image->images[IMAGE_ORIGINAL]);
          }
          node_validate($image);
          if (!form_get_errors()) {
            $image = node_submit($image);
            node_save($image);
            $node->iid = $image->nid;
            $node->new_image = TRUE;
          }
        }
      }
      elseif (!empty($_POST['iid'])) {
        $node->iid = (int) $_POST['iid'];
      }
      break;

    case 'insert':
    case 'update':
      if (isset($node->iid)) {
        db_query("DELETE FROM {image_attach} WHERE nid=%d", $node->nid);
        if ($node->iid > 0) {
          db_query("INSERT INTO {image_attach} (nid, iid) VALUES (%d, %d)", $node->nid, $node->iid);
        }
      }
      break;

    case 'delete':
      db_query("DELETE FROM {image_attach} WHERE nid=%d", $node->nid);
      break;

    case 'load':
      $iid = db_result(db_query("SELECT iid FROM {image_attach} WHERE nid=%d", $node->nid));
      return array('iid' => $iid);

    // Pass the body and teaser objects to the theme again to add the images
    case 'view':
      if ($node->iid) {
        $teaser_or_body = $teaser ? 'teaser' : 'body';
        $node->content['image_attach'] = array(
          '#value' => theme("image_attach_{$teaser_or_body}", $node),
          '#weight' => variable_get("image_attach_weight_{$teaser_or_body}_{$node->type}", 0),
        );
      }
      break;

    case 'rss item':
      $ret = array();
      if ($node->iid && $image = node_load($node->iid)) {
        $info = image_get_info(file_create_path($image->images[IMAGE_PREVIEW]));
        $ret[] = array(
          'key' => 'enclosure',
          'attributes' => array(
            'url' => url("image/view/{$node->iid}/". IMAGE_PREVIEW, array('absolute' => TRUE)),
            'length' => $info['file_size'],
            'type' => $info['mime_type'],
          )
        );
      }
      return $ret;
  }
}

/**
 * Fetch an array of all candidate referenced nodes, for use in presenting the selection form to the user.
 */
function _image_attach_get_image_nodes() {
  $result = db_query(db_rewrite_sql("SELECT n.nid, n.title FROM {node} n WHERE n.status=1 AND type='image' ORDER BY n.sticky DESC, n.title ASC"));
  $result_count = db_result(db_query("SELECT COUNT(*) FROM {node} n WHERE n.status=1 AND type='image'"));
  $rows = array(0 => t('None'));
  while ($node = db_fetch_object($result)) {
    $rows[$node->nid] = $node->title;
  }
  return $rows;
}

/**
 * Implementation of hook_views_tables().
 */
function image_attach_views_tables() {
  $tables['image_attach'] = array(
    'name' => 'image_attach',
    'join' => array(
      'left' => array(
        'table' => 'node',
        'field' => 'nid'
      ),
      'right' => array(
        'field' => 'nid'
      ),
    ),
    'fields' => array(
      'iid' => array(
        'name' => t('Image Attach: Display Image'),
        'handler' => array(
          'image_attach_views_handler_field_iid' => t('Image'),
          'image_attach_views_handler_field_iid_link_node' => t('Image with link to attaching node'),
          'image_attach_views_handler_field_iid_link_image' => t('Image with link to attached image'),
        ),
        'option' => array(
          '#type' => 'select',
          '#options' => 'image_views_handler_filter_image_size',
        ),
        'sortable' => FALSE,
      ),
    ),
    'filters' => array(
      'iid' => array(
        'name' => t('Image Attach: Attached image'),
        'operator' => array('=' => t('Exists')),
        'list' => 'views_handler_operator_yesno',
        'list-type' => 'select',
        'handler' => 'image_attach_views_handler_filter_iid_exist',
        'help' => t('Filter by whether or not the node has an attached image.'),
      ),
    ),
  );

  return $tables;
}

/**
 * Views handler for displaying the image.
 */
function image_attach_views_handler_field_iid($field_info, $field_data, $value, $data) {
  if ($value) {
    $image = node_load($value);
    return image_display($image, $field_data['options']);
  }
}

/**
 * Views handler for displaying the image in a link to the image node that attaches the image.
 */
function image_attach_views_handler_field_iid_link_node($field_info, $field_data, $value, $data) {
  if ($value) {
    $image = node_load($value);
    return l(image_display($image, $field_data['options']), 'node/'. $data->nid, array(), NULL, NULL, FALSE, TRUE);
  }
}

/**
 * Views handler for displaying the image in a link to the attached image.
 */
function image_attach_views_handler_field_iid_link_image($field_info, $field_data, $value, $data) {
  if ($value) {
    $image = node_load($value);
    return l(image_display($image, $field_data['options']), 'node/'. $value, array(), NULL, NULL, FALSE, TRUE);
  }
}

/**
 * Views handler for filtering whether or not the node has an attached image.
 */
function image_attach_views_handler_filter_iid_exist($op, $filter, $filterdata, &$query) {
  switch ($op) {
    case 'handler':
      $query->ensure_table('image_attach');
      if ($filter['value']) {
        $query->add_where('image_attach.iid');
      }
      else {
        $query->add_where('ISNULL(image_attach.iid)');
      }
      break;
  }
}

/**
 * Implementation of hook_theme() registry.
 **/
function image_attach_theme() {
  return array(
    'image_attach_teaser' => array(
      'arguments' => array('node' => new stdClass()),
    ),
    'image_attach_body' => array(
      'arguments' => array('node' => new stdClass()),
    ),
  );
}

/**
 * Theme the teaser.
 *
 * 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_teaser($node) {
  $img_size = variable_get('image_attach_size_teaser_'. $node->type, 'thumbnail');

  if ($img_size != IMAGE_ATTACH_HIDDEN) {
    drupal_add_css(drupal_get_path('module', 'image_attach') .'/image_attach.css');

    $image = node_load($node->iid);
    if (!node_access('view', $image)) {
      // If the image is restricted, don't show it as an attachment.
      return NULL;
    }
    $info = image_get_info(file_create_path($image->images[$img_size]));

    $output = '<div style="width: '. $info['width'] .'px" class="image-attach-teaser">';
    $output .= l(image_display($image, $img_size), "node/$node->nid", array('html' => TRUE));
    $output .= '</div>'."\n";

    return $output;
  }
}

/**
 * Theme the body
 */
function theme_image_attach_body($node) {
  $img_size = variable_get('image_attach_size_body_'. $node->type, IMAGE_THUMBNAIL);

  if ($img_size != IMAGE_ATTACH_HIDDEN) {
    drupal_add_css(drupal_get_path('module', 'image_attach') .'/image_attach.css');

    $image = node_load($node->iid);
    if (!node_access('view', $image)) {
      // If the image is restricted, don't show it as an attachment.
      return NULL;
    }
    $info = image_get_info(file_create_path($image->images[$img_size]));

    $output = '<div style="width: '. $info['width'] .'px" class="image-attach-body">';
    $output .= l(image_display($image, $img_size), "node/$node->iid", array('html' => TRUE));
    $output .= '</div>'."\n";

    return $output;
  }
}

