media_browser_plus.module in Media Browser Plus 7
Same filename and directory in other branches
Adds fields to the media browser forms for better UX
File
media_browser_plus.moduleView source
<?php
/**
* @file
* Adds fields to the media browser forms for better UX
*/
/** ***************************************** */
/** INCLUDES */
/** ***************************************** */
// A registry of variable_get defaults.
require_once dirname(__FILE__) . '/includes/media_browser_plus.variables.inc';
/**
* Alter the media browser from to enable new UI
*/
function media_browser_plus_form_media_admin_alter(&$form, &$form_state) {
$path = drupal_get_path('module', 'media_browser_plus');
// Add css for both views.
$form['#attached']['library'][] = array(
'media_browser_plus',
'media_browser_plus',
);
$form['#attached']['library'][] = array(
'media_browser_plus',
'colorbox',
);
// Set base href for javascript requests.
$settings = media_browser_plus_main_view_javascript_settings();
$form['#attached']['js'][] = array(
'type' => 'setting',
'data' => $settings,
);
// Check which mode we are in.
if (isset($form_state['build_info']['args'][0]) && $form_state['build_info']['args'][0] != 'thumbnails') {
return _media_browser_plus_media_admin_list_alter($form, $form_state);
}
// Check access rights.
if (!media_browser_plus_access('media grid view')) {
drupal_access_denied();
return array();
}
// Adding grid view js and css.
$form['#attached']['js'][] = $path . '/js/media_browser_plus.admin.js';
drupal_add_library('system', 'ui.draggable');
drupal_add_library('system', 'ui.droppable');
// Removing options form part.
unset($form['options']);
if (!media_browser_plus_access('media list view') || !media_browser_plus_access('media grid view')) {
unset($form['switch']);
}
$form['admin'] = media_browser_plus_grid_view_form();
$form['media-basket'] = media_browser_plus_media_basket_form();
if (media_access('preview')) {
$form['media-preview'] = media_browser_plus_media_preview_form();
}
return $form;
}
/**
* Enter description here
*
* @param $form
* @param $form_state
*/
function media_browser_plus_media_admin_validate($form, &$form_state) {
// Copy input files to values.
if ($form_state['values']['op'] != 'Download') {
$form_state['values']['files'] = array();
if (!empty($form_state['input']['files'])) {
$form_state['values']['files'] = $form_state['input']['files'];
}
// Call the old validate.
module_load_include('inc', 'media', 'includes/media.admin');
media_admin_validate($form, $form_state);
}
}
/**
* Enter description here
*
* @param $form
* @param $form_state
*/
function media_browser_plus_edit_multiple_redirect($form, &$form_state) {
$fids = implode(' ', array_keys(array_filter($form_state['values']['files'])));
$form_state['redirect'] = array(
'admin/content/media/edit_multiple/' . $fids,
array(
'query' => array(
'destination' => 'admin/content/media/thumbnails',
),
),
);
}
/**
* Enter description here
*
* @param $form
* @param $form_state
*/
function media_browser_plus_delete_multiple_redirect($form, &$form_state) {
$fids = implode(' ', array_keys(array_filter($form_state['values']['files'])));
$form_state['redirect'] = array(
'admin/content/media/delete_multiple/' . $fids,
array(
'query' => array(
'destination' => 'admin/content/media/thumbnails',
),
),
);
}
/**
* Puts all selected media items into a zip archive and sends it as download.
*
* @TODO: check for internet sources etc. Only local files should be parsed.
*
* @param $form
* @param $form_state
*/
function media_browser_plus_download_images_submit($form, &$form_state) {
if (isset($form_state['input']['selected_media']) && media_access('download')) {
$ids = array_keys($form_state['input']['selected_media']);
// only load those
$conditions[] = array(
'property' => array(
'fid',
array(
$ids,
),
'IN',
),
);
$media_entities = media_browser_plus_load_multiple(array(
'conditions' => $conditions,
'apply_filter' => FALSE,
'paging' => FALSE,
));
// Create archive.
apache_setenv('no-gzip', '1');
$name = 'media-download-' . md5(microtime() . uniqid());
$zip_file = '/tmp/' . $name . '.zip';
$zip = new ZipArchive();
$res = $zip
->open($zip_file, ZipArchive::CREATE);
if ($res === TRUE && count($media_entities->results)) {
foreach ($media_entities->results as $media) {
$zip
->addFile(drupal_realpath($media->uri), $media->filename);
}
$zip
->close();
/** OLD
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename=' . $zip_file);
header('Content-Length: ' . filesize($zip_file));
header('Pragma: no-cache');
header('Expires: 0');
*/
header('Cache-Control: public');
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: public');
// header('Content-Description: File Transfer');
// header('Content-type: application/zip');
header('Content-Disposition: attachment; filename=' . $zip_file);
// header('Content-Transfer-Encoding: binary');
header('Content-length: ' . filesize($zip_file));
readfile($zip_file);
unlink($zip_file);
die;
}
else {
drupal_set_message(t('Failed to create download archive'), 'error');
}
}
}
/**
* Alter the media list display.
*
*/
function _media_browser_plus_media_admin_list_alter(&$form, &$form_state) {
global $user;
// Check access rights.
if (!media_browser_plus_access('media list view')) {
drupal_access_denied();
return array();
}
$header = array(
'title' => array(
'data' => t('Title'),
'specifier' => 'filename',
'type' => 'property',
'field' => 'f.filename',
),
'type' => array(
'data' => t('Type'),
'specifier' => 'filemime',
'type' => 'property',
'field' => 'f.filemime',
),
'folder' => array(
'data' => t('Folder'),
'specifier' => array(
'field' => 'field_folder',
'column' => 'tid',
),
'type' => 'field',
),
'size' => array(
'data' => t('Size'),
'specifier' => 'filesize',
'type' => 'property',
'field' => 'f.filesize',
),
'author' => array(
'data' => t('Author'),
'specifier' => 'uid',
'type' => 'property',
'field' => 'u.name',
),
'timestamp' => array(
'data' => t('Updated'),
'specifier' => 'timestamp',
'type' => 'property',
'sort' => 'desc',
'field' => 'f.timestamp',
),
'operations' => array(
'data' => t('Operations'),
),
);
$destination = drupal_get_destination();
$options = array();
$media_entities = media_browser_plus_load_multiple(array(
'conditions' => array(),
'header' => $header,
));
// Gather the data from each media object.
foreach ($media_entities->results as $media) {
// Load folder name.
$folder = '';
if (isset($media->field_folder[LANGUAGE_NONE][0]['tid']) && ($term = taxonomy_term_load($media->field_folder[LANGUAGE_NONE][0]['tid']))) {
$folder = $term->name;
}
// Load user object if media author is not the current user.
if ($media->uid != $user->uid) {
$media_user = user_load($media->uid);
}
else {
$media_user = $user;
}
$options[$media->fid] = array(
'title' => theme('media_link', array(
'file' => $media,
)),
'folder' => $folder,
'type' => check_plain($media->filemime),
'size' => format_size($media->filesize),
'author' => theme('username', array(
'account' => $media_user,
)),
'timestamp' => format_date($media->timestamp, 'short'),
);
$options[$media->fid]['operations'] = l(t('edit'), 'media/' . $media->fid . '/edit', array(
'query' => $destination,
));
}
// Grab old options.
$ops = $form['options']['operation']['#options'];
// Redo the options form.
unset($form['options']);
$form['options'] = array(
'#type' => 'fieldset',
'#title' => t('Operations'),
'#weight' => -10,
'operations' => array(
'#type' => 'container',
'#prefix' => '<div class="container-inline">',
'#suffix' => '</div>',
'operation' => array(
'#type' => 'select',
'#options' => $ops,
'#default_value' => 'delete',
),
'submit' => array(
'#type' => 'submit',
'#value' => t('Submit'),
'#submit' => array(
'media_admin_submit',
),
'#validate' => array(
'media_admin_validate',
),
),
),
'folder' => array(
'#type' => 'container',
'selected_folder' => array(
'#type' => 'select',
'#title' => t('Media Folder*'),
'#required' => FALSE,
'#options' => _media_browser_plus_folder_list(),
),
'submit' => array(
'#type' => 'container',
'#prefix' => '<div class="container-inline">',
'#suffix' => '</div>',
'submit' => array(
'#type' => 'submit',
'#value' => t('Change Folder'),
'#submit' => array(
'media_browser_plus_media_admin_folder_change_submit',
),
'#validate' => array(
'media_admin_validate',
),
),
'notice' => array(
'#type' => 'item',
'#markup' => t('*: change will be applied to ALL selected media files'),
),
),
),
);
$form['admin']['files']['#header'] = $header;
$form['admin']['files']['#options'] = $options;
// Reset pager.
unset($form['admin']['pager']);
$form['admin']['pager'] = array(
'#markup' => _media_browser_plus_pager($media_entities->page, $media_entities->pages),
);
return $form;
}
/**
* Called by the JS fronted (ajax) to change the folder of a media object.
*/
function media_browser_plus_change_folder($form, &$form_state) {
// Parse values.
$folder = (int) str_replace('folder_load_', '', $form_state['input']['folder']);
$media = file_load((int) str_replace('edit-files-', '', $form_state['input']['media']));
// Apply new folder.
if (isset($media->field_folder[LANGUAGE_NONE][0]['tid'])) {
$media->field_folder[LANGUAGE_NONE][0]['tid'] = $folder;
}
else {
$media->field_folder = array(
LANGUAGE_NONE => array(
array(
'tid' => $folder,
),
),
);
}
// Save changes.
media_browser_plus_move_file($folder, $media);
// @fixme Decide: die() or return.
die('');
return $form;
}
/**
* Called by the JS fronted (ajax) to get the media list for a given folder.
*/
function media_browser_plus_thumbnailsJSON() {
if (isset($_GET['folder'])) {
$folder = (int) str_replace('folder_load_', '', $_GET['folder']);
// Create conditions.
$conditions = array();
// Check for filter set by library.
if (isset($_GET['filter'])) {
$filter = drupal_json_decode($_GET['filter']);
// Bugfix - $conditions = $filter;
foreach ($filter as $key => $value) {
// Checking each filter.
$valid = TRUE;
foreach ($value as $type => $params) {
foreach ($params as $param) {
if (is_array($param)) {
if (empty($param)) {
$valid = FALSE;
break;
}
foreach ($param as $media_type) {
if (strlen(trim($media_type)) == 0) {
$valid = FALSE;
break;
}
}
}
else {
if (strlen(trim($param)) == 0) {
$valid = FALSE;
break;
}
}
}
}
if ($valid) {
$conditions[] = $value;
}
}
}
// More conditions.
$conditions[] = array(
'field' => array(
'field_folder',
'tid',
array(
$folder,
),
'IN',
),
);
$order = array(
array(
'property' => array(
'fid',
'DESC',
),
),
);
$media_entities = media_browser_plus_load_multiple(array(
'conditions' => $conditions,
'order' => $order,
));
module_load_include('inc', 'media', 'includes/media.browser');
foreach ($media_entities->results as $media) {
media_browser_build_media_item($media);
}
$output = array(
'media' => array_values($media_entities->results),
'folder_loaded' => 'folder_load_' . $folder,
'overall_count' => $media_entities->overall_count,
);
drupal_json_output($output);
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function media_browser_plus_form_media_add_upload_multiple_alter(&$form, &$form_state) {
// This builds the tags textfield and adds the autocomplete handlers to it.
// The #element_validate may not be necessary because this never triggers
// hook_field_update() or hook_field_insert()
$form['field_tags'] = _media_browser_plus_tag_form();
$form['field_folder'] = _media_browser_plus_folder_form();
// Change the weight of the other form items so they appear in the right order
$form['upload']['#weight'] = 0;
$form['submit']['#weight'] = 2;
// Add an additional form submission callback that fires after the default.
$form['#submit'][] = 'media_browser_plus_submit';
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function media_browser_plus_form_media_import_alter(&$form, &$form_state) {
$form['field_tags'] = _media_browser_plus_tag_form();
$form['field_folder'] = _media_browser_plus_folder_form();
// Change submit.
$form['submit']['#weight'] = 2;
$form['#submit'] = array(
'media_browser_plus_media_import_submit',
);
}
/**
* Changing the media import standard submit to use our own batch process.
*
* @param $form
* @param $form_state
*/
function media_browser_plus_media_import_submit($form, &$form_state) {
if ($form_state['values']['op'] == 'Confirm') {
$files = $form_state['storage']['files'];
$batch = array(
'title' => t('Importing Media'),
'operations' => array(
array(
'media_browser_plus_media_import_batch_import_files',
array(
$files,
$form_state['values'],
),
),
),
'finished' => 'media_browser_plus_media_import_batch_complete',
);
if (!empty($form_state['values']['field_tags'])) {
// Create any new taxonomy terms.
foreach ($form_state['values']['field_tags'] as $i => &$item) {
if ($item['tid'] == 'autocreate') {
$term = (object) $item;
unset($term->tid);
taxonomy_term_save($term);
$item['tid'] = $term->tid;
}
}
}
batch_set($batch);
return;
}
$form_state['rebuild'] = TRUE;
}
/**
* Batch process that only differs in the ability to apply the field values to the items
*
* @param $files
* @param $form_values
* @param $context
*/
function media_browser_plus_media_import_batch_import_files($files, $form_values, &$context) {
// Split up attributes.
// list($files, $form_values) = $attributes;
// Need to repeat a lot of code here just to add the fields :-(
if (!isset($context['sandbox']['files'])) {
// This runs the first time the batch runs.
// This is stupid, but otherwise, I don't think it will work...
$context['results'] = array(
'success' => array(),
'errors' => array(),
);
$context['sandbox']['max'] = count($files);
$context['sandbox']['files'] = $files;
}
$files =& $context['sandbox']['files'];
// Take a cut of files. Let's do 10 at a time.
$length = media_variable_get('import_batch_size', 0);
if ($length > count($files)) {
$length = count($files);
}
$to_process = array_splice($files, 0, $length);
$image_in_message = '';
foreach ($to_process as $file) {
try {
$file_obj = media_parse_to_file($file);
$context['results']['success'][] = $file;
if (!$image_in_message) {
$media = file_load($file_obj->fid);
$image_in_message = field_view_field('file', $media, 'file', 'media_preview');
}
// adding fields here
$media = file_load($file_obj->fid);
$media->field_folder[LANGUAGE_NONE][0] = array(
'tid' => $form_values['field_folder'],
);
$media->field_tags[LANGUAGE_NONE] = $form_values['field_tags'];
media_browser_plus_move_file($form_values['field_folder'], $media);
} catch (Exception $e) {
$context['results']['errors'][] = $file . ' Reason: ' . $e
->getMessage();
}
}
$context['message'] = t('Importing') . theme('item_list', array(
'items' => $to_process,
));
// Just for kicks, show an image we are importing.
$context['message'] .= drupal_render($image_in_message);
$context['finished'] = ($context['sandbox']['max'] - count($files)) / $context['sandbox']['max'];
}
/**
* Same completed batch method as in media.
*
* @param $success
* @param $results
* @param $operations
*/
function media_browser_plus_media_import_batch_complete($success, $results, $operations) {
if ($results['errors']) {
drupal_set_message(filter_xss(theme('item_list', array(
'items' => $results['errors'],
))), 'error');
}
if ($results['success']) {
drupal_set_message(filter_xss(theme('item_list', array(
'items' => $results['success'],
))));
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function media_browser_plus_form_media_internet_add_alter(&$form, &$form_state) {
// Add an additional form submission callback that fires after the default.
media_browser_plus_form_media_add_upload_alter($form, $form_state);
}
/**
* Form element validate handler for taxonomy term autocomplete element.
*
* Because media_browser_plus_form_media_add_upload_multiple_alter() adds a
* tags widget to a form that is not an entity editing form, but it is desired
* for taxonomy_autocomplete_validate() to have access to the settings of the
* field for which this widget is being added, this handler runs before
* taxonomy_autocomplete_validate(), and adds the expected information to
* $form_state, as expected by taxonomy_autocomplete_validate().
*/
function media_browser_plus_prepare_taxonomy_autocomplete_validate(&$element, &$form_state) {
// Causes: Notice: Undefined index: #language in
// media_browser_plus_prepare_taxonomy_autocomplete_validate()
// (line 436 of ...sites/all/modules/media_browser_plus-HEAD/media_browser_plus.module).
// @TODO: Fix
$form_state['field'][$element['#field_name']][$element['#language']]['field'] = field_info_field($element['#field_name']);
// Fixes: undefined index #field_parents in field_widget_field().
if (!isset($element['#field_parents'])) {
$element['#field_parents'] = array();
}
}
/**
* Submit handler for the media browser forms that create new media entities.
*
* Enhances the media creation process by populating field content for the newly
* created entities from user-submitted data and/or data available from a
* remote provider.
*
* @see media_browser_plus_form_media_add_upload_multiple_alter()
* @see media_browser_plus_form_media_internet_add_alter()
*/
function media_browser_plus_submit($form, &$form_state) {
// Grab the fids of the newly created media entities from the redirect query
// string that was created by the form's primary submit handler, and load the
// corresponding entities.
$fids = $form_state['redirect'][1]['query']['fid'];
if (!is_array($fids)) {
$fids = array(
$fids,
);
}
$media_entities = file_load_multiple($fids);
// If tags have been entered, apply them to each new entity.
if (!empty($form_state['values']['field_tags'])) {
// Create any new taxonomy terms.
foreach ($form_state['values']['field_tags'] as $i => &$item) {
if ($item['tid'] == 'autocreate') {
$term = (object) $item;
unset($term->tid);
taxonomy_term_save($term);
$item['tid'] = $term->tid;
}
unset($item);
}
foreach ($media_entities as $media) {
$media->field_tags[LANGUAGE_NONE] = $form_state['values']['field_tags'];
}
}
// Apply folder.
foreach ($media_entities as $media) {
$media->field_folder[LANGUAGE_NONE] = array(
array(
'tid' => $form_state['values']['field_folder'],
),
);
}
// If the new media is from a 3rd party provider, and that provider also
// provides MRSS data about the media, then populate the title and description
// fields from that data.
if (!empty($form_state['values']['embed_code'])) {
$provider = media_internet_get_provider($form_state['values']['embed_code']);
if ($data = _media_browser_plus_metadata($provider)) {
foreach ($data as $field_name => $value) {
$field = field_info_field($field_name);
// Limiting value population only if the field is of type 'text' or
// 'text_long' isn't as extensible as would be ideal, but we need some
// protection against populating a field with incompatible content.
if (isset($field) && in_array($field['type'], array(
'text',
'text_long',
)) && isset($field['bundles']['media'])) {
foreach ($media_entities as $media) {
if (in_array($media->type, $field['bundles']['media']) && !isset($media->{$field_name}[LANGUAGE_NONE][0]['value'])) {
$media->{$field_name}[LANGUAGE_NONE][0]['value'] = $value;
}
}
}
}
}
}
foreach ($media_entities as $media) {
media_browser_plus_move_file($form_state['values']['field_folder'], $media);
}
}
/**
* Form submit handler for the media browser forms that edit media entities.
*
* Changes file's filesystem physical folder
*
* @see media_browser_plus_form_media_edit_alter()
*/
function media_browser_plus_edit_file_submit($form, &$form_state) {
$media = $form_state['file'];
$folder_id = $media->field_folder[LANGUAGE_NONE][0]['tid'];
// Only save it if the folder id is changed
if ($form['field_folder'][LANGUAGE_NONE]['#default_value'][0] != $folder_id) {
media_browser_plus_move_file($folder_id, $media);
}
}
/**
* Helper function to return metadata from a 3rd party media provider.
*
* Support for 3rd party metadata such as YouTube.
*
* @param $provider
* A provider object as returned by media_internet_get_provider().
*
* @return
* An array of media metadata available from the provider, keyed on field
* name.
*
* @see http://video.search.yahoo.com/mrss
* @see media_internet_get_provider()
* @see MediaInternetYouTubeHandler::getMRSS()
*/
function _media_browser_plus_metadata($provider) {
// @todo This is early, experimental code, still subject to much change. For
// now, we assume $provider->getMRSS() returns a SimpleXML element. We'll
// want to change this assumption and have it return an array instead, but
// that requires fixing media_retrieve_xml() to handle XML namespaces
// properly.
$data = array();
if (is_callable(array(
$provider,
'getMRSS',
)) && ($rss = $provider
->getMRSS())) {
// MRSS is an extension of RSS, so the title field is available in the
// default (ATOM) namespace.
$data['media_title'] = (string) $rss->title;
// The MRSS extensions are in their own namespace.
$mrss = $rss
->children('http://search.yahoo.com/mrss/');
$data['media_description'] = (string) $mrss->group->description;
}
$data = array_filter($data, 'strlen');
return $data;
}
/**
* Implements hook_preprocess_media_link().
*/
function media_browser_plus_preprocess_media_link(&$variables) {
// Use the value of the title field, when there is one, as the link text for
// all links that would otherwise default to the filename.
// @todo Solve generically using the 'label' key of hook_entity_indo(). See
// http://drupal.org/node/910396.
$media = file_load($variables['file']->fid);
if (empty($variables['file']->description) && isset($media->media_title[LANGUAGE_NONE][0]['value'])) {
$variables['file']->description = $media->media_title[LANGUAGE_NONE][0]['value'];
}
}
/**
* Implements hook_preprocess_media_thubmnail().
*/
function media_browser_plus_preprocess_media_thumbnail(&$variables) {
// See media_browser_plus_preprocess_media_link(). Same thing here, but for
// the links that appear underneath thumbnail previews.
$media = $variables['element']['#file'];
if (isset($media->media_title[LANGUAGE_NONE][0]['value'])) {
$variables['element']['#name'] = $media->media_title[LANGUAGE_NONE][0]['value'];
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Altering the add file upload form the include folder and tag options
*/
function media_browser_plus_form_media_add_upload_alter(&$form, &$form_state) {
// Alter weight to display new forms in correct order.
$form['file']['#weight'] = -5;
$form['submit']['#weight'] = 5;
$form['field_tags'] = _media_browser_plus_tag_form();
$form['field_folder'] = _media_browser_plus_folder_form();
$form['#submit'][] = 'media_browser_plus_submit';
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Ensure the tagging form is below the folder form part.
*/
function media_browser_plus_form_media_edit_alter(&$form, &$form_state) {
// Setting the weight accordingly.
$form['field_folder']['#weight'] = $form['field_tags']['#weight'] - 1;
$form['actions']['cancel'] = array(
'#type' => 'submit',
'#value' => t('Cancel'),
'#weight' => 20,
'#submit' => array(
'media_browser_plus_edit_cancel',
),
);
$form['actions']['submit']['#submit'][] = 'media_browser_plus_edit_file_submit';
}
/**
* @todo Document what this function does.
*
* @param $form
* @param $form_state
*/
function media_browser_plus_edit_cancel($form, &$form_state) {
$destination = array();
if (isset($_GET['destination'])) {
$destination = drupal_get_destination();
unset($_GET['destination']);
}
if (isset($destination['destination'])) {
$form_state['redirect'] = $destination['destination'];
}
}
/**
* Returns the tag form element.
*/
function _media_browser_plus_tag_form() {
return array(
'#weight' => 1,
'#language' => LANGUAGE_NONE,
'#field_name' => 'field_tags',
'#columns' => array(
'tid',
),
'#title' => t('Tags'),
'#description' => t('Enter a comma-separated list of words to describe your media.'),
'#required' => FALSE,
'#delta' => 0,
'#type' => 'textfield',
'#default_value' => '',
'#autocomplete_path' => 'taxonomy/autocomplete/field_tags',
'#element_validate' => array(
'media_browser_plus_prepare_taxonomy_autocomplete_validate',
'taxonomy_autocomplete_validate',
),
'#size' => 60,
);
}
/**
* Returns a select form item with a selectable media folders.
*/
function _media_browser_plus_folder_form() {
$list = _media_browser_plus_folder_list();
return array(
'#type' => 'select',
'#language' => LANGUAGE_NONE,
'#title' => t('Media Folder'),
'#field_name' => 'field_tags',
'#weigth' => -2,
'#options' => $list,
'#description' => t('Select a folder for the media to be put in'),
);
}
/**
* Implements hook_menu().
*/
function media_browser_plus_menu() {
$items['admin/content/media/change_folder'] = array(
'title' => 'Change Folder',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'media_browser_plus_change_folder',
),
'type' => MENU_CALLBACK,
'access callback' => 'media_access',
'access arguments' => array(
'edit',
),
);
$items['admin/content/media/filter'] = array(
'title' => 'Media Filter',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'media_browser_plus_media_filter',
),
'file' => 'includes/media_browser_plus.pages.inc',
'access callback' => 'media_access',
'access arguments' => array(
'filter',
),
'type' => MENU_LOCAL_ACTION,
'context' => MENU_CONTEXT_INLINE,
);
$items['admin/content/media/thumbnailsJSON'] = array(
'title' => 'Load Media Entities',
'page callback' => 'media_browser_plus_thumbnailsJSON',
'access callback' => 'media_access',
'access arguments' => array(
'preview',
),
);
$items['admin/config/media/media_browser_plus_settings'] = array(
'title' => 'Media Browser Plus Settings',
'description' => 'Change the behaviour and layout of the media browser plus UI',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'media_browser_plus_media_settings',
),
'access callback' => 'media_access',
'access arguments' => array(
'administer',
),
);
$items['admin/content/media/edit_multiple/%'] = array(
'title' => 'Edit Media Items',
'page callback' => 'media_browser_plus_edit_multiple_form',
'page arguments' => array(
4,
),
'file' => 'includes/media_browser_plus.pages.inc',
'access callback' => 'media_access',
'access arguments' => array(
'edit',
),
);
$items['admin/content/media/delete_multiple/%'] = array(
'title' => 'Delete Media Items',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'media_browser_plus_delete_multiple_form',
4,
),
'file' => 'includes/media_browser_plus.pages.inc',
'access callback' => 'media_access',
'access arguments' => array(
'edit',
),
);
// folder management disabled until menu bug has been fixed
$items['admin/content/media/folder_list'] = array(
'title' => 'Administer folders',
'description' => 'Manage your media folders',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'media_browser_plus_folder_list',
),
'file' => 'includes/media_browser_plus.folders.inc',
'access callback' => 'media_browser_plus_access',
'access arguments' => array(
'administer media folders',
),
);
$items['admin/content/media/add_folder'] = array(
'title' => 'Add Folder',
'description' => 'Add a new media folder',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'media_browser_plus_folder_add',
),
'access callback' => 'media_browser_plus_access',
'access arguments' => array(
'administer media folders',
),
'file' => 'includes/media_browser_plus.folders.inc',
);
$items['admin/content/media/folder/%media_browser_plus_folder/edit'] = array(
'title' => 'Edit Folder',
'description' => 'Edit media folder',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'media_browser_plus_folder_edit',
4,
),
'access callback' => 'media_browser_plus_access',
'access arguments' => array(
'administer media folders',
),
'file' => 'includes/media_browser_plus.folders.inc',
);
$items['admin/content/media/folder/%media_browser_plus_folder/delete'] = array(
'title' => 'Delete Folder',
'description' => 'Delete media folder',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'media_browser_plus_folder_delete',
4,
),
'access callback' => 'media_browser_plus_access',
'access arguments' => array(
'administer media folders',
),
'file' => 'includes/media_browser_plus.folders.inc',
);
$items['admin/content/media/%file/preview'] = array(
'title' => 'Preview Media',
'description' => 'Preview Media Item',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'media_browser_plus_media_preview',
3,
),
'access callback' => 'media_access',
'access arguments' => array(
'preview',
),
'file' => 'includes/media_browser_plus.pages.inc',
);
return $items;
}
/**
* Implements hook_menu_alter().
*
* @param $items
*/
function media_browser_plus_menu_alter(&$items) {
$items['admin/content/media']['access arguments'] = array(
'access media backend',
);
$items['admin/content/media']['access callback'] = array(
'media_browser_plus_access',
);
}
/**
* Implements hook_permission().
*/
function media_browser_plus_permission() {
return array(
'media grid view' => array(
'title' => t('Grid View'),
'description' => t('Allow users to use the grid view.'),
),
'media list view' => array(
'title' => t('List View'),
'description' => t('Allow users to use the list view.'),
),
'access media backend' => array(
'title' => t('Access media backend'),
'description' => t('Allow user to access the media backend according to their privileges.'),
),
'upload media' => array(
'title' => t('Upload media'),
'description' => t('Allow user to add media.'),
),
'download media' => array(
'title' => t('Download Media'),
'description' => t('Allows the user to download the original media items.'),
),
'filter media' => array(
'title' => t('Filter Media'),
'description' => t('Allows the user to filter the displayed media in the backend.'),
),
'administer media folders' => array(
'title' => t('Administer Media Folders'),
// @TODO better description
'description' => t('Allows the user to add, edite, delete and resort media folders.'),
),
'preview media' => array(
'title' => t('Preview media'),
// @TODO better description
'description' => t('Allows the user to view a configurable preview of the original media item.'),
),
);
}
/**
* Implements hook_library().
*/
function media_browser_plus_library() {
$library_path = variable_get('media_browser_plus_library_path', 'sites/all/libraries');
$stylesheet = variable_get('media_browser_plus_stylesheet', 'example1');
$libraries['colorbox'] = array(
'title' => 'Colorbox',
'website' => 'http://colorpowered.com/colorbox/',
'version' => '1.3.9',
'js' => array(
$library_path . '/colorbox/jquery.colorbox-min.js' => array(),
),
'css' => array(
$library_path . '/colorbox/' . $stylesheet . '/colorbox.css' => array(
'type' => 'file',
'media' => 'screen',
),
),
);
$path = drupal_get_path('module', 'media_browser_plus');
$libraries['media_browser_plus'] = array(
'title' => 'Media Browser Plus',
'version' => '1',
'js' => array(
$path . '/js/media_browser_plus.admin.menu.js' => array(),
),
'css' => array(
$path . '/css/media_browser_plus.admin.css' => array(
'type' => 'file',
'media' => 'screen',
),
$path . '/css/colorbox.css' => array(
'type' => 'file',
'media' => 'screen',
),
),
);
return $libraries;
}
/**
* Checks if the user has the permission to download a file.
*
* @param $field
* @param $entity_type
* @param $entity
*/
function media_browser_plus_file_download_access($field, $entity_type, $entity) {
// Only check against media entities.
if ($entity_type == 'file') {
// Check for media admin AND return true if found.
return media_browser_plus_media_access($entity);
}
}
/**
* Checks access to a given media entity.
*
* @param $media_entity
*/
function media_browser_plus_media_access($media_entity) {
if (media_browser_plus_access('administer media')) {
return TRUE;
}
// Start with ACCESS_ALLOW - by default media items are fully accessible.
$access = MEDIA_ENTITY_ACCESS_ALLOW;
// Collect all modules implementing hook_media_entity_access.
foreach (module_implements('media_entity_access') as $module) {
// and invoke the hook
$return = module_invoke($module, 'media_entity_access', $media_entity);
// If no ALLOW or DENY was returned we assume IGNORE and check the next.
if ($return != MEDIA_ENTITY_ACCESS_ALLOW && $return != MEDIA_ENTITY_ACCESS_DENY) {
continue;
}
// If we have a DENY we can return a complete false here.
if ($return === MEDIA_ENTITY_ACCESS_DENY) {
return FALSE;
}
// Otherwise it is an ALLOW and we save it.
$access = MEDIA_ENTITY_ACCESS_ALLOW;
}
// Check if we had one allow.
return $access === MEDIA_ENTITY_ACCESS_ALLOW;
}
/**
* Revokes the general 'view media' == 'download media' access rule.
*
* @param $grants
* @param $field
* @param $entity_type
* @param $entity
*/
function media_browser_plus_file_download_access_alter(&$grants, $field, $entity_type, $entity = NULL) {
if ($entity_type == 'file') {
unset($grants['file']);
}
}
/**
* Implements hook_media_operations().
*/
function media_browser_plus_media_operations() {
return array(
'edit_multiple' => array(
'label' => t('Edit'),
'callback' => NULL,
'redirect' => 'admin/content/media/edit_multiple/%fids',
),
);
}
/**
* Manages access for media browser plus actions.
*
* @param $op
*/
function media_browser_plus_access($op) {
return user_access('administer media') || user_access($op);
}
/**
* Implements of hook_load().
*
* Used to load media folders.
*/
function media_browser_plus_folder_load($id) {
return taxonomy_term_load($id);
}
/**
* Creates the folder media tree.
*/
function _media_browser_plus_folder_hierarchy_list($list) {
if (!isset($list['parents']) || !isset($list['children'])) {
return;
}
if (count($list['parents']) == 0) {
return t('No folders created yet');
}
else {
if (_media_browser_plus_has_unsorted_media()) {
$all_folders = array();
$all_folders[0] = new stdClass();
$all_folders[0]->name = t('Unsorted');
$all_folders[0]->tid = 0;
$list['parents'] = array_merge($all_folders, $list['parents']);
}
return _media_browser_plus_folder_hierarchy_list_helper($list['parents'], $list['children']);
}
}
/**
* @todo Document what this function does.
*
* @param $parents
* @param $children
* @param $hide
*/
function _media_browser_plus_folder_hierarchy_list_helper($parents, &$children, $hide = FALSE) {
$path = base_path() . drupal_get_path('module', 'media_browser_plus');
$buffer = '<ul' . ($hide ? ' class="hidden"' : '') . '>' . "\n";
foreach ($parents as $item) {
$has_children = isset($children[$item->tid]);
$has_media = _media_browser_plus_folder_empty($item->tid) || $item->tid == 0;
$buffer .= '<li class="media_folder';
if ($has_children) {
$buffer .= ' parent">';
$buffer .= '<div class="folder';
$buffer .= $has_media ? '' : ' emptyParent';
$buffer .= ' folder-children-toggle">' . '<img src="' . $path . '/images/pixel.gif" border="0" alt="">' . '</div> ';
$buffer .= '<div id="folder_load_' . $item->tid . '" class="folder_load';
$buffer .= $has_media ? '' : ' emptyFolder';
$buffer .= '">' . $item->name . '</div>' . "\n";
$buffer .= _media_browser_plus_folder_hierarchy_list_helper($children[$item->tid], $children, TRUE);
$buffer .= '</li>' . "\n";
}
else {
$buffer .= '">';
$buffer .= '<div class="folder';
$buffer .= $has_media ? '' : ' empty';
$buffer .= ' ">' . '<img src="' . $path . '/images/pixel.gif" border="0" alt="">' . '</div> ';
$buffer .= '<div id="folder_load_' . $item->tid . '" class="folder_load';
$buffer .= $has_media ? '' : ' emptyFolder';
$buffer .= '">' . $item->name . '</div></li>' . "\n";
}
}
$buffer .= '</ul>' . "\n";
return $buffer;
}
/**
* @todo Document what this function does.
*
* helper function
*/
function _media_browser_plus_create_relationship_list($categories) {
$return = array();
$parents = array();
$children = array();
foreach ($categories as $key => $value) {
// root node
if ($value->parents[0] == 0) {
// create parent entry
$parents[$value->tid] = $value;
continue;
}
else {
// create child entry
$children[$value->parents[0]][$value->tid] = $value;
continue;
}
}
// if no root parents
if (!count($parents) && count($children)) {
foreach ($children as $pid => $parents_children) {
if (!isset($parents[$pid])) {
// move child into parent array keeping indexes
foreach ($children[$pid] as $id => $item) {
$parents[$id] = $item;
}
unset($children[$pid]);
}
}
}
$return['parents'] = $parents;
$return['children'] = $children;
return $return;
}
/**
* Checks for unsorted (i.e. media not in folders) media.
*/
function _media_browser_plus_has_unsorted_media() {
// loading media
$entity_controller = entity_get_controller('file');
$media_entities = $entity_controller
->load(NULL, array(), 0, 100);
foreach ($media_entities as $media) {
if (!isset($media->field_folder[LANGUAGE_NONE][0]['tid'])) {
return TRUE;
}
}
return FALSE;
}
/**
* @todo Document what this function does.
*
* @param string $prefix_padding
*/
function _media_browser_plus_folder_list($prefix_padding = '-') {
$vocabulary = taxonomy_vocabulary_machine_name_load('media_folders');
$folders = taxonomy_get_tree($vocabulary->vid);
$folders = _media_browser_plus_filter_folder_access($folders);
// Fill list with padded folders.
$list = array();
foreach ($folders as $folder) {
$pad = $folder->depth * strlen($prefix_padding) + strlen($folder->name);
$list[$folder->tid] = str_pad($folder->name, $pad, $prefix_padding, STR_PAD_LEFT);
}
return $list;
}
/**
* Changes the folder of the submitted media items.
*/
function media_browser_plus_media_admin_folder_change_submit(&$form, &$form_state) {
// Get IDs.
$fids = array_keys(array_filter($form_state['values']['files']));
$folder = (int) $form_state['values']['selected_folder'];
$media_entities = file_load_multiple($fids);
// Apply folder.
foreach ($media_entities as $media) {
if (isset($media->field_folder[LANGUAGE_NONE][0]['tid'])) {
$media->field_folder[LANGUAGE_NONE][0]['tid'] = $folder;
}
else {
$media->field_folder = array(
LANGUAGE_NONE => array(
array(
'tid' => $folder,
),
),
);
}
media_browser_plus_move_file($folder, $media);
}
drupal_set_message(t('Folder changes applied successfully'));
}
/**
* Loads media entities and allows filtering, sorting and paging.
*
* @param $variables holds an array with the following optional parameters
* $ids
* one dimensional array of entity_ids
* $conditions
* multidemsional array build like this:
* array(
* array('entity' => array('comlumn', 'value', 'condition')),
* array('property' => array('comlumn', 'value', 'condition')),
* array('field' => array('field_name', 'comlumn', 'value', 'condition')),
* )
* $order
* multidemsional array build like this:
* array(array('entity' => array('comlumn', 'direction')),
* array('property' => array('comlumn', 'direction')),
* array('field' => array('comlumn', 'direction')))
* $header
* table header used for sorting
* $per_page
* items per page
* @param array $paging
* enables/disables paging - default is paging on
*/
function media_browser_plus_load_multiple($variables) {
// Set up default parameter.
$params = array(
'ids' => array(),
'conditions' => array(),
'order' => array(),
'header' => array(),
'page' => -1,
'per_page' => variable_get('media_media_per_page'),
'paging' => TRUE,
'ids_only' => FALSE,
'count_only' => FALSE,
'apply_filter' => TRUE,
);
// Override defaults.
// @todo Is this loop really necessary. Something like
// $params = $variables + $params; should work too, right?
foreach ($variables as $key => $value) {
if (isset($params[$key])) {
$params[$key] =& $variables[$key];
}
}
if ($params['apply_filter'] && isset($_SESSION['media-filter'])) {
if (strlen($_SESSION['media-filter']['filename'])) {
$params['conditions'][] = array(
'property' => array(
'filename',
'%' . $_SESSION['media-filter']['filename'] . '%',
'LIKE',
),
);
}
if (count($_SESSION['media-filter']['type'])) {
$params['conditions'][] = array(
'property' => array(
'type',
explode(',', $_SESSION['media-filter']['type']),
'IN',
),
);
}
if (count($_SESSION['media-filter']['field_folder'])) {
$params['conditions'][] = array(
'field' => array(
'field_folder',
'tid',
$_SESSION['media-filter']['field_folder'],
'IN',
),
);
}
if (count($_SESSION['media-filter']['field_tags'])) {
foreach ($_SESSION['media-filter']['field_tags'] as $tag_id) {
$params['conditions'][] = array(
'field' => array(
'field_tags',
'tid',
$tag_id,
'=',
),
);
}
}
}
// Allow other modules to add/alter conditions.
foreach (module_implements('media_access_conditions') as $module) {
$params['conditions'] = array_merge(module_invoke($module, 'media_access_conditions'), $params['conditions']);
}
$query = new EntityFieldQuery();
// Set entity type to media.
$query
->entityCondition('entity_type', 'file');
// Parse ids if any have been passed.
if (count($params['ids'])) {
$query
->entityCondition('entity_id', $params['ids'], 'IN');
}
// Check for table header.
if (count($params['header'])) {
$query
->tableSort($params['header']);
}
// Parse conditions.
foreach ($params['conditions'] as $condition) {
// Look what type we have.
$condition_keys = array_keys($condition);
switch (array_pop($condition_keys)) {
case 'entity':
$query
->entityCondition($condition['entity'][0], $condition['entity'][1], $condition['entity'][2]);
break;
case 'property':
$query
->propertyCondition($condition['property'][0], $condition['property'][1], $condition['property'][2]);
break;
case 'field':
$query
->fieldCondition($condition['field'][0], $condition['field'][1], $condition['field'][2], $condition['field'][3]);
break;
}
}
// Parse order array.
foreach ($params['order'] as $condition) {
// Look what type we have.
$condition_keys = array_keys($condition);
switch (array_pop($condition_keys)) {
case 'entity':
$query
->entityOrderBy($condition['entity'][0], $condition['entity'][1]);
break;
case 'property':
$query
->propertyOrderBy($condition['property'][0], $condition['property'][1]);
break;
case 'field':
$query
->fieldOrderBy($condition['field'][0], $condition['field'][1], $condition['field'][2]);
break;
}
}
// Prepare result object.
$res_object = new stdClass();
if ($params['paging'] && !$params['count_only']) {
// Doing a seperate count query here, because including the internal pager
// doesn't work but seems the only way to get a total result count.
$count = clone $query;
$count
->pager();
$count
->execute();
$res_object->overall_count = $count->pager['total'];
// Using range here, because as said above the internal pager seems to be
// bugged.
$page = $params['page'];
if ($page == -1) {
$page = isset($_REQUEST['page']) ? $_REQUEST['page'] : 0;
}
$query
->range($page * $params['per_page'], $params['per_page']);
// Adding the addition result fields.
$res_object->page = $page;
$res_object->pages = ceil($res_object->overall_count / variable_get('media_media_per_page'));
$res_object->per_page = $params['per_page'];
}
// Count only query.
if ($params['count_only']) {
$query
->pager();
$query
->execute();
return $query->pager['total'];
}
$res_object->results = array();
// Execute query and load results.
$result = $query
->execute();
if (!empty($result['file'])) {
$res_object->results = $params['ids_only'] ? array_keys($result['file']) : entity_load('file', array_keys($result['file']));
}
return $res_object;
}
/**
* Looks if a filter is active and filters the folders accordingly.
*
* @param array $folders
*/
function _media_browser_plus_filter_folders($folders) {
// No filter active, return unchanged $folders array.
$filtered_folders = $folders;
if (isset($_SESSION['media-filter'])) {
$folder_filtered = array();
// Look through the tree and add elements that match filter.
foreach ($folders as $item) {
if (in_array($item->tid, $_SESSION['media-filter']['field_folder'])) {
$folder_filtered[] = $item;
}
}
$filtered_folders = $folder_filtered;
}
$filtered_folders = _media_browser_plus_filter_folder_access($filtered_folders);
return $filtered_folders;
}
/**
* @todo Document what this function does.
*
* @param $folders
*/
function _media_browser_plus_filter_folder_access($folders) {
$temp_folders = $folders;
$filtered_folders = array();
foreach ($temp_folders as $item) {
$access = TRUE;
foreach (module_implements('media_folder_access') as $module) {
$access = module_invoke($module, 'media_folder_access', $item);
if ($access === FALSE) {
break;
}
else {
$access = TRUE;
}
}
if ($access) {
$filtered_folders[] = $item;
}
}
return $filtered_folders;
}
/**
* @todo Document what this function does.
*
* @param $page
* @param $pages
*/
function _media_browser_plus_pager($page, $pages) {
// Get url for paging link.
$destination = drupal_get_destination();
$link = base_path() . '?q=admin/content/media/list';
$sort = isset($_GET['sort']) ? '&sort=' . check_plain($_GET['sort']) : '';
$order = isset($_GET['order']) ? '&order=' . check_plain($_GET['order']) : '';
$url = $link . $sort . $order;
// Create paging div inside buffer.
$output = '<div id="media_paging_table" align="center">';
// Calculate paging.
$start = max(0, $page - ceil(variable_get('media_page_items_per_page') / 2));
$end = min($pages, $start + variable_get('media_page_items_per_page'));
if ($start > 0) {
$output .= _media_browser_plus_pager_add_page_item($url, $start - 1, $page, '...');
}
// Create numbers.
for ($i = $start; $i < $end; $i++) {
$output .= _media_browser_plus_pager_add_page_item($url, $i, $page, $i + 1);
}
if ($pages > $i) {
$output .= _media_browser_plus_pager_add_page_item($url, $i, $page, '...');
}
return $output . '</div>';
}
/**
* @todo Document what this function does.
*
* @param $url
* @param $page
* @param $title
*/
function _media_browser_plus_pager_add_page_item($url, $page, $current_page, $title) {
$page_item = '<a class="media_paging_page';
if ($page == $current_page) {
$page_item .= ' active_page';
}
$page_item .= '" href="' . $url . '&page=' . $page . '">' . $title . '</a>';
return $page_item;
}
/**
* Creates the media browser plus settings form.
*
* @param $form
* @param $form_state
*/
function media_browser_plus_media_settings($form, &$form_state = array()) {
$form = array(
'media_per_page' => array(
'#type' => 'textfield',
'#title' => 'Media Items per page',
'#description' => t('Insert a number higher than one for the amount of media items displayed per page.'),
'#default_value' => variable_get('media_media_per_page'),
'#maxlength' => 4,
'#required' => TRUE,
),
'grid_window_height' => array(
'#type' => 'textfield',
'#title' => 'Grind Window Height',
'#default_value' => variable_get('media_grid_window_height'),
'#description' => t('Set a maximum height of pixels for the media grid view.'),
'#maxlength' => 4,
'#required' => TRUE,
),
'page_items_per_page' => array(
'#type' => 'textfield',
'#title' => 'Page Items per page',
'#default_value' => variable_get('media_page_items_per_page'),
'#description' => t('Set how many page items you want in the paging navigation of each page.'),
'#maxlength' => 4,
'#required' => TRUE,
),
'max_filesize' => array(
'#type' => 'textfield',
'#title' => 'Upload Maximum Filesize',
'#default_value' => media_variable_get('max_filesize'),
'#description' => t('Standard unit is MB and therefore can be left out. Otherwise use "NUMBER UNIT"'),
'#maxlength' => 20,
'#required' => TRUE,
),
'root_folder' => array(
'#type' => 'textfield',
'#title' => 'Media Root folder',
'#default_value' => variable_get('media_root_folder', 'media'),
'#description' => t('The root folder of uploaded images.Dont use start or end slashes. eg "media/images"'),
'#required' => TRUE,
),
);
$form['actions'] = array(
'#type' => 'actions',
);
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save Changes'),
);
return $form;
}
/**
* Saves the entered settings.
*
* @param $form
* @param $form_state
*/
function media_browser_plus_media_settings_submit($form, &$form_state) {
$scheme = variable_get('file_default_scheme', 'public') . '://';
// Get current media root folder.
$old_root = variable_get('media_root_folder');
// And set the new.
$new_root = trim($form_state['values']['root_folder'], '/');
// Change settings.
variable_set('media_media_per_page', (int) $form_state['values']['media_per_page']);
variable_set('media_grid_window_height', (int) $form_state['values']['grid_window_height']);
variable_set('media_page_items_per_page', (int) $form_state['values']['page_items_per_page']);
media_variable_set('max_filesize', trim($form_state['values']['max_filesize']));
// Move the files to the new root folder if its changed.
if ($old_root != $new_root) {
variable_set('media_root_folder', $new_root);
$source = $scheme . $old_root;
$destination = $scheme . $new_root;
media_browser_plus_move_physical_folder($source, $destination);
}
// Notify user.
drupal_set_message(t('Media Browser Plus Settings changed successfully'));
// Go back to media overview.
$form_state['redirect'] = array(
'admin/config',
);
}
/**
* Validates the settings.
*
* @param unknown_type $form
* @param unknown_type $form_state
*/
function media_browser_plus_media_settings_validate($form, &$form_state) {
// Validate settings.
$value = (int) $form_state['values']['media_per_page'];
if ($value <= 0) {
form_set_error('Media Settings', t('Illegal value for "Media Items per page"'));
}
$value = (int) $form_state['values']['grid_window_height'];
if ($value <= 100) {
form_set_error('Media Settings', t('Illegal value for "Grind Window Height"'));
}
$value = (int) $form_state['values']['page_items_per_page'];
if ($value <= 2) {
form_set_error('Media Settings', t('Illegal value for "Page Items per page"'));
}
$value = parse_size(trim($form_state['values']['max_filesize']));
if ($value === 0) {
form_set_error('Media Settings', t('Illegal value for "Upload Maximum Filesize"'));
}
}
/**
* Implements hook_field_attach_presave().
*
* Makes sure all media are in a folder.
*/
function media_browser_plus_field_attach_presave($entity_type, $entity) {
if ($entity_type != 'file') {
return;
}
// Look for folder and set default if none found
// $media->field_folder[LANGUAGE_NONE] = array(array('tid' => $form_state['values']['field_folder']));
if (!isset($entity->field_folder) || !isset($entity->field_folder[LANGUAGE_NONE]) || !count($entity->field_folder[LANGUAGE_NONE]) || !isset($entity->field_folder[LANGUAGE_NONE][0]['tid']) || (int) $entity->field_folder[LANGUAGE_NONE][0]['tid'] == 0) {
// sSt default folder is no folder or incorrect value.
$root = media_browser_plus_get_media_root_folder();
$entity->field_folder = array();
$entity->field_folder[LANGUAGE_NONE] = array(
array(
'tid' => $root->tid,
),
);
}
}
/**
* Check if a given folder has media in it (does include current filter)
*
* @param int $folder_id
*/
function _media_browser_plus_folder_empty($folder_id) {
// Save paging values.
$gp = isset($_GET['page']) ? $_GET['page'] : NULL;
$pp = isset($_POST['page']) ? $_POST['page'] : NULL;
// Set media condition.
$condition = array(
array(
'field' => array(
'field_folder',
'tid',
array(
$folder_id,
),
'IN',
),
),
);
$variables = array(
'conditions' => $condition,
'per_page' => 1,
'ids_only' => TRUE,
);
$media = media_browser_plus_load_multiple($variables);
// Restore paging values if necessary.
if ($gp) {
$_GET['page'] = $gp;
}
if ($pp) {
$_POST['page'] = $pp;
}
// Check if media has been found in the folder.
return $media->overall_count > 0;
}
/**
* @todo Document what this funciont does.
*
* @param string $tags
* @param boolean $tids_only
* @param boolean $auto_create
* @return array
*/
function media_browser_plus_load_tag_terms($tags, $tids_only = TRUE, $auto_create = FALSE) {
$vocabulary = taxonomy_vocabulary_machine_name_load('tags');
$select = $tids_only ? 'tid, name' : '*';
$all_tags = array();
$found_tags = array();
$found_terms = array();
$terms = explode(',', $tags);
foreach ($terms as $tag) {
// Check if tag exists.
// @todo Would an EntityFieldQuery be appropriate?
// http://drupal.org/node/916776
$results = db_query('SELECT ' . $select . ' FROM {taxonomy_term_data} ttd WHERE ttd.name = :name AND ttd.vid = :vocabulary', array(
'name' => check_plain(trim($tag)),
'vocabulary' => $vocabulary->vid,
));
foreach ($results as $result) {
$term = taxonomy_term_load($result->tid);
if ($tids_only) {
$found_terms[] = array(
'tid' => $term->tid,
);
}
else {
$found_terms[] = get_object_vars($term);
}
$found_tags[] = trim($tag);
}
$all_tags[] = trim($tag);
}
if ($auto_create) {
foreach (array_diff($all_tags, $found_tags) as $id => $tag) {
$term = new stdClass();
$term->name = $tag;
$term->vid = $vocabulary->vid;
if (strlen(trim($term->name))) {
taxonomy_term_save($term);
if ($tids_only) {
$found_terms[] = array(
'tid' => $term->tid,
);
}
else {
$found_terms[] = get_object_vars($term);
}
}
}
}
return $found_terms;
}
/**
* Loads and (if $autocreate is set) creates the default media folder object.
*/
function media_browser_plus_get_media_root_folder($autocreate = FALSE) {
$vocabulary = taxonomy_vocabulary_machine_name_load('media_folders');
if ($vocabulary) {
// @todo Would an EntityFieldQuery be appropriate?
// http://drupal.org/node/916776
$results = db_query('SELECT * FROM {taxonomy_term_data} ttd WHERE ttd.name = :name AND ttd.vid = :vocabulary', array(
'name' => 'Media Root',
'vocabulary' => $vocabulary->vid,
));
$term = NULL;
foreach ($results as $result) {
$term_id = $result->tid;
}
if (!isset($term_id) && $autocreate) {
$media_root_term = new stdClass();
$media_root_term->name = 'Media Root';
$media_root_term->description = 'default media folder';
$media_root_term->vid = $vocabulary->vid;
$media_root_term->weight = '-10';
// Save (default folder) term.
taxonomy_term_save($media_root_term);
// @todo Would an EntityFieldQuery be appropriate?
// http://drupal.org/node/916776
$results = db_query('SELECT * FROM {taxonomy_term_data} ttd WHERE ttd.name = :name AND ttd.vid = :vocabulary', array(
'name' => 'Media Root',
'vocabulary' => $vocabulary->vid,
));
foreach ($results as $result) {
$term_id = $result->tid;
}
}
if ($term_id) {
return media_browser_plus_folder_load($term_id);
}
}
}
/**
* Implements hook_media_browser_plugin_info().
*/
function media_browser_plus_media_browser_plugin_info() {
$plugins = array();
$plugins['library_plus'] = array(
'#weight' => 10,
'#title' => t('Library Plus'),
);
return $plugins;
}
/**
* Implements hook_media_browser_plugin_view().
*
* @param $plugin_name
* @param $params
*/
function media_browser_plus_media_browser_plugin_view($plugin_name, $params) {
$types = isset($params['types']) ? $params['types'] : array();
$multiselect = isset($params['multiselect']) ? $params['multiselect'] : FALSE;
// Get plugin form.
$upload_form = drupal_get_form('media_browser_plus_library_browser', $multiselect, $types);
return array(
'#title' => t('Library Plus'),
'form' => array(
$upload_form,
),
);
}
/**
* Remove the old Library for the media browser popup.
*
* @param $form
* @param $form_state
*/
function media_browser_plus_media_browser_plugins_alter(&$form, &$form_state) {
// @TODO: find a better way to keep the library_plus from popping up only when
// the old library would without editing media module if possible
if (!isset($form['library'])) {
unset($form['library_plus']);
}
// remove old library
if (isset($form['library'])) {
unset($form['library']);
}
}
/**
* Creates the Extended Library for the media browser popup.
*
* @param $form
* @param $form_state
* @param $multiselect
* @param $types
*/
function media_browser_plus_library_browser($form, &$form_state, $multiselect, $types) {
$path = drupal_get_path('module', 'media_browser_plus');
// Assemble library from grid view.
$form['#attached']['library'][] = array(
'media_browser_plus',
'media_browser_plus',
);
$form['#attached']['library'][] = array(
'media_browser_plus',
'colorbox',
);
// Set base href for javascript requests.
$settings = media_browser_plus_main_view_javascript_settings();
$settings['media_browser_plus']['multiselect'] = $multiselect;
$settings['media_browser_plus']['folder_dnd_enabled'] = FALSE;
// Setting filter condition.
$filter = array(
array(
'property' => array(
'type',
$types,
'IN',
),
),
);
$settings['media_browser_plus']['filter'] = drupal_json_encode($filter);
// Attach settings.
$form['#attached']['js'][] = array(
'type' => 'setting',
'data' => $settings,
);
// Check access rights.
if (!media_browser_plus_access('media grid view')) {
drupal_access_denied();
return array();
}
// Adding grid view js and css.
$form['#attached']['js'][] = $path . '/js/media_browser_plus.admin.js';
$form['#attached']['js'][] = $path . '/js/media_browser_plus.library.js';
drupal_add_library('system', 'ui.draggable');
drupal_add_library('system', 'ui.droppable');
// Removing options form part.
unset($form['options']);
if (!media_browser_plus_access('media list view') || !media_browser_plus_access('media grid view')) {
unset($form['switch']);
}
// Add main grid view window.
$form['admin'] = media_browser_plus_grid_view_form(TRUE, $multiselect);
// Append media basket only for multi select.
if ($multiselect) {
$form['media-basket'] = media_browser_plus_media_basket_form(TRUE);
}
return $form;
}
/**
* Deleting all field data attached to the media entity.
*
* @todo: This should actually be done in media module
*
* @param $file
*/
function media_browser_plus_file_delete($file) {
$media = file_load($file->fid);
module_invoke_all('entity_delete', $media, 'file');
field_attach_delete('file', $media);
}
/**
* Appends main grid view form.
*/
function media_browser_plus_grid_view_form($library_mode = FALSE, $multiselect = FALSE) {
// Load the media folders.
$vocabulary = taxonomy_vocabulary_machine_name_load('media_folders');
$folders = taxonomy_get_tree($vocabulary->vid);
$folders = _media_browser_plus_filter_folders($folders);
$list = _media_browser_plus_create_relationship_list($folders, TRUE);
$folders = _media_browser_plus_folder_hierarchy_list($list);
// Build the folder form.
$form['admin']['folder'] = array(
'#type' => 'markup',
'#markup' => '<div id="folder" style="height:' . variable_get('media_grid_window_height') . 'px;">' . $folders . ' </div>',
);
$form['admin']['files']['#prefix'] = '<div class="media-display-thumbnails media-clear clearfix">' . '<ul class="media-list-thumbnails" style="height:' . variable_get('media_grid_window_height') . 'px;">';
// Aetting up the header.
$header = array(
array(
'data' => t('Folders'),
'width' => '200',
),
array(
'data' => t('Media Files'),
'width' => '*',
),
);
// and the data
$form['buttons'] = array();
$form['buttons']['selection_assets'] = array(
'#type' => 'markup',
'#markup' => '<a href="#media_folder_table" id="media_main_view_select_all" >' . t('Select All') . '</a>' . '<a href="#media_folder_table" id="media_main_view_deselect_all" >' . t('Deselect All') . '</a>',
);
if (!$library_mode) {
if (media_access('view')) {
$form['buttons']['view_media'] = array(
'#type' => 'button',
'#attributes' => array(
'id' => 'media_buttons_view',
),
'#value' => t('View'),
);
}
if (media_access('preview')) {
$form['buttons']['preview_media'] = array(
'#type' => 'button',
'#attributes' => array(
'id' => 'media_buttons_preview',
),
'#value' => t('Preview'),
);
}
if (media_access('edit')) {
$form['buttons']['edit_media'] = array(
'#type' => 'submit',
'#attributes' => array(
'id' => 'media_buttons_edit',
),
'#submit' => array(
'media_browser_plus_edit_multiple_redirect',
),
'#validate' => array(
'media_browser_plus_media_admin_validate',
),
'#value' => t('Edit'),
);
}
if (media_access('edit')) {
// edit-submit
$form['buttons']['delete_media'] = array(
'#type' => 'submit',
'#submit' => array(
'media_browser_plus_delete_multiple_redirect',
),
'#validate' => array(
'media_browser_plus_media_admin_validate',
),
'#value' => t('Delete'),
);
}
}
$form['buttons']['select_media'] = array(
'#type' => 'button',
'#attributes' => array(
'id' => 'media_buttons_select',
),
'#value' => t('Add to Media Basket'),
);
if ($library_mode && !$multiselect) {
// Remove select/deselect all.
unset($form['buttons']['selection_assets']);
// Change "Add to media basket" to process with selection.
$form['buttons']['select_media'] = _media_browser_plus_media_basket_select_button();
}
$options = array(
array(
'categories' => array(
'data' => drupal_render($form['admin']['folder']),
),
'media' => array(
'data' => '<div class="media-display-thumbnails media-clear clearfix">' . '<ul class="media-list-thumbnails" id="media-thumb-list" style="height: ' . variable_get('media_grid_window_height') . 'px;">' . '</ul></div>',
),
),
array(
'categories' => array(
'data' => '',
),
'media' => array(
'data' => '',
'id' => array(
'media_browser_plus_pages',
),
),
),
);
// If no library mode with single selection add media basket buttons.
if (!$library_mode || $multiselect) {
$options[] = array(
'categories' => array(
'data' => '',
),
'media' => array(
'data' => drupal_render($form['buttons']),
'id' => array(
'media_browser_plus_selection_panel',
),
),
);
}
// Table setup.
$table = array(
'header' => $header,
'rows' => $options,
'attributes' => array(
'id' => 'media_folder_table',
),
'empty' => t('No media added yet.'),
);
// Return themed table.
$output = array(
'#type' => 'markup',
'#markup' => theme('table', $table),
'buttons' => $form['buttons'],
);
if ($library_mode && !$multiselect) {
$output['#markup'] .= drupal_render($form['buttons']);
}
return $output;
}
/**
* Returns default javascript settings.
*/
function media_browser_plus_main_view_javascript_settings() {
global $base_url;
// Gather enviroment data.
$path = drupal_get_path('module', 'media_browser_plus');
$url = $base_url . base_path();
// Create default settings.
$settings = array(
'media_browser_plus' => array(
'filter_active' => isset($_SESSION['media-filter']),
'url' => $url,
'images_url' => $base_url . '/' . $path . '/images/',
'page' => isset($_GET['page']) ? $_GET['page'] : 0,
'per_page' => variable_get('media_media_per_page'),
'page_items_per_page' => variable_get('media_page_items_per_page'),
'folder_management_url' => url('admin/content/media/folder_list'),
'multiselect' => TRUE,
// texts
'messages' => array(
'only_one_selection_allowed' => t('Only one media item may be selected'),
),
// access settings
'folder_dnd_enabled' => media_access('edit'),
'manage_folders' => media_access('edit folders'),
'filter_allowed' => media_access('filter'),
'add_files' => media_access('upload'),
),
);
return $settings;
}
/**
* Appends the media basket.
*/
function media_browser_plus_media_basket_form($library_mode = FALSE) {
$header = array(
array(
'data' => t('Media Basket'),
),
);
$form['basket_actions'] = array();
$form['basket_actions']['selection_assets'] = array(
'#type' => 'markup',
'#markup' => '<a href="#media_basket_table" id="media_basket_remove_all" >' . t('Remove All') . '</a>',
);
if ($library_mode) {
$form['basket_actions']['select'] = _media_browser_plus_media_basket_select_button();
}
else {
if (media_access('download')) {
$form['basket_actions']['download'] = array(
'#type' => 'submit',
'#value' => t('Download'),
'#attributes' => array(
'id' => 'perform_download',
),
'#limit_validation_errors' => array(),
'#validate' => array(
'media_browser_plus_media_admin_validate',
),
'#submit' => array(
'media_browser_plus_download_images_submit',
),
);
}
}
$options = array(
array(
'media' => array(
'data' => '<ul id="media-basket-list" class="media-list-thumbnails"></ul>',
),
),
array(
'media' => array(
'data' => drupal_render($form['basket_actions']),
'id' => array(
'media_browser_plus_basket_panel',
),
),
),
);
$table = array(
'header' => $header,
'rows' => $options,
'attributes' => array(
'id' => 'media_basket_table',
),
'empty' => t('No media added yet.'),
);
return array(
'#type' => 'markup',
'#markup' => theme('table', $table),
'basket_actions' => $form['basket_actions'],
);
}
/**
* Appends the hidden preview form.
*/
function media_browser_plus_media_preview_form() {
$header = array(
array(
'data' => t('Media Preview'),
'id' => array(
'media-preview-label',
),
),
);
$form['preview_actions'] = array(
'previous' => array(
'#type' => 'submit',
'#value' => t('previous'),
'#attributes' => array(
'id' => 'previous_preview_item',
),
),
'select' => array(
'#type' => 'submit',
'#value' => t('Select'),
'#attributes' => array(
'id' => 'select_preview_item',
),
),
'next' => array(
'#type' => 'submit',
'#value' => t('next'),
'#attributes' => array(
'id' => 'next_preview_item',
),
),
);
$options = array(
array(
'media' => array(
'data' => '',
'id' => array(
'media_browser_plus_preview_content',
),
),
),
array(
'media' => array(
'data' => drupal_render($form['preview_actions']),
'id' => array(
'media_browser_plus_preview_panel',
),
),
),
);
$table = array(
'header' => $header,
'rows' => $options,
'attributes' => array(
'id' => 'media-preview-table',
),
'empty' => t('No media added yet.'),
);
return array(
'#type' => 'markup',
'#markup' => '<div id="media-preview-table-container" style="display: none;">' . theme('table', $table) . '</div>',
'preview_actions' => $form['preview_actions'],
);
}
/**
* @todo Document what this is for!
*
* @return array
*/
function _media_browser_plus_media_basket_select_button() {
return array(
'#type' => 'submit',
'#value' => t('Continue with Selection'),
'#attributes' => array(
'id' => 'proceed_with_select',
),
'#limit_validation_errors' => array(),
'#validate' => array(
'media_browser_plus_media_admin_validate',
),
);
}
/**
* Construct the path of a media_folder term.
*
* @param $term object containing term id and term name
*/
function media_browser_plus_construct_dir_path($term) {
$file_default_scheme = variable_get('file_default_scheme', 'public') . ':/';
if ($term) {
$parents = array_reverse(taxonomy_get_parents_all($term->tid));
$path = $file_default_scheme . '/';
if (is_array($parents) && !empty($parents)) {
foreach ($parents as $parent) {
$path .= $parent->name . '/';
}
}
$path = str_replace('Media Root', variable_get('media_root_folder', 'media'), $path);
$dir_path = rtrim($path, '/');
}
return isset($dir_path) ? $dir_path : $file_default_scheme;
}
/**
* Cut-paste a directory with its children into a new filesystem location.
*
* @param $source string the current folder path
* @param $destination string the path we want the folder moved to
*/
function media_browser_plus_move_physical_folder($source, $destination) {
$destination = drupal_realpath($destination);
$source = drupal_realpath($source);
$jail = drupal_realpath(variable_get('file_default_scheme', 'public') . '://');
// @todo Please avoid an error by checking the preconditions instead.
$files = @scandir($source);
if ($files && count($files) > 2) {
$transfer = new FileTransferLocal($jail);
$transfer
->copyDirectory($source, $destination);
$transfer
->removeDirectory($source);
}
else {
// The folder is empty so just delete and create the new one.
drupal_rmdir($source);
file_prepare_directory($destination, FILE_CREATE_DIRECTORY);
}
}
/**
* Moves and saves permanently a media file.
*
* Every media file that is saved or updated,should pass through this to make
* sure the filesystem location is the same with the folder term.
*
* @param $tid the folder's term id.
* @param $media the media object.
* @param $replace Replace behavior when the destination file already exists.
*/
function media_browser_plus_move_file($tid, $media, $replace = FILE_EXISTS_RENAME) {
// Dont change the uri for media files with external source
if (strpos($media->uri, 'public') === FALSE && strpos($media->uri, 'private') === FALSE) {
file_save($media);
}
else {
// media translation module does need this since it allows the creation of
// file references which shouldn't move the referenced file itself when moved.
// see http://drupal.org/node/1331818 for details.
if (module_exists('media_translation') && media_translation_is_virtual_file($media->fid)) {
file_save($media);
return;
}
$folder = media_browser_plus_folder_load($tid);
$path = media_browser_plus_construct_dir_path($folder);
file_prepare_directory($path, FILE_CREATE_DIRECTORY);
$destination = $path . '/' . $media->filename;
file_move($media, $destination, $replace);
}
}
Functions
Name![]() |
Description |
---|---|
media_browser_plus_access | Manages access for media browser plus actions. |
media_browser_plus_change_folder | Called by the JS fronted (ajax) to change the folder of a media object. |
media_browser_plus_construct_dir_path | Construct the path of a media_folder term. |
media_browser_plus_delete_multiple_redirect | Enter description here |
media_browser_plus_download_images_submit | Puts all selected media items into a zip archive and sends it as download. |
media_browser_plus_edit_cancel | @todo Document what this function does. |
media_browser_plus_edit_file_submit | Form submit handler for the media browser forms that edit media entities. |
media_browser_plus_edit_multiple_redirect | Enter description here |
media_browser_plus_field_attach_presave | Implements hook_field_attach_presave(). |
media_browser_plus_file_delete | Deleting all field data attached to the media entity. |
media_browser_plus_file_download_access | Checks if the user has the permission to download a file. |
media_browser_plus_file_download_access_alter | Revokes the general 'view media' == 'download media' access rule. |
media_browser_plus_folder_load | Implements of hook_load(). |
media_browser_plus_form_media_add_upload_alter | Implements hook_form_FORM_ID_alter(). |
media_browser_plus_form_media_add_upload_multiple_alter | Implements hook_form_FORM_ID_alter(). |
media_browser_plus_form_media_admin_alter | Alter the media browser from to enable new UI |
media_browser_plus_form_media_edit_alter | Implements hook_form_FORM_ID_alter(). |
media_browser_plus_form_media_import_alter | Implements hook_form_FORM_ID_alter(). |
media_browser_plus_form_media_internet_add_alter | Implements hook_form_FORM_ID_alter(). |
media_browser_plus_get_media_root_folder | Loads and (if $autocreate is set) creates the default media folder object. |
media_browser_plus_grid_view_form | Appends main grid view form. |
media_browser_plus_library | Implements hook_library(). |
media_browser_plus_library_browser | Creates the Extended Library for the media browser popup. |
media_browser_plus_load_multiple | Loads media entities and allows filtering, sorting and paging. |
media_browser_plus_load_tag_terms | @todo Document what this funciont does. |
media_browser_plus_main_view_javascript_settings | Returns default javascript settings. |
media_browser_plus_media_access | Checks access to a given media entity. |
media_browser_plus_media_admin_folder_change_submit | Changes the folder of the submitted media items. |
media_browser_plus_media_admin_validate | Enter description here |
media_browser_plus_media_basket_form | Appends the media basket. |
media_browser_plus_media_browser_plugins_alter | Remove the old Library for the media browser popup. |
media_browser_plus_media_browser_plugin_info | Implements hook_media_browser_plugin_info(). |
media_browser_plus_media_browser_plugin_view | Implements hook_media_browser_plugin_view(). |
media_browser_plus_media_import_batch_complete | Same completed batch method as in media. |
media_browser_plus_media_import_batch_import_files | Batch process that only differs in the ability to apply the field values to the items |
media_browser_plus_media_import_submit | Changing the media import standard submit to use our own batch process. |
media_browser_plus_media_operations | Implements hook_media_operations(). |
media_browser_plus_media_preview_form | Appends the hidden preview form. |
media_browser_plus_media_settings | Creates the media browser plus settings form. |
media_browser_plus_media_settings_submit | Saves the entered settings. |
media_browser_plus_media_settings_validate | Validates the settings. |
media_browser_plus_menu | Implements hook_menu(). |
media_browser_plus_menu_alter | Implements hook_menu_alter(). |
media_browser_plus_move_file | Moves and saves permanently a media file. |
media_browser_plus_move_physical_folder | Cut-paste a directory with its children into a new filesystem location. |
media_browser_plus_permission | Implements hook_permission(). |
media_browser_plus_prepare_taxonomy_autocomplete_validate | Form element validate handler for taxonomy term autocomplete element. |
media_browser_plus_preprocess_media_link | Implements hook_preprocess_media_link(). |
media_browser_plus_preprocess_media_thumbnail | Implements hook_preprocess_media_thubmnail(). |
media_browser_plus_submit | Submit handler for the media browser forms that create new media entities. |
media_browser_plus_thumbnailsJSON | Called by the JS fronted (ajax) to get the media list for a given folder. |
_media_browser_plus_create_relationship_list | @todo Document what this function does. |
_media_browser_plus_filter_folders | Looks if a filter is active and filters the folders accordingly. |
_media_browser_plus_filter_folder_access | @todo Document what this function does. |
_media_browser_plus_folder_empty | Check if a given folder has media in it (does include current filter) |
_media_browser_plus_folder_form | Returns a select form item with a selectable media folders. |
_media_browser_plus_folder_hierarchy_list | Creates the folder media tree. |
_media_browser_plus_folder_hierarchy_list_helper | @todo Document what this function does. |
_media_browser_plus_folder_list | @todo Document what this function does. |
_media_browser_plus_has_unsorted_media | Checks for unsorted (i.e. media not in folders) media. |
_media_browser_plus_media_admin_list_alter | Alter the media list display. |
_media_browser_plus_media_basket_select_button | @todo Document what this is for! |
_media_browser_plus_metadata | Helper function to return metadata from a 3rd party media provider. |
_media_browser_plus_pager | @todo Document what this function does. |
_media_browser_plus_pager_add_page_item | @todo Document what this function does. |
_media_browser_plus_tag_form | Returns the tag form element. |