You are here

function content_storage in Content Construction Kit (CCK) 6.3

Same name and namespace in other branches
  1. 6 content.module \content_storage()
  2. 6.2 content.module \content_storage()

Handle storage ops for _content_field_invoke_default().

1 call to content_storage()
_content_field_invoke_default in ./content.module
Invoke content.module's version of a field hook.

File

./content.module, line 986
Allows administrators to associate custom fields to content types.

Code

function content_storage($op, $node) {

  // Don't try this before content module's update is run to add
  // the active and module columns.
  if (variable_get('content_schema_version', -1) < 6007) {
    return FALSE;
  }
  $type_name = $node->type;
  $type = content_types($type_name);
  switch ($op) {
    case 'load':

      // OPTIMIZE: load all non multiple fields in a single JOIN query ?
      // warning: 61-join limit in MySQL ?
      $additions = array();

      // For each table used by this content type,
      foreach ($type['tables'] as $table) {
        $schema = drupal_get_schema($table);

        // The per-type table might not have any fields actually stored in it.
        if (!$schema['content fields']) {
          continue;
        }
        $query = 'SELECT * FROM {' . $table . '} WHERE vid = %d';

        // If we're loading a table for a multiple field,
        // we fetch all rows (values) ordered by delta,
        // else we only fetch one row.
        $result = isset($schema['fields']['delta']) ? db_query($query . ' ORDER BY delta', $node->vid) : db_query_range($query, $node->vid, 0, 1);

        // For each table row, populate the fields.
        while ($row = db_fetch_array($result)) {

          // For each field stored in the table, add the field item.
          foreach ($schema['content fields'] as $field_name) {
            $item = array();
            $field = content_fields($field_name, $type_name);
            $db_info = content_database_info($field);

            // For each column declared by the field, populate the item.
            foreach ($db_info['columns'] as $column => $attributes) {
              $item[$column] = $row[$attributes['column']];
            }

            // Add the item to the field values for the node.
            if (!isset($additions[$field_name])) {
              $additions[$field_name] = array();
            }

            // Preserve deltas when loading items from database.
            if (isset($row['delta'])) {

              // Make sure multiple value fields have consecutive deltas.
              if ($row['delta'] > 0 && !isset($additions[$field_name][$row['delta'] - 1])) {
                $empty = array();
                foreach (array_keys($db_info['columns']) as $column) {
                  $empty[$column] = NULL;
                }
                $next_delta = !empty($additions[$field_name]) ? max(array_keys($additions[$field_name])) + 1 : 0;
                for ($delta = $next_delta; $delta < $row['delta']; $delta++) {
                  if (!isset($additions[$field_name][$delta])) {
                    $additions[$field_name][$delta] = $empty;
                  }
                }
              }
              $additions[$field_name][$row['delta']] = $item;
            }
            else {
              $additions[$field_name][] = $item;
            }
          }
        }
      }
      return $additions;
    case 'insert':
    case 'update':
      foreach ($type['tables'] as $table) {
        $schema = drupal_get_schema($table);
        $record = array();
        foreach ($schema['content fields'] as $field_name) {
          if (isset($node->{$field_name})) {
            $field = content_fields($field_name, $type_name);

            // Multiple fields need specific handling, we'll deal with them later on.
            if ($field['multiple']) {
              continue;
            }
            $db_info = content_database_info($field);
            foreach ($db_info['columns'] as $column => $attributes) {
              $record[$attributes['column']] = $node->{$field_name}[0][$column];
            }
          }
        }

        // $record might be empty because
        // - the table stores a multiple field :
        //   we do nothing, this is handled later on
        // - this is the per-type table and no field is actually stored in it :
        //   we still store the nid and vid
        if (count($record) || empty($schema['content fields'])) {
          $record['nid'] = $node->nid;
          $record['vid'] = $node->vid;

          // Can't rely on the insert/update op of the node to decide if this
          // is an insert or an update, a node or revision may have existed
          // before any fields were created, so there may not be an entry here.
          // TODO - should we auto create an entry for all existing nodes when
          // fields are added to content types -- either a NULL value
          // or the default value? May need to offer the user an option of
          // how to handle that.
          if (db_result(db_query("SELECT COUNT(*) FROM {" . $table . "} WHERE vid = %d", $node->vid))) {
            content_write_record($table, $record, array(
              'vid',
            ));
          }
          else {
            content_write_record($table, $record);
          }
        }
      }

      // Handle multiple fields.
      foreach ($type['fields'] as $field) {
        if ($field['multiple'] && isset($node->{$field}['field_name'])) {
          $db_info = content_database_info($field);

          // Delete and insert, rather than update, in case a value was added.
          if ($op == 'update') {
            db_query('DELETE FROM {' . $db_info['table'] . '} WHERE vid = %d', $node->vid);
          }

          // Collect records for non-empty items.
          $function = $field['module'] . '_content_is_empty';
          $records = array();
          foreach ($node->{$field}['field_name'] as $delta => $item) {
            if (!$function($item, $field)) {
              $record = array();
              foreach ($db_info['columns'] as $column => $attributes) {
                $record[$attributes['column']] = $item[$column];
              }
              $record['nid'] = $node->nid;
              $record['vid'] = $node->vid;
              $record['delta'] = $delta;
              $records[] = $record;
            }
          }

          // If there was no non-empty item, insert delta 0 with NULL values.
          if (empty($records)) {
            $record = array();
            foreach ($db_info['columns'] as $column => $attributes) {
              $record[$attributes['column']] = NULL;
            }
            $record['nid'] = $node->nid;
            $record['vid'] = $node->vid;
            $record['delta'] = 0;
            $records[] = $record;
          }

          // Insert the collected records for this field into database.
          foreach ($records as $record) {
            content_write_record($db_info['table'], $record);
          }
        }
      }
      break;
    case 'delete':
      foreach ($type['tables'] as $table) {
        db_query('DELETE FROM {' . $table . '} WHERE nid = %d', $node->nid);
      }
      break;
    case 'delete revision':
      foreach ($type['tables'] as $table) {
        db_query('DELETE FROM {' . $table . '} WHERE vid = %d', $node->vid);
      }
      break;
  }
}