file_admin.module in File admin 7
Enhances file administration by adding published, promote, and sticky fields.
File
file_admin.moduleView source
<?php
/**
* @file
* Enhances file administration by adding published, promote, and sticky fields.
*/
/**
* File is not published.
*/
define('FILE_NOT_PUBLISHED', 0);
/**
* File is published.
*/
define('FILE_PUBLISHED', 1);
/**
* File is not promoted.
*/
define('FILE_NOT_PROMOTED', 0);
/**
* File is promoted.
*/
define('FILE_PROMOTED', 1);
/**
* File is not sticky at top of a list.
*/
define('FILE_NOT_STICKY', 0);
/**
* File is sticky at top of a list.
*/
define('FILE_STICKY', 1);
/**
* Implements hook_permission().
*/
function file_admin_permission() {
$perms = array(
'view any unpublished files' => array(
'title' => t('View any unpublished file details'),
'description' => t('For viewing file details, not for downloading files.'),
),
'view own unpublished files' => array(
'title' => t('View own unpublished file details'),
'description' => t('For viewing file details, not for downloading files.'),
),
);
return $perms;
}
/**
* Implements hook_entity_presave().
*
* Set created timestamp and file admin settings when entity is created.
*/
function file_admin_entity_presave($entity, $type) {
if ($type == 'file' && !isset($entity->fid)) {
$entity->created = REQUEST_TIME;
$file_options = variable_get('file_admin_file_options_' . $entity->type, array(
'published' => 'published',
));
foreach (array(
'published',
'promote',
'sticky',
) as $key) {
$entity->{$key} = (int) (isset($file_options[$key]) && $file_options[$key]);
}
}
}
/**
* Implements hook_file_entity_access().
*
* Restrict view access to file entities based on published status.
*/
function file_admin_file_entity_access($op, $file, $account) {
// Deny view access to unpublished files unless the user has "bypass file
// access" permission or has "view own published files" and is the author of
// the file.
if ($op == 'view' && $file->published == FILE_NOT_PUBLISHED && !user_access('view any unpublished files', $account) && !(user_access('view own unpublished files', $account) && $account->uid == $file->uid && $account->uid != 0)) {
return FILE_ENTITY_ACCESS_DENY;
}
return FILE_ENTITY_ACCESS_IGNORE;
}
/**
* Implements hook_form_FORM_ID_alter() for file_entity_admin_file.
*
* Add a published field to the file administration form.
*/
function file_admin_form_file_entity_admin_file_alter(&$form, &$form_state) {
// Only act if we're in a list display mode.
// TODO: find a less awkward way to determine the mode.
if (is_null(arg(3)) && !empty($form['admin']['files']['#options'])) {
$header =& $form['admin']['files']['#header'];
$operations_header = array_pop($header);
$header['published'] = array(
'data' => t('Published'),
'field' => 'f.published',
);
$header['operations'] = $operations_header;
$files = db_query('SELECT fid, published FROM {file_managed} WHERE fid IN (:fids)', array(
':fids' => array_keys($form['admin']['files']['#options']),
))
->fetchAllAssoc('fid');
foreach ($form['admin']['files']['#options'] as $fid => &$option) {
$operations_row = array_pop($option);
$option['published'] = $files[$fid]->published ? t('published') : t('not published');
$option['operations'] = $operations_row;
}
}
}
/**
* Implements hook_form_FORM_ID_alter() for file_entity_edit.
*
* Add file settings defaults.
*/
function file_admin_form_file_entity_file_type_form_alter(&$form, &$form_state) {
$file_type = $form['#file_type']->type;
$form['additional_settings'] = array(
'#type' => 'vertical_tabs',
'#attached' => array(
'js' => array(
drupal_get_path('module', 'file_admin') . '/file_admin.js',
),
),
);
$form['submission'] = array(
'#type' => 'fieldset',
'#title' => t('Submission form settings'),
'#collapsible' => TRUE,
'#group' => 'additional_settings',
);
$form['submission']['help'] = array(
'#type' => 'textarea',
'#title' => t('Explanation or submission guidelines'),
'#default_value' => variable_get('file_admin_help_' . $file_type, ''),
'#description' => t('This text will be displayed at the top of the page when creating or editing files of this type.'),
);
$form['workflow'] = array(
'#type' => 'fieldset',
'#title' => t('Publishing options'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#group' => 'additional_settings',
);
$form['workflow']['file_options'] = array(
'#type' => 'checkboxes',
'#title' => t('Default options'),
'#default_value' => variable_get('file_admin_file_options_' . $file_type, array(
'published' => 'published',
)),
'#options' => array(
'published' => t('Published'),
'promote' => t('Promoted'),
'sticky' => t('Sticky at top of lists'),
),
'#description' => t('Users with the <em>Administer files</em> permission will be able to override these options.'),
);
$form['display'] = array(
'#type' => 'fieldset',
'#title' => t('Display settings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#group' => 'additional_settings',
);
$form['display']['file_submitted'] = array(
'#type' => 'checkbox',
'#title' => t('Display owner and date information.'),
'#default_value' => variable_get('file_submitted_' . $file_type, FALSE),
'#description' => t('Owner username and upload date will be displayed.'),
);
$form['submit']['#weight'] = 10;
$form['#submit'][] = 'file_admin_file_entity_file_type_form_submit';
}
/**
* Submit handler for file_entity_file_type_form.
*/
function file_admin_file_entity_file_type_form_submit($form, &$form_state) {
$file_type = $form['#file_type']->type;
foreach (array(
'help',
'file_options',
) as $variable) {
variable_set('file_admin_' . $variable . '_' . $file_type, $form_state['values'][$variable]);
}
$file_type = $form['#file_type']->type;
variable_set('file_submitted_' . $file_type, $form_state['values']['file_submitted']);
}
/**
* Implements hook_views_api().
*/
function file_admin_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'file_admin') . '/includes',
);
}
/**
* Helper to build the Workflow fieldset.
*
* @see file_admin_form_file_entity_edit_alter()
* @see file_admin_form_file_entity_add_upload_alter()
* @see file_entity_edit()
*/
function _file_admin_add_file_admin_fieldset(&$form, $form_state, $file) {
$file->date = format_date($file->created, 'custom', 'Y-m-d H:i:s O');
if (!isset($form['additional_settings'])) {
$form['additional_settings'] = array(
'#type' => 'vertical_tabs',
'#attached' => array(
'js' => array(
drupal_get_path('module', 'file_admin') . '/file_admin.js',
),
),
);
}
// Basic file information.
// This element is just a value so it is not even sent to the client.
$form['created'] = array(
'#type' => 'value',
'#value' => isset($file->created) ? $file->created : NULL,
);
// In some cases this fieldset will be provided by file_entity.
// @see file_entity_edit().
if (!isset($form['user'])) {
// File user information for administrators.
$form['user'] = array(
'#type' => 'fieldset',
'#access' => user_access('administer files'),
'#title' => t('User information'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#group' => 'additional_settings',
'#attributes' => array(
'class' => array(
'file-form-user',
),
),
'#attached' => array(
'js' => array(
drupal_get_path('module', 'file_entity') . '/file_entity.js',
array(
'type' => 'setting',
'data' => array(
'anonymous' => variable_get('anonymous', t('Anonymous')),
),
),
),
),
'#weight' => 90,
);
$form['user']['name'] = array(
'#type' => 'textfield',
'#title' => t('Associated with'),
'#maxlength' => 60,
'#autocomplete_path' => 'user/autocomplete',
'#default_value' => !empty($file->uid) ? user_load($file->uid)->name : '',
'#weight' => -1,
'#description' => t('Leave blank for %anonymous.', array(
'%anonymous' => variable_get('anonymous', t('Anonymous')),
)),
);
}
$form['user']['date'] = array(
'#type' => 'textfield',
'#title' => t('Posted on'),
'#maxlength' => 25,
'#description' => t('Format: %time. The date format is YYYY-MM-DD and %timezone is the time zone offset from UTC. Leave blank to use the time of form submission.', array(
'%time' => !empty($file->date) ? date_format(date_create($file->date), 'Y-m-d H:i:s O') : format_date($file->created, 'custom', 'Y-m-d H:i:s O'),
'%timezone' => !empty($file->date) ? date_format(date_create($file->date), 'O') : format_date($file->created, 'custom', 'O'),
)),
'#default_value' => !empty($file->date) ? $file->date : '',
);
// File options for administrators.
$form['options'] = array(
'#type' => 'fieldset',
'#access' => user_access('administer files'),
'#title' => t('Workflow'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#group' => 'additional_settings',
'#attributes' => array(
'class' => array(
'file-entity-form-options',
),
),
'#attached' => array(
'js' => array(
drupal_get_path('module', 'file_admin') . '/file_admin.js',
),
),
'#weight' => 95,
);
$form['options']['published'] = array(
'#type' => 'checkbox',
'#title' => t('Published'),
'#default_value' => $file->published,
);
$form['options']['promote'] = array(
'#type' => 'checkbox',
'#title' => t('Promoted'),
'#default_value' => $file->promote,
);
$form['options']['sticky'] = array(
'#type' => 'checkbox',
'#title' => t('Sticky at the top of lists'),
'#default_value' => $file->sticky,
);
if (isset($form['actions']['submit']['#validate'])) {
$form['actions']['submit']['#validate'][] = 'file_admin_file_entity_edit_validate';
}
else {
$form['#validate'][] = 'file_admin_file_entity_edit_validate';
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* @see file_entity_edit()
*/
function file_admin_form_file_entity_edit_alter(&$form, &$form_state) {
$file = file_load($form['fid']['#value']);
if ($help = variable_get('file_admin_help_' . $form['#bundle'], '')) {
$form['#prefix'] = (isset($form['#prefix']) ? $form['#prefix'] : '') . '<p>' . filter_xss_admin($help) . '</p>';
}
_file_admin_add_file_admin_fieldset($form, $form_state, $file);
}
/**
* Implements hook_form_FORM_ID_alter().
*
* @see file_entity_add_upload()
*/
function file_admin_form_file_entity_add_upload_alter(&$form, &$form_state, $form_id) {
if (isset($form['#step']) && $form['#step'] == 4) {
// Default to the settings for the 'image' file type.
$file_admin_image_options = variable_get('file_admin_file_options_image', array(
'published' => 'published',
));
$file = new stdClass();
$file->created = time();
foreach (array(
'published',
'promote',
'sticky',
) as $property) {
$file->{$property} = !empty($file_admin_image_options[$property]);
}
_file_admin_add_file_admin_fieldset($form, $form_state, $file);
}
}
/**
* Validate handler for file_entity_edit form.
*
* Prepare additional fields' data for saving to the file entity. Actual saving
* is handled by file_entity_edit_submit().
*/
function file_admin_file_entity_edit_validate($form, &$form_state) {
// Validate the "posted on" field.
if (!empty($form_state['values']['date']) && strtotime($form_state['values']['date']) === FALSE) {
form_set_error('date', t('You have to specify a valid date.'));
}
$created = !empty($form_state['values']['date']) ? strtotime($form_state['values']['date']) : time();
form_set_value($form['created'], $created, $form_state);
}
/**
* Implement hook_file_operations().
*/
function file_admin_file_operations() {
$operations = array(
'publish' => array(
'label' => t('Publish'),
'callback' => 'file_admin_mass_update',
'callback arguments' => array(
'updates' => array(
'published' => FILE_PUBLISHED,
),
),
),
'unpublish' => array(
'label' => t('Unpublish'),
'callback' => 'file_admin_mass_update',
'callback arguments' => array(
'updates' => array(
'published' => FILE_NOT_PUBLISHED,
),
),
),
'promote' => array(
'label' => t('Promote selected files'),
'callback' => 'file_admin_mass_update',
'callback arguments' => array(
'updates' => array(
'published' => FILE_PUBLISHED,
'promote' => FILE_PROMOTED,
),
),
),
'demote' => array(
'label' => t('Demote selected files'),
'callback' => 'file_admin_mass_update',
'callback arguments' => array(
'updates' => array(
'promote' => FILE_NOT_PROMOTED,
),
),
),
);
return $operations;
}
/**
* Implements hook_action_info().
*/
function file_admin_action_info() {
return array(
'file_admin_publish_action' => array(
'type' => 'file',
'label' => t('Publish file'),
'configurable' => FALSE,
'triggers' => array(
'entity_presave',
),
),
'file_admin_unpublish_action' => array(
'type' => 'file',
'label' => t('Unpublish file'),
'configurable' => FALSE,
'triggers' => array(
'entity_presave',
),
),
);
}
/**
* Sets the published field of a file to 1 (published).
*
* @param file_entity $file_entity
* A file entity object.
* @param array $context
* (optional) Array of additional information about what triggered the action.
* Not used for this action.
*
* @ingroup actions
*/
function file_admin_publish_action($file_entity, $context = array()) {
file_admin_mass_update(array(
'fid' => $file_entity->fid,
), array(
'published' => FILE_PUBLISHED,
));
if (!empty($file_entity->title)) {
$title = $file_entity->title;
}
else {
$title = $file_entity->filename;
}
watchdog('action', 'Set @type %title to published.', array(
'@type' => file_get_type($file_entity),
'%title' => $title,
));
}
/**
* Sets the published field of a file to 0 (unpublished).
*
* @param file_entity $file_entity
* A file entity object.
* @param array $context
* (optional) Array of additional information about what triggered the action.
* Not used for this action.
*
* @ingroup actions
*/
function file_admin_unpublish_action($file_entity, $context = array()) {
file_admin_mass_update(array(
'fid' => $file_entity->fid,
), array(
'published' => FILE_NOT_PUBLISHED,
));
if (!empty($file_entity->title)) {
$title = $file_entity->title;
}
else {
$title = $file_entity->filename;
}
watchdog('action', 'Set @type %title to unpublished.', array(
'@type' => file_get_type($file_entity),
'%title' => $title,
));
}
/**
* Make mass update of files, changing all files in the $files array
* to update them with the field values in $updates.
*
* IMPORTANT NOTE: This function is intended to work when called
* from a form submit handler. Calling it outside of the form submission
* process may not work correctly.
*
* @param array $files
* Array of file fids to update.
* @param array $updates
* Array of key/value pairs with file field names and the
* value to update that field to.
*/
function file_admin_mass_update($files, $updates) {
// We use batch processing to prevent timeout when updating a large number
// of files.
if (count($files) > 10) {
$batch = array(
'operations' => array(
array(
'_file_mass_update_batch_process',
array(
$files,
$updates,
),
),
),
'finished' => '_file_mass_update_batch_finished',
'title' => t('Processing'),
// We use a single multi-pass operation, so the default
// 'Remaining x of y operations' message will be confusing here.
'progress_message' => '',
'error_message' => t('The update has encountered an error.'),
// The operations do not live in the .module file, so we need to
// tell the batch engine which file to load before calling them.
'file' => drupal_get_path('module', 'file_admin') . '/file.admin.inc',
);
batch_set($batch);
}
else {
foreach ($files as $fid) {
_file_mass_update_helper($fid, $updates);
}
drupal_set_message(t('The update has been performed.'));
}
}
/**
* File Mass Update - helper function.
*/
function _file_mass_update_helper($fid, $updates) {
$file = file_load($fid, NULL, TRUE);
// For efficiency manually save the original file before applying any changes.
$file->original = clone $file;
foreach ($updates as $name => $value) {
$file->{$name} = $value;
}
file_save($file);
return $file;
}
/**
* File Mass Update Batch operation
*/
function _file_mass_update_batch_process($files, $updates, &$context) {
if (!isset($context['sandbox']['progress'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['max'] = count($files);
$context['sandbox']['files'] = $files;
}
// Process files by groups of 5.
$count = min(5, count($context['sandbox']['files']));
for ($i = 1; $i <= $count; $i++) {
// For each fid, load the file, reset the values, and save it.
$fid = array_shift($context['sandbox']['files']);
$file = _file_mass_update_helper($fid, $updates);
// Store result for post-processing in the finished callback.
$context['results'][] = l($file->title, 'file/' . $file->fid);
// 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'];
}
}
/**
* File Mass Update Batch 'finished' callback.
*/
function _file_mass_update_batch_finished($success, $results, $operations) {
if ($success) {
drupal_set_message(t('The update has been performed.'));
}
else {
drupal_set_message(t('An error occurred and processing did not complete.'), 'error');
$message = format_plural(count($results), '1 item successfully processed:', '@count items successfully processed:');
$message .= theme('item_list', array(
'items' => $results,
));
drupal_set_message($message);
}
}
Functions
Constants
Name | Description |
---|---|
FILE_NOT_PROMOTED | File is not promoted. |
FILE_NOT_PUBLISHED | File is not published. |
FILE_NOT_STICKY | File is not sticky at top of a list. |
FILE_PROMOTED | File is promoted. |
FILE_PUBLISHED | File is published. |
FILE_STICKY | File is sticky at top of a list. |