Newer
Older
Jacob Singh
committed
<?php
/**
* @file
* Lets users create galleries made up of media items.
*/
require_once(dirname(__FILE__) . '/media_gallery.fields.inc');
require_once(dirname(__FILE__) . '/fields_rsi_prevention.inc');
/**
* The pager element to use for paging through the media items in a gallery.
*
* We avoid using the default pager for now because there is too much risk of
* it colliding with other pagers initialized for the same page (for example,
* by the comment module, if the gallery node manages to get comment loading or
* display functions called on it).
*/
define('MEDIA_GALLERY_PAGER_ELEMENT', 1);
Alex Bronstein
committed
/**
* Helper function to return the view modes used by this module for displaying files in gallery context.
*/
function media_gallery_file_view_modes() {
return array(
'media_gallery_thumbnail' => t('Gallery thumbnail'),
'media_gallery_lightbox' => t('Gallery lightbox'),
'media_gallery_detail' => t('Gallery detail'),
'media_gallery_block_thumbnail' => t('Gallery block thumbnail'),
'media_gallery_collection_thumbnail' => t('Gallery collection thumbnail'),
);
}
Jacob Singh
committed
/**
* Implements hook_menu().
*/
function media_gallery_menu() {
$items['admin/config/media/galleries'] = array(
'title' => 'Gallery settings',
'description' => 'Configure settings for the "All galleries" page.',
'access arguments' => array('administer media galleries'),
'page callback' => 'media_gallery_admin_settings',
'file' => 'media_gallery.admin.inc',
);
$items['media-gallery/sort/collection/%taxonomy_term/%'] = array(
'title' => 'Gallery sort callback',
'access callback' => 'media_gallery_edit_access_ajax',
'access arguments' => array('collection', 3, 4),
'page callback' => 'media_gallery_ajax_sort',
'page arguments' => array('collection', 3),
'file' => 'media_gallery.pages.inc',
);
$items['media-gallery/sort/gallery/%node/%'] = array(
'title' => 'Gallery sort callback',
'access callback' => 'media_gallery_edit_access_ajax',
'access arguments' => array('gallery', 3, 4),
'page callback' => 'media_gallery_ajax_sort',
'page arguments' => array('gallery', 3),
'file' => 'media_gallery.pages.inc',
);
Moloc
committed
$items['media-gallery/detail/%media_gallery_mg_node/%media_gallery_mg_item'] = array(
Jacob Singh
committed
'page callback' => 'media_gallery_detail_page',
'page arguments' => array(2, 3),
'access callback' => 'media_gallery_view_item_access',
'access arguments' => array(2, 3),
Moloc
committed
'load arguments' => array(2),
Jacob Singh
committed
'file' => 'media_gallery.pages.inc',
);
Moloc
committed
$items['media-gallery/detail/%media_gallery_mg_node/%media_gallery_mg_item/view'] = array(
Jacob Singh
committed
'title' => 'View',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
Moloc
committed
'load arguments' => array(2),
Jacob Singh
committed
);
Alex Bronstein
committed
// An in-gallery-context version of media/%file/edit.
Moloc
committed
$items['media-gallery/detail/%media_gallery_mg_node/%media_gallery_mg_item/edit'] = array(
Jacob Singh
committed
'title' => 'Edit',
'page callback' => 'media_gallery_media_page_edit',
'page arguments' => array(2, 3),
'access callback' => 'media_gallery_edit_item_access',
'access arguments' => array(2, 3),
Moloc
committed
'load arguments' => array(2),
Jacob Singh
committed
'weight' => 0,
'type' => MENU_LOCAL_TASK,
'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
'file' => 'media_gallery.pages.inc',
);
Moloc
committed
$items['media-gallery/detail/%media_gallery_mg_node/%media_gallery_mg_item/remove'] = array(
Jacob Singh
committed
'title' => 'Remove',
'page callback' => 'drupal_get_form',
'page arguments' => array('media_gallery_remove_item_form', 2, 3),
'access callback' => 'media_gallery_remove_item_access',
'access arguments' => array(2, 3),
Moloc
committed
'load arguments' => array(2),
Jacob Singh
committed
'type' => MENU_LOCAL_TASK,
'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
'file' => 'media_gallery.pages.inc',
);
Moloc
committed
$items['media-gallery/lightbox/%media_gallery_mg_node/%media_gallery_mg_item'] = array(
Jacob Singh
committed
'page callback' => 'media_gallery_lightbox_page',
'page arguments' => array(2, 3),
'access callback' => 'media_gallery_view_item_access',
'access arguments' => array(2, 3),
Moloc
committed
'load arguments' => array(2),
Jacob Singh
committed
'file' => 'media_gallery.pages.inc',
'delivery callback' => 'media_gallery_lightbox_delivery_callback',
Jacob Singh
committed
);
$items['media-gallery/add-images/%node/%'] = array(
'access callback' => 'media_gallery_edit_access_ajax',
'access arguments' => array('gallery', 2, 3),
'page callback' => 'media_gallery_add_images',
'page arguments' => array(2),
'file' => 'media_gallery.pages.inc',
);
// An in-gallery-context version of media/%media_multi/edit.
$items['node/%node/multiedit'] = array(
Jacob Singh
committed
'page callback' => 'media_gallery_media_page_multiedit',
'page arguments' => array(1),
'access callback' => 'media_gallery_multiedit_access',
'access arguments' => array(1),
'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
'type' => MENU_LOCAL_TASK,
'file' => 'media_gallery.pages.inc',
);
// @todo Move to Media module once it is ready.
Alex Bronstein
committed
$items['media/%file/download'] = array(
Jacob Singh
committed
'title' => 'Download',
'page callback' => 'media_download',
'page arguments' => array(1),
'access callback' => 'media_access',
'access arguments' => array('view'),
'type' => MENU_CALLBACK,
'file' => 'media.pages.inc',
);
return $items;
}
Moloc
committed
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/**
* Load a node object from the database.
*
* @see node_load()
* @see media_gallery_menu()
*
* @param $nid
* The node ID.
* @param $nid2
* The same as $nid. Unused.
*
* @return
* A fully-populated node object, or FALSE if the node is not found.
*/
function media_gallery_mg_node_load($nid, $nid2 = NULL) {
return node_load($nid);
}
/**
* Load a file object from the database, if it is part of the media_gallery
* node.
*
* @see node_load()
* @see file_load()
* @see media_gallery_menu()
*
* @param $fid
* The file ID.
* @param $nid
* The media_gallery node ID.
*
* @return
* A fully-populated file object, or FALSE if the file is not part of the
* media_gallery.
*/
function media_gallery_mg_item_load($fid, $nid) {
$node = node_load($nid);
if ($node && $node->type == 'media_gallery' && in_array($fid, media_gallery_get_file_ids($node))) {
return file_load($fid);
}
return FALSE;
}
Jacob Singh
committed
/**
* Implements hook_menu_alter().
*/
function media_gallery_menu_alter(&$items) {
// Take over taxonomy term list pages by substituting our own callback.
// TODO: Use hook_entity_info_alter() to change the entity uri callback for
// gallery collections only.
$items['taxonomy/term/%taxonomy_term']['page callback'] = 'media_gallery_list_galleries';
$items['taxonomy/term/%taxonomy_term']['file'] = 'media_gallery.pages.inc';
$items['taxonomy/term/%taxonomy_term']['module'] = 'media_gallery';
// If you're viewing a media item in context somewhere (which we do inside
// media gallery nodes), that means it's being used on your site, which means
// you won't be allowed to delete it anyway. Therefore, do not show
// contextual links there.
// @todo Perhaps this should be changed in the media module itself?
Alex Bronstein
committed
$items['media/%file/delete']['context'] = MENU_CONTEXT_PAGE;
Jacob Singh
committed
}
/**
* Implements hook_admin_paths().
*/
function media_gallery_admin_paths() {
$paths = array(
'media-gallery/detail/*/*/edit' => TRUE,
'media-gallery/detail/*/*/remove' => TRUE,
'node/*/multiedit' => TRUE,
);
return $paths;
}
/**
* Implements hook_menu_local_tasks_alter().
*/
function media_gallery_menu_local_tasks_alter(&$data, $router_item, $root_path) {
// Rename the "Edit" tab on gallery nodes to "Edit gallery".
if (($node = menu_get_object()) && isset($node->type) && $node->type == 'media_gallery' && !empty($data['tabs'])) {
Jacob Singh
committed
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
$tabs = &$data['tabs'][0]['output'];
foreach ($tabs as &$tab) {
if (isset($tab['#link']['path']) && $tab['#link']['path'] == 'node/%/edit') {
$tab['#link']['title'] = t('Edit gallery');
}
}
}
// Rename the "Edit" tab on the "All Galleries" taxonomy term to "Edit all
// galleries" and point it to our configuration page.
// @todo: Once we have additional gallery-related taxonomy terms and
// http://drupal.org/node/678592 is committed to core (so the term edit
// pages show the correct admin theme) we'll do something different here,
// perhaps not even alter anything at all.
if (($term = menu_get_object('taxonomy_term', 2)) && isset($term->vid) && $term->vid == variable_get('media_gallery_collection_vid')) {
$tabs = &$data['tabs'][0]['output'];
foreach ($tabs as &$tab) {
if (isset($tab['#link']['path']) && $tab['#link']['path'] == 'taxonomy/term/%/edit') {
$tab['#link']['href'] = 'admin/config/media/galleries';
$tab['#link']['title'] = t('Edit all galleries');
}
}
}
}
/**
* Implements hook_node_load().
*/
function media_gallery_node_load($nodes, $types) {
// Store a copy of the media_gallery_file field before mucking with it in
Jacob Singh
committed
// media_gallery_view(). We use hook_node_load() instead of hook_load(),
// because the latter runs before fields are loaded.
if (in_array('media_gallery', $types)) {
foreach ($nodes as $node) {
if ($node->type == 'media_gallery') {
$node->media_gallery_file_original = $node->media_gallery_file;
Jacob Singh
committed
}
}
}
}
/**
* Implements hook_view().
*/
function media_gallery_view($node, $view_mode) {
// Add display elements and resources for users who can edit the gallery.
if (node_access('update', $node)) {
// Add the "Add images" link, themed as a local action. Note that this
// element is listed in hook_field_extra_fields(), so whether or not it
// will *actually* be displayed in the current view mode depends on the
// site's configuration for the corresponding pseudo-field.
Jacob Singh
committed
'#theme' => 'menu_local_action',
'#link' => array(
Jacob Singh
committed
'href' => 'media/browser',
'localized_options' => array(
'query' => array('render' => 'media-popup'),
'attributes' => array(
'class' => 'media-gallery-add launcher',
),
),
),
// @todo Drupal could really use a theme_menu_local_actions() function...
'#prefix' => '<ul class="field action-links">',
'#suffix' => '</ul>',
);
// Enable the "Add media" link to launch the media browser.
module_load_include('inc', 'media', 'includes/media.browser');
media_attach_browser_js($node->content['add_media_link']);
$node->content['add_media_link']['#attached']['js'][] = drupal_get_path('module', 'media_gallery') . '/media_gallery.addimage.js';
// These JS settings are used by the "add media" link but some are also
// shared by the drag-and-drop code below.
$instance = field_info_instance('node', 'media_gallery_file', $node->type);
David Rothstein
committed
$token = drupal_get_token('media_gallery');
Jacob Singh
committed
$gallery_js_settings = array(
David Rothstein
committed
'mediaGalleryAddImagesUrl' => url('media-gallery/add-images/' . $node->nid . '/' . $token),
'mediaGallerySortGalleryUrl' => url('media-gallery/sort/gallery/' . $node->nid . '/' . $token),
'mediaGalleryAllowedMediaTypes' => array_filter($instance['widget']['settings']['allowed_types']),
Jacob Singh
committed
);
// When viewing the full node, add front-end resources for drag-and-drop
// sorting.
if ($view_mode == 'full') {
drupal_add_css(drupal_get_path('module', 'media_gallery') . '/media_gallery.dragdrop.css');
drupal_add_library('system', 'ui.sortable');
Alex Bronstein
committed
drupal_add_library('system', 'jquery.bbq');
Jacob Singh
committed
drupal_add_js(drupal_get_path('module', 'media_gallery') . '/media_gallery.dragdrop.js');
drupal_add_js($gallery_js_settings, array('type' => 'setting'));
}
else {
// Otherwise, attach the setting to the "add media" link, as per above.
$node->content['add_media_link']['#attached']['js'][] = array(
Jacob Singh
committed
'type' => 'setting',
'data' => $gallery_js_settings,
);
}
}
// For the teaser, only the first thumbnail needs to be displayed, so remove the
Jacob Singh
committed
// rest from the node's field data, so that the field formatter doesn't waste
// time building the render structure for items that won't be shown.
if ($view_mode == 'teaser') {
if (!empty($node->media_gallery_file[LANGUAGE_NONE])) {
if (media_access('view')) {
$first_item = array_shift($node->media_gallery_file[LANGUAGE_NONE]);
$node->media_gallery_file[LANGUAGE_NONE] = array($first_item);
$node->media_gallery_file[LANGUAGE_NONE] = array();
Jacob Singh
committed
}
}
// For the full display, implement pagination.
elseif ($view_mode == 'full' || $view_mode == 'media_gallery_block') {
$full = $view_mode == 'full' ? TRUE : FALSE;
if (!empty($node->media_gallery_file) && media_access('view')) {
$media = $node->media_gallery_file[LANGUAGE_NONE];
}
else {
$media = array();
}
Jacob Singh
committed
// Only display the requested number of media items per page.
$columns = $full ? $node->media_gallery_columns[LANGUAGE_NONE][0]['value'] : $node->media_gallery_block_columns[LANGUAGE_NONE][0]['value'];
$rows = $full ? $node->media_gallery_rows[LANGUAGE_NONE][0]['value'] : $node->media_gallery_block_rows[LANGUAGE_NONE][0]['value'];
Jacob Singh
committed
$number_per_page = $columns * $rows;
Jacob Singh
committed
$total = count($deltas);
// Initialize the pager and find out what page we are viewing.
$page = $full ? pager_default_initialize($total, $number_per_page, MEDIA_GALLERY_PAGER_ELEMENT) : 0;
Jacob Singh
committed
// Deny access to all media items that aren't on this page.
$min_on_page = $number_per_page * $page;
$max_on_page = $number_per_page * ($page + 1) - 1;
Jacob Singh
committed
foreach ($deltas as $key => $delta) {
Jacob Singh
committed
$fid = _media_gallery_get_media_fid($item);
if ($key < $min_on_page) {
$pre_links[$key] = array(
Jacob Singh
committed
'href' => 'media-gallery/detail/' . $node->nid . '/' . $fid,
'attributes' => array('class' => array('colorbox-supplemental-link pre')),
Jacob Singh
committed
);
Jacob Singh
committed
}
elseif ($key > $max_on_page) {
$post_links[$key] = array(
Jacob Singh
committed
'href' => 'media-gallery/detail/' . $node->nid . '/' . $fid,
'attributes' => array('class' => array('colorbox-supplemental-link post')),
Jacob Singh
committed
);
Jacob Singh
committed
}
}
// Field rendering requires sequential deltas, so re-key.
// @todo Open a Drupal core issue about this.
$node->media_gallery_file[LANGUAGE_NONE] = array_values($media);
$node->media_gallery_file[LANGUAGE_NONE] = array();
Jacob Singh
committed
// Create a set of dummy links to media items that don't appear on this
// page, so colorbox can link to them in the slideshow.
// @todo If the gallery contains 1000 media, then rendering each link takes
Jacob Singh
committed
// extra server-side time, extra network time to transfer the markup, and
// extra client-side time to initialize the DOM. Performance can likely be
// significantly improved if we only send the fids to Drupal.settings, and
// add JavaScript code to make that information usable by Colorbox.
$node->content['colorbox_links_pre'] = array(
'#theme' => 'links',
'#links' => $pre_links,
'#weight' => -20,
Alex Bronstein
committed
'#attributes' => array('class' => array('colorbox-supplemental-links')),
Jacob Singh
committed
);
$node->content['colorbox_links_post'] = array(
'#theme' => 'links',
'#links' => $post_links,
'#weight' => 20,
Alex Bronstein
committed
'#attributes' => array('class' => array('colorbox-supplemental-links')),
Jacob Singh
committed
);
// Finally, display the pager, with a high weight so it appears at the
// bottom.
if ($full) {
$node->content['media_gallery_pager'] = array(
'#theme' => 'pager',
'#element' => MEDIA_GALLERY_PAGER_ELEMENT,
'#weight' => 2000,
);
}
Jacob Singh
committed
}
return $node;
}
/**
* Implements hook_field_extra_fields().
*/
function media_gallery_field_extra_fields() {
// Allow the "Add media" link to be sorted with respect to the actual media
Jacob Singh
committed
// gallery fields.
$extra['node']['media_gallery'] = array(
'display' => array(
'add_media_link' => array(
'label' => t('"Add media" link'),
Jacob Singh
committed
'weight' => 1,
),
),
);
return $extra;
}
/**
* Access callback for AJAX-based gallery editing operations.
Jacob Singh
committed
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
* @param string $type
* The type of item being edited: 'gallery' for an individual gallery or
* 'collection' for a gallery collection.
* @param mixed $item
* For a media gallery, the $node object for that gallery; for gallery
* collections, the taxonomy term corresponding to the collection.
* @param string $token
* A token from drupal_get_token.
*/
function media_gallery_edit_access_ajax($type, $item, $token) {
if (!drupal_valid_token($token, 'media_gallery')) {
return FALSE;
}
switch ($type) {
case 'gallery':
return node_access('update', $item);
break;
case 'collection':
return user_access('administer media galleries');
break;
default:
return FALSE;
}
}
/**
* Implements hook_theme().
*/
function media_gallery_theme() {
return array(
'media_gallery_collection' => array(
'render element' => 'element',
'file' => 'media_gallery.theme.inc',
),
'media_gallery_teaser' => array(
'render element' => 'element',
'file' => 'media_gallery.theme.inc',
),
'media_gallery_media_item_thumbnail' => array(
'render element' => 'element',
'file' => 'media_gallery.theme.inc',
'template' => 'media-gallery-media-item-thumbnail',
),
'media_gallery_media_item_lightbox' => array(
'render element' => 'element',
'file' => 'media_gallery.theme.inc',
),
'media_gallery_media_item_detail' => array(
'render element' => 'element',
'file' => 'media_gallery.theme.inc',
),
'media_gallery_block_thumbnail' => array(
'render element' => 'element',
'file' => 'media_gallery.theme.inc',
),
'media_gallery_collection_thumbnail' => array(
'render element' => 'element',
'file' => 'media_gallery.theme.inc',
),
'media_gallery_download_link' => array(
'variables' => array('file' => NULL, 'text' => NULL, 'options' => array()),
'file' => 'media_gallery.theme.inc',
),
'media_gallery_meta' => array(
'variables' => array('display' => NULL, 'location' => NULL, 'title' => NULL, 'license' => NULL, 'description' => NULL),
Jacob Singh
committed
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
'file' => 'media_gallery.theme.inc',
),
'media_gallery_item' => array(
'variables' => array('image' => NULL, 'link_path' => NULL, 'classes' => NULL),
'file' => 'media_gallery.theme.inc',
),
'media_gallery_license' => array(
'variables' => array('element' => NULL, 'color' => 'dark'),
'file' => 'media_gallery.theme.inc',
),
'media_gallery_file_field_inline' => array(
'render element' => 'element',
'file' => 'media_gallery.theme.inc',
),
);
}
/**
* Implements hook_permission().
*/
function media_gallery_permission() {
return array(
'administer media galleries' => array(
'title' => t('Administer media galleries'),
),
);
}
/**
* Implements hook_node_info().
*/
function media_gallery_node_info() {
return array(
'media_gallery' => array(
'name' => t('Gallery'),
'base' => 'media_gallery',
'description' => t('A flexible gallery of media.'),
'help' => t('Create a gallery of thumbnails including custom display settings. Once your gallery is saved, your media can be added.'),
Jacob Singh
committed
),
);
}
/**
* Implements hook_update().
*/
function media_gallery_update($node) {
// If the media gallery node is being saved and is configured to not provide
// a block, remove all blocks associated with it from the database. The block
// module might not be installed, so we need to check that the database table
// exists before querying it.
if (empty($node->media_gallery_expose_block[LANGUAGE_NONE][0]['value']) && db_table_exists('block')) {
Jacob Singh
committed
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
db_delete('block')
->condition('module', 'media_gallery')
->condition('delta', $node->nid)
->execute();
}
}
/**
* Implements hook_block_info().
*/
function media_gallery_block_info() {
$blocks = array();
// Define a block for each media gallery node that is configured to expose
// one.
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node');
$query->entityCondition('bundle', 'media_gallery');
$query->fieldCondition('media_gallery_expose_block', 'value', 1);
$result = $query->execute();
if (!empty($result['node'])) {
// There is no reason to waste going through a full node_load_multiple()
// when we only need the titles.
$nids = array_keys($result['node']);
$node_titles = db_query("SELECT nid, title FROM {node} WHERE nid IN (:nids)", array(':nids' => $nids))->fetchAllKeyed();
foreach ($node_titles as $nid => $title) {
// The 'info' element is escaped on display, so we pass it through
// unfiltered here.
$blocks[$nid]['info'] = t('Recent gallery items: !title', array('!title' => $title));
$blocks[$nid]['visibility'] = 0;
$blocks[$nid]['pages'] = 'node/' . $nid . "\ngalleries";
}
}
Jacob Singh
committed
return $blocks;
}
Jacob Singh
committed
/**
* Implements hook_block_view().
*/
function media_gallery_block_view($delta = '') {
$node = node_load($delta);
if (empty($node->media_gallery_expose_block[LANGUAGE_NONE][0]['value'])) {
// Bail out now if the node doesn't exist or if it is configured not to
// display a block.
$block['subject'] = NULL;
$block['content'] = '';
}
elseif (empty($node->media_gallery_file_original) || !media_access('view')) {
Jacob Singh
committed
// Bail out now if there won't be any media items to show.
$block['subject'] = check_plain($node->title);
Jacob Singh
committed
$block['content'] = t('No content available.');
}
else {
// Collect an array of file IDs associated with this gallery. For
// simplicity we will assume (here and below) that this is not a
// multilingual field. Also note that the node may have been loaded and
// viewed elsewhere on the page, in which case the 'media_gallery_file'
Jacob Singh
committed
// field was modified and does not contain what we want, so we have to go
// back to the original field value set in hook_node_load() instead, and
// also clone the node before changing it so our modifications do not
// affect other places where it might be being viewed.
$node = clone $node;
$node->media_gallery_file = $node->media_gallery_file_original;
$files = &$node->media_gallery_file[LANGUAGE_NONE];
Jacob Singh
committed
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
$gallery_fids = array();
foreach ($files as $file) {
$gallery_fids[] = _media_gallery_get_media_fid($file);
}
// Construct a list of file IDs that is limited to the specified number of
// items and ordered by most recent; these are the files that will be
// displayed in the block.
$columns = !empty($node->media_gallery_block_columns[LANGUAGE_NONE][0]['value']) ? $node->media_gallery_block_columns[LANGUAGE_NONE][0]['value'] : 1;
$rows = !empty($node->media_gallery_block_rows[LANGUAGE_NONE][0]['value']) ? $node->media_gallery_block_rows[LANGUAGE_NONE][0]['value'] : 1;
$number_to_show = $columns * $rows;
$block_fids = db_select('file_managed', 'f')
->fields('f', array('fid'))
->condition('fid', $gallery_fids, 'IN')
->orderBy('timestamp', 'DESC')
->range(0, $number_to_show)
->execute()
->fetchCol();
// Before sorting, remove any items that will not display in the block.
$fid_order = array_flip($block_fids);
if ($number_to_show < count($files)) {
foreach ($files as $key => $file) {
if (!isset($fid_order[_media_gallery_get_media_fid($file)])) {
unset($files[$key]);
}
}
}
// Prepare the sorting function with the list of file ID orders.
_media_gallery_sort_by_recent(NULL, NULL, $fid_order);
// Perform the sort.
usort($files, '_media_gallery_sort_by_recent');
// Display the block.
$block['subject'] = check_plain($node->title);
David Rothstein
committed
$block['content']['gallery'] = node_view($node, 'media_gallery_block');
// Move the node's contextual links so that they display on the block
// rather than the node (i.e., in the same dropdown as the "Configure
// block" link). This is also required in order to properly integrate with
// the code in media_gallery_contextual_links_view_alter().
if (isset($block['content']['gallery']['#contextual_links'])) {
$block['content']['#contextual_links'] = $block['content']['gallery']['#contextual_links'];
unset($block['content']['gallery']['#contextual_links']);
}
Jacob Singh
committed
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
$block['content']['more_link'] = array(
'#theme' => 'more_link',
'#url' => 'node/' . $node->nid,
'#title' => t('Show the complete gallery'),
'#weight' => 1000,
);
}
return $block;
}
/**
* Implements hook_block_configure().
*/
function media_gallery_block_configure($delta = '') {
// Duplicate the form for configuring media gallery node fields, including
// our module's custom alterations. We can't use drupal_get_form() here
// because that will mess up the form submission, so for now we have to live
// without getting any other module's alterations to this part of the node
// form.
$node = node_load($delta);
$form = array();
$form_state = array();
field_attach_form('node', $node, $form, $form_state, $node->language);
media_gallery_form_media_gallery_node_form_alter($form, $form_state);
// Pull out only the parts of the node form that allow configuration of the
// block settings; these are the ones we want to display.
Jacob Singh
committed
// Store a record of all node fields that we will need to save when
// hook_block_save() is called.
$block_settings['block']['media_gallery_block_fields'] = array(
Jacob Singh
committed
'#type' => 'value',
'#value' => element_children($block_settings['block']),
Jacob Singh
committed
);
// Don't allow people to destroy the block itself from the block
// configuration page.
$block_settings['block']['media_gallery_expose_block']['#access'] = FALSE;
Jacob Singh
committed
// Customize the fieldset display.
$block_settings['block']['#collapsible'] = FALSE;
$block_settings['block']['#title'] = t('Block settings');
unset($block_settings['block']['#weight']);
Jacob Singh
committed
// Add the necessary attached JS and CSS.
_media_gallery_attach_form_resources($block_settings['block']);
Jacob Singh
committed
return $block_settings;
}
/**
* Implements hook_block_save().
*/
function media_gallery_block_save($delta = '', $edit = array()) {
// Save the block-related media gallery fields on the node.
$node = node_load($delta);
foreach ($edit['media_gallery_block_fields'] as $field) {
$node->{$field} = $edit[$field];
}
node_save($node);
}
/**
* Implements hook_library().
*/
function media_gallery_library() {
$colorbox_path = variable_get('media_gallery_library_path', FALSE);
if ($colorbox_path === FALSE ) {
$colorbox_path = module_exists('libraries') ? libraries_get_path('colorbox') : 'sites/all/libraries/colorbox';
}
else {
$colorbox_path .= '/colorbox';
}
Jacob Singh
committed
$stylesheet = variable_get('media_gallery_colorbox_stylesheet', 'example1');
$libraries['colorbox'] = array(
'title' => 'Colorbox',
'website' => 'http://colorpowered.com/colorbox/',
'version' => '1.3.9',
'js' => array(
$colorbox_path . '/colorbox/jquery.colorbox-min.js' => array(),
Jacob Singh
committed
),
'css' => array(
$colorbox_path . '/' . $stylesheet . '/colorbox.css' => array(
Jacob Singh
committed
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
'type' => 'file',
'media' => 'screen',
),
),
);
return $libraries;
}
/**
* Helper function to sort media gallery items by an ordered list of file IDs.
*
* Call once with $set_fid_order set to an array of file orders, keyed by the
* file ID, before performing the actual sort.
*/
function _media_gallery_sort_by_recent($a, $b, $set_fid_order = NULL) {
$fid_order = &drupal_static(__FUNCTION__, array());
// Stored the ordered list if this is a preparatory call.
if (isset($set_fid_order)) {
$fid_order = $set_fid_order;
return;
}
// Otherwise, perform the sort.
$a_order = $fid_order[_media_gallery_get_media_fid($a)];
$b_order = $fid_order[_media_gallery_get_media_fid($b)];
if ($a_order < $b_order) {
return -1;
}
elseif ($b_order < $a_order) {
return 1;
}
else {
return 0;
}
}
/**
* Returns the number of files of each type attached to a media gallery node.
*/
function media_gallery_get_media_type_count($node, $media_field = 'media_gallery_file') {
$fids = media_gallery_get_file_ids($node, $media_field);
if (empty($fids)) {
return array();
}
$query = db_select('file_managed', 'f');
$type = $query->addField('f', 'type');
$query->addExpression('COUNT(*)');
$type_count = $query->condition('f.fid', $fids, 'IN')
->groupBy($type)
->execute()
->fetchAllKeyed();
return $type_count;
}
Jacob Singh
committed
/**
* Returns all file IDs attached to a media gallery node.
*/
function media_gallery_get_file_ids($node, $media_field = 'media_gallery_file') {
Jacob Singh
committed
$fids = array();
$media_items = _media_gallery_field_get_items('node', $node, $media_field);
if ($media_items !== FALSE) {
lsolesen
committed
foreach ($media_items as $item) {
$fids[] = _media_gallery_get_media_fid($item);
}
Jacob Singh
committed
}
return drupal_map_assoc($fids);
}
* media_gallery_file_original is not a field and therefore cannot be used by field_get_items.
*/
function _media_gallery_field_get_items($entity_type, $entity, $field_name, $langcode = NULL) {
if ($entity_type == 'node' && $field_name == 'media_gallery_file_original') {
$media = $entity->media_gallery_file;
$entity->media_gallery_file = $entity->media_gallery_file_original;
$field_name = 'media_gallery_file';
}
$items = field_get_items($entity_type, $entity, $field_name, $langcode);
if (isset($media)) {
$entity->media_gallery_file = $media;
}
return $items;
}
Jacob Singh
committed
/**
* Determines the file ID from a media file array or object.
*
* This is ugly, but necessary since a media field attached to a node may
* be represented either as an array or a full object, depending on whether the
* node has been processed for viewing yet or not.
*
* @param $file
* Either a media file object or media file array.
*
* @return
* The value of the 'fid' object property or array key.
*/
function _media_gallery_get_media_fid($file) {
return is_object($file) ? $file->fid : $file['fid'];
}
/**
* Removes a media item from a gallery.
*
* @param $node
* The gallery node object.
Alex Bronstein
committed
* @param $file
* The file to remove from the gallery.
Jacob Singh
committed
*
* @return
* The updated gallery node object.
*/
Alex Bronstein
committed
function media_gallery_remove_item_from_gallery($node, $file) {
$items = &$node->media_gallery_file[LANGUAGE_NONE];
Jacob Singh
committed
foreach ($items as $key => $item) {
Alex Bronstein
committed
if ($file->fid == _media_gallery_get_media_fid($item)) {
Jacob Singh
committed
unset($items[$key]);
}
}
node_save($node);
return $node;
}
/**
* Implements hook_entity_info_alter().
*/
Alex Bronstein
committed
function media_gallery_entity_info_alter(&$entity_info) {
// Add view modes for displaying files in gallery contexts.
foreach (media_gallery_file_view_modes() as $view_mode => $label) {
$entity_info['file']['view modes'][$view_mode] = array('label' => $label, 'custom settings' => FALSE);
Jacob Singh
committed
}
Alex Bronstein
committed
// Add a view mode for media_gallery_block_view() to use for displaying a
// media gallery node in a block. Drupal does not support restricting view
// modes to specific bundles.
$entity_info['node']['view modes']['media_gallery_block'] = array('label' => t('Media gallery block'), 'custom settings' => FALSE);
Jacob Singh
committed
}
/**
* Implements hook_form().
*/
function media_gallery_form($node, $form_state) {
$form = node_content_form($node, $form_state);
return $form;
}
/**
* Implements hook_form_alter().
*/
function media_gallery_form_alter(&$form, &$form_state, $form_id) {
if (strpos($form_id, 'media_edit') === 0) {
Jacob Singh
committed
// Act on both the regular and multiform versions of the edit form.
if ($form_id === 'media_edit' || preg_match('/^media_edit_[0-9]+$/', $form_id)) {
// Prepopulate the media_edit form with our best guess at the image title.
Jacob Singh
committed
if (!empty($form['media_title']) && empty($form['media_title'][LANGUAGE_NONE][0]['value']['#default_value'])) {
$fid = $form['fid']['#value'];
Alex Bronstein
committed
$file = file_load($fid);
if ($file->type === 'image') {
$form['media_title'][LANGUAGE_NONE][0]['value']['#default_value'] = _media_gallery_get_media_title($file);
Jacob Singh
committed
}
}
// Prepopulate the license field with the correct default.
if ($form['field_license'][LANGUAGE_NONE]['#default_value'] == '_none') {
$form['field_license'][LANGUAGE_NONE]['#default_value'] = 'none';
}
unset($form['field_license'][LANGUAGE_NONE]['#options']['_none']);
Jacob Singh
committed
}
David Rothstein
committed
// Attach JavaScript and CSS needed to alter elements in the form.
_media_gallery_attach_edit_resources($form);
Jacob Singh
committed
}
}
/*
* Implements hook_form_FORM_ID_alter().
*/
function media_gallery_form_media_gallery_node_form_alter(&$form, &$form_state) {
_media_gallery_attach_form_resources($form);
// The UI for the multi value media field and the node weight is elsewhere.
$form['media_gallery_file']['#access'] = FALSE;
Jacob Singh
committed
$form['media_gallery_weight']['#access'] = FALSE;
Jacob Singh
committed
// Hiding this field because we only support a single collection at the moment.
$form['media_gallery_collection']['#access'] = FALSE;
// Wrap a fieldset around the gallery settings.
$form['settings_wrapper'] = array(
'#type' => 'fieldset',
'#title' => t('Gallery settings'),
'#weight' => 10,
);
unset($form['media_gallery_lightbox_extras'][LANGUAGE_NONE]['#description']);
$form['media_gallery_lightbox_extras'][LANGUAGE_NONE]['#label'] = 'Show title and description';
Jacob Singh
committed
// These are the items that need to be added to the fieldset. The array
// values represent a subgroup within the fieldset array that the items are
// further grouped by.
$fieldset = array(
'media_gallery_columns' => 'gallery',
'media_gallery_rows' => 'gallery',
'media_gallery_image_info_where' => 'gallery',
'media_gallery_allow_download' => 'presentation',
'media_gallery_format' => 'presentation',
'media_gallery_lightbox_extras' => 'presentation',
);
// Move the items to the fieldset.
foreach ($fieldset as $id => $subgroup) {
$form['settings_wrapper'][$subgroup][$id] = $form[$id];
Alex Bronstein
committed
// locale_field_node_form_submit() looks for field language information in
// a hard-coded part of $form.
// @todo Other modules may as well, so would be best to move form elements
// within #pre_render rather than in hook_form_alter().
$form[$id] = array('#language' => $form[$id]['#language']);
}
// Add a vertical tab menu for blocks
$form['block'] = array(
'#type' => 'fieldset',
'#title' => 'Blocks',
'#collapsible' => TRUE,
'#collapsed' => FALSE,
'#group' => 'additional_settings',
'#attached' => array(),
'#weight' => -100,
);
$fieldset = array(
Jacob Singh
committed
'media_gallery_expose_block' => 'block',
'media_gallery_block_columns' => 'block',
'media_gallery_block_rows' => 'block',
);
// Move the items to the fieldset.
foreach ($fieldset as $id => $subgroup) {
Alex Bronstein
committed
// locale_field_node_form_submit() looks for field language information in
// a hard-coded part of $form.
// @todo Other modules may as well, so would be best to move form elements
// within #pre_render rather than in hook_form_alter().
$form[$id] = array('#language' => $form[$id]['#language']);
Jacob Singh
committed
}
// Add a class to the fieldset to target it in the js
$form['block']['#attributes']['class'] = array('block-form');
Jacob Singh
committed
// Add classes where necessary for JS enhancement.
$form['settings_wrapper']['gallery']['media_gallery_image_info_where']['#attributes']['class'][] = 'form-inline label';
$form['settings_wrapper']['gallery']['media_gallery_image_info']['#attributes']['class'][] = 'form-inline';
// Use #prefix and #suffix to group the fields.
$form['settings_wrapper']['presentation']['media_gallery_format']['#attributes']['class'][] = 'media-gallery-show no-group-label';