User login

Functions needed to define a new CCK field; Field placement module thoughts

If we were to implement Field Placement's imagecache preset option as a CCK field itself, here are (a lot of) the parts we would have to implement, drawn from imagefield itself. Many helper functions left out, but the below code is the gist of defining a CCK field type.

All in all, it seems like more work than warranted to display a setting option that does not get displayed on the node itself, but rather affects the display of another CCK field.

The other thing that became clear (I think) is that there is no CCK way for adding complexity to an existing field (such as adding the imagecache dropdown select list right after the alt and title text options) nor for interrupting the display of a CCK field via the module rather than the theme layer, although I may try the phptemplate_ hack for now in Drupal 5.

Without further ado, here are the functions that seem to be necessary to pass yourself off as a Content Construction Kit field:

<?php
function imagefield_default_item() {
  return array(
    'fid' => 0,
    'title' => '',
    'alt' => '',
  );
}

/**
* Implementation of hook_field_info().
*/
function imagefield_field_info() {
  return array(
    'image' => array('label' => 'Image'),
  );
}

/**
* Implementation of hook_field_settings().
*/
function imagefield_field_settings($op, $field) {
  switch ($op) {
    case 'form':
      $form = array();
      return $form;
    case 'validate':

      break;
    case 'save':
      return array();
    case 'database columns':
      $columns = array(
        'fid' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
        'title' => array('type' => 'varchar', length => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
        'alt' => array('type' => 'varchar', length => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
      );
      return $columns;
  }
}

/**
* Implementation of hook_field().
*/
function imagefield_field($op, $node, $field, &$node_field, $teaser, $page) {
  $fieldname = $field['field_name'];
  switch ($op) {
    // called after content.module loads default data.
    case 'load':
      if (count($node_field)) {
        $values = array();
        foreach ($node_field as $delta => $file) {
          if (!empty($file)) {
            $file = _imagefield_file_load($file['fid']);

            // In certain cases, content.module calls this function with
            // $items[$delta] set, even if the field has not yet been stored at
            // all or has already been deleted. In that case, $file['fid'] == 0
            // and file_load() returns an empty array. When that happens,
            // unset() the delta so that subsequent hooks are not bothered.
            if (empty($file)) {
              unset($node_field[$delta]);
            }
            else { // otherwise, merge our info with CCK's, and all is fine.
                $node_field[$delta]  = array_merge((array)$node_field[$delta], $file);
            }
          }
        }
        return array($fieldname => $node_field);
      }
      return array();
     
    // called before content.module defaults.
    case 'insert':
      foreach ($node_field as  $delta => $item) {
        $node_field[$delta] = imagefield_file_insert($node, $item, $field);
        // Remove non-existant images from items
        if (empty($node_field[$delta])) {
          unset($node_field[$delta]);
        }
      }
      imagefield_clear_field_session($fieldname);
      break;

    // called before content.module defaults.
    case 'update':
      foreach ($node_field as $delta => $item) {

        // If we're dealing with a single value field, and we just received
        // a new file item, we need to mark the existing (old) one for
        // deletion.  Otherwise, it will become orphaned.
        if (!$field['multiple'] && (count($node_field) > 1) && ($delta === 0)) {
          $item['flags']['delete'] = TRUE;
        }
       
        // Update each file item.
        $node_field[$delta] = imagefield_file_update($node, $item, $field);

        // If the file has been deleted, unset the file entry so that it's
        // actually deleted from the database, or at least set it to a
        // default item if CCK won't delete it.
        if (empty($node_field[$delta])) {
         if ($field['multiple']) {
            unset($node_field[$delta]);
          }
          else {
            $node_field[$delta] = imagefield_default_item();
          }
        }
      }
      // Compact deltas.
      $node_field = array_values($node_field);
      imagefield_clear_field_session($fieldname);
      break;

    case 'delete':
      foreach ($node_field as $delta => $item) {
        _imagefield_file_delete($item, $field['field_name']);
      }
      break;
  }
}

/**
* Implementation of hook_widget_info().
*/
function imagefield_widget_info() {
  return array(
    'image' => array(
      'label' => 'Image',
      'field types' => array('image'),
    ),
  );
}

/**
* Implementation of hook_widget_settings().
*/
function imagefield_widget_settings($op, $widget) {
  switch ($op) {
    case 'callbacks':
      return array('default value' => CONTENT_CALLBACK_CUSTOM);

    case 'form':
      $form = array();
      $form['max_resolution'] = array (
        '#type' => 'textfield',
        '#title' => t('Maximum resolution for Images'),
        '#default_value' => $widget['max_resolution'] ? $widget['max_resolution'] : 0,
        '#size' => 15,
        '#maxlength' => 10,
        '#description' =>
        t('The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Set to 0 for no restriction.')
      );
      $form['image_path'] = array(
        '#type' => 'textfield',
        '#title' => t('Image path'),
        '#default_value' => $widget['image_path'] ? $widget['image_path'] : '',
        '#description' => t('Optional subdirectory within the "%dir" directory where images will be stored. Do not include trailing slash.', array('%dir' => variable_get('file_directory_path', 'files'))),
        '#after_build' => array('imagefield_form_check_directory'),
      );
      $form['custom_alt'] = array(
        '#type' => 'checkbox',
        '#title' => t('Enable custom alternate text'),
        '#default_value' =>  $widget['custom_alt'] ? $widget['custom_alt'] : 0,
        '#description' => t('Enable custom alternate text for images. Filename will be used if not checked.'),
      );
      $form['custom_title'] = array(
        '#type' => 'checkbox',
        '#title' => t('Enable custom title text'),
        '#default_value' =>  $widget['custom_title'] ? $widget['custom_title'] : 0,
        '#description' => t('Enable custom title text for images. Filename will be used if not checked.'),
      );
      return $form;

    case 'validate':
      break;

    case 'save':
      return array('max_resolution', 'image_path', 'custom_alt', 'custom_title', 'teaser_preset', 'body_preset');
  }
}

/**
* Implementation of hook_widget().
*/
function imagefield_widget($op, &$node, $field, &$node_field) {
  $fieldname = $field['field_name'];
  $content_type = $field['type_name'];
  switch ($op) {
    case 'default value':
      return array();

    case 'prepare form values':
      _imagefield_widget_prepare_form_values($node, $field, $node_field);
      return;

    case 'form':
      $form = _imagefield_widget_form($node, $field, $node_field);
      return $form;

    case 'validate':
      _imagefield_widget_form_validate($node, $field, $node_field);
      return;
  }
}

/**
* Implementation of hook_field_formatter_info().
*/
function imagefield_field_formatter_info() {
  $formatters = array(
    'default' => array(
      'label' => 'Default',
      'field types' => array('image'),
    ),
  );
  return $formatters;
}

/**
* Implementation of hook_field_formatter().
*
*/
function imagefield_field_formatter($field, $item, $formatter) {
  if (empty($item['fid'])) {
    return '';
  }
  $file = _imagefield_file_load($item['fid']);
  return theme('imagefield_image', $file, $item['alt'], $item['title']);
}
?>

Resolution

Comments

Post new comment

The content of this field is kept private and will not be shown publicly.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.
  • You can use Markdown syntax to format and style the text. Also see Markdown Extra for tables, footnotes, and more.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <img> <blockquote> <small> <h2> <h3> <h4> <h5> <h6> <sub> <sup> <p> <br> <strike> <table> <tr> <td> <thead> <th> <tbody> <tt> <output>
  • Syntax highlight code surrounded by the {syntaxhighlighter SPEC}...{/syntaxhighlighter} tags, where SPEC is a Syntaxhighlighter options string or "class="OPTIONS" title="the title".
  • Lines and paragraphs break automatically.

More information about formatting options

By submitting this form, you accept the Mollom privacy policy.