[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

/sites/all/modules/filefield/ -> filefield_field.inc (source)

   1  <?php
   2  
   3  /**
   4   * @file
   5   * FileField CCK field hooks and callbacks.
   6   */
   7  
   8  /**
   9   * Implementation of CCK's hook_field_settings($op = 'form').
  10   */
  11  function filefield_field_settings_form($field) {
  12    drupal_add_js(drupal_get_path('module', 'filefield') .'/filefield.js');
  13  
  14    $form = array();
  15  
  16    $form['list_field'] = array(
  17      '#type' => 'radios',
  18      '#title' => t('List field'),
  19      '#options' => array(0 => t('Disabled'), 1 => t('Enabled')),
  20      '#default_value' => $field['list_field'] === '' ? 0 : (int) $field['list_field'],
  21      '#description' => t('Display a checkbox where users may choose if a file should be shown when viewing the content. Most formatters other than <em>Generic file</em> do not support this option.'),
  22      '#attributes' => array('class' => 'filefield-list-field'),
  23    );
  24    $form['list_default'] = array(
  25      '#type' => 'checkbox',
  26      '#title' => t('Files listed by default'),
  27      '#default_value' => $field['list_default'] === '' ? 1 : (int) $field['list_default'],
  28    );
  29    $form['description_field'] = array(
  30      '#type' => 'radios',
  31      '#title' => t('Description field'),
  32      '#default_value' => $field['description_field'] === '' ? 0 : (int) $field['description_field'],
  33      '#options' => array(0 => t('Disabled'), 1 => t('Enabled')),
  34      '#description' => t('Display a text field where users may enter a description about the uploaded file. The description text is used when using the <em>Generic file</em> formatter to link to the file, the file name will be used otherwise. Most other formatters do not use the description field on output.'),
  35    );
  36  
  37    return $form;
  38  }
  39  
  40  /**
  41   * Implementation of CCK's hook_field_settings($op = 'save').
  42   */
  43  function filefield_field_settings_save($field) {
  44    return array('list_field', 'list_default', 'description_field');
  45  }
  46  
  47  /**
  48   * Implementation of CCK's hook_field_settings($op = 'database_columns').
  49   */
  50  function filefield_field_settings_database_columns($field) {
  51    return array(
  52      'fid' => array('type' => 'int', 'not null' => FALSE, 'views' => TRUE),
  53      'list' => array('type' => 'int', 'size' => 'tiny', 'not null' => FALSE, 'views' => TRUE),
  54      'data' => array('type' => 'text', 'serialize' => TRUE, 'views' => TRUE),
  55    );
  56  }
  57  
  58  /**
  59   * Implementation of CCK's hook_field_settings($op = 'views_data').
  60   */
  61  function filefield_field_settings_views_data($field) {
  62    $data = content_views_field_views_data($field);
  63    $db_info = content_database_info($field);
  64    $table_alias = content_views_tablename($field);
  65  
  66    // By defining the relationship, we already have a "Has file" filter
  67    // plus all the filters that Views already provides for files.
  68    // No need for having a filter by ourselves.
  69    unset($data[$table_alias][$field['field_name'] .'_fid']['filter']);
  70  
  71    // Add a relationship for related file.
  72    $data[$table_alias][$field['field_name'] .'_fid']['relationship'] = array(
  73      'base' => 'files',
  74      'field' => $db_info['columns']['fid']['column'],
  75      'handler' => 'content_handler_relationship',
  76      'label' => t($field['widget']['label']),
  77      'content_field_name' => $field['field_name'],
  78      'skip base' => array('files'),
  79    );
  80  
  81    // Use the Views boolean handler for filtering the list value.
  82    $data[$table_alias][$field['field_name'] .'_list']['filter']['handler'] = 'views_handler_filter_boolean_operator';
  83  
  84    // Add our special handler for serialized data.
  85    $data[$table_alias][$field['field_name'] .'_data']['field'] = array(
  86      'title' => $data[$table_alias][$field['field_name'] .'_data']['title'],
  87      'title short' => $data[$table_alias][$field['field_name'] .'_data']['title short'],
  88      'help' => t('Can be used to display specific alt, title, or description information. May cause duplicate rows if grouping fields.'),
  89      'field' => $db_info['columns']['data']['column'],
  90      'table' => $db_info['table'],
  91      'handler' => 'filefield_handler_field_data',
  92      'click sortable' => FALSE,
  93      'access callback' => 'content_access',
  94      'access arguments' => array('view', $field),
  95    );
  96  
  97    // Remove handlers that are probably unnecessary.
  98    unset($data[$table_alias][$field['field_name'] .'_data']['filter']);
  99    unset($data[$table_alias][$field['field_name'] .'_data']['argument']);
 100    unset($data[$table_alias][$field['field_name'] .'_list']['argument']);
 101  
 102    // Set up relationship with file views.
 103    $data[$table_alias]['table']['join']['files'] = array(
 104      'table' => $db_info['table'],
 105      'left_field' => 'fid',
 106      'field' => $db_info['columns']['fid']['column'],
 107    );
 108    $data[$table_alias]['vid'] = array(
 109      'title' => t($field['widget']['label']),
 110      'help' => t('The node the uploaded file is attached to'),
 111      'relationship' => array(
 112        'label' => t($field['widget']['label']),
 113        'base' => 'node',
 114        'base field' => 'vid',
 115        // This allows us to not show this relationship if the base is already
 116        // node so users won't create circular relationships.
 117        'skip base' => array('node', 'node_revisions'),
 118      ),
 119    );
 120  
 121    return $data;
 122  }
 123  
 124  /**
 125   * Implementation of CCK's hook_field($op = 'load').
 126   */
 127  function filefield_field_load($node, $field, &$items, $teaser, $page) {
 128    if (empty($items)) {
 129      return array();
 130    }
 131    foreach ($items as $delta => $item) {
 132      // Despite hook_content_is_empty(), CCK still doesn't filter out
 133      // empty items from $op = 'load', so we need to do that ourselves.
 134      if (empty($item['fid']) || !($file = field_file_load($item['fid']))) {
 135        $items[$delta] = NULL;
 136      }
 137      else {
 138        if (isset($item['data']) && !empty($item['data'])) {
 139          $item['data'] = unserialize($item['data']);
 140        }
 141        // Temporary fix to unserialize data serialized multiple times.
 142        // See the FileField issue http://drupal.org/node/402860.
 143        // And the CCK issue http://drupal.org/node/407446.
 144        while (!empty($item['data']) && is_string($item['data'])) {
 145          $item['data'] = unserialize($item['data']);
 146        }
 147        // Merge any data added by modules in hook_file_load().
 148        if (isset($file['data']) && isset($item['data'])) {
 149          $file['data'] = array_merge((array) $file['data'], (array) $item['data']);
 150        }
 151        $items[$delta] = array_merge($file, $item);
 152      }
 153    }
 154  
 155    return array($field['field_name'] => $items);
 156  }
 157  
 158  /**
 159   * Implementation of CCK's hook_field($op = 'insert').
 160   */
 161  function filefield_field_insert($node, $field, &$items, $teaser, $page) {
 162    return filefield_field_update($node, $field, $items, $teaser, $page);
 163  }
 164  
 165  /**
 166   * Implementation of CCK's hook_field($op = 'update').
 167   */
 168  function filefield_field_update($node, $field, &$items, $teaser, $page) {
 169  
 170    // Accumulator to gather current fid to compare with the original node
 171    // for deleting replaced files.
 172    $curfids = array();
 173    foreach ($items as $delta => $item) {
 174      $items[$delta] = field_file_save($node, $item);
 175      // Remove items from the array if they have been deleted.
 176      if (empty($items[$delta]) || empty($items[$delta]['fid'])) {
 177        $items[$delta] = NULL;
 178      }
 179      else {
 180        $curfids[] = $items[$delta]['fid'];
 181      }
 182    }
 183  
 184    // If this is a new node there are no old items to worry about.
 185    // On new revisions, old files are always maintained in the previous revision.
 186    if ($node->is_new || !empty($node->revision) || !empty($node->skip_filefield_delete)) {
 187      return;
 188    } 
 189  
 190    // Delete items from original node.
 191    $orig = node_load($node->nid); 
 192    // If there are, figure out which ones must go.
 193    if (!empty($orig->$field['field_name'])) {
 194      foreach ($orig->$field['field_name'] as $oitem) {
 195        if (isset($oitem['fid']) && !in_array($oitem['fid'], $curfids)) {
 196          // For hook_file_references, remember that this is being deleted.
 197          $oitem['field_name'] = $field['field_name'];
 198          $oitem['delete_vid'] = $orig->vid;
 199          filefield_field_delete_file($oitem, $field); 
 200        }
 201      }
 202    }
 203  }
 204  
 205  /**
 206   * Implementation of CCK's hook_field($op = 'delete_revision').
 207   */
 208  function filefield_field_delete_revision($node, $field, &$items, $teaser, $page) {
 209    foreach ($items as $delta => $item) {
 210      if (isset($item['fid'])) {
 211        // For hook_file_references, remember that this is being deleted.
 212        $item['field_name'] = $field['field_name'];
 213        $item['delete_vid'] = $node->vid;
 214        if (filefield_field_delete_file($item, $field)) {
 215          $items[$delta] = NULL;
 216        }
 217      }
 218    }
 219  }
 220  
 221  /**
 222   * Implementation of CCK's hook_field($op = 'delete').
 223   */
 224  function filefield_field_delete($node, $field, &$items, $teaser, $page) {
 225    foreach ($items as $delta => $item) {
 226      if (isset($item['fid'])) {
 227        // For hook_file_references(), remember that this is being deleted.
 228        $item['field_name'] = $field['field_name'];
 229        // Pass in the nid of the node that is being removed so all references can
 230        // be counted in hook_file_references().
 231        $item['delete_nid'] = $node->nid;
 232        filefield_field_delete_file($item, $field);
 233      }
 234    }
 235  
 236    // Delete all the remaining items present only in older revisions.
 237    $db_info = content_database_info($field);
 238    $result = db_query('SELECT vid, f.* FROM {' . $db_info['table'] . '} t INNER JOIN {files} f ON t.' . $db_info['columns']['fid']['column'] . ' = f.fid WHERE nid = %d AND vid != %d', $node->nid, $node->vid);
 239    while ($item = db_fetch_array($result)) {
 240      if (isset($item['fid'])) {
 241        $item['field_name'] = $field['field_name'];
 242        $item['delete_vid'] = $item['vid'];
 243        filefield_field_delete_file($item, $field); 
 244      }
 245    }
 246  }
 247  
 248  /**
 249   * Check that FileField controls a file before attempting to deleting it.
 250   */
 251  function filefield_field_delete_file($file, $field) {
 252    $file = (object) $file;
 253  
 254    // Remove the field_name and delete_nid properties so that references can be
 255    // counted including the files to be deleted.
 256    $field_name = isset($file->field_name) ? $file->field_name : NULL;
 257    $delete_nid = isset($file->delete_nid) ? $file->delete_nid : NULL;
 258    unset($file->field_name, $file->delete_nid);
 259  
 260    // To prevent FileField from deleting files it doesn't know about, check the
 261    // FileField reference count. Temporary files can be deleted because they
 262    // are not yet associated with any content at all.
 263    if ($file->status == 0 || filefield_get_file_reference_count($file, $field) > 0) {
 264      $file->field_name = $field_name;
 265      $file->delete_nid = $delete_nid;
 266      return field_file_delete($file);
 267    }
 268  
 269    // Even if the file is not deleted, return TRUE to indicate the FileField
 270    // record can be removed from the FileField database tables.
 271    return TRUE;
 272  }
 273  
 274  /**
 275   * Implementation of CCK's hook_field($op = 'sanitize').
 276   */
 277  function filefield_field_sanitize($node, $field, &$items, $teaser, $page) {
 278    foreach ($items as $delta => $item) {
 279      // Cleanup $items during node preview.
 280      if (empty($item['fid']) || !empty($item['delete'])) {
 281        // Check for default images at the widget level.
 282        // TODO: Provide an API to ImageField to do this itself?
 283        if (!empty($field['widget']['use_default_image']) && !empty($field['widget']['default_image']['filepath']) && $delta == 0) {
 284          $items[$delta] = $field['widget']['default_image'];
 285          $items[$delta]['default'] = TRUE;
 286        }
 287        else {
 288          $items[$delta] = NULL;
 289          continue;
 290        }
 291      }
 292  
 293      // Add nid so formatters can create a link to the node.
 294      $items[$delta]['nid'] = $node->nid;
 295  
 296      // Get the 'data' column stored by CCK into an array. This is necessary
 297      // for Views, which doesn't call the "load" $op and to fix an issue with
 298      // CCK double-serializing data.
 299      // See the FileField issue http://drupal.org/node/402860.
 300      // And the CCK issue http://drupal.org/node/407446.
 301      while (!empty($items[$delta]['data']) && is_string($items[$delta]['data'])) {
 302        $items[$delta]['data'] = unserialize($items[$delta]['data']);
 303      }
 304  
 305      // Load the complete file if a filepath is not available.
 306      if (!empty($item['fid']) && empty($item['filepath'])) {
 307        $file = (array) field_file_load($item['fid']);
 308        if (isset($file['data'])) {
 309          $file['data'] = array_merge($file['data'], $items[$delta]['data']);
 310        }
 311        $items[$delta] = array_merge($file, $items[$delta]);
 312      }
 313  
 314      // Verify the file exists on the server.
 315      if (!empty($item['filepath']) && !file_exists($item['filepath'])) {
 316        watchdog('filefield', 'FileField was trying to display the file %file, but it does not exist.', array('%file' => $item['filepath']), WATCHDOG_WARNING);
 317      }
 318    }
 319  }


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7