You are here

filefield_paths.module in File (Field) Paths 6

Contains core functions for the FileField Paths module.

File

filefield_paths.module
View source
<?php

/**
 * @file
 * Contains core functions for the FileField Paths module.
 */

/**
 * Include additional files.
 */
foreach (module_list() as $module) {
  if (file_exists($file = dirname(__FILE__) . "/modules/{$module}.inc")) {
    require_once $file;
  }
}

/**
 * Implements hook_theme().
 */
function filefield_paths_theme() {
  return array(
    'filefield_paths_token_help' => array(
      'arguments' => array(
        'prefix' => '[',
        'suffix' => ']',
      ),
    ),
  );
}
function theme_filefield_paths_token_help($prefix = '[', $suffix = ']') {
  token_include();
  $full_list = array_merge(filefield_paths_token_list(), token_get_list('node'));
  if (function_exists('filefield_token_list')) {
    $temp_tokens = filefield_token_list();
    $full_list['file'] = array_merge($temp_tokens['file'], $full_list['file']);
  }
  $headers = array(
    t('Token'),
    t('Replacement value'),
  );
  $rows = array();
  foreach ($full_list as $key => $category) {
    $rows[] = array(
      array(
        'data' => drupal_ucfirst($key) . ' ' . t('tokens'),
        'class' => 'region',
        'colspan' => 2,
      ),
    );
    foreach ($category as $token => $description) {
      $row = array();
      $row[] = $prefix . $token . $suffix;
      $row[] = $description;
      $rows[] = $row;
    }
  }
  return theme('table', $headers, $rows, array(
    'class' => 'description',
  ));
}

/**
 * Implements hook_form_alter().
 */
function filefield_paths_form_alter(&$form, $form_state, $form_id) {
  $ffp = array();

  // Invoke hook_filefield_paths_form_alter().
  foreach (module_implements('filefield_paths_form_alter') as $module) {
    $function = "{$module}_filefield_paths_form_alter";
    $function($form, $ffp);
  }

  // If supporting module enabled, show FileField Paths settings form.
  if (count($ffp) > 0) {
    $fields = module_invoke_all('filefield_paths_field_settings');
    foreach ($ffp as $field_name => $field_data) {
      $result = db_fetch_object(db_query("SELECT * FROM {filefield_paths} WHERE type = '%s' AND field = '%s'", $field_data['type'], $field_name));
      if (!empty($result)) {
        foreach ($fields as &$field) {
          $field['settings'] = unserialize($result->{$field}['sql']);
        }
        unset($field);
      }
      $count = 0;
      foreach ($fields as $name => $field) {
        $count++;
        if (isset($field['form']) && is_array($field['form'])) {
          $keys = array_keys($field['form']);
          for ($i = 1; $i < count($field['form']); $i++) {
            $field['form'][$keys[$i]]['#weight'] = ($count - 1) * 3 + 2 + $i;
          }
          unset($keys);
          $field_data['form_path'] = array_merge_recursive($field_data['form_path'], $field['form']);
        }
        $field_data['form_path']['#tree'] = TRUE;
        $field_data['form_path'][$name]['#weight'] = ($count - 1) * 3;

        // Set defualt value for patterns.
        if (isset($field['settings']['value'])) {
          $field_data['form_path'][$name]['#default_value'] = $field['settings']['value'];
          if (isset($field['data'])) {
            foreach ($field['data'] as $key => $value) {
              $field_data['form_path'][$value]['#default_value'] = $field['settings'][$key];
            }
          }
        }
        $field_data['form_path']["{$name}_cleanup"] = array(
          '#type' => 'fieldset',
          '#title' => t('!title cleanup settings', array(
            '!title' => $field['title'],
          )),
          '#collapsible' => TRUE,
          '#collapsed' => TRUE,
          '#weight' => ($count - 1) * 3 + 1,
          '#attributes' => array(
            'class' => array(
              "{$name} cleanup",
            ),
          ),
        );

        // Cleanup field with Pathauto module.
        $field_data['form_path']["{$name}_cleanup"]["{$name}_pathauto"] = array(
          '#type' => 'checkbox',
          '#title' => t('Cleanup using Pathauto') . '.',
          '#default_value' => isset($field['settings']['pathauto']) ? $field['settings']['pathauto'] : 0,
          '#description' => t('Cleanup !title using !url', array(
            '!title' => $field['title'],
            '!url' => l(t('Pathauto settings'), 'admin/build/path/pathauto'),
          )),
        );
        if (!module_exists('pathauto')) {
          $field_data['form_path']["{$name}_cleanup"]["{$name}_pathauto"]['#disabled'] = TRUE;
          $field_data['form_path']["{$name}_cleanup"]["{$name}_pathauto"]['#default_value'] = 0;
        }

        // Convert field to lower case.
        $field_data['form_path']["{$name}_cleanup"]["{$name}_tolower"] = array(
          '#type' => 'checkbox',
          '#title' => t('Convert to lower case') . '.',
          '#default_value' => isset($field['settings']['tolower']) ? $field['settings']['tolower'] : 0,
          '#description' => t('Convert !title to lower case', array(
            '!title' => $field['title'],
          )) . '.',
        );

        // Transliterate field with Transliteration module.
        $field_data['form_path']["{$name}_cleanup"]["{$name}_transliterate"] = array(
          '#type' => 'checkbox',
          '#title' => t('Transliterate') . '.',
          '#default_value' => isset($field['settings']['transliterate']) ? $field['settings']['transliterate'] : 0,
          '#description' => t('Transliterate !title', array(
            '!title' => $field['title'],
          )) . '.',
        );
        if (!module_exists('transliteration')) {
          $field_data['form_path']["{$name}_cleanup"]["{$name}_transliterate"]['#disabled'] = TRUE;
          $field_data['form_path']["{$name}_cleanup"]["{$name}_transliterate"]['#default_value'] = 0;
        }

        // Replacement patterns for field.
        $field_data['form_path']["{$name}_tokens"] = array(
          '#type' => 'fieldset',
          '#title' => t('!title replacement patterns', array(
            '!title' => $field['title'],
          )),
          '#collapsible' => TRUE,
          '#collapsed' => TRUE,
          '#description' => theme('filefield_paths_token_help'),
          '#weight' => ($count - 1) * 3 + 2,
          '#attributes' => array(
            'class' => $name . ' tokens',
          ),
        );
      }

      // Retroactive updates.
      $field_data['form_path']['retroactive_update'] = array(
        '#type' => 'checkbox',
        '#title' => t('Retroactive update'),
        '#description' => t('Move and rename previously uploaded files') . '.' . '<br /> <strong style="color: #FF0000;">' . t('Warning') . ':</strong> ' . t('This feature should only be used on developmental servers or with extreme caution') . '.',
        '#weight' => 10,
      );

      // Active updating.
      $field_data['form_path']['active_updating'] = array(
        '#type' => 'checkbox',
        '#title' => t('Active updating'),
        '#default_value' => variable_get("ffp_{$field_data['type']}_{$field_name}", 0),
        '#description' => t('Actively move and rename previously uploaded files as required') . '.' . '<br /> <strong style="color: #FF0000;">' . t('Warning') . ':</strong> ' . t('This feature should only be used on developmental servers or with extreme caution') . '.',
        '#weight' => 11,
      );
      if (!in_array('filefield_paths_form_submit', $form['#submit'])) {
        $form['#submit'][] = 'filefield_paths_form_submit';
      }
    }
  }
}

/**
 * Implements hook_form_submit().
 */
function filefield_paths_form_submit($form, &$form_state) {
  $ffp = array();

  // Invoke hook_filefield_paths_form_submit().
  foreach (module_implements('filefield_paths_form_submit') as $module) {
    $function = "{$module}_filefield_paths_form_submit";
    $function($form_state, $ffp);
  }
  if (count($ffp) > 0) {
    $retroactive_update = FALSE;
    $fields = module_invoke_all('filefield_paths_field_settings');
    foreach ($ffp as $field_name => $field_data) {
      $cols = $vals = $data = array();
      foreach ($fields as $name => &$field) {
        $field['settings'] = array(
          'value' => $form_state['values']["ffp_{$field_name}"][$name],
          'tolower' => $form_state['values']["ffp_{$field_name}"]["{$name}_cleanup"]["{$name}_tolower"],
          'pathauto' => $form_state['values']["ffp_{$field_name}"]["{$name}_cleanup"]["{$name}_pathauto"],
          'transliterate' => $form_state['values']["ffp_{$field_name}"]["{$name}_cleanup"]["{$name}_transliterate"],
        );

        // Store additional settings from addon modules.
        if (isset($field['data'])) {
          foreach ($field['data'] as $key => $value) {
            $field['settings'][$key] = $form_state['values']["ffp_{$field_name}"][$value];
          }
        }
        $cols[] = $field['sql'];
        $vals[] = "'%s'";
        $data[] = serialize($field['settings']);
      }
      $result = db_fetch_object(db_query("SELECT * FROM {filefield_paths} WHERE type = '%s' AND field = '%s'", $field_data['type'], $field_name));

      // Update existing entry.
      if (!empty($result)) {
        foreach ($cols as &$col) {
          $col .= " = '%s'";
        }
        db_query("UPDATE {filefield_paths} SET " . implode(', ', $cols) . " WHERE type = '%s' AND field = '%s'", array_merge($data, array(
          $field_data['type'],
          $field_name,
        )));
      }
      else {
        db_query("INSERT INTO {filefield_paths} (type, field, " . implode(', ', $cols) . ") VALUES ('%s', '%s', " . implode(', ', $vals) . ")", array_merge(array(
          $field_data['type'],
          $field_name,
        ), $data));
      }
      if ($form_state['values']["ffp_{$field_name}"]['retroactive_update']) {
        $retroactive_update = TRUE;
        $module = isset($form['#field']) ? $form['#field']['module'] : $field_name;
        filefield_paths_batch_update($module, $field_name, arg(3));
      }
      variable_set("ffp_{$field_data['type']}_{$field_name}", $form_state['values']["ffp_{$field_name}"]['active_updating']);
    }
    if ($retroactive_update) {

      // Run batch.
      batch_process($form_state['redirect']);
    }
  }
}

/**
 * Set batch process to update FileField Paths.
 *
 * @param $module
 *   The upload widgets module ('filefield', 'upload', etc).
 * @param $field
 *   The CCK field name - set as NULL if not applicable.
 * @param $type
 *   The Node type ('page', 'story', etc).
 */
function filefield_paths_batch_update($module, $field, $type) {
  $objects = array();

  // Invoke hook_filefield_paths_batch_update().
  if (function_exists($function = "{$module}_filefield_paths_batch_update")) {
    $function($field, str_replace('-', '_', $type), $objects);
  }

  // Create batch.
  $batch = array(
    'title' => t('Updating FileField Paths'),
    'operations' => array(
      array(
        '_filefield_paths_batch_update_process',
        array(
          array_unique($objects),
          $module,
          $field,
        ),
      ),
    ),
  );
  batch_set($batch);
}
function _filefield_paths_batch_update_process($objects, $module, $field, &$context) {
  if (!isset($context['sandbox']['progress'])) {
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['max'] = count($objects);
    $context['sandbox']['objects'] = $objects;
  }

  // Process nodes by groups of 5.
  $count = min(5, count($context['sandbox']['objects']));
  for ($i = 1; $i <= $count; $i++) {

    // For each oid, load the object, update the files and save it.
    $oid = array_shift($context['sandbox']['objects']);

    // Invoke hook_filefield_paths_update().
    if (function_exists($function = "{$module}_filefield_paths_update")) {
      $function($oid, $field);
    }

    // Update our progress information.
    $context['sandbox']['progress']++;
  }

  // Inform the batch engine that we are not finished,
  // and provide an estimation of the completion level we reached.
  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
  }
}

/**
 * Implements hook_nodeapi().
 */
function filefield_paths_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  $function = 'filefield_paths_node_' . $op;
  if (function_exists($function)) {
    $function($node);
  }
}

/**
 * Implements hook_node_presave().
 */
function filefield_paths_node_presave(&$node) {
  if (module_exists('content')) {
    $content_type = content_types($node->type);
    foreach ($content_type['fields'] as $field) {
      if ($field['type'] == 'filefield' && is_array($node->{$field}['field_name'])) {
        foreach ($node->{$field}['field_name'] as $count => &$file) {
          if (!is_array($file) || empty($file['filepath'])) {
            continue;
          }

          // If file is newly uploaded, flag to be processed
          if ($file['status'] == 0) {
            $file['data']['process'] = TRUE;
          }
        }
      }
    }
  }
}

/**
 * Implements hook_node_insert().
 */
function filefield_paths_node_insert(&$node) {
  filefield_paths_node_update($node);
}

/**
 * Implements hook_node_update().
 */
function filefield_paths_node_update(&$node) {
  if (($ffp = filefield_paths_get_fields($node)) !== FALSE) {
    $update = new stdClass();
    $update->node = FALSE;

    // Process files.
    foreach ($ffp['#files'] as &$file) {

      // Invoke hook_filefield_paths_process_file().
      foreach (module_implements('filefield_paths_process_file') as $module) {
        $function = "{$module}_filefield_paths_process_file";
        $function($file['new'] || variable_get("ffp_{$node->type}_{$file['name']}", 0), $file, $ffp['#settings'][$file['name']], $node, $update);
      }
    }

    // Re-write node entry if required.
    if ($update->node == TRUE) {
      global $user;
      drupal_write_record('node', $node, 'nid');
      _node_save_revision($node, $user->uid, 'vid');
    }

    // Re-write cck fields.
    if (module_exists('content')) {
      if (module_exists('filefield')) {
        _field_file_cache(NULL, TRUE);
      }
      _content_field_invoke_default('update', $node);
      cache_clear_all("content:{$node->nid}:{$node->vid}", content_cache_tablename());
    }

    // Cleanup temporary paths.
    if ($ffp['#settings']) {
      foreach ($ffp['#settings'] as $name => $field) {
        $paths = explode('/', $field['filepath']['value']);
        filefield_paths_cleanup_temp($paths);

        // Invoke hook_filefield_paths_cleanup().
        foreach (module_implements('filefield_paths_cleanup') as $module) {
          $function = "{$module}_filefield_paths_cleanup";
          $function($ffp, $paths, $name);
        }
      }
    }
  }
}

/**
 * Implements hook_content_fieldapi().
 */
function filefield_paths_content_fieldapi($op, $field) {
  switch ($op) {
    case 'delete instance':
      db_query("DELETE FROM {filefield_paths} WHERE type = '%s' AND field = '%s'", $field['type_name'], $field['field_name']);
      break;
  }
}
function filefield_paths_cleanup_temp($paths) {
  while ($paths) {
    if (@rmdir(file_directory_path() . '/' . implode('/', $paths)) === TRUE) {
      array_pop($paths);
      continue;
    }
    break;
  }
}
function filefield_paths_get_fields(&$node, $op = NULL) {
  $ffp = array();

  // Invoke hook_filefield_paths_get_fields().
  foreach (module_implements('filefield_paths_get_fields') as $module) {
    $function = "{$module}_filefield_paths_get_fields";
    $function($node, $ffp);
  }
  if (count($ffp) == 0 || isset($ffp['#types']) && !is_array($ffp['#types'])) {
    return FALSE;
  }
  $fields = module_invoke_all('filefield_paths_field_settings');

  // Load fields settings
  foreach ($ffp['#types'] as $name => $temp) {
    $result = db_fetch_object(db_query("SELECT * FROM {filefield_paths} WHERE type = '%s' AND field = '%s'", $node->type, $name));
    if (!empty($result)) {
      foreach ($fields as $field) {
        $ffp['#settings'][$name][$field['sql']] = unserialize($result->{$field}['sql']);
      }
    }
  }
  return $ffp;
}

/**
 * Implements hook_filefield_paths_process_file().
 */
function filefield_paths_filefield_paths_process_file($new, &$file, $settings, &$node, &$update) {
  if ($new && !empty($file['field']['filename'])) {

    // Process filename
    $file['filename']['old'] = $file['field']['filename'];
    if (($file['filename']['new'] = $settings['filename']['value']) != '') {
      $file['filename']['new'] = filefield_paths_process_string($file['filename']['new'], 'node', $node, $settings['filename']);
      $file['filename']['new'] = filefield_paths_process_string($file['filename']['new'], 'field', array(
        0 => $file['field'],
      ), $settings['filename']);
    }
    else {
      $file['filename']['new'] = $file['field']['filename'];
    }

    // Process filepath
    $file['filepath']['old'] = $file['field']['filepath'];
    $file['filepath']['new'] = filefield_paths_process_string(file_directory_path() . "/{$settings['filepath']['value']}/{$file['filename']['new']}", 'node', $node, $settings['filepath']);
    $file['filepath']['new'] = filefield_paths_process_string($file['filepath']['new'], 'field', array(
      0 => $file['field'],
    ), $settings['filepath']);

    // Finalize files if necessary
    if (dirname($file['filepath']['new']) != dirname($file['field']['filepath']) || $file['filename']['new'] != $file['field']['filename']) {
      if (filefield_paths_file_move($file)) {

        // Fix reference to old paths.
        if (isset($node->body) || module_exists('content')) {
          $file['filepath']['new'] = str_replace($file['filename']['old'], $file['filename']['new'], $file['filepath']['new']);
          $file_directory_path = variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC ? file_directory_path() : 'system/files';

          // Regular expression to replace old file reference.
          $pattern = array(
            'regex' => str_replace('/', '\\/', $file_directory_path) . '([^"]*?)' . str_replace('/', '\\/', str_replace(file_directory_path(), '', $file['filepath']['old'])),
            'regex_enc' => str_replace('/', '\\/', drupal_urlencode($file_directory_path)) . '([^"]*?)' . str_replace('/', '\\/', str_replace(drupal_urlencode(file_directory_path()), '', drupal_urlencode($file['filepath']['old']))),
            'replace' => $file_directory_path . '$1' . str_replace(file_directory_path(), '', $file['filepath']['new']),
          );

          // Process regular expression.
          _filefield_paths_replace_pattern($pattern, $node, $update);
        }

        // Store new filename in file Array
        $file['field']['filename'] = $file['filename']['new'];
      }
    }
  }
}

/**
 * Run regular expression over all available text-based fields.
 */
function _filefield_paths_replace_pattern($pattern, &$node, &$update) {
  $fields = _filefield_paths_text_fields($node);

  // Loop through all fields and process filter.
  foreach ($fields as $field => &$data) {
    ${$field} = preg_match("/{$pattern['regex']}/s", $data) ? preg_replace("/{$pattern['regex']}/s", $pattern['replace'], $data) : preg_replace("/{$pattern['regex_enc']}/s", $pattern['replace'], $data);
    if (${$field} != $data) {
      $data = ${$field};

      // Mark node for update.
      if ($field == 'body' || $field == 'teaser') {
        $update->node = TRUE;
      }
    }
  }
}

/**
 * Get all text-based fields attached to node.
 */
function _filefield_paths_text_fields($node) {
  $fields = array();

  // Get Node fields.
  if (isset($node->body)) {
    $fields += array(
      'body' => &$node->body,
      'teaser' => &$node->teaser,
    );
  }

  // Get CCK fields.
  if (module_exists('content')) {
    $content_type = content_types($node->type);
    foreach ($content_type['fields'] as $name => $field) {
      if ($field['type'] == 'text' && is_array($node->{$name})) {
        foreach ($node->{$name} as $key => $value) {
          if (isset($node->{$name}[$key]['value'])) {
            $fields["{$name}_{$key}"] =& $node->{$name}[$key]['value'];
          }
        }
      }
    }
  }
  return $fields;
}

/**
 * Implements hook_token_list().
 */
function filefield_paths_token_list($type = 'all') {
  if ($type == 'field' || $type == 'all') {
    $tokens = array();
    if (!module_exists('filefield')) {
      $tokens['file']['filefield-onlyname'] = t("File name without extension");
      $tokens['file']['filefield-extension'] = t("File extension");
    }
    $tokens['file']['filefield-onlyname-original'] = t("File name without extension - original");
    $tokens['file']['filefield-extension-original'] = t("File extension - original");

    // Tokens for Image module integration.
    if (module_exists('image')) {
      $tokens['image']['image-derivative'] = t("Image derivative (thumbnail, preview, etc)");
    }
    return $tokens;
  }
}

/**
 * Implements hook_token_values().
 */
function filefield_paths_token_values($type, $object = NULL) {
  if ($type == 'field') {
    $item = pathinfo($object[0]['filename']);
    $tokens = array();
    if (!module_exists('filefield')) {

      // PHP < 5.2: pathinfo() doesn't return 'filename' variable.
      $tokens['filefield-onlyname'] = isset($item['filename']) ? $item['filename'] : basename($object[0]['filename'], ".{$item['extension']}");
      $tokens['filefield-extension'] = $item['extension'];
    }

    // Original filename.
    $orig = $item;
    $filename = $object[0]['filename'];
    $result = db_fetch_object(db_query("SELECT origname FROM {files} WHERE fid = %d", $object[0]['fid']));
    if (!empty($result->origname)) {
      $object[0]['origname'] = $result->origname;
    }
    if (!empty($object[0]['origname'])) {
      $orig = pathinfo($object[0]['origname']);
      $filename = $object[0]['origname'];
    }

    // PHP < 5.2: pathinfo() doesn't return 'filename' variable.
    $tokens['filefield-onlyname-original'] = isset($orig['filename']) ? $orig['filename'] : basename($filename, ".{$orig['extension']}");
    $tokens['filefield-extension-original'] = $orig['extension'];

    // Tokens for Image module integration.
    if (module_exists('image')) {
      $tokens['image-derivative'] = isset($object[0]['type']) && $object[0]['type'] !== '_original' ? ".{$object[0]['type']}" : '';
    }
    return $tokens;
  }
}

/**
 * Process and cleanup strings.
 */
function filefield_paths_process_string($value, $type, $object, $settings = array()) {

  // Process string tokens.
  $placeholders = _filefield_paths_get_values($type, $object, module_exists('pathauto') && isset($settings['pathauto']) && $settings['pathauto']);
  $value = str_replace($placeholders['tokens'], $placeholders['values'], $value);

  // Transliterate string.
  if (module_exists('transliteration') && isset($settings['transliterate']) && $settings['transliterate']) {
    $value = transliteration_get($value);
    if ($type == 'field') {
      $paths = explode('/', $value);
      foreach ($paths as &$path) {
        $path = transliteration_clean_filename($path);
      }
      $value = implode('/', $paths);
    }
  }

  // Convert string to lower case.
  if (isset($settings['tolower']) && $settings['tolower'] || isset($settings['pathauto']) && $settings['pathauto'] && variable_get('pathauto_case', 0)) {

    // Convert string to lower case
    $value = drupal_strtolower($value);
  }

  // Ensure that there are no double-slash sequences due to empty token values.
  $value = preg_replace('/\\/+/', '/', $value);
  return $value;
}
function _filefield_paths_get_values($type, $object, $pathauto = FALSE) {
  switch ($type) {
    case 'node':
      $full = token_get_values($type, $object, TRUE);
      break;
    case 'field':
      $all = filefield_paths_token_values($type, $object);
      if (function_exists('filefield_token_values')) {
        $all = array_merge(filefield_token_values($type, $object), $all);
      }
      $full = new stdClass();
      $full->tokens = array_keys($all);
      $full->values = array_values($all);
      break;
  }
  $full->tokens = token_prepare_tokens($full->tokens);
  if ($pathauto) {
    $temp = clone $full;

    // Strip square brackets from tokens for Pathauto.
    foreach ($temp->tokens as &$token) {
      $token = trim($token, "[]");
    }
    if (!function_exists('pathauto_clean_token_values')) {
      module_load_include('inc', 'pathauto');
    }
    $full->values = pathauto_clean_token_values($temp);
  }
  return array(
    'tokens' => $full->tokens,
    'values' => $full->values,
  );
}

/**
 * Move file and update its database record.
 */
function filefield_paths_file_move(&$file, $replace = FILE_EXISTS_RENAME) {
  $dest = _filefield_paths_strip_path(dirname($file['filepath']['new']));
  foreach (explode('/', $dest) as $dir) {
    $dirs[] = $dir;
    $path = file_create_path(implode($dirs, '/'));
    if (!_filefield_paths_check_directory($path, FILE_CREATE_DIRECTORY)) {
      watchdog('filefield_paths', 'FileField Paths failed to create directory (%d).', array(
        '%d' => $path,
      ), WATCHDOG_ERROR);
      return FALSE;
    }
  }
  if (!file_move($file['field']['filepath'], "{$dest}/{$file['filename']['new']}", $replace)) {
    watchdog('filefield_paths', 'FileField Paths failed to move file (%o) to (%n).', array(
      '%o' => $file['filepath']['old'],
      '%n' => "{$dest}/{$file['filename']['new']}",
    ), WATCHDOG_ERROR);
    return FALSE;
  }
  $result = db_fetch_object(db_query("SELECT origname FROM {files} WHERE fid = %d", $file['field']['fid']));

  // Set 'origname' and update 'filename'.
  if (empty($result->origname)) {
    db_query("UPDATE {files} SET filename = '%s', filepath = '%s', origname = '%s' WHERE fid = %d", $file['filename']['new'], $file['field']['filepath'], $file['filename']['old'], $file['field']['fid']);
  }
  else {
    db_query("UPDATE {files} SET filename = '%s', filepath = '%s' WHERE fid = %d", $file['filename']['new'], $file['field']['filepath'], $file['field']['fid']);
  }
  return TRUE;
}
function _filefield_paths_strip_path($path) {
  $dirpath = file_directory_path();
  $dirlen = drupal_strlen($dirpath);
  if (drupal_substr($path, 0, $dirlen + 1) == "{$dirpath}/") {
    $path = drupal_substr($path, $dirlen + 1);
  }
  return $path;
}
function _filefield_paths_check_directory(&$directory, $mode = 0, $form_item = NULL) {
  $directory = rtrim($directory, '/\\');

  // error if dir is a file.
  if (is_file($directory)) {
    watchdog('file system', 'check_directory: The path  %directory is a file.', array(
      '%directory' => $directory,
    ), WATCHDOG_ERROR);
    if ($form_item) {
      form_set_error($form_item, t('The directory %directory is a file!', array(
        '%directory' => $directory,
      )));
    }
    return FALSE;
  }

  // create the directory if it is missing.
  if (!is_dir($directory) && $mode & FILE_CREATE_DIRECTORY && !@mkdir($directory, 0775, TRUE)) {
    watchdog('file system', 'The directory %directory does not exist.', array(
      '%directory' => $directory,
    ), WATCHDOG_ERROR);
    if ($form_item) {
      form_set_error($form_item, t('The directory %directory does not exist.', array(
        '%directory' => $directory,
      )));
    }
    return FALSE;
  }

  // Check to see if the directory is writable.
  if (!is_writable($directory) && $mode & FILE_MODIFY_PERMISSIONS && !@chmod($directory, 0775)) {
    watchdog('file system', 'The directory %directory is not writable, because it does not have the correct permissions set.', array(
      '%directory' => $directory,
    ), WATCHDOG_ERROR);
    if ($form_item) {
      form_set_error($form_item, t('The directory %directory is not writable', array(
        '%directory' => $directory,
      )));
    }
    return FALSE;
  }
  if ((file_directory_path() == $directory || file_directory_temp() == $directory) && !is_file("{$directory}/.htaccess")) {
    $htaccess_lines = "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nOptions None\nOptions +FollowSymLinks";
    if (($fp = fopen("{$directory}/.htaccess", 'w')) && fputs($fp, $htaccess_lines)) {
      fclose($fp);
      chmod("{$directory}/.htaccess", 0664);
    }
    else {
      $repl = array(
        '%directory' => $directory,
        '!htaccess' => nl2br(check_plain($htaccess_lines)),
      );
      form_set_error($form_item, t("Security warning: Couldn't write .htaccess file. Please create a .htaccess file in your %directory directory which contains the following lines:<br /><code>!htaccess</code>", $repl));
      watchdog('security', "Security warning: Couldn't write .htaccess file.  Please create a .htaccess file in your %directory directory which contains the following lines:<br /><code>!htaccess</code>", $repl, WATCHDOG_ERROR);
    }
  }
  return TRUE;
}

Functions

Namesort descending Description
filefield_paths_batch_update Set batch process to update FileField Paths.
filefield_paths_cleanup_temp
filefield_paths_content_fieldapi Implements hook_content_fieldapi().
filefield_paths_filefield_paths_process_file Implements hook_filefield_paths_process_file().
filefield_paths_file_move Move file and update its database record.
filefield_paths_form_alter Implements hook_form_alter().
filefield_paths_form_submit Implements hook_form_submit().
filefield_paths_get_fields
filefield_paths_nodeapi Implements hook_nodeapi().
filefield_paths_node_insert Implements hook_node_insert().
filefield_paths_node_presave Implements hook_node_presave().
filefield_paths_node_update Implements hook_node_update().
filefield_paths_process_string Process and cleanup strings.
filefield_paths_theme Implements hook_theme().
filefield_paths_token_list Implements hook_token_list().
filefield_paths_token_values Implements hook_token_values().
theme_filefield_paths_token_help
_filefield_paths_batch_update_process
_filefield_paths_check_directory
_filefield_paths_get_values
_filefield_paths_replace_pattern Run regular expression over all available text-based fields.
_filefield_paths_strip_path
_filefield_paths_text_fields Get all text-based fields attached to node.