0) {
$entity_info = entity_get_info($form['#instance']['entity_type']);
$fields = module_invoke_all('filefield_paths_field_settings');
foreach ($ffp as $field_name => $field_data) {
$active_updating = 0;
$results = db_select('filefield_paths', 'f')
->fields('f')
->condition('type', $field_data['type'])
->condition('field', $field_name)
->execute()
->fetchAllAssoc('type');
if (!empty($results[$field_data['type']])) {
$result = $results[$field_data['type']];
foreach ($fields as &$field) {
$field['settings'] = unserialize($result->{$field['sql']});
}
unset($field);
$active_updating = $result->active_updating;
}
$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;
$field['form'][$keys[$i]]['#element_validate'] = array('token_element_validate');
$field['form'][$keys[$i]]['#token_types'] = array('file', $entity_info['token type']);
}
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', array('@title' => $field['title'])) . ' ' . l(t('Pathauto settings'), 'admin/config/search/path/settings'),
);
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']['token_tree'] = array(
'#type' => 'fieldset',
'#title' => t('Replacement patterns'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#description' => theme('token_tree', array('token_types' => array('file', $entity_info['token type']))),
'#weight' => 10,
);
// Retroactive updates.
$field_data['form_path']['retroactive_update'] = array(
'#type' => 'checkbox',
'#title' => t('Retroactive update'),
'#description' => t('Move and rename previously uploaded files') . '.' .
'
' . t('Warning') . ': ' .
t('This feature should only be used on developmental servers or with extreme caution') . '.',
'#weight' => 11
);
// Active updating.
$field_data['form_path']['active_updating'] = array(
'#type' => 'checkbox',
'#title' => t('Active updating'),
'#default_value' => $active_updating,
'#description' => t('Actively move and rename previously uploaded files as required') . '.' .
'
' . t('Warning') . ': ' .
t('This feature should only be used on developmental servers or with extreme caution') . '.',
'#weight' => 12
);
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 = array(
'type' => $field_data['type'],
'field' => $field_name,
'active_updating' => $form_state['values']["ffp_{$field_name}"]['active_updating'],
);
foreach ($fields as $name => &$field) {
$cols[$field['sql']] = 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 add-on modules.
if (isset($field['data'])) {
foreach ($field['data'] as $key => $value) {
$cols[$field['sql']][$key] = $form_state['values']["ffp_{$field_name}"][$value];
}
}
}
$results = db_select('filefield_paths', 'f')
->fields('f')
->condition('type', $cols['type'])
->condition('field', $cols['field'])
->execute()
->fetchAll();
// Update existing entry.
if (!empty($results)) {
drupal_write_record('filefield_paths', $cols, array('type', 'field'));
}
// Create new entry.
else {
drupal_write_record('filefield_paths', $cols);
}
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($form_state['values']['instance']);
}
}
if ($retroactive_update) {
// Run batch.
batch_process($form_state['redirect']);
}
}
}
/**
* Set batch process to update FileField Paths.
*
* @param $instance
*/
function filefield_paths_batch_update($instance) {
$objects = array();
// Invoke hook_filefield_paths_batch_update().
if (function_exists($function = "{$instance['widget']['module']}_filefield_paths_batch_update")) {
$function($instance, $objects);
}
// Create batch.
$batch = array(
'title' => t('Updating FileField Paths'),
'operations' => array(
array('_filefield_paths_batch_update_process', array($objects, $instance))
),
);
batch_set($batch);
}
function _filefield_paths_batch_update_process($objects, $instance, &$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 = "{$instance['widget']['module']}_filefield_paths_update")) {
$function($oid, $instance);
}
// 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_entity_insert().
*/
function filefield_paths_entity_insert($entity, $type) {
filefield_paths_entity_update($entity, $type);
}
/**
* Implements hook_entity_update().
*/
function filefield_paths_entity_update($entity, $type) {
if (($ffp = filefield_paths_get_fields($entity, $type)) !== FALSE) {
$update = new stdClass;
$update->entity = 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";
$settings = isset($ffp['#settings'][$file['name']]) ? $ffp['#settings'][$file['name']] : NULL;
if (!is_null($settings)) {
$function(($file['new'] || $settings['active_updating']), $file, $settings, $entity, $type, $update);
}
}
}
if ($update->entity == TRUE) {
field_attach_update($type, $entity);
}
// Cleanup temporary paths.
if ($ffp['#settings']) {
foreach ($ffp['#settings'] as $name => $field) {
// Invoke hook_filefield_paths_cleanup().
foreach (module_implements('filefield_paths_cleanup') as $module) {
$function = "{$module}_filefield_paths_cleanup";
$function($ffp, $name);
}
}
}
}
}
/**
* Implements hook_file_presave().
*/
function filefield_paths_file_presave($file) {
// Store original filename in the database.
if (empty($file->origname)) {
$file->origname = $file->filename;
}
}
/**
* Implements hook_field_delete_instance().
*/
function filefield_paths_field_delete_instance($instance) {
db_delete('filefield_paths')
->condition('type', "{$instance['entity_type']}::{$instance['bundle']}")
->condition('field', $instance['field_name'])
->execute();
}
/**
*
*/
function filefield_paths_get_fields(&$entity, $type, $op = NULL) {
$ffp = array();
$entity_info = entity_get_info();
// Invoke hook_filefield_paths_get_fields().
foreach (module_implements('filefield_paths_get_fields') as $module) {
$function = "{$module}_filefield_paths_get_fields";
$function($entity, $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 (array_keys($ffp['#types']) as $name) {
$field_type = isset($entity->{$entity_info[$type]['entity keys']['bundle']}) ? "{$type}::{$entity->{$entity_info[$type]['entity keys']['bundle']}}" : "{$type}::{$type}";
$results = db_select('filefield_paths', 'f')
->fields('f')
->condition('type', $field_type)
->condition('field', $name)
->execute()
->fetchAllAssoc('type');
if (!empty($results[$field_type])) {
$result = $results[$field_type];
foreach ($fields as $field) {
$ffp['#settings'][$name][$field['sql']] = unserialize($result->$field['sql']);
}
$ffp['#settings'][$name]['active_updating'] = $result->active_updating;
}
}
return $ffp;
}
/**
* Run regular expression over all available text-based fields.
*/
function _filefield_paths_replace_path($old, $new, &$entity, &$update) {
// Build regular expression.
$info = parse_url($old);
$info['path'] = !empty($info['path']) ? $info['path'] : '';
$absolute = str_replace("{$info['host']}{$info['path']}", '', file_create_url($old));
$relative = parse_url($absolute, PHP_URL_PATH);
$regex = str_replace('/', '\/', "({$absolute}|{$relative}|{$info['scheme']}://)(styles/.*?/{$info['scheme']}/|)({$info['host']}{$info['path']})");
// Build replacement.
$info = parse_url($new);
$replacement = "\$1\$2{$info['host']}{$info['path']}";
$fields = field_info_fields();
foreach ($fields as $name => $field) {
if ($field['module'] == 'text' && isset($entity->{$field['field_name']}) && is_array($entity->{$field['field_name']})) {
foreach ($entity->{$field['field_name']} as &$language) {
foreach ($language as &$item) {
$item['value'] = preg_replace("/$regex/", $replacement, $item['value']);
}
}
}
}
}
/**
* Process and cleanup strings.
*/
function filefield_paths_process_string($value, $data, $settings = array()) {
$transliterate = module_exists('transliteration') && isset($settings['transliterate']) && $settings['transliterate'];
$pathauto = module_exists('pathauto') && isset($settings['pathauto']) && $settings['pathauto'] == TRUE;
if ($pathauto == TRUE) {
module_load_include('inc', 'pathauto');
}
$paths = explode('/', $value);
foreach ($paths as &$path) {
// Process string tokens.
$path = token_replace($path, $data, array('clear' => TRUE));
// Cleanup with pathauto.
if ($pathauto == TRUE) {
$path_parts = explode('.', $path);
foreach ($path_parts as &$path_part) {
$path_part = pathauto_cleanstring($path_part);
}
$path = implode('.', $path_parts);
}
// Transliterate string.
if ($transliterate == TRUE) {
$path = transliteration_clean_filename($path);
}
}
$value = implode('/', $paths);
// Convert string to lower case.
if (isset($settings['tolower']) && $settings['tolower'] == TRUE) {
$value = drupal_strtolower($value);
}
// Ensure that there are no double-slash sequences due to empty token values.
$value = preg_replace('/\/+/', '/', $value);
return $value;
}