'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',
);
}