<?php
// error handling for event editing
// conference display
function JSSafe ( $s )
{
return str_replace( array( "\\", "'" ), array( "\\\\", "\\'" ), $s );
}
function defaultValue ( $values, $key, $error_array )
{
if ( count( $error_array ) )
{
if ( strlen( $values[$key] ) )
{
printf( ' value="%s"', htmlspecialchars( $values[$key] ) );
}
print '';
}
}
require './classes/DB.php';
require './classes/Admin.php';
function nullOut ( &$s )
{
$s = strlen( $s ) ? $s : null;
}
$reload_form_entry = false;
$submission_errors = array();
$form = array();
if ( Admin::isLoggedIn() && $_GET['action'] == 'deleteitem' )
{
$id = intval( $_GET['id'] );
$delete_query = DB::getDB()->prepare( 'DELETE FROM tblCalendarItems WHERE calendarItemID = ?' );
$delete_query->bind_param( 'i', $id );
$delete_query->execute();
$delete_query->close();
header( 'Location: /calendar' );
exit;
}
if ( Admin::isLoggedIn() && ( $_GET['action'] == 'newitem' || $_GET['action'] == 'edititem' ) )
{
$reload_form_entry = true;
$error_strings = array(
'enddate' => 'At least one of date/time must be nonempty.',
'endtime' => 'At least one of date/time must be nonempty.',
'location' => 'Location must be nonempty.',
'papertitle' => 'Paper title must be nonempty.',
'startdate' => 'At least one of date/time must be nonempty.',
'starttime' => 'At least one of date/time must be nonempty.'
);
$paper_title = trim( $_POST['papertitle'] );
$event_start_time = trim( $_POST['starttime'] );
$event_end_time = trim( $_POST['endtime'] );
$conference_start_date = trim( $_POST['startdate'] );
$conference_end_date = trim( $_POST['enddate'] );
$conference_name = trim( $_POST['conferencename'] );
$conference_url = trim( $_POST['conferenceurl'] );
$location = trim( $_POST['location'] );
$location_address = trim( $_POST['locationaddress'] );
$location_url = trim( $_POST['locationurl'] );
$location_lat_lng = trim( $_POST['locationlatlng'] );
$details = trim( $_POST['details'] );
$paper_url = trim( $_POST['paperurl'] );
// clean input
if ( !preg_match( '/^\d{4}?\-\d\d?\-\d\d?\s*[Tt\s]\s*\d\d?:\d\d\s*(?:[AaPp][Mm]?)?$/', $event_start_time ) )
{
$event_start_time = '';
}
if ( !preg_match( '/^\d{4}\-\d\d?\-\d\d\s*[Tt\s]\s*\d\d?:\d\d\s*(?:[AaPp][Mm]?)?$/', $event_end_time ) )
{
$event_end_time = '';
}
if ( !preg_match( '/^\d{4}\-\d\d?\-\d\d?$/', $conference_start_date ) )
{
$conference_start_date = '';
}
if ( !preg_match( '/^\d{4}\-\d\d?\-\d\d?$/', $conference_end_date ) )
{
$conference_end_date = '';
}
if ( !preg_match( '/^https?:\/\//', $conference_url ) )
{
$conference_url = '';
}
if ( !preg_match( '/^https?:\/\//', $location_url ) )
{
$location_url = '';
}
if ( !preg_match( '/^https?:\/\//', $paper_url ) )
{
$paper_url = '';
}
if ( !preg_match( '/^\-?\d+\.?\d*,\s*\-?\d+\.?\d*$/', $location_lat_lng ) )
{
$location_lat_lng = '';
}
$form = array(
'conferencename' => $conference_name,
'conferenceurl' => $conference_url,
'details' => $details,
'enddate' => $conference_end_date,
'endtime' => $event_end_time,
'location' => $location,
'locationaddress' => $location_address,
'locationlatlng' => $location_lat_lng,
'locationurl' => $location_url,
'papertitle' => $paper_title,
'paperurl' => $paper_url,
'startdate' => $conference_start_date,
'starttime' => $event_start_time
);
// set errors
if ( strlen( $paper_title ) < 1 )
{
$submission_errors['papertitle'] = $error_strings['papertitle'];
}
if ( strlen( $location ) < 1 )
{
$submission_errors['location'] = $error_strings['location'];
}
if ( ( strlen( $event_start_time ) < 1 || strlen( $event_end_time ) < 1 ) && ( strlen( $conference_start_date ) < 1 || strlen( $conference_end_date ) < 1 ) )
{
if ( strlen( $event_start_time ) )
{
$submission_errors['endtime'] = $error_strings['endtime'];
}
else if ( strlen( $event_end_time ) )
{
$submission_errors['starttime'] = $error_strings['starttime'];
}
if ( strlen( $conference_start_date ) )
{
$submission_errors['enddate'] = $error_strings['enddate'];
}
else if ( strlen( $conference_end_date ) )
{
$submission_errors['startdate'] = $error_strings['startdate'];
}
if ( strlen( $event_start_time ) < 1 && strlen( $event_end_time ) < 1 && strlen( $conference_start_date ) < 1 && strlen( $conference_end_date ) < 1 )
{
$submission_errors['starttime'] = $error_strings['starttime'];
}
}
if ( count( $submission_errors ) < 1 )
{
$event_id = -1;
if ( $_GET['action'] == 'newitem' )
{
DB::getDB()->query( 'INSERT INTO tblCalendarItems ( paperTitle ) VALUES ( "" )' );
$event_id = DB::getDB()->insert_id;
}
else if ( isset( $_POST['eventid'] ) && preg_match( '/^\d+$/', $_POST['eventid'] ) )
{
$event_id = $_POST['eventid'];
}
nullOut( $event_start_time );
nullOut( $event_end_time );
nullOut( $conference_start_date );
nullOut( $conference_end_date );
nullOut( $conference_name );
nullOut( $conference_url );
nullOut( $location );
nullOut( $location_address );
nullOut( $location_url );
nullOut( $location_lat_lng );
nullOut( $details );
nullOut( $paper_title );
nullOut( $paper_url );
$update_query_string = <<<EOQ
UPDATE tblCalendarItems
SET
eventStartTime = ?,
eventEndTime = ?,
conferenceStartDate = ?,
conferenceEndDate = ?,
conferenceName = ?,
conferenceURL = ?,
location = ?,
locationAddress = ?,
locationURL = ?,
locationLatLng = ?,
details = ?,
paperTitle = ?,
paperURL = ?
WHERE calendarItemID = ?
EOQ;
$update_query = DB::getDB()->prepare( $update_query_string );
$update_query->bind_param( 'sssssssssssssi',
$event_start_time,
$event_end_time,
$conference_start_date,
$conference_end_date,
$conference_name,
$conference_url,
$location,
$location_address,
$location_url,
$location_lat_lng,
$details,
$paper_title,
$paper_url,
$event_id
);
$update_query->execute();
$update_query->close();
header( 'Location: calendar.php' );
exit;
}
}
require './classes/Page.php';
$page = new Page();
$page->setTitle( 'calendar' );
$page->setParentURL( 'research.php' );
$page->addHeader( <<<EOS
<style type="text/css">
.schemadata
{
display: none;
}
.schema-data
{
display: none;
}
ul
{
list-style-type: none;
}
li
{
margin-bottom: 3ex;
}
td > input:not([type="submit"]):not([type="button"])
{
width: 100%;
}
.event-details
{
}
.event-location
{
}
.event-time
{
display: block;
font-weight: 500;
}
.event-title
{
display: block;
}
.hidden-details
{
display: none;
}
</style>
EOS
);
if ( Admin::isLoggedIn() )
{
$page->addHeader( <<<EOJ
<script language="javascript">
function deleteItem ( e, id )
{
if ( confirm( 'Delete item ' + id + '?' ) )
{
parent.location = '?action=deleteitem&id=' + id;
}
}
function editItem ( e, id )
{
// load form structure, relabel with unique id
var h = document.getElementById( 'eventform' ).innerHTML.replace( /for="/gi, 'for="edit-' + id + '-' ).replace( /id="/gi, 'id="edit-' + id + '-' ).replace( /Create/, 'Edit' );
var f = document.createElement( 'form' );
f.setAttribute( 'action', '?action=edititem' );
f.setAttribute( 'method', 'post' );
f.innerHTML = h;
while ( e.tagName.toUpperCase() != 'LI' && e.parentNode )
{
e = e.parentNode;
}
// hide existing display data
for ( var i = 0; i < e.childNodes.length; ++i )
{
if ( e.childNodes[i].style )
{
e.childNodes[i].style.display = 'none';
}
}
// add form controls
e.appendChild( f );
var b = document.createElement( 'input' );
b.setAttribute( 'type', 'button' );
b.setAttribute( 'value', 'Cancel' );
var close_form = function () {
var e = f.parentNode;
e.removeChild( f );
for ( var i = 0; i < e.childNodes.length; ++i )
{
if ( e.childNodes[i].style )
{
e.childNodes[i].style.display = '';
}
}
};
b.addEventListener( 'click', close_form );
document.getElementById( 'edit-' + id + '-newitemsubmit' ).parentNode.appendChild( b );
// update values from json
var d = eval( '[' + document.getElementById( 'event-' + id + '-json' ).innerHTML + ']' );
for ( var k in d[0] )
{
document.getElementById( 'edit-' + id + '-' + k ).value = d[0][k];
}
// add event id to form
var i = document.createElement( 'input' );
i.setAttribute( 'name', 'eventid' );
i.setAttribute( 'type', 'hidden' );
i.setAttribute( 'value', id );
f.appendChild( i );
// focus
document.getElementById( 'edit-' + id + '-papertitle' ).focus();
var inputs = f.getElementsByTagName( 'input' );
for ( var i = 0; i < inputs.length; ++i )
{
inputs[i].addEventListener( 'keyup', function ( e ) {
if ( e.which == 27 || e.keyCode == 27 )
{
close_form();
}
} );
}
return false;
}
</script>
EOJ
);
}
$page->printPageHeader();
class CalendarItem implements JSONSerializable
{
private $conference_end_date;
private $conference_name;
private $conference_start_date;
private $conference_url;
private $details;
private $event_end_time;
private $event_start_time;
private $id;
private $location;
private $location_address;
private $location_lat_lng;
private $location_url;
private $paper_title;
private $paper_url;
public function __construct ( $id, $event_start_time, $event_end_time, $conference_start_date, $conference_end_date, $conference_name, $conference_url, $location, $location_address, $location_url, $location_lat_lng, $details, $paper_title, $paper_url )
{
$this->conference_end_date = $conference_end_date;
$this->conference_name = $conference_name;
$this->conference_start_date = $conference_start_date;
$this->conference_url = $conference_url;
$this->details = $details;
$this->event_end_time = $event_end_time;
$this->event_start_time = $event_start_time;
$this->id = $id;
$this->location = $location;
$this->location_address = $location_address;
$this->location_lat_lng = $location_lat_lng;
$this->location_url = $location_url;
$this->paper_title = $paper_title;
$this->paper_url = $paper_url;
}
public static function fetchFutureCalendarItems ()
{
$items = array();
$query_string = <<<EOQ
SELECT
calendarItemID,
UNIX_TIMESTAMP( eventStartTime ),
UNIX_TIMESTAMP( eventEndTime ),
UNIX_TIMESTAMP( conferenceStartDate ),
UNIX_TIMESTAMP( conferenceEndDate ),
conferenceName,
conferenceURL,
location,
locationAddress,
locationURL,
locationLatLng,
details,
paperTitle,
paperURL
FROM tblCalendarItems
WHERE
(
(
eventEndTime > NOW()
OR
(
MONTH( eventEndTime ) = MONTH( NOW() )
AND YEAR( eventEndTime ) = YEAR( NOW() )
)
)
OR
(
conferenceEndDate > NOW()
OR
(
MONTH( conferenceEndDate ) = MONTH( NOW() )
AND YEAR( conferenceEndDate ) = YEAR( NOW() )
)
)
)
ORDER BY IFNULL( eventStartTime, conferenceStartDate ) ASC
EOQ;
$event_query = DB::getDB()->query( $query_string );
while ( $query_row = $event_query->fetch_row() )
{
array_push( $items, new CalendarItem( $query_row[0], $query_row[1], $query_row[2], $query_row[3], $query_row[4], $query_row[5], $query_row[6], $query_row[7], $query_row[8], $query_row[9], $query_row[10], $query_row[11], $query_row[12], $query_row[13] ) );
}
$event_query->close();
return $items;
}
public function getMonth ()
{
if ( $this->event_start_time )
{
return date( 'F Y', $this->event_start_time );
}
else
{
return date( 'F Y', $this->conference_start_date );
}
}
public function isConference ()
{
return $this->conference_start_date > 0;
}
public function isConferencePresentation ()
{
return $this->isConference() && $this->isPresentation();
}
public function isPresentation ()
{
return $this->event_start_time > 0;
}
public function jsonSerialize ()
{
return array(
'papertitle' => $this->paper_title,
'starttime' => strlen( $this->event_start_time ) ? date( 'Y-m-d\TH:i', $this->event_start_time ) : '',
'endtime' => strlen( $this->event_end_time ) ? date( 'Y-m-d\TH:i', $this->event_end_time ) : '',
'startdate' => strlen( $this->conference_start_date ) ? date( 'Y-m-d', $this->conference_start_date ) : '',
'enddate' => strlen( $this->conference_end_date ) ? date( 'Y-m-d', $this->conference_end_date ) : '',
'conferencename' => $this->conference_name,
'conferenceurl' => $this->conference_url,
'location' => $this->location,
'locationaddress' => $this->location_address,
'locationurl' => $this->location_url,
'locationlatlng' => $this->location_lat_lng,
'details' => $this->details,
'paperurl' => $this->paper_url
);
}
public function render ( $is_admin = false, $do_print = true )
{
$event_string = <<<EOE
<li itemscope itemtype="http://schema.org/Event">
<span class="schemadata" itemprop="performer" itemscope itemtype="http://schema.org/Person">
<span itemprop="name">Kyle Woodward</span>
<span itemprop="sameas">http://kylewoodward.com</span>
</span>
<link itemtype="eventstatus" href="http://schema.org/EventScheduled" />
<span itemprop="offers"></span>
EOE;
if ( Admin::isLoggedIn() )
{
$event_string .= <<<EOH
<div style="float:right;width:48px;text-align:center;cursor:pointer;background-color:#ffe6e6;line-height:48px;margin-left:5px;" onclick="return deleteItem( this, {$this->id} );">delete</div>
<div style="float:right;width:48px;text-align:center;cursor:pointer;background-color:#eee;line-height:48px;" onclick="return editItem( this, {$this->id} );">edit</div>
EOH;
$event_string .= sprintf( '<span id="event-%d-json" class="schemadata">%s</span>', $this->id, json_encode( $this ) );
}
//
// CreativeWork
// * Name
// * URL
// (Event title)
// StartDate - EndDate ====== DONE TO HERE
// Location
// * Name
// * Address
// * URL
// (SuperEvent ============== DONE FROM HERE
// * Name
// * StartDate - EndDate
// * Location
// - Name
// - Address
// - URL
// )
// Details
//
$creative_work = <<<EOCW
<span itemprop="workfeatured" itemscope itemtype="http://schema.org/CreativeWork">
%s<span class="event-title" itemprop="name">%s</span>%s
</span><a class="schema-data" href="/calendar.php" itemprop="url"><span itemprop="name">%s</span></a>
EOCW;
$creative_work = sprintf( $creative_work,
strlen( $this->paper_url ) ? sprintf( '<a href="%s" itemprop="url">', htmlspecialchars( $this->paper_url ) ) : '',
htmlspecialchars( $this->paper_title ),
strlen( $this->paper_url ) ? '</a>' : '',
htmlspecialchars( $this->paper_title )
);
$time_template = '<time datetime="%s" itemprop="%sdate">%s</time>';
$event_time_string = sprintf( "{$time_template}–{$time_template}", date( 'c', $this->event_start_time ), 'start', date( 'F d, g:ia', $this->event_start_time ), date( 'c', $this->event_end_time ), 'end', date( 'g:ia', $this->event_end_time ) );
$conference_date_string = sprintf( $time_template, date( 'Y-m-d', $this->conference_start_date ), 'start', date( 'F d', $this->conference_start_date ) ) . (
$this->conference_start_date != $this->conference_end_date ? sprintf( "–{$time_template}", date( 'Y-m-d', $this->conference_end_date ), 'end', date( 'F d', $this->conference_end_date ) ) :
''
);
// need to add lat/lng
// need to add differential places (?)
$location = <<<EOL
<span itemprop="location" itemscope itemtype="http://schema.org/Place">
%s<span itemprop="name">%s</span>%s
<span class="%s">(<span itemprop="address">%s</span>)</span>
</span>
EOL;
$location = sprintf( $location,
strlen( $this->location_url ) ? sprintf( '<a href="%s" itemprop="url">', htmlspecialchars( $this->location_url ) ) : '',
htmlspecialchars( $this->location ),
strlen( $this->location_url ) ? '</a>' : '',
$this->isConference() ? 'event-location' : 'schema-data',
$this->location_address
);
$super_event = <<<EOSE
<span class="schema-data" itemprop="superevent" itemscope itemtype="http://schema.org/Event">
<link itemprop="eventstatus" itemtype="http://schema.org/EventScheduled" />
%s<span itemprop="name">%s</span>%s
%s
%s
</span>
EOSE;
$super_event = sprintf( $super_event,
strlen( $this->conference_url ) ? sprintf( '<a href="%s" itemprop="url">', htmlspecialchars( $this->conference_url ) ) : '',
htmlspecialchars( $this->conference_name ),
strlen( $this->conference_url ) ? '</a>' : '',
$conference_date_string,
$location
);
$event_string .= $creative_work;
$event_string .= sprintf( '<span class="event-time">%s</span>', $this->isPresentation() ? $event_time_string : $conference_date_string );
$event_string .= $this->isConference() ? $super_event : '';
$event_string .= $location;
$event_string .= sprintf( '<span class="event-details" itemprop="description">%s</span>', htmlspecialchars( $this->details ) );
$event_string .= '</li>';
//
// Display string
//
if ( $do_print )
{
print $event_string;
}
else
{
return $event_string;
}
}
}
?>
<!-- h3>calendar</h3 -->
<?
$calendar = CalendarItem::fetchFutureCalendarItems();
$month = '';
for ( $i = 0; $i < count( $calendar ); ++$i )
{
$item = $calendar[$i];
if ( $item->getMonth() != $month )
{
if ( strlen( $month ) > 0 )
{
print '</ul>';
}
$month = $item->getMonth();
printf( '<h3>%s</h3><ul>', strtolower( $month ) );
}
$item->render( Admin::isLoggedIn() );
}
if ( strlen( $month ) > 0 )
{
print '</ul>';
}
else
{
?>
<h3>calendar</h3>
<p>
No upcoming events.
</p>
<?php
}
?>
<?php
if ( Admin::isLoggedIn() )
{
if ( $_GET['action'] == 'edititem' )
{
// why are these in here?
// $form = array();
// $submission_errors = array();
}
?>
<h3>create new event</h3>
<?php
if ( count( $submission_errors ) )
{
?>
<div style="background-color:rgba(153,0,0,0.2);margin:1ex;padding:1ex;">
<p>Please fix the following errors:</p>
<ul style="margin:0ex 0ex 0ex 2ex;">
<?php
foreach ( $submission_errors as $error )
{
?><li><?php print $error; ?></li><?
}
?>
</ul></div>
<?php
}
?>
<form action="?action=newitem" method="post" id="eventform" style="margin-top:2ex;">
<table>
<tbody>
<tr><td><label for="papertitle">Title</label></td><td><input id="papertitle" name="papertitle" type="text"<?php defaultValue( $form, 'papertitle', $submission_errors ); ?> /></td></tr>
<tr><td><label for="starttime">Start time</label></td><td><input id="starttime" name="starttime" placeholder="yyyy-mm-dd hh:mm[AP]" type="datetime-local"<?php defaultValue( $form, 'starttime', $submission_errors ); ?> /></td></tr>
<tr><td><label for="endtime">End time</label></td><td><input id="endtime" name="endtime" placeholder="yyyy-mm-dd hh:mm[AP]" type="datetime-local"<?php defaultValue( $form ,'endtime', $submission_errors );?> /></td></tr>
<tr><td><label for="startdate">Event start</label></td><td><input id="startdate" name="startdate" placeholder="yyyy-mm-dd" type="date"<?php defaultValue( $form, 'startdate', $submission_errors ); ?> /></td></tr>
<tr><td><label for="enddate">Event end</label></td><td><input id="enddate" name="enddate" placeholder="yyyy-mm-dd" type="date"<?php defaultValue( $form, 'enddate', $submission_errors ); ?> /></td></tr>
<tr><td><label for="conferencename">Conference name</label></td><td><input id="conferencename" name="conferencename" type="text"<?php defaultValue( $form, 'conferencename', $submission_errors ); ?> /></td></tr>
<tr><td><label for="conferenceurl">Conference URL</label></td><td><input id="conferenceurl" name="conferenceurl" type="url"<?php defaultValue( $form, 'conferenceurl', $submission_errors ); ?> /></td></tr>
<tr><td><label for="location">Location name</label></td><td><input id="location" name="location" type="text"<?php defaultValue( $form, 'location', $submission_errors ); ?> /></td></tr>
<tr><td><label for="locationaddress">Location address</label></td><td><input id="locationaddress" name="locationaddress" type="text"<?php defaultValue( $form, 'locationaddress', $submission_errors ); ?> /></td></tr>
<tr><td><label for="locationurl">Location URL</label></td><td><input id="locationurl" name="locationurl" type="url"<?php defaultValue( $form, 'locationurl', $submission_errors ); ?> /></td></tr>
<tr><td><label for="locationlatlng">Location</label></td><td><input id="locationlatlng" name="locationlatlng" placeholder="latitude, longitude" type="text"<?php defaultValue( $form, 'locationlatlng', $submission_errors ); ?> /></td></tr>
<tr><td><label for="details">Details</label></td><td><textarea id="details" name="details" style="font-family:inherit;"><?php
if ( strlen( $form['details'] ) )
{
print htmlspecialchars( $form['details'] );
}
?></textarea></td></tr>
<tr><td><label for="paperurl">URL</label></td><td><input id="paperurl" name="paperurl" type="url"<?php defaultValue( $form, 'paperurl', $submission_errors ); ?> /></td></tr>
<tr><td></td><td><input id="newitemsubmit" type="submit" value="Create" /></td></tr>
</tbody>
</table>
</form>
<?
}
$page->printPageFooter();
?>