Events and Birthdays [ 282 ] Next, we have our save method, which depending on whether an ID is set or not, either inserts a new record into the database or updates an existing one. If we are inserting a new record, it also iterates through the invitees, and adds them to the attendees table as an invitee. This would be where we may wish to add an e-mail notication to the user to inform them that they have been invited to the event: /** * Save the event * @return bool */ public function save() { // handle the updating of a profile if( $this->registry->getObject('authenticate')->isLoggedIn() && ( $this->registry->getObject('authenticate')- >getUser()->getUserID() == $this->creator || $this->registry- >getObject('authenticate')->getUser()->isAdmin() == true || $this->ID == 0 ) ) { // we are either the user created the event, or we are the administrator, or the event is being created $event = array(); foreach( $this as $field => $data ) { if( ! is_array( $data ) && ! is_object( $data ) && $field != 'ID' ) { $event[ $field ] = $this->$field; } } if( $this->ID == 0 ) { $this->registry->getObject('db')->insertRecords( 'events', $event ); $this->ID = $this->registry->getObject('db')- >lastInsertID(); if( is_array( $this->invitees ) && count( $this- >invitees ) > 0 ) { foreach( $this->invitees as $invitee ) { $insert = array(); $insert['event_id'] = $this->ID; $insert['user_id'] = $invitee; This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 9 [ 283 ] $insert['status'] = 'invited'; $this->registry->getObject('db')->insertRecords( 'event_attendees', $insert ); } } $insert = array(); $insert['event_id'] = $this->ID; $insert['user_id'] = $this->creator; $insert['status'] = 'going'; $this->registry->getObject('db')->insertRecords( 'event_ attendees', $insert ); return true; } else { $this->registry->getObject('db')->updateRecords( 'events', $event, 'ID=' . $this->ID ); if( $this->registry->getObject('db')->affectedRows() == 1 ) { return true; } else { return false; } } } else { return false; } } Next, we have the standard toTags method, which takes a prex, and converts all of the data that isn't an object or an array to template tags: /** * Convert the event data to template tags * @param String $prefix prefix for the template tags * @return voID */ public function toTags( $prefix='' ) { foreach( $this as $field => $data ) This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Events and Birthdays [ 284 ] { if( ! is_object( $data ) && ! is_array( $data ) ) { $this->registry->getObject('template')->getPage()- >addTag( $prefix.$field, $data ); } } } Finally, we have any getter methods that we may require: /** * Get the event name * @return String */ public function getName() { return $this->name; } /** * Get the users ID * @return int */ public function getID() { return $this->ID; } } ?> Events model Now, let's look at creating the events model to generate a list of events that a user may be interested in (models/events.php): <?php /** * Events model * - builds lists of events */ class Events{ This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 9 [ 285 ] We need to dene our registry, and construct the object: /** * Registry object */ private $registry; /** * Events constructor * @param Registry $registry * @return void */ public function __construct( Registry $registry ) { $this->registry = $registry; } To list events by connected users in a certain month, we simply use the relationships model, call the getIDsByUser method, and then query the events table, ltering by the results from the getIDs query, where the date is in a specic month and year: /** * List events by connected users in specified month / year * @param int $connectedTo events of users connected to this user * @param int $month * @param int $year * @return int database cacehe */ public function listEventsMonthYear( $connectedTo, $month, $year ) { require_once( FRAMEWORK_PATH . 'models/relationships.php'); $relationships = new Relationships( $this->registry ); $idsSQL = $relationships->getIDsByUser( $connectedTo ); $sql = "SELECT p.name as creator_name, e.* FROM events e, profile p WHERE p.user_id=e.creator AND e.event_date LIKE '{$year}-{$month}-%' AND e.creator IN ($idsSQL) "; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Events and Birthdays [ 286 ] Similar to the above query, here we use the DATE_ADD MySQL function to add X days to the current date, and return any events within the range between now and X days time: /** * List events by connected users in specified time period * @param int $connectedTo events of users connected to this user * @param int $days days in the future * @return int database cacehe */ public function listEventsFuture( $connectedTo, $days ) { require_once( FRAMEWORK_PATH . 'models/relationships.php'); $relationships = new Relationships( $this->registry ); $idsSQL = $relationships->getIDsByUser( $connectedTo ); $sql = "SELECT p.name as creator_name, e.* FROM events e, profile p WHERE p.user_id=e.creator AND e.event_date >= CURDATE() AND e.event_date <= DATE_ADD(CURDATE(), INTERVAL {$days} DAY ) AND e.creator IN ($idsSQL) "; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } This method lists any events X days in the future that were created by a specic user. This might be used on a user's prole, or for a user to see which events they had created: /** * List events by a specific user within next X days * @param int $user user whose events to list * @param int $days * @return int database cache */ public function listEventsUserFuture( $user, $days ) { $sql = "SELECT p.name as creator_name, e.* FROM events e, profile p WHERE p.user_id=e.creator AND e.event_date >= CURDATE() AND e.event_date <= DATE_ADD(CURDATE(), INTERVAL {$days} DAY ) AND e.creator={$user} "; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 9 [ 287 ] Finally, we have methods to return events that the current user was either invited to, is attending, isn't attending, or is maybe attending: /** * List events in the future user is invited to * @param int $user the user * @return int database cache */ public function listEventsInvited( $user ) { $sql = "SELECT p.name as creator_name, e.* FROM events e, profile p WHERE p.user_id=e.creator AND e.event_date >= CURDATE() AND ( SELECT COUNT(*) FROM events_attendees a WHERE a.event_id=e.ID AND a.user_id={$user} AND a.status='invited' ) > 0"; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } /** * List events in the future user is attending * @param int $user the user * @return int database cache */ public function listEventsAttending( $user ) { $sql = "SELECT p.name as creator_name, e.* FROM events e, profile p WHERE p.user_id=e.creator AND e.event_date >= CURDATE() AND ( SELECT COUNT(*) FROM events_attendees a WHERE a.event_id=e.ID AND a.user_id={$user} AND a.status='going' ) > 0"; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } /** * List events in the future user is not attending * @param int $user the user * @return int database cache */ public function listEventsNotAttending( $user ) { $sql = "SELECT p.name as creator_name, e.* FROM events e, profile p WHERE p.user_id=e.creator AND e.event_date >= CURDATE() AND ( SELECT COUNT(*) FROM events_attendees a WHERE a.event_id=e.ID AND a.user_id={$user} AND This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Events and Birthdays [ 288 ] a.status='not going' ) > 0"; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } /** * List events in the future user is maybe attending * @param int $user the user * @return int database cache */ public function listEventsMaybeAttending( $user ) { $sql = "SELECT p.name as creator_name, e.* FROM events e, profile p WHERE p.user_id=e.creator AND e.event_date >= CURDATE() AND ( SELECT COUNT(*) FROM events_attendees a WHERE a.event_id=e.ID AND a.user_id={$user} AND a.status='maybe' ) > 0"; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } } ?> Attendees, invitations, and RSVPs To list who is attending, invited, maybe attending, and not attending an event, we can add some new methods to our event model (models/event.php). These methods query the database for users who are attending, not attending, maybe attending or invited, cache the results, and return the cache. /** * Get users attending the event * @return int cache id */ public function getAttending() { $sql = "SELECT p.* FROM profile p, event_attendees WHERE p.user_id=a.user_id AND a.status='attending' AND a.event_id=" . $this->ID; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 9 [ 289 ] /** * Get users not attending the event * @return int cache id */ public function getNotAttending() { $sql = "SELECT p.* FROM profile p, event_attendees WHERE p.user_id=a.user_id AND a.status='not attending' AND a.event_id=" . $this->ID; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } /** * Get users maybe attending the event * @return int cache id */ public function getMaybeAttending() { $sql = "SELECT p.* FROM profile p, event_attendees WHERE p.user_id=a.user_id AND a.status='maybe' AND a.event_id=" . $this->ID; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } /** * Get users invited to the event * @return int cache id */ public function getInvited() { $sql = "SELECT p.* FROM profile p, event_attendees WHERE p.user_id=a.user_id AND a.status='invited' AND a.event_id=" . $this->ID; $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Events and Birthdays [ 290 ] RSVPs To allow a user to change their attendance preference for an event, we need a method in our event controller (controllers/event/controller.php), which we are going to create in the next section. This takes the event ID as a parameter, and POST data is submitted indicating the user's new choice for the event: private function changeAttendance( $event ) { $sql = "SELECT * FROM event_attendees WHERE event_id={$event} AND user_id=" . $this->registry->getObject('authenticate')- >getUser()->getID(); $this->registry->getObject('db')->executeQuery( $sql ); if( $this->registry->getObject('db')->numRows() == 1 ) { $data = $this->registry->getObject('db')->getRows(); $changes = array(); $changes['status'] = $this->registry->getObject('db')- >sanitizeData( $_POST['status'] ); $this->registry->getObject('db')->updateRecords( 'event_ attendees', $changes, 'ID=' . $data['ID'] ); $this->registry->redirectUser( $this->registry- >buildURL(array( 'home' ), '', false ), 'Attendance updated', 'Thanks, your attendance has been updated for that event', false ); } else { $this->registry->errorPage('Attendance not logged', 'Sorry, we could not find any record of your attendance for that event, please try again'); } } Controller With our event and events models in place, we now need a controller to allow the user to create, edit, view, and accept attendance of events. Creating an event To create an event, we need to see whether the user is submitting the form; if they are, we instantiate the event object, set the details, look for any invitees the user has added, set those, and create the event before redirecting them to the view event page. If no post data was submitted, we simply show the user the form. We may also want to provide a list of the users' connections on this page, so they can invite them to the event. After creating an event, you may wish to add functionality to e-mail those invitees: This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com Chapter 9 [ 291 ] /** * Create an event * @return void */ private function createEvent() { // if post data is set, we are creating an event if( isset( $_POST ) && count( $_POST ) > 0 ) { require_once( FRAMEWORK_PATH . 'models/event.php' ); $event = new Event( $this->registry, 0 ); $event->setName( $this->registry->getObject('db')- >sanitizeData( $_POST['name'] ) ); $event->setDescription( $this->registry->getObject('db')- >sanitizeData( $_POST['description'] ) ); $event->setDate( $this->registry->getObject('db')- >sanitizeData( $_POST['date'] ), false ); $event->setStartTime( $this->registry->getObject('db')- >sanitizeData( $_POST['start_time'] ) ); $event->setEndTime( $this->registry->getObject('db')- >sanitizeData( $_POST['end_time'] ) ); $event->setCreator( $this->registry->getObject('authenticate')- >getUser()->getID() ); $event->setType( $this->registry->getObject('db')- >sanitizeData( $_POST['type'] ) ); if( isset( $_POST['invitees'] ) && is_array( $_POST['invitees'] ) && count( $_POST['invitees'] ) > 0 ) { // assumes invitees are added to a table using javascript, with a hidden field with name invitees[] for the ID of invitee $is = array(); foreach( $_POST['invitees'] as $i ) { $is[] = intval( $i ); } $event->setInvitees( $is ); } $event->save(); $this->registry->redirectUser( $this->registry- >buildURL(array( 'event', 'view', $event->getID() ), '', false ), 'Event created', 'Thanks, the event has been created', false ); } else { $this->registry->getObject('template')->buildFromTemplates( 'header.tpl.php', 'events/create.tpl.php', 'footer.tpl.php' ); } } This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010 3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246 Download from www.eBookTM.com . $this->registry->getObject('authenticate' )- >getUser( )-& gt;getID(); $this->registry->getObject('db' )-& gt;executeQuery( $sql ); if( $this->registry->getObject('db' )-& gt;numRows(). $this->$field; } } if( $this->ID == 0 ) { $this->registry->getObject('db' )-& gt;insertRecords( 'events', $event ); $this->ID = $this->registry->getObject('db' )-. $this->registry->getObject('authenticate' )-& gt;isLoggedIn() && ( $this->registry->getObject('authenticate' )- >getUser( )-& gt;getUserID() == $this->creator