You are here

views_media_browser.module in Views Media Browser 7

Same filename and directory in other branches
  1. 7.2 views_media_browser.module

Code for the Views Media Browser feature.

File

views_media_browser.module
View source
<?php

/**
 * @file
 * Code for the Views Media Browser feature.
 */

/**
 * Variable namespace
 */
define('VIEWS_MEDIA_BROWSER_VAR_NAMESPACE', 'views_media_browser');

/**
 * Default Media URL
 */
define('FILE_DEFAULT_MEDIA_URL', 'media/browser/list');

/**
 * Default View Name
 */
define('VIEWS_MEDIA_BROWSER_DEFAULT_VIEW_NAME', 'views_media_browser');

/**
 * Default view display
 */
define('VIEWS_MEDIA_BROWSER_DEFAULT_VIEW_DISPLAY', 'browser_thumbs');

/**
 * Variable: View Name
 */
define('VIEWS_MEDIA_BROWSER_VAR_VIEW_NAME', VIEWS_MEDIA_BROWSER_VAR_NAMESPACE . '__view_name');

/**
 * Variable: View Display
 */
define('VIEWS_MEDIA_BROWSER_VAR_VIEW_DISPLAY', VIEWS_MEDIA_BROWSER_VAR_NAMESPACE . '__view_display');

/**
 * Implementation of hook_views_api().
 */
function views_media_browser_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'views_media_browser') . '/includes',
    'template path' => drupal_get_path('module', 'views_media_browser') . '/templates',
  );
}

/**
 * Implements hook_media_browser_plugin_info().
 *
 * Defines a separate tab for our media browsing elements.
 */
function views_media_browser_media_browser_plugin_info() {
  return array(
    'views_media_browser' => array(
      '#weight' => 11,
    ),
  );
}

/**
 * Returns the browser view display
 * @return null
 */
function views_media_browser_get_view_display() {
  return !empty($_REQUEST['display_format']) ? $_REQUEST['display_format'] : variable_get(VIEWS_MEDIA_BROWSER_VAR_VIEW_DISPLAY, VIEWS_MEDIA_BROWSER_DEFAULT_VIEW_DISPLAY);
}

/**
 * Adds supporting javascript to the file browser
 * @return void
 */
function views_media_browser_add_browser_javascript() {
  drupal_add_js(base_path() . 'misc/jquery.ba-bbq.js');
  drupal_add_js(drupal_get_path('module', 'views_media_browser') . '/js/views_media_browser.js');
}

/**
 * Implements hook_media_browser_plugins_alter().
 *
 * Inserts our exposed filter form in the media browser library.
 */
function views_media_browser_media_browser_plugins_alter(&$plugins) {

  // Remove our file repo tab because we're not using it.
  // @todo: May create a separate tab in the future.
  unset($plugins['views_media_browser']);

  // If this is an add-media form; there is no library.
  if (!array_key_exists('library', $plugins)) {
    return;
  }
  views_media_browser_add_browser_javascript();

  // Load our view to pull out the exposed filters only.
  $view_name = views_media_browser_get_view_name();
  $view = views_get_view($view_name);
  if (!$view) {
    drupal_set_message(t('View %view not found.', array(
      '%view' => $view_name,
    )), 'error');
    return;
  }
  $success = $view
    ->set_display(views_media_browser_get_view_display());
  if (!$success) {

    // Display did not initialize
    // @todo do something here?
  }
  $view
    ->init_handlers();

  //initialize display handlers
  $form_state = array(
    'view' => $view,
    'display' => $view->display_handler->display,
    'exposed_form_plugin' => $view->display_handler
      ->get_plugin('exposed_form'),
    //exposed form plugins are used in Views 3
    'method' => 'get',
    'rerender' => TRUE,
    'no_redirect' => TRUE,
  );
  $form = drupal_build_form('views_exposed_form', $form_state);

  //create the filter form

  // Add a fake button for filtering.
  $form['exposed_button'] = array(
    '#markup' => '<a class="exposed-button button">Filter</a>',
  );

  // Remove the submit (Apply) button on the exposed filter form because it
  // remove the "fake" submit button from the media browser list.
  unset($form['submit']);

  // @todo: Add additional button that refreshes browser contents.
  // @todo: Ensure that additional params are passed to the listing function.
  $form = drupal_render($form);
  $view
    ->execute();
  $output = $view->style_plugin
    ->render(array());

  // Add a display format selection to change the rendered view.
  $display_form = drupal_get_form('views_media_browser_browser_view_form');
  $display_form = drupal_render($display_form);

  // Add our exposed filters above our view results.
  $plugins['library']['#markup'] = $display_form . $form;
  $plugins['library']['#markup'] .= '<div id="container"><div id="scrollbox">' . $output . '<div id="status"></div></div></div>';

  // Make sure we re-add the submit/cancel buttons since we're erasing the original HTML provided by the Media module.
  if (views_media_browser_get_media_version() >= 2) {
    $plugins['library']['#markup'] .= l(t('Submit'), '', array(
      'attributes' => array(
        'class' => array(
          'button',
          'fake-submit',
          'library',
        ),
      ),
    ));
    $plugins['library']['#markup'] .= l(t('Cancel'), '', array(
      'attributes' => array(
        'class' => array(
          'button',
          'fake-cancel',
          'library',
        ),
      ),
    ));
  }
  drupal_add_library('system', 'jquery.bbq');

  // Update our javascript reference
  $plugins['library']['#attached']['js'] = array(
    drupal_get_path('module', 'views_media_browser') . '/js/views_media_browser_library.js',
  );
  $plugins['library']['#attached']['css'][] = drupal_get_path('module', 'views_media_browser') . '/css/views_media_browser.css';
}

/**
 * Implements hook_menu_alter().
 */
function views_media_browser_menu_alter(&$menu) {

  // Redirect the Library tab to leverage our code so we can use views and
  // provide additional functionality.
  $menu['media/browser/list']['page callback'] = 'views_media_browser_list';

  // Leave the file intact because we'll need functions from the file.
}

/**
 * Queries the file browser view and returns the appropriate set of results.
 * @param array $types
 * @param int $start
 * @param int $limit
 * @return array
 */
function views_media_browser_get_paged_view($start = 0, $limit = 15) {
  $name = views_media_browser_get_view_name();
  $display_id = views_media_browser_get_view_display();
  $view = views_get_view($name);
  $view
    ->set_items_per_page($limit);
  $view
    ->set_offset($start);
  if (is_object($view)) {
    if (is_string($display_id)) {
      $view
        ->set_display($display_id);
    }
    else {
      $view
        ->init_display();
    }
    $display = $view->display_handler;
    $display
      ->set_option('items_per_page', $limit);
    $display
      ->set_option('offset', $start);
    $view
      ->pre_execute();
    $view
      ->execute();
    $rendered_rows = views_media_browser_get_rendered_rows($view);
    return array(
      'results' => $view->result,
      'rows' => $rendered_rows,
    );
  }
  else {
    return array();
  }
}
function views_media_browser_get_rendered_rows(&$view) {
  $style =& $view->style_plugin;
  if ($style
    ->uses_row_plugin() && empty($style->row_plugin)) {
    debug('views_plugin_style_default: Missing row plugin');
    return;
  }

  // Group the rows according to the grouping field, if specified.
  $sets = $style
    ->render_grouping($style->view->result, $style->options['grouping']);

  // Render each group separately and concatenate.  Plugins may override style
  // method if they wish some other way of handling grouping.
  $output = '';
  foreach ($sets as $title => $records) {
    if ($style
      ->uses_row_plugin()) {
      $rows = array();
      foreach ($records as $row_index => $row) {
        $style->view->row_index = $row_index;
        $rows[$row_index] = $style->row_plugin
          ->render($row);
      }
    }
    else {
      $rows = $records;
    }
  }
  return $rows;
}

/**
 * Step in and return our list for media brower.
 */
function views_media_browser_list() {
  $params = drupal_get_query_parameters();
  $view_filters = isset($params['filters']) ? $params['filters'] : array();

  // Example of an exposed form values coming in through params
  // $view_filters = array('fid_op' => '=', 'fid' => Array ( 'value' => 6, 'min' => NULL ,'max' => NULL));
  $_GET = array_merge($_GET, $view_filters);

  // @todo: Pass params received to the view for filtering.
  // @todo: Make every reference of the page not load the same item again.
  // @todo: Add paging support to the request
  $limit = isset($params['limit']) ? $params['limit'] : 15;
  $start = isset($params['start']) ? $params['start'] : 0;
  $results = views_media_browser_get_paged_view($start, $limit);
  $files = $fids = array();
  foreach ($results['results'] as $row) {
    $fids[] = $row->fid;
  }
  $files = file_load_multiple($fids);
  foreach ($files as $file) {
    media_browser_build_media_item($file);
  }
  foreach ($files as $file) {
    $file->thumbnail = $file->preview;
    $file->preview = array_shift($results['rows']);
  }

  /*
  $files = array();
  foreach ($results as $file) {
    $files->preview = $file;
  }
  */
  drupal_json_output(array(
    'media' => array_values($files),
  ));
  exit;
}

/**
 * Implements hook_media_browser_plugin_view().
 *
 * This function is here only to support the concept of having a separate tab
 * for media browsing.
 */
function views_media_browser_media_browser_plugin_view($key, $plugins) {
  return $plugins;
}

/*
 * Returns the browser view name
 *
 */
function views_media_browser_get_view_name() {
  return variable_get(VIEWS_MEDIA_BROWSER_VAR_VIEW_NAME, VIEWS_MEDIA_BROWSER_DEFAULT_VIEW_NAME);
}

/**
 * Theme Preprocess function.
 * Updates the title attribute to use the title-field content, and append language.
 *
 * @param  $variables
 * @return void
 */
function views_media_browser_preprocess_media_thumbnail(&$variables) {

  // Set the name for the thumbnail to be the filename.  This is done here so
  // that other modules can hijack the name displayed if it should not be the
  // filename.
  $file = $variables['element']['#file'];
  if (is_object($file) && isset($file->field_title) && !empty($file->field_title)) {
    $display_title = NULL;
    $title_items = field_get_items('file', $file, 'field_title');

    // In the case where the current language results in no data, we will show any language.
    if (!$title_items) {
      $title_items = reset($file->field_title);
    }
    if (!empty($title_items)) {
      $title = $title_items[0];
      if ($title) {
        $display_title = isset($title['safe_value']) ? $title['safe_value'] : NULL;
        $display_title = $display_title || isset($title['value']) ? check_plain($title['value']) : NULL;
        if ($display_title) {
          $variables['element']['#name'] = $display_title;
        }
      }
    }
  }

  // Add the language field data
  if (is_object($file) && isset($file->language)) {
    $variables['element']['#name'] .= ' [' . $file->language . ']';
  }
}

/**
 * Implements hook_theme()
 * Allows preprocess functions to be caught by the theme_build_registry().
 *
 * @return array
 */
function views_media_browser_theme() {
  return array(
    'views_view_views_media_browser_table' => array(
      'variables' => array(
        'view' => NULL,
        'options' => NULL,
        'row' => NULL,
      ),
      'template' => 'views-view-views-media-browser-table',
      'path' => drupal_get_path('module', 'views_media_browser') . '/includes',
      // 'base hook' => 'views_view_table',
      'preprocess functions' => array(
        'views_view_table',
        'views_view_views_media_browser_table',
      ),
    ),
  );
}

/**
 * Implements hook_views_pre_render
 * This adds a translatable no-results message to the view if there are no results.
 * @param  $view
 * @return void
 */
function views_media_browser_views_pre_render($view) {
  if ($view->name === 'views_media_browser' && empty($view->result)) {
    $view->attachment_after = '<div class="view-no-results">' . t('There are no matching files for the selected filters.') . '</div>';
  }
}

/**
 * Theme Preprocess Function
 * Converts the unthemed display to thumbnails linking to the media base page.
 * @param  $elements
 * @return void
 */
function views_media_browser_preprocess_views_view_unformatted(&$elements) {

  //@todo:find out how to implement a new row formatter so that the rows are only rendered once.
  $view = $elements['view'];
  if ($view->current_display === 'browser_thumbs' && $view->name === 'views_media_browser') {
    $fids = array();
    foreach ($view->result as $delta => $row) {
      $fids[] = $row->fid;
    }
    $files = file_load_multiple($fids);
    foreach ($view->result as $delta => $row) {
      $preview = media_get_thumbnail_preview($files[$row->fid], TRUE);
      $rendered_thumbnail = drupal_render($preview);
      $elements['rows'][$delta] = $rendered_thumbnail;
    }
    drupal_add_css(drupal_get_path('module', 'views_media_browser') . '/css/media_thumbs_view.css', array(
      'preprocess' => FALSE,
    ));
    drupal_add_js(drupal_get_path('module', 'views_media_browser') . '/js/media_thumbs_smart_wrap.js');
  }
}

/**
 * Theme Prepreprocess function.
 * THis adds the "EDit/Delete" values to the table.
 * @param  $elements
 * @return void
 */
function views_media_browser_preprocess_views_view_table(&$elements) {
  $view = $elements['view'];
  if ($view->current_display === 'browser_list' && $view->name === 'views_media_browser') {
    $elements['header']['actions'] = t('Actions');
    $elements['header_classes']['actions'] = t('Actions');
    $elements['fields']['actions'] = 'actions';
    $elements['field_attributes']['actions'] = array();
    $elements['field_classes']['actions'] = array();
    foreach ($elements['rows'] as $delta => &$row) {
      $fid = $view->result[$delta]->fid;
      $elements['field_attributes']['actions'][$delta] = array();
      $elements['field_classes']['actions'][$delta] = array();
      $row['actions'] = l(t('Edit'), sprintf('media/%d/edit', $fid)) . ' ' . l(t('Delete'), sprintf('media/%d/delete', $fid));
    }
    unset($row);
  }
}

/**
 * Implements hook_admin_paths().
 * Doesn't do anything currently.
 * @return array
 */
function views_media_browser_admin_paths() {
  return array(
    'admin/content/media_browser' => TRUE,
    'admin/content/media_browser/*' => TRUE,
  );
}
function template_preprocess_views_view_views_media_browser_table(&$vars) {

  // @todo: Find a better way to do this.
  $rows = $vars['rows'];
  template_preprocess_views_view_table($vars);
  $vars['rows'] = $rows;
  drupal_add_css(drupal_get_path('module', 'views_media_browser') . '/css/media_list_view.css', array(
    'preprocess' => TRUE,
    'weight' => 1000,
  ));
}
function views_media_browser_browser_view_form() {
  $form = array();
  $form['display_format'] = array(
    '#type' => 'select',
    '#options' => views_media_browser_browser_views(),
    '#default_value' => views_media_browser_get_view_display(),
  );
  return $form;
}
function views_media_browser_browser_views() {

  // @todo: Make this more flexible and allow other views.
  return array(
    'browser_thumbs' => t('Thumbnails'),
    'browser_list' => t('Table'),
  );
}

/**
 * Determines which version of the media module is installed on the site.
 * @return int
 * The major version number of the media module.
 */
function views_media_browser_get_media_version() {
  $media_version = variable_get('views_media_browser_media_version', 0);
  if (!$media_version) {
    $media_info = drupal_parse_info_file(drupal_get_path('module', 'media') . '/media.info');
    $media_version = 1;
    $media_version_info = NULL;
    if (preg_match('/7\\.x-(\\d)\\./', $media_info['version'], $media_version_info)) {
      if (isset($media_version_info[1])) {
        $media_version = $media_version_info[1];
      }
    }

    // @todo: Separate out the versions as they are on d.o. at some point.
    variable_set('views_media_browser_media_version', $media_version);
  }
  return $media_version;
}

Functions

Namesort descending Description
template_preprocess_views_view_views_media_browser_table
views_media_browser_add_browser_javascript Adds supporting javascript to the file browser
views_media_browser_admin_paths Implements hook_admin_paths(). Doesn't do anything currently.
views_media_browser_browser_views
views_media_browser_browser_view_form
views_media_browser_get_media_version Determines which version of the media module is installed on the site.
views_media_browser_get_paged_view Queries the file browser view and returns the appropriate set of results.
views_media_browser_get_rendered_rows
views_media_browser_get_view_display Returns the browser view display
views_media_browser_get_view_name
views_media_browser_list Step in and return our list for media brower.
views_media_browser_media_browser_plugins_alter Implements hook_media_browser_plugins_alter().
views_media_browser_media_browser_plugin_info Implements hook_media_browser_plugin_info().
views_media_browser_media_browser_plugin_view Implements hook_media_browser_plugin_view().
views_media_browser_menu_alter Implements hook_menu_alter().
views_media_browser_preprocess_media_thumbnail Theme Preprocess function. Updates the title attribute to use the title-field content, and append language.
views_media_browser_preprocess_views_view_table Theme Prepreprocess function. THis adds the "EDit/Delete" values to the table.
views_media_browser_preprocess_views_view_unformatted Theme Preprocess Function Converts the unthemed display to thumbnails linking to the media base page.
views_media_browser_theme Implements hook_theme() Allows preprocess functions to be caught by the theme_build_registry().
views_media_browser_views_api Implementation of hook_views_api().
views_media_browser_views_pre_render Implements hook_views_pre_render This adds a translatable no-results message to the view if there are no results.

Constants

Namesort descending Description
FILE_DEFAULT_MEDIA_URL Default Media URL
VIEWS_MEDIA_BROWSER_DEFAULT_VIEW_DISPLAY Default view display
VIEWS_MEDIA_BROWSER_DEFAULT_VIEW_NAME Default View Name
VIEWS_MEDIA_BROWSER_VAR_NAMESPACE Variable namespace
VIEWS_MEDIA_BROWSER_VAR_VIEW_DISPLAY Variable: View Display
VIEWS_MEDIA_BROWSER_VAR_VIEW_NAME Variable: View Name