'3', 'path' => drupal_get_path('module', 'fullcalendar') . '/includes/views', ); } /** * Implements hook_theme(). */ function fullcalendar_theme($existing, $type, $theme, $path) { return array( 'fullcalendar_event' => array( 'variables' => array( 'event' => NULL, 'entity' => NULL, ), 'file' => 'theme.inc', 'path' => $path . '/theme', ), ); } /** * Implements hook_library(). */ function fullcalendar_library() { $path = variable_get('fullcalendar_path', fullcalendar_default_path()); $css_files = array($path . '/fullcalendar.css' => array('media' => 'screen')); // Add fullcalendar.print.css if it is available. if (version_compare(fullcalendar_get_version(), '1.5.0', '>=')) { $css_files[$path . '/fullcalendar.print.css'] = array('media' => 'print'); } $libraries['fullcalendar'] = array( 'title' => 'FullCalendar', 'website' => 'http://arshaw.com/fullcalendar', 'version' => FULLCALENDAR_MIN_PLUGIN_VERSION, 'js' => array( fullcalendar_get_js_path() => array(), $path . '/gcal.js' => array(), ), 'css' => $css_files, 'dependencies' => array( array('system', 'ui.draggable'), array('system', 'ui.droppable'), array('system', 'ui.resizable'), array('system', 'effects.highlight'), ), ); return $libraries; } /** * Implements hook_permission(). * * @return array * An array of valid permissions for the FullCalendar module. */ function fullcalendar_permission() { return array( 'update any fullcalendar event' => array( 'title' => t('Update any FullCalendar event'), 'description' => t('Allow user to edit events, ignoring other permissions.'), ), ); } /** * Implements hook_menu(). * * @return array * An array of menu items. */ function fullcalendar_menu() { $items = array(); $items['admin/config/user-interface/fullcalendar'] = array( 'title' => 'FullCalendar', 'description' => 'Adjust FullCalendar settings.', 'file' => 'fullcalendar.admin.inc', 'file path' => drupal_get_path('module', 'fullcalendar') . '/includes', 'page callback' => 'drupal_get_form', 'page arguments' => array('fullcalendar_admin_settings'), 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, 'weight' => 0, ); $items['admin/config/user-interface/fullcalendar/default'] = array( 'title' => 'FullCalendar', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => 0, ); $items['fullcalendar/ajax/update/%/%'] = array( 'title' => 'Update event', 'description' => 'Save the updated event datetime.', 'page callback' => 'fullcalendar_update', 'page arguments' => array(3, 4), 'access callback' => '_fullcalendar_update_access', 'access arguments' => array(4), 'type' => MENU_CALLBACK, ); $items['fullcalendar/ajax/results'] = array( 'title' => 'Events', 'description' => 'Get events from views with arguments', 'page callback' => 'fullcalendar_results', 'access arguments' => array('access content'), 'delivery callback' => 'ajax_deliver', 'theme callback' => 'ajax_base_page_theme', 'type' => MENU_CALLBACK, ); return $items; } /** * Saves the updated FullCalendar event's datetime. * * @param string $action * Value can be 'drop' or 'resize'. * @param int $eid * The id of the entity that will be updated. */ function fullcalendar_update($action, $eid) { if (empty($_POST['field']) || !isset($_POST['index'])) { return; } // Retrieve the post vars form the ajax call. $field = check_plain($_POST['field']); $index = check_plain($_POST['index']); $all_day = isset($_POST['all_day']) ? check_plain($_POST['all_day']) : ''; $delta = ' ' . check_plain($_POST['day_delta']) . ' days ' . check_plain($_POST['minute_delta']) . ' minutes'; $entity_type = check_plain($_POST['entity_type']); $entity = entity_load($entity_type, array($eid)); $entity = reset($entity); $langcode = field_language($entity_type, $entity, $field); $item = &$entity->{$field}[$langcode][$index]; $old_start = $item['value']; $old_end = $item['value2']; // Adjust for different date formats. $format = date_type_format($item['date_type']); // Datestamp can't combine with words for strtotime, convert to ISO for now. if ($format == DATE_FORMAT_UNIX) { $old_start = date(DATE_FORMAT_ISO, $old_start); $old_end = date(DATE_FORMAT_ISO, $old_end); } // No break after 'drop' so it will reuse the code of 'resize'. switch ($action) { case 'drop': $item['value'] = date($format, strtotime($old_start . $delta)); case 'resize': $item['value2'] = date($format, strtotime($old_end . $delta)); break; } // Save the new start/end values. if (module_exists('entity')) { entity_save($entity_type, $entity); } else { field_attach_presave($entity_type, $entity); field_attach_update($entity_type, $entity); } drupal_json_output(array('msg' => t('The new event time has been saved.') . ' [' . l(t('Close'), NULL, array('attributes' => array('class' => array('fullcalendar-status-close')))) . ']', 'dom_id' => $_POST['dom_id'])); } /** * Implements hook_fullcalendar_classes(). */ function fullcalendar_fullcalendar_classes($entity) { $classes = array( 'fc-event-default', $entity->bundle, ); // Add a class for the date field being used. if (isset($entity->fullcalendar_date_field)) { $classes[] = "fc-event-field-$entity->fullcalendar_date_field"; } return $classes; } /** * Implements hook_form_FORM_ID_alter() for views_ui_edit_display_form(). * * Since we force the query to be distinct, reflect that in the UI. */ function fullcalendar_form_views_ui_edit_display_form_alter(&$form, &$form_state, $form_id) { if ($form_state['view']->display_handler->get_option('style_plugin') != 'fullcalendar' || empty($form['options']['query']['options']['distinct'])) { return; } $distinct = &$form['options']['query']['options']['distinct']; if (!isset($distinct['#description'])) { $distinct['#description'] = ''; } else { $distinct['#description'] .= '
'; } $distinct['#disabled'] = TRUE; $distinct['#description'] .= '' . t('FullCalendar requires that the query be distinct.') . ''; } /** * Returns events for FullCalendar. */ function fullcalendar_results($view_name = NULL, $view_display = NULL) { // Bail out if no view_name or view_display is passed. if (empty($view_name) || empty($view_display) || empty($_POST['dom_id'])) { return; } // Find Views arguments. $args = func_get_args(); unset($args[0], $args[1]); $args = array_values($args); $dom_id = check_plain($_POST['dom_id']); $view_name = check_plain($view_name); $view_display = check_plain($view_display); // Add all $_POST data, because AJAX is always a post and many things, // such as tablesorts, exposed filters and paging assume $_GET. $_GET += $_POST; // Get the view and check access. $view = views_get_view($view_name); if (!$view || !$view->access($view_display)) { return; } if (!$view->set_display($view_display)) { return; } $view->dom_id = $dom_id; $view->fullcalendar_ajax = TRUE; $view->pre_execute($args); $view->init_style(); $view->execute($view_display); $output = $view->style_plugin->render(); $view->post_execute(); return array( '#type' => 'ajax', '#commands' => array( array('command' => 'fullcalendar_results_response', 'data' => $output), ), ); } /** * Checks if the user has access to update the given FullCalendar event. * * @param object $entity * The entity that will be updated. * * @return bool * TRUE if the user is allowed to update the entity; * FALSE if the user is not permitted to update the entity. */ function _fullcalendar_update_access($entity) { global $user; if (!empty($entity) && ((user_access('administer content') || user_access('update any fullcalendar event') || user_access('edit any ' . $entity->bundle . ' content') || (user_access('edit own ' . $entity->bundle . ' content') && $entity->uid == $user->uid)))) { return TRUE; } return FALSE; } /** * Implements hook_fullcalendar_editable(). * * Use our access callback as the editable setting. */ function fullcalendar_fullcalendar_editable($entity, $view) { return _fullcalendar_update_access($entity); } /** * Determines if a given field is a date field. * * @param object $field * A Views field handler object. * @param bool $include_gcal * Boolean indicating whether or not to count gcal fields as a date field. * * @return bool * Boolean, TRUE if the field is a date field, FALSE otherwise. */ function fullcalendar_field_is_date($field, $include_gcal = FALSE) { if ($include_gcal && $field->field == 'gcal') { return TRUE; } return !empty($field->definition['is date']) && isset($field->field_info); } /** * Checks FullCalendar dependencies. * * @return bool * Array with TRUE/FALSE for each dependency. * * @see fullcalendar_requirements() */ function _fullcalendar_status() { $status = array(); $status['fullcalendar_plugin'] = FALSE; $path = fullcalendar_get_js_path(); if (!file_exists($path)) { return FALSE; } if (version_compare(fullcalendar_get_version($path), FULLCALENDAR_MIN_PLUGIN_VERSION, '>=')) { $status['fullcalendar_plugin'] = TRUE; } return $status; } /** * Returns the version of FullCalendar plugin that is installed. * * This can be used by other modules' hook_requirements() to ensure that the * proper version of FullCalendar plugin is installed. * * @see version_compare() */ function fullcalendar_get_version($fullcalendar_path = NULL) { $version = &drupal_static(__FUNCTION__); if (empty($version)) { $version = 0; $pattern = '#FullCalendar v([0-9\.a-z]+)#'; // No file is passed in so use the default location. if (is_null($fullcalendar_path)) { $fullcalendar_path = fullcalendar_get_js_path(); } // Return the version of FullCalendar plugin. $fullcalendar_plugin = file_get_contents($fullcalendar_path, NULL, NULL, 0, 40); if (preg_match($pattern, $fullcalendar_plugin, $matches)) { $version = $matches[1]; } } return $version; } /** * Returns the path to the FullCalendar plugin. */ function fullcalendar_get_js_path() { $fullcalendar_file = array('none' => 'fullcalendar.js', 'min' => 'fullcalendar.min.js'); return variable_get('fullcalendar_path', fullcalendar_default_path()) . '/' . $fullcalendar_file[variable_get('fullcalendar_compression_type', 'min')]; } /** * Includes all FullCalendar API plugins. */ function fullcalendar_include_api() { ctools_include('plugins'); return ctools_plugin_api_include('fullcalendar', 'fullcalendar', fullcalendar_api_version(), fullcalendar_api_minimum_version()); } /** * Implements hook_ctools_plugin_api_hook_name(). */ function fullcalendar_ctools_plugin_api_hook_name() { return 'fullcalendar_api'; } /** * Declares the current FullCalendar API version. */ function fullcalendar_api_version() { return '1'; } /** * Declares the minimum FullCalendar API version. */ function fullcalendar_api_minimum_version() { return '1'; } /** * Implements hook_fullcalendar_api(). */ function fullcalendar_fullcalendar_api() { return array( 'api' => fullcalendar_api_version(), 'path' => drupal_get_path('module', 'fullcalendar') . '/includes', ); }