Projet

Général

Profil

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

root / drupal7 / sites / all / modules / calendar / calendar.module @ c169e7c4

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
        $item['localized_options'] += array('query' => array());
173
        $item['localized_options']['query'] += drupal_get_destination();
174
        if (array_key_exists('access', $item) && $item['access']) {
175
          $data['actions']['output'][] = array(
176
            '#theme' => 'menu_local_action',
177
            '#link' => $item,
178
          );
179
        }
180
      }
181
    }
182
  }
183
  return;
184
}
185

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

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

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

    
213
/**
214
 * Implements hook_theme().
215
 */
216
function calendar_theme() {
217
  $module_path = drupal_get_path('module', 'calendar');
218

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

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

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

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

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

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

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

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

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

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

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

    
441
/**
442
 * Implementation of hook_block_configure().
443
 */
444
function calendar_block_configure($delta = '') {
445
  switch ($delta) {
446
    case 'calendar_legend':
447
    $options = calendar_list_views();
448
    $form['calendar_legend_view'] = array(
449
      '#type' => 'select',
450
      '#title' => t('Legend View'),
451
      '#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.'),
452
      '#default_value' => variable_get('calendar_legend_view_' . $delta, ''),
453
      '#options' => $options,
454
    );
455
    return $form;
456
  }
457
}
458

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

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

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

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

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

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

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