Projet

Général

Profil

Paste
Télécharger (19,1 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / calendar / calendar.module @ 87dbc3bf

1
<?php
2
define('CALENDAR_SHOW_ALL', 0);
3
define('CALENDAR_HIDE_ALL', -1);
4
define('CALENDAR_EMPTY_STRIPE', '#ffffff');
5

    
6
/**
7
 * @file
8
 * Adds calendar filtering and displays to Views.
9
 */
10
/**
11
 * Implements hook_menu().
12
 */
13
function calendar_menu() {
14
  $items = array();
15
  $items['admin/config/date/calendar'] = array(
16
    'title' => 'Calendar',
17
    'description' => 'Calendar administration.',
18
    'page callback' => 'drupal_get_form',
19
    'page arguments' => array('calendar_admin_settings'),
20
    'access callback' => 'user_access',
21
    'access arguments' => array('administer site configuration'),
22
  );
23
  return $items;
24
}
25

    
26
/**
27
 * General Calendar administration.
28
 */
29
function calendar_admin_settings() {
30
  $form = array();
31

    
32
  $form['#prefix']  = '<h2>Calendar Administration</h2>';
33

    
34
  $form['calendar_track_date'] = array(
35
    '#title' => t('Track current date in session'),
36
    '#type' => 'radios',
37
    '#options' => array(0 => t("Never"), 1 => t('For authenticated users'), 2 => t('For all users')),
38
    '#default_value' => variable_get('calendar_track_date', 0),
39
    '#description' => t("Store session information about the user's current date as they move back and forth through the calendar. Without this setting users will revert to the current day each time they choose a new calendar period (year, month, week, or day). With this option set they will move to a day that conforms to the time period they were viewing before they switched. Requires session tracking which is not ordinarily enabled for anonymous users."),
40
    );
41

    
42
  $form['calendar_add_colorbox'] = array(
43
    '#title' => t('Add Colorbox settings to Node calendar templates'),
44
    '#default_value' => variable_get('calendar_add_colorbox'),
45
    '#type' => 'radios',
46
    '#options' => array(0 => t('No'), 1 => t('Yes')),
47
    '#description' => t('To try the Colorbox settings, choose the option to add Colorbox settings to the calendar templates. Install and enable the Colorbox module, following the instructions on the Colorbox project page, then create a new calendar from a template using any date field in the Node base table. The calendar will be set up to display the calendar items in a Colorbox.'),
48
    );
49

    
50
  return system_settings_form($form);
51
}
52

    
53
/**
54
 * Implements hook_preprocess_date_views_pager().
55
 *
56
 * Creates a calendar_links array which is stored in the session and used
57
 * in calendar_menu_local_tasks_alter() to display the links as action items.
58
 * The links can be altered or deleted using hook_calendar_links_alter().
59
 *
60
 */
61
function calendar_preprocess_date_views_pager(&$vars) {
62
  $view = $vars['plugin']->view;
63

    
64
  // If no one has added date information, nothing to do here.
65
  if (empty($view->date_info) || empty($view->argument)) {
66
    return;
67
  }
68

    
69
  // If we're not on a view with a path (a page), no links are needed.
70
  $current_path = !empty($view->display_handler->options['path']) ? $view->display_handler->options['path'] : '';
71
  if (empty($current_path)) {
72
    return;
73
  }
74

    
75
  // If this display has been set up as a default tab, the current path
76
  // is actually the base path, i.e. if the path is 'calendar/month'
77
  // and this is a default tab, the path for this display will actually
78
  // be 'calendar'.
79
  if ($view->display_handler->options['menu']['type'] == 'default tab') {
80
    $parts = explode('/', $current_path);
81
    array_pop($parts);
82
    $current_path = implode('/', $parts);
83
  }
84

    
85
  // If an 'Add new ... link is provided, add it here.
86
  if (!empty($view->date_info->calendar_date_link) && !empty($view->date_info->url)
87
  && (user_access("administer nodes") || user_access('create ' . $view->date_info->calendar_date_link . ' content'))) {
88
    $name = node_type_get_name($view->date_info->calendar_date_link);
89
    $href = 'node/add/' . str_replace('_', '-', $view->date_info->calendar_date_link);
90
    $calendar_links[$current_path]['actions'][] = array('title' => t('Add @name', array('@name' => $name)), 'path' => $href);
91
  }
92

    
93
  // Pass this through drupal_alter() so it can be adjusted in custom code or in the theme.
94
  drupal_alter('calendar_links', $calendar_links);
95

    
96
  // Add the value to the session so it can be used to create the action links.
97
  if (!empty($calendar_links[$current_path])) {
98
    $_SESSION['calendar_links'][$current_path] = $calendar_links[$current_path];
99
  }
100
}
101

    
102
/**
103
 * Implements hook_date_default_argument_alter().
104
 *
105
 * Adjust the default date for a view based on the stored session value.
106
 */
107
function calendar_date_default_argument_alter(&$argument, &$value) {
108
  global $user;
109
  $style_options = $argument->view->display_handler->get_option('style_options');
110
  $tracking = variable_get('calendar_track_date', 0);
111
  if (!empty($tracking) && ($tracking == 2 || !empty($user->uid))) {
112

    
113
    // If this is a default date, i.e. we are visiting a new calendar display,
114
    // set the default date for the display. See if we already have a session
115
    // date to use. If so, use it. Otherwise the default is the current date.
116
    if (!empty($_SESSION[$argument->view->name]['default_date'])) {
117
      $default_date = $_SESSION[$argument->view->name]['default_date'];
118
    }
119
    else {
120
      $default_date = date_now();
121
      $_SESSION[$argument->view->name]['default_date'] = $default_date;
122
    }
123
    // Get the current date from the session.
124
    $value = $default_date->format($argument->arg_format);
125
  }
126
}
127

    
128
/**
129
 * Implements hook_views_pre_render().
130
 *
131
 * Track the current date as the user moves from calendar display to calendar display.
132
 */
133
function calendar_views_pre_render(&$view) {
134
  global $user;
135

    
136
  $style_options = $view->display_handler->get_option('style_options');
137
  $tracking = variable_get('calendar_track_date', 0);
138
  if (!empty($tracking) && ($tracking == 2 || !empty($user->uid))) {
139
    foreach ($view->argument as $id => &$argument) {
140

    
141
      // If this is not a default date, i.e. we have browsed to a new calendar
142
      // period on a display we were already on, store the midpoint of the current
143
      // view as the current date in a session.
144
      if (date_views_handler_is_date($argument, 'argument') && empty($argument->is_default)) {
145
        $date_range = $argument->date_handler->arg_range($argument->argument);
146
        $session_date = $date_range[0];
147
        $days = intval(($date_range[1]->format('U') - $date_range[0]->format('U')) / 3600 / 24 / 2);
148
        date_modify($session_date, "+$days days");
149
        $_SESSION[$view->name]['default_date'] = $session_date;
150
      }
151
    }
152
  }
153
}
154

    
155
/**
156
 * Implements hook_menu_local_tasks_alter().
157
 *
158
 * Takes the calendar links created in calendar_preprocess_date_views_pager()
159
 * and reconfigures them as action items. The links can be altered
160
 * before they are displayed using hook_calendar_links_alter().
161
 */
162
function calendar_menu_local_tasks_alter(&$data, $router_item, $root_path) {
163
  if (!empty($_SESSION['calendar_links']) && array_key_exists($root_path, $_SESSION['calendar_links'])) {
164
    $calendar_data = $_SESSION['calendar_links'][$root_path];
165
    if (!empty($calendar_data['actions'])) {
166
      foreach ($calendar_data['actions'] as $action) {
167
        $item = menu_get_item($action['path']);
168
        $item['title'] = $action['title'];
169
        // The add new content page would redirect to the new event
170
        // if we did not override that here. This way they will
171
        // redirect back to the calendar.
172
	if (!isset($item['localized_options'])) {
173
          $item['localized_options'] = array();
174
        }
175
        $item['localized_options'] += array('query' => array());
176
        $item['localized_options']['query'] += drupal_get_destination();
177
        if (array_key_exists('access', $item) && $item['access']) {
178
          $data['actions']['output'][] = array(
179
            '#theme' => 'menu_local_action',
180
            '#link' => $item,
181
          );
182
        }
183
      }
184
    }
185
  }
186
  return;
187
}
188

    
189
/**
190
 * Implements hook_views_api().
191
 */
192
function calendar_views_api() {
193
  return array(
194
    'api' => 3.0,
195
    'path' => drupal_get_path('module', 'calendar') . '/includes',
196
  );
197
}
198

    
199
/**
200
 * Calendar display types.
201
 */
202
function calendar_display_types() {
203
  return array('year' => t('Year'), 'month' => t('Month'), 'day' => t('Day'), 'week' => t('Week'));
204
}
205

    
206
/**
207
 * Implementation of hook_help().
208
 */
209
function calendar_help($section, $arg) {
210
  switch ($section) {
211
    case 'admin/help#calendar':
212
      return t("<p>View complete documentation at !link.</p>", array('!link' => l(t('Date and Calendar Documentation'), 'http://drupal.org/node/262062')));
213
  }
214
}
215

    
216
/**
217
 * Implements hook_theme().
218
 */
219
function calendar_theme() {
220
  $module_path = drupal_get_path('module', 'calendar');
221

    
222
  $base = array(
223
    'file' => 'theme.inc',
224
    'path' => "$module_path/theme",
225
  );
226
  return array(
227
    'calendar_item' => $base + array(
228
      'template' => 'calendar-item',
229
      'variables' => array('view' => NULL, 'rendered_fields' => NULL, 'item' => NULL),
230
      ),
231
    'calendar_datebox' => $base + array(
232
      'template' => 'calendar-datebox',
233
      'variables' => array(
234
        'date' => NULL, 'view' => NULL, 'items' => NULL, 'selected' => NULL),
235
      ),
236
    'calendar_empty_day' => $base + array(
237
      'variables' => array('curday' => NULL, 'view' => NULL),
238
      ),
239
    'calendar_stripe_legend' => $base + array(
240
      'variables' => array('view' => NULL),
241
      ),
242
    'calendar_stripe_stripe' => $base + array(
243
      'variables' => array('node' => NULL),
244
      ),
245
    'calendar_time_row_heading' => $base + array(
246
      'variables' => array('start_time' => NULL, 'next_start_time' => NULL, 'curday_date' => NULL),
247
      ),
248
    'calendar_month_col' => $base + array(
249
      'template' => 'calendar-month-col',
250
      'variables' => array('item' => NULL),
251
      ),
252
    'calendar_month_row' => $base + array(
253
      'template' => 'calendar-month-row',
254
      'variables' => array('inner' => NULL, 'class' => NULL, 'iehint' => NULL),
255
      ),
256
    'calendar_month_multiple_entity' => $base + array(
257
      'template' => 'calendar-month-multiple-entity',
258
      'variables' => array('
259
         curday' => NULL, 'count' => NULL, 'view' => NULL, 'ids' => NULL),
260
      ),
261
    );
262
}
263

    
264
/**
265
 * Implements hook_node_view().
266
 *
267
 * Add link to calendar to nodes, formerly hook_link().
268
 * Controlled by value of 'calendar_date_link' in the view.
269
 */
270
function calendar_node_view($node, $view_mode, $langcode) {
271
  $path = variable_get('calendar_date_link_' . $node->type);
272
  if (!empty($path)) {
273
    $links['calendar_link'] = array(
274
      'title' => t('Calendar'),
275
      'href' => $path,
276
      'attributes' => array('title' => t('View the calendar.')),
277
    );
278
    $node->content['links']['calendar'] = array(
279
      '#theme' => 'links__node__caledar',
280
      '#links' => $links,
281
      '#attributes' => array('class' => array('links', 'inline')),
282
    );
283
  }
284
}
285

    
286
/**
287
 * Helper function to link an entity type to a calendar.
288
 *
289
 * @param $entity_type - the type of entity.
290
 * @param $bundle - the entity bundle name.
291
 * @param $path - the calendar path to use for this bundle.
292
 */
293
function calendar_set_link($entity_type, $bundle, $path) {
294
  switch ($entity_type) {
295
    case 'node':
296
      variable_set('calendar_date_link_' . $bundle, $path);
297
      break;
298
    default:
299
      variable_set('calendar_date_link_' . $entity_type . '_' . $bundle, $path);
300
      break;
301
  }
302
}
303

    
304
/**
305
 * Helper function to clear previously-set links to calendars.
306
 *
307
 * @param $bundle, Clear all links for this bundle. If NULL, clear all links.
308
 */
309
function calendar_clear_link_bundle($bundle = NULL) {
310
  if (empty($bundle)) {
311
    $result = db_select('variable', 'v')
312
      ->fields('v', 'name')
313
      ->condition('name', 'calendar_date_link_%', 'LIKE')
314
      ->execute()->fetchAll(PDO::FETCH_ASSOC);
315
  }
316
  else {
317
    $result = db_select('variable', 'v')
318
      ->fields('v', 'name')
319
      ->condition('name', 'calendar_date_link_' . $bundle)
320
      ->execute()->fetchAll(PDO::FETCH_ASSOC);
321
  }
322
  // Iterate over all the values and delete them.
323
  foreach ($result as $row) {
324
    variable_del($row['name']);
325
  }
326
}
327

    
328
/**
329
 * Helper function to clear previously-set links to calendars.
330
 *
331
 * @param $path, Clear all links to this path. If NULL, clear all links.
332
 */
333
function calendar_clear_link_path($path = NULL) {
334
  $result = db_select('variable', 'v')
335
    ->fields('v', array('name', 'value'))
336
    ->condition('name', 'calendar_date_link_%', 'LIKE')
337
    ->execute()->fetchAll(PDO::FETCH_ASSOC);
338
  // Iterate over all the values and delete them.
339
  foreach ($result as $row) {
340
    if (empty($path) || unserialize($row['value']) == $path) {
341
      variable_del($row['name']);
342
    }
343
  }
344
  if (isset($_SESSION['calendar_links'][$path]['actions'])) {
345
    unset($_SESSION['calendar_links'][$path]['actions']);
346
    if (empty($_SESSION['calendar_links'][$path])) {
347
      unset($_SESSION['calendar_links'][$path]);
348
    }
349
  }
350
}
351

    
352
/**
353
 * Formats the weekday information into table header format
354
 *
355
 * @ingroup event_support
356
 * @return array with weekday table header data
357
 */
358
function calendar_week_header($view) {
359
  $len = isset($view->date_info->style_name_size) ? $view->date_info->style_name_size : (!empty($view->date_info->mini) ? 1 : 3);
360
  $with_week = !empty($view->date_info->style_with_weekno);
361

    
362
  // create week header
363
  $untranslated_days = calendar_untranslated_days();
364
  $full_translated_days = date_week_days_ordered(date_week_days(TRUE));
365
  if ($len == 99) {
366
    $translated_days = $full_translated_days;
367
  }
368
  else {
369
    $translated_days = date_week_days_ordered(date_week_days_abbr(TRUE));
370
  }
371
  if ($with_week) {
372
    $row[] = array('header' => TRUE, 'class' => "days week", 'data' => '&nbsp;', 'header_id' => 'Week');
373
  }
374
  foreach ($untranslated_days as $delta => $day) {
375
    $label = $len < 3 ? drupal_substr($translated_days[$delta], 0 , $len) : $translated_days[$delta];
376
    $row[] = array('header' => TRUE, 'class' => "days " . $day, 'data' => $label, 'header_id' => $full_translated_days[$delta]);
377
  }
378
  return $row;
379
}
380

    
381
/**
382
 * Array of untranslated day name abbreviations, forced to lowercase
383
 * and ordered appropriately for the site setting for the first day of week.
384
 *
385
 * The untranslated day abbreviation is used in css classes.
386
 */
387
function calendar_untranslated_days() {
388
  $untranslated_days = date_week_days_ordered(date_week_days_untranslated());
389
  foreach ($untranslated_days as $delta => $day) {
390
    $untranslated_days[$delta] = strtolower(substr($day, 0, 3));
391
  }
392
  return $untranslated_days;
393
}
394

    
395
/**
396
 * Default settings array for calendar time grouping.
397
 */
398
function calendar_groupby_times($type = '') {
399
  $times = array();
400
  switch ($type) {
401
    case 'hour':
402
      for ($i = 0; $i <= 23; $i++) {
403
        $times[] = date_pad($i) . ':00:00';
404
      }
405
      break;
406
    case 'half':
407
      for ($i = 0; $i <= 23; $i++) {
408
        $times[] = date_pad($i) . ':00:00';
409
        $times[] = date_pad($i) . ':30:00';
410
      }
411
      break;
412
    default:
413
      break;
414
  }
415
  return $times;
416
}
417

    
418
function calendar_list_views() {
419
  $calendar_views = array();
420
  $views = views_get_enabled_views();
421
  foreach ($views as $view) {
422
    $displays = array();
423
    $view->init_display();   // Make sure all the handlers are set up
424
    foreach ($view->display as $display_id => $display) {
425
      if ($display_id != 'default' && !empty($display->display_options['style_plugin']) && $display->display_options['style_plugin'] == 'calendar_style') {
426
        $index = $view->name . ':' . $display_id;
427
        $calendar_views[$index] = ucfirst($view->name) . ' ' . strtolower($view->display[$display_id]->display_title) . ' [' . $view->name . ':' . $display_id . ']';
428
      }
429
    }
430
  }
431
  return $calendar_views;
432
}
433

    
434
/**
435
 *  Implementation of hook_block_info()
436
 */
437
function calendar_block_info() {
438
  $blocks['calendar_legend'] = array(
439
    'info' => t('Calendar Legend'),
440
  );
441
  return $blocks;
442
}
443

    
444
/**
445
 * Implementation of hook_block_configure().
446
 */
447
function calendar_block_configure($delta = '') {
448
  switch ($delta) {
449
    case 'calendar_legend':
450
    $options = calendar_list_views();
451
    $form['calendar_legend_view'] = array(
452
      '#type' => 'select',
453
      '#title' => t('Legend View'),
454
      '#description' => t('Choose the view display that contains the settings for the stripes that should be displayed in a legend in this block. Note that if you change the stripe values in that view you will need to clear the cache to pick up the new values in this block.'),
455
      '#default_value' => variable_get('calendar_legend_view_' . $delta, ''),
456
      '#options' => $options,
457
    );
458
    return $form;
459
  }
460
}
461

    
462
/**
463
 * Implementation of hook_block_save().
464
 */
465
function calendar_block_save($delta, $edit = array()) {
466
  if ($delta == 'calendar_legend') {
467
    variable_set('calendar_legend_view_' . $delta, $edit['calendar_legend_view']);
468
    drupal_set_message(t('The view for the calendar legend has been set.'));
469
  }
470
}
471

    
472
/**
473
 *  Implementation of hook_block_view().
474
 */
475
function calendar_block_view($delta = '') {
476
  switch ($delta) {
477
    case 'calendar_legend':
478
      // Create the content before returning the block
479
      // so empty content won't still create the block.
480
      $view = variable_get('calendar_legend_view_' . $delta, '');
481
      $content = theme('calendar_stripe_legend', array('view' => $view));
482
      $block['subject'] = t('Calendar Legend');
483
      $block['content'] = $content;
484
      return $block;
485
  }
486
}
487

    
488
/**
489
 * Find the path for the calendar display that has a specific granularity.
490
 */
491
function calendar_granularity_path(&$view, $granularity) {
492
  $paths = &drupal_static(__FUNCTION__, array());
493
  if (!array_key_exists($view->name, $paths) || !(array_key_exists($granularity, $paths[$view->name]))) {
494
    $paths[$view->name][$granularity] = '';
495
    foreach ($view->display as $id => $display) {
496
      // Check for !empty() in case the view is not fully formed or has displays that are marked to be deleted
497
      if (!empty($display->deleted) || empty($display->display_options['style_plugin']) || (isset($display->display_options['enabled']) && $display->display_options['enabled'] == FALSE)) {
498
        continue;
499
      }
500

    
501
      if ($display->display_plugin != 'feed' && !empty($display->display_options['path']) && !empty($display->display_options['arguments'])) {
502

    
503
        // Set to the default value, reset below if another value is found.
504
        $type = 'month';
505
        foreach ($display->display_options['arguments'] as $name => $argument) {
506
          if (!empty($argument['granularity'])) {
507
            $type = $argument['granularity'];
508
          }
509
        }
510

    
511
        if ($type == $granularity) {
512
          $part_path =  $display->display_options['path'];
513
          $parts = explode('/', $part_path);
514
          if (in_array('%', $parts)) {
515
            $current_path = parse_url($_GET['q']);
516
            $current_parts = explode('/', $current_path['path']);
517
            foreach ($parts as $key => $part) {
518
              if ($part == '%' && !empty($current_parts[$key])) {
519
                $parts[$key] = $current_parts[$key];
520
              }
521
            }
522
            $part_path = implode('/', $parts);
523
          }
524
          $paths[$view->name][$granularity] = $part_path;
525
        }
526
      }
527
    }
528
  }
529
  return $paths[$view->name][$granularity];
530
}
531

    
532
/**
533
 *  Check to make sure the user has entered a valid 6 digit hex color.
534
 */
535
function calendar_validate_hex_color($element, &$form_state) {
536
  if (!$element['#required'] && empty($element['#value'])) {
537
    return;
538
  }
539
  if (!preg_match('/^#(?:(?:[a-f\d]{3}){1,2})$/i', $element['#value'])) {
540
    form_error($element, t("'@color' is not a valid hex color", array('@color' => $element['#value'])));
541
  }
542
  else {
543
    form_set_value($element, $element['#value'], $form_state);
544
  }
545
}