Skip to content

Instantly share code, notes, and snippets.

@b4oshany
Created February 4, 2015 07:05
Show Gist options
  • Save b4oshany/26966b8673d081d8c7d8 to your computer and use it in GitHub Desktop.
Save b4oshany/26966b8673d081d8c7d8 to your computer and use it in GitHub Desktop.
Full Calendar
<?php
namespace libs\schedule;
require_once "setup.php";
use libs\vecni\Vecni;
use libs\mongodb\Model;
use libs\user\User;
use libs\location\Location;
use libs\schedule\Event;
class Calendar extends Model{
# Basic calendars information,
public $title; // Title of the calendar.
public $description; // Description of the calendar.
public $creator; // Creator of the calendar.
public static $collection = "calendar"; // name of collection to be used
/**
* __callstatic is triggered when invoking inaccessible methods in an static context
* This method will initiate the mongodb connection and select the desired database
* In addition, it will initiate the collection model for the user data.
*/
public static function setUp(){
parent::setUp();
$collection = self::$collection;
self::$model = self::$mongodb->$collection;
}
/**
* Set the collection settings for monogodb
* such as the unique attributes in the collection
*/
public static function collectionSettings(){
self::$mongodb->calendar->createIndex(
array("title"=>1,
"creator"=>1
),
array("unique"=>1)
);
}
/**
* Create a new calendar
* @param mixed $title - calendar title
* @param mixed $description - calendar description
* @return Event - event obejct with the start time, title and description attached to it
*/
public static function create($title, $description=""){
# create a new event object and set the values of the title, description and start time
$new_cal = new self();
$new_cal->title = $title;
$new_cal->description = $description;
$date = new \DateTime('NOW');
$new_cal->date_created = $date;
$new_cal->creator = User::get_current_user_db()->get_MongoId();
$new_cal->save();
return $new_cal;
}
/**
* Set the duration of the event
* @param mixed $duration duration of the event which will determine the end time
* @return Event - new created event
*/
public function create_event($title, \DateTime $start_time, $description){
$new_event = Event::create($title, $start_time, $description);
$new_event->default_calendar = $this->get_MongoId();
$new_event->subscribe_calendar[0] = $this->get_MongoId();
$new_event->save();
return $new_event;
}
public function get_month_events(\DateTime $from = null, \DateTime $to = null){
if(!isset($from)){
$from = new \DateTime('NOW');
}
$from->sub(new \DateInterval('P1M'));
if(!isset($to)){
$to = clone $from;
$to->add(new \DateInterval('P3M'));
}
return Event::find(array(
'$or'=>array(
array(
"subscribe_calendar"=>array(
'$all'=>array($this->get_MongoId())
)
),
array("default_calendar"=>$this->get_MongoId())
),
"start_time.date" =>array(
'$gte'=>$from->format("Y-m-d H:i:s"),
'$lte'=>$to->format("Y-m-d H:i:s")
)
));
}
public function get_calendar_events(\DateTime $from = null, \DateTime $to = null){
$events = $this->get_month_events($from, $to);
$calendar_format = array();
foreach($events as $event){
array_push($calendar_format, $event->get_calendar_format());
}
return $calendar_format;
}
public function get_event($event_id){
$event_object_id = self::create_MongoId($event_id);
$event = Event::find_one(array(
"_id"=>$event_object_id,
"subscribe_calendar"=>array(
'$all'=>array($this->get_MongoId())
)
));
if(isset($event)){
return $event;
}
return null;
}
/**
* Calculate the ending time of the event based on the duration and start time
* @return date end time of the event
*/
public function get_end_time(){
$date = $this->start_time;
date_add($date, date_interval_create_from_date_string($this->duration));
return $date;
}
/**
* Set the location of the event
* @param Location|string $venue - set the location of the venue, if Location, then there will be
* an associated location object with the event address and cordinates on map, else it's a stirng
* that will be displayed
*/
public function change_venue($venue = " "){
if($venue instanceof Location || $venue instanceof string){
$this->venue = $venue;
}else{
throw new \Exception("Incorrect type, venue must be a Location object or String");
}
}
}
Calendar::setUp();
Calendar::collectionSettings();
?>
<?php
namespace libs\schedule;
require_once "setup.php";
use libs\vecni\Vecni;
use libs\mongodb\Model;
use libs\mongodb\MongoIdRef;
use libs\user\User;
use libs\location\Location;
use libs\schedule\Calendar;
class Event extends Model{
public static $collection = "event";
# Basic event information
public $title; // title of the event
public $venue; // location of the event
public $description; // description of the event
public $start_time; // start time of the event
public $duration; // duration of the event which will determine the end time
public $recurrence_type; // type of recurrency event, such as hourly, daily, weekly, etc
public $end_date; // ending date for the recurrent event should stop
public $creator; // creator of the event
public $attendees; // attendees of the event
public $default_calendar; // main calendar
public $subscribe_calendar;
/**
* __callstatic is triggered when invoking inaccessible methods in an static context
* This method will initiate the mongodb connection and select the desired database
* In addition, it will initiate the collection model for the user data.
*/
public static function setUp(){
parent::setUp();
$collection = self::$collection;
self::$model = self::$mongodb->$collection;
}
/**
* Set the collection settings for monogodb
* such as the unique attributes in the collection
*/
public static function collectionSettings(){
self::$mongodb->user->createIndex(
array("title"=>1,
"calendar"=>1,
"creator"=>1
),
array("unique"=>1)
);
}
public function enforce_constraints(){
$this->start_time = self::cast("DateTime", $this->start_time);
$this->duration = self::cast("DateInterval", $this->duration);
}
public function __construct(){
$this->duration = new \DateInterval("PT1H");
$this->subscribe_calendar = array();
}
/**
* Create a new event
* @param mixed $title - event title
* @param mixed $description - event description
* @param date $start_time - the time which the event will start
* @return Event - event obejct with the start time, title and description attached to it
*/
public static function create($title, \DateTime $start_time, $description=""){
# create a new event object and set the values of the title, description and start time
$new_event = new self();
$new_event->title = $title;
$new_event->description = $description;
$new_event->start_time = $start_time;
$new_event->creator = User::get_current_user_db()->get_MongoId();
return $new_event;
}
/**
* Add a calendar that subscribes to this event.
* @param MongoId $calendar_ref - Calendar document ref.
* @return bool - true if the update is successful else false.
*/
public function add_calendar_subscription(\MongoId $calendar_id){
if($this->update(array(
'$addToSet'=>array('subscribe_calendar'=>$calendar_id)
))){
return true;
}
return false;
}
/**
* Set the duration of the event, which is a DateInterval that will be used
* as the DateTime add method parameter
* @param int $hours - number of hours for the event duration
* @param int $mins - number of minutes for the event duration
* @param int $secs - number of seconds for the event duration
*/
public function set_duration_time($hours = 0, $mins = 0, $secs = 0){
$this->duration->h = $hours; // set duration hours
$this->duration->i = $mins; // set duration minutes
$this->duration->s = $secs; // set duration seconds
}
/**
* Calculate the ending time of the event based on the duration and start time
* @return DateTime - end time of the event
*/
public function get_end_time(){
$date = $this->start_time;
$date->add($this->duration);
return $date;
}
/**
* Set the location of the event
* @param Location|string $venue - set the location of the venue, if Location, then there will be
* an associated location object with the event address and cordinates on map, else it's a stirng
* that will be displayed
*/
public function change_venue($venue = " "){
if($venue instanceof Location || $venue instanceof string){
$this->venue = $venue;
}else{
throw new \Exception("Incorrect type, venue must be a Location object or String");
}
}
/**
* Get a basic event summary for the calendar which includes, the title, description,
* start and end time of the event as well as the event creator name and id
* @return array - event data
*/
public function get_calendar_format(){
$event_data = array();
$event_data["start"] = $this->start_time->format("c");
$end_time = $this->get_end_time();
$event_data["end"] = $end_time->format("c");
$event_data["title"] = $this->title;
$event_data["description"] = $this->description;
$event_data["id"] = $this->id;
$user = User::find_one(
array("_id"=>$this->creator),
array("first_name", "last_namee")
);
$event_data["creator"] = array(
"name"=>"$user->first_name $user->last_name",
"id"=>"$user->id"
);
return $event_data;
}
}
Event::setUp();
Event::collectionSettings();
?>
var Schedule = function(){
this.date = new Date;
this.d = this.date.getDate(),
this.m = this.date.getMonth(),
this.y = this.date.getFullYear(),
this.url = 'calendar/event',
this.curColor = "#00c0ef",
this.event_source = [
// your event source
{
url: this.url, // use the `url` property
color: 'yellow', // an option!
textColor: 'black', // an option!
cache: true
}
// any other sources...
],
/* initialize the external events
-----------------------------------------------------------------*/
this.ini_events = function(ele) {
ele.each(function() {
// create an Event Object (http://arshaw.com/fullcalendar/docs/event_data/Event_Object/)
// it doesn't need to have a start or end
var eventObject = {
title: $.trim($(this).text()) // use the element's text as the event title
};
// store the Event Object in the DOM element so we can get to it later
$(this).data('eventObject', eventObject);
// make the event draggable using jQuery UI
$(this).draggable({
zIndex: 1070,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
});
}
this.ini_calendar = function(){
var schedule = this;
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
buttonText: {//This is to add icons to the visible buttons
prev: "previous",
next: "next",
today: 'today',
month: 'month',
week: 'week',
day: 'day'
},
dayClick: function(date, jsEvent, view ) {
$('#calendar').fullCalendar( 'changeView', "agendaDay");
$('#calendar').fullCalendar( 'gotoDate', date);
},
eventRender: function(event, element){
element.attr("id", event.id);
},
eventClick: function(calEvent, jsEvent, view) {
console.log(calid);
$.post("calendar/"+calid+"/event/"+calEvent.id,
function(data){
$("#remote-modal .modal-content").html(data);
$("#remote-modal").modal('show');
});
},
//Random default events
eventSources: schedule.event_source,
editable: true,
droppable: true, // this allows things to be dropped onto the calendar !!!
drop: function(date, allDay) { // this function is called when something is dropped
// retrieve the dropped element's stored Event Object
var originalEventObject = $(this).data('eventObject');
// we need to copy it, so that multiple events don't have a reference to the same object
var copiedEventObject = $.extend({}, originalEventObject);
// assign it the date that was reported
copiedEventObject.start = date;
copiedEventObject.allDay = allDay;
copiedEventObject.backgroundColor = $(this).css("background-color");
copiedEventObject.borderColor = $(this).css("border-color");
// render the event on the calendar
// the last `true` argument determines if the event "sticks" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/)
$('#calendar').fullCalendar('renderEvent', copiedEventObject, true);
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
$(this).remove();
}
}
});
}
this.color_picker = function(){
var schedule = this;
/* ADDING EVENTS */
schedule.currColor = "#f56954"; //Red by default
//Color chooser button
var colorChooser = $("#color-chooser-btn");
$("#color-chooser > li > a").click(function(e) {
e.preventDefault();
//Save color
schedule.currColor = $(this).css("color");
//Add color effect to button
colorChooser
.css({"background-color": schedule.currColor, "border-color": schedule.currColor})
.html($(this).text()+' <span class="caret"></span>');
});
this.curr
}
this.add_event_onclick = function(){
var schedule = this;
$(document).on("submit", "form[name=new_event]", function(e){
e.preventDefault();
$.post("calendar/event/create", $(this).serialize(), function(data){
$('#calendar').fullCalendar('renderEvent', data, true);
flash_notification("Your event has been created", "success");
});
});
}
}
$(function() {
var schedule = new Schedule();
schedule.ini_events($('#external-events div.external-event'));
schedule.ini_calendar();
schedule.color_picker();
schedule.add_event_onclick();
});
/**
* Request the addition of universities to Tattle Tale
*/
Vecni::set_route("/calendar/create", "calendar_create");
function calendar_create(){
global $twig;
if(User::is_login()){
if($title = Request::POST("calendar_title")){
$calendar = Calendar::create($title);
if(Request::is_async()){
return Response::json_response(200, $calendar->id);
}
Vecni::redirect("Vecni::$host/calendar/schedule?calid=$calendar->id");
}
return $twig->render('calendar_create.html',
array(
"html_class"=>"calendar_create",
"title"=>"Create Calendar"
)
);
}else{
return signin_require("You need to signin first, before you can add a university");
}
}
/**
* Scheduling page for users
*/
Vecni::set_route("/calendar/schedule", "view_schedule");
function view_schedule($message=""){
global $twig;
if(User::is_login()){
$current_user = User::get_current_user_db();
$calendar = $current_user->get_default_calendar();
return $twig->render('scheduling.html',
array(
"html_class"=>"calendar_view",
"title"=>"Schedules",
"calendar"=>$calendar
)
);
}else{
return signin_require("You need to signin first, before can view schedules");
}
}
/**
* get events for the calendars
*/
Vecni::set_route("/calendar/event", "get_events");
function get_events(){
if($cal_id = Request::GET("calid")){
$calendar = Calendar::get_by_id($cal_id);
}else{
$current_user = User::get_current_user_db();
$calendar = $current_user->get_default_calendar();
$events = $calendar->get_calendar_events();
return Response::json_feed($events);
}
}
/* view events */
Vecni::set_route("/calendar/{calendar_id}/event/{event_id}", "view_event");
function view_event(){
global $twig;
if(($cal_id = Request::GET("calendar_id")) &&
($event_id = Request::GET("event_id"))
){
$calendar = Calendar::get_by_id($cal_id);
$event = $calendar->get_event($event_id);
if(Request::is_async()){
return $twig->render("bit/views/event_view.html",
array(
"event"=>$event,
"calendar"=>$calendar
)
);
}else{
return $twig->render('bit/views/event_view.html',
array(
"event"=>$event,
"calendar"=>$calendar
)
);
}
}
return "No event found";
}
/* view events */
Vecni::set_route("/calendar/{calendar_id}/event/{event_id}/edit", "event_edit");
function event_edit(){
global $twig;
if(($cal_id = Request::GET("calendar_id")) &&
($event_id = Request::GET("event_id"))
){
$calendar = Calendar::get_by_id($cal_id);
$event = $calendar->get_event($event_id);
if(Request::is_async()){
return $twig->render("bit/views/event_view.html",
array(
"event"=>$event,
"calendar"=>$calendar
)
);
}else{
return $twig->render('bit/views/event_view.html',
array(
"event"=>$event,
"calendar"=>$calendar
)
);
}
}
}
/**
* get events for the calendars
*/
Vecni::set_route("/calendar/event/create", "create_event");
function create_event(){
if(($start_time = Request::POST("event_start_time")) &&
($title = Request::POST("event_title")) &&
($start_date = Request::POST("event_start_date"))
){
$description = Request::POST("event_description", "");
$duration = "2 hours";
$current_user = User::get_current_user_db();
$calendar = $current_user->get_default_calendar();
$date = DateTime::createFromFormat('G:i Y-m-d',
"$start_time $start_date");
if($date){
$event = $calendar->create_event($title, $date, $description);
if(!empty($event)){
$event_data = $event->get_calendar_format();
return Response::json_feed($event_data);
}
}
}
}
<?php
namespace libs\vecni;
require_once "__autoload.php";
require_once "Request.php";
class Response{
public static function init(){
if(!isset($_SESSION["access_key"])){
$_SESSION["access_key"] = uniqid('vecni_');
}
}
public static function json_response($status_code=200, $message="ok"){
header('Content-Type: application/json');
return json_encode(array('status'=>$status_code,
'message'=>$message));
}
public static function json_feed($message=""){
header('Content-Type: application/json');
return json_encode($message);
}
public static function abort($message = null){
header("Connection: close", true);
if(!empty($message)){
if(Request::is_async()){
header("Message: $message");
}else{
echo $message;
}
}
header("HTTP/1.0 404 Not Found");
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment