agenda.admin.php in Agenda 7.2
Same filename and directory in other branches
Administration interface for the agenda module
File
agenda.admin.phpView source
<?php
/**
* @file
* Administration interface for the agenda module
*/
/**
* Admin configuration page
*/
function agenda_admin() {
// Headers
$header = array(
'id' => t('Block ID'),
'name' => t('Name'),
'ops' => t('Operations'),
);
// Rows
$res = db_query("SELECT id, bid, value FROM {agenda} WHERE name = 'title'");
$rows = array();
while ($row = $res
->fetchObject()) {
$actions = array(
'configure' => l(t('Configure'), sprintf('admin/config/services/agenda/%d/configure', $row->bid)),
'delete' => l(t('Delete'), sprintf('admin/config/services/agenda/%d/delete', $row->bid)),
'debug' => l(t('Debug'), sprintf('admin/config/services/agenda/%d/debug', $row->bid)),
'clear' => l(t('Clear'), sprintf('admin/config/services/agenda/%d/clear', $row->bid)),
);
$rows[] = array(
'id' => $row->bid,
'name' => $row->value,
'ops' => implode(' | ', $actions),
);
}
$table = '';
if (!empty($rows)) {
$table = theme('table', array(
'header' => $header,
'rows' => $rows,
));
}
return theme('agenda_admin', array(
'table' => $table,
));
}
/**
* Delete agenda
*/
function agenda_admin_delete($form, $form_state, $delta) {
$form = array();
$form['agenda_admin_delete_bid'] = array(
'#type' => 'hidden',
'#value' => (int) $delta,
);
$form['agenda_admin_delete_markup'] = array(
'#markup' => '<p>' . t('Are you sure you wish to delete this block?') . '</p>',
);
$form['agenda_admin_delete_confirm'] = array(
'#type' => 'submit',
'#value' => t('Delete block'),
);
return $form;
}
/**
* Delete an agenda action
*/
function agenda_admin_delete_submit($form, $form_state) {
// Clear the agenda variables table
db_delete('agenda')
->condition('bid', $form_state['values']['agenda_admin_delete_bid'])
->execute();
// Also clear the block table
db_delete('block')
->condition('delta', $form_state['values']['agenda_admin_delete_bid'])
->condition('module', 'agenda')
->execute();
drupal_set_message('Agenda block was deleted');
drupal_goto('admin/config/services/agenda');
}
/**
* Set Google API Key
*/
function agenda_admin_googleapi($form, &$form_state) {
$form['agenda_googleapi'] = array(
'#type' => 'textfield',
'#title' => t('Google API Key'),
'#default_value' => variable_get('agenda_googleapi', ''),
'#size' => 39,
'#maxlength' => 39,
'#description' => t('Key for server applications - <a href="https://developers.google.com/console/help/new/#usingkeys">https://developers.google.com/console/help/new/#usingkeys</a>'),
'#required' => TRUE,
);
return system_settings_form($form);
}
/**
* Manage agenda
*/
function agenda_admin_configure($form, $form_state, $delta) {
$form = array();
$form['agenda_bid'] = array(
'#type' => 'hidden',
'#value' => (int) $delta,
);
$form['agenda_title'] = array(
'#type' => 'textfield',
'#title' => t('Administrative title'),
'#default_value' => agenda_variable_get($delta, 'title', 'New block'),
'#description' => t('The Administrative title for this block'),
'#required' => TRUE,
'#agenda_setting' => TRUE,
);
$form['agenda_start'] = array(
'#type' => 'textfield',
'#title' => t('Agenda start'),
'#default_value' => agenda_variable_get($delta, 'start', '-1 day'),
'#description' => t('Any events that are older than this are not displayed. For example "-1 day" or "yesterday" will include events that occured yesterday, where as "now" will only include events that have not yet started. You can use any string <a href="http://php.net/strtotime">strtotime</a> can parse.'),
'#required' => TRUE,
'#agenda_setting' => TRUE,
);
$form['agenda_end'] = array(
'#type' => 'textfield',
'#title' => t('Agenda end'),
'#default_value' => agenda_variable_get($delta, 'end', '+2 months'),
'#description' => t('Any events newer than this are not displayed. For example, "+2 months" will display any events that occur in the next 2 months. You can use any string <a href="http://php.net/strtotime">strtotime</a> can parse.'),
'#required' => TRUE,
'#agenda_setting' => TRUE,
);
$form['agenda_datelimit'] = array(
'#type' => 'textfield',
'#title' => t('Dates to display'),
'#default_value' => agenda_variable_get($delta, 'datelimit', 4),
'#description' => t("The maximum number of unique dates to display."),
'#required' => TRUE,
'#agenda_setting' => TRUE,
);
$form['agenda_maxevents'] = array(
'#type' => 'textfield',
'#title' => t('Maximum number of events to fetch'),
'#default_value' => agenda_variable_get($delta, 'maxevents', 25),
'#description' => t("The maximum number of events to fetch."),
'#required' => TRUE,
'#agenda_setting' => TRUE,
);
$form['agenda_dateformat'] = array(
'#type' => 'textfield',
'#title' => t('Date formatting'),
'#default_value' => agenda_variable_get($delta, 'dateformat', 'l, F jS'),
'#description' => t('Specify the date format.'),
'#required' => TRUE,
'#agenda_setting' => TRUE,
);
$form['agenda_timeformat'] = array(
'#type' => 'textfield',
'#title' => t('Time formatting'),
'#default_value' => agenda_variable_get($delta, 'timeformat', 'h:ia'),
'#description' => t('Specify the time format.'),
'#required' => TRUE,
'#agenda_setting' => TRUE,
);
$form['agenda_noeventstext'] = array(
'#type' => 'textfield',
'#title' => t('Text to display if no events are found'),
'#default_value' => agenda_variable_get($delta, 'noeventstext', '<p>No upcoming events</p>'),
'#description' => t('Leave blank to have the block hide when no events are found.'),
'#agenda_setting' => TRUE,
);
$form['agenda_linktext'] = array(
'#type' => 'textfield',
'#title' => t('Calendar link text'),
'#default_value' => agenda_variable_get($delta, 'linktext', 'View this event in Google Calendar'),
'#description' => t('Text to display when linking to the Google Calendar event.'),
'#agenda_setting' => TRUE,
);
$form['agenda_hangoutlinktext'] = array(
'#type' => 'textfield',
'#title' => t('Calendar hangout link text'),
'#default_value' => agenda_variable_get($delta, 'hangoutlinktext', 'Join Google Calendar Event Hangout'),
'#description' => t('Text to display when linking to the Google Calendar event Hangout.'),
'#agenda_setting' => TRUE,
);
$form['agenda_cachetime'] = array(
'#type' => 'textfield',
'#title' => t('Amount of time to cache event data'),
'#default_value' => agenda_variable_get($delta, 'cachetime', 3600),
'#description' => t("How long (in seconds) the module should hold onto the ICS data before re-requesting it from Google."),
'#required' => TRUE,
'#agenda_setting' => TRUE,
);
$form['agenda_display_keys'] = array(
'#type' => 'textfield',
'#title' => t('Display fields'),
'#default_value' => agenda_variable_get($delta, 'display_keys', 'calendar, start time, description'),
'#description' => t("A comma separated list of fields to display in the event summary. The available fields are shown on the <em>Test settings</em> page."),
'#required' => FALSE,
'#agenda_setting' => TRUE,
);
$form['agenda_hide_labels'] = array(
'#type' => 'textfield',
'#title' => t('Hide labels'),
'#default_value' => agenda_variable_get($delta, 'hide_labels', 'link, description'),
'#description' => t("A comma separated list of fields for which the label should not be displayed."),
'#required' => FALSE,
'#agenda_setting' => TRUE,
);
$form['agenda_calendars'] = array(
'#type' => 'textarea',
'#title' => t('Google Calendar IDs'),
'#default_value' => agenda_variable_get($delta, 'calendars', 'drupalagenda@gmail.com'),
'#rows' => 4,
'#description' => t("The IDs of each google calendar you want to display, each on a new line. For private calendars, include the access token after the email with a forward slash."),
'#required' => TRUE,
'#agenda_setting' => TRUE,
);
$form['agenda_timezone'] = array(
'#type' => 'textfield',
'#title' => t('Timezone'),
'#default_value' => agenda_variable_get($delta, 'timezone', variable_get('date_default_timezone', date_default_timezone_get())),
'#description' => t('The timezone identifier to be used for this calendar, as described in <a href="http://php.net/timezones">the PHP manual</a>.'),
'#required' => TRUE,
'#agenda_setting' => TRUE,
);
$form['agenda_googleapi_override'] = array(
'#type' => 'textfield',
'#title' => t('Google API Key'),
'#default_value' => agenda_variable_get($delta, 'googleapi_override', ''),
'#size' => 39,
'#maxlength' => 39,
'#description' => t("Use this Google API key instead of default set on agenda settings page."),
'#agenda_setting' => TRUE,
);
$form['agenda_confirm'] = array(
'#type' => 'submit',
'#value' => t('Save settings'),
);
return $form;
}
/**
* Validate function for the admin configuration
*/
function agenda_admin_configure_validate($form, &$form_state) {
// clear the cache
drupal_set_message(t('Cache cleared for agenda block'));
cache_clear_all('agenda_block_' . $form['agenda_bid']['#value'], 'cache');
// calendars (has the form of a valid email address and an optional access key)
$calendars = $form_state['values']['agenda_calendars'];
$ids = preg_split('@\\r\\n?|\\n@', $calendars);
if (empty($ids)) {
form_set_error('agenda_calendars', t('Field can not be left blank'));
}
foreach ($ids as $id) {
if (!_agenda_parse_googleid($id)) {
form_set_error('agenda_calendars', t('Invalid calendar ID'));
}
}
// start (strtotime parseable)
$string = $form_state['values']['agenda_start'];
if (false === strtotime($string)) {
form_set_error('agenda_start', t('Unable to parse newer-than input with strtotime'));
}
// end (strtotime parseable)
$string = $form_state['values']['agenda_end'];
if (false === strtotime($string)) {
form_set_error('agenda_end', t('Unable to parse older-than input with strtotime'));
}
// datelimit (positive integer)
$datelimit = $form_state['values']['agenda_datelimit'];
if (!is_numeric($datelimit)) {
form_set_error('agenda_datelimit', t('You must specify a number.'));
}
elseif ($datelimit <= 0) {
form_set_error('agenda_datelimit', t('The number must be positive.'));
}
// cachetime (positive integer)
$cachetime = $form_state['values']['agenda_cachetime'];
if (!is_numeric($cachetime)) {
form_set_error('agenda_cachetime', t('You must specify the number of seconds to cache calendar data.'));
}
elseif ($cachetime <= 0) {
form_set_error('agenda_cachetime', t('The cache time must be positive.'));
}
// timezone
if (!@date_default_timezone_set($form_state['values']['agenda_timezone'])) {
form_set_error('agenda_timezone', t('Invalid timezone.'));
}
}
/**
* Save all the settings into our agenda settings table
*/
function agenda_admin_configure_submit($form, $form_state) {
// Check if we're creating a new block, in which case the delta is 0
$delta = $form['agenda_bid']['#value'];
if ($delta == 0) {
$delta = db_query('SELECT COALESCE(MAX(bid)+1,1) AS count FROM {agenda}')
->fetchField();
}
// Save the settings
foreach ($form_state['values'] as $key => $value) {
if (!isset($form[$key]['#agenda_setting'])) {
continue;
}
$setting = substr($key, 7);
agenda_variable_set($delta, $setting, $value);
}
drupal_set_message('Block settings were saved successfully');
drupal_goto('admin/config/services/agenda');
}
/**
* Provide a page to debug a calendar ID that is not working
*/
function agenda_debug($bid) {
$output = array();
// Date check (http://drupal.org/node/545174)
$output[] = t('Checking server time: %date', array(
'%date' => gmdate('r'),
));
$output[] = t('Checking real UTC time via NTP: %date', array(
'%date' => gmdate('r', agenda_debug_ntp_time('0.pool.ntp.org')),
));
$output[] = t('Ensure these values are approximately the same, otherwise your system is incorrectly configured and agenda will be unable to calculate dates properly.');
// Find calendar sources
$block = agenda_settings($bid);
$debug_title = array(
'#markup' => '<h2>' . t('Debugging %calendar block', array(
'%calendar' => $block->title,
)) . ' - ' . l('Edit', 'admin/config/services/agenda/' . $bid . '/configure', array(
'query' => drupal_get_destination(),
)) . '</h2>',
);
$output[] = t('Reading calendar input:');
$output[] = '<pre>' . htmlspecialchars($block->calendars) . '</pre>';
$calendars = preg_split('@\\r\\n?|\\n@', $block->calendars);
$calendars = array_map('trim', $calendars);
$output[] = t('Found following calendars:');
$output[] = sprintf('<pre>%s</pre>', print_r($calendars, TRUE));
$googleid = $calendars[0];
if (count($calendars) > 1) {
$output[] = t('Multiple calendars found, debugging with the first calendar: %googleid', array(
'%googleid' => $googleid,
));
}
$timeMin = date('Y-m-d', strtotime($block->start)) . 'T00:00:00' . date('P');
$timeMax = date('Y-m-d', strtotime($block->end)) . 'T00:00:00' . date('P');
$output[] = t('Using Agenda Block start value of %blockStart converted for Google API to %timeMin', array(
'%blockStart' => $block->start,
'%timeMin' => $timeMin,
));
$output[] = t('Using Agenda Block end value of %blockEnd converted for Google API to %timeMax', array(
'%blockEnd' => $block->end,
'%timeMax' => $timeMax,
));
$output[] = t('Maximum number of events to fetch: %maxEvents', array(
'%maxEvents' => $block->maxevents,
));
$output[] = t('Timezone: %timezone', array(
'%timezone' => $block->timezone,
));
$googlekey = !empty($block->googleapi_override) ? $block->googleapi_override : variable_get('agenda_googleapi', '');
$output[] = t('Using Google API Key: %googlekey', array(
'%googlekey' => $googlekey,
));
// Load the calendar
list($address, $token) = _agenda_parse_googleid($googleid);
// Load the XML
$calendar = _agenda_load_google($address, $token, $block);
if (!$calendar) {
$output[] = t('<strong>Warning</strong>: Failed');
return theme('item_list', $output, NULL, 'ul', array(
'id' => 'agenda-debug',
));
}
$output[] = t('Loaded Calendar successfully');
// Find the events
$calendar_events = $calendar
->getItems();
$number_of_events = count($calendar_events);
$output[] = t('Found @count events', array(
'@count' => $number_of_events,
));
if ($number_of_events === 0) {
$output[] = t('<strong>Warning</strong>: Nothing to do with empty calendar, stopping!');
$debug_log = theme('item_list', array(
'items' => $output,
));
return array(
'title' => array(
'#markup' => '<h2>' . t('Debugging %calendar block', array(
'%calendar' => $block->title,
)) . ' - ' . l('Edit', 'admin/config/services/agenda/' . $bid . '/configure') . '</h2>',
),
'debug_log' => array(
'#markup' => $debug_log,
'#prefix' => '<h3>Log</h3><div id="agenda-debug-log">',
'#suffix' => '</div>',
),
'#attached' => array(
'css' => array(
drupal_get_path('module', 'agenda') . '/agenda.css',
),
),
);
}
// Parse the events
$i = 0;
$eventdata = array();
foreach ($calendar_events as $event) {
$thisevent = _agenda_parse_event($event, $block);
if (!$thisevent) {
$output[] = t('<strong>Warning</strong>: Failed to parse event!');
continue;
}
$output[] = t('Successfully parsed event:');
$output[] = '<pre>' . print_r($thisevent, TRUE) . '</pre>';
$eventdata[] = $thisevent;
}
$output[] = t('Parsed @success/@total events successfully', array(
'@success' => count($eventdata),
'@total' => $number_of_events,
));
$output[] = t('Begin filtering based on date: string provided (@old) which has timestamp (@timestamp) which has date (@date).', array(
'@old' => $what_is_old = agenda_variable_get($bid, 'start', '-1 day'),
'@timestamp' => $what_is_old_ts = strtotime($what_is_old),
'@date' => format_date($what_is_old_ts),
));
foreach ($eventdata as $key => $event) {
if ($event['start timestamp'] < $what_is_old_ts) {
$output[] = t('» Discarding %title because %start is older than %old', array(
'%title' => $event['title'],
'%start' => format_date($event['start timestamp'], 'small'),
'%old' => format_date($what_is_old_ts, 'small'),
));
unset($eventdata[$key]);
}
}
$output[] = t('Finished. Started with @total events, will display @display events', array(
'@total' => $number_of_events,
'@display' => count($eventdata),
));
// Now take all of our debug data and theme it up, starting with the logs
$debug_log = theme('item_list', array(
'items' => $output,
));
// Build a table of all of the events found
$event_table = '';
if (count($eventdata)) {
$first_row = array_slice($eventdata, 0, 1);
$event_table = theme('table', array(
'header' => array_keys($first_row[0]),
'rows' => $eventdata,
'sticky' => TRUE,
));
}
// Render
return array(
'title' => $debug_title,
'debug_log' => array(
'#markup' => $debug_log,
'#prefix' => '<h3>Log</h3><div id="agenda-debug-log">',
'#suffix' => '</div>',
),
'event_table' => array(
'#markup' => $event_table,
'#prefix' => '<h3>Events</h3><div id="agenda-debug-table">',
'#suffix' => '</div>',
),
'#attached' => array(
'css' => array(
drupal_get_path('module', 'agenda') . '/agenda.css',
),
),
);
}
/**
* Grab the time from an NTP server
*
* @param string $host The NTP server to retrieve the time from
* @return int The current unix timestamp
*/
function agenda_debug_ntp_time($host) {
// Create a socket and connect to NTP server
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_connect($sock, $host, 123);
// Send request
$msg = "\10" . str_repeat("\0", 47);
socket_send($sock, $msg, strlen($msg), 0);
// Receive response and close socket
socket_recv($sock, $recv, 48, MSG_WAITALL);
socket_close($sock);
// Interpret response
$data = unpack('N12', $recv);
$timestamp = sprintf('%u', $data[9]);
// NTP is number of seconds since 0000 UT on 1 January 1900
// Unix time is seconds since 0000 UT on 1 January 1970
$timestamp -= 2208988800;
return $timestamp;
}
/**
* Agenda clear cache
*/
function agenda_clear($bid) {
drupal_set_message(t('Cache cleared for agenda block'));
cache_clear_all('agenda_block_' . $bid, 'cache');
drupal_goto('admin/config/services/agenda');
}
Functions
Name | Description |
---|---|
agenda_admin | Admin configuration page |
agenda_admin_configure | Manage agenda |
agenda_admin_configure_submit | Save all the settings into our agenda settings table |
agenda_admin_configure_validate | Validate function for the admin configuration |
agenda_admin_delete | Delete agenda |
agenda_admin_delete_submit | Delete an agenda action |
agenda_admin_googleapi | Set Google API Key |
agenda_clear | Agenda clear cache |
agenda_debug | Provide a page to debug a calendar ID that is not working |
agenda_debug_ntp_time | Grab the time from an NTP server |