From 7495a34b32fdf1ea08bd2eaa378b216345077f7f Mon Sep 17 00:00:00 2001 From: rabuzarus <> Date: Sun, 19 Jun 2016 22:04:34 +0200 Subject: [PATCH] implement a public calendar for vistors of someones profile page --- include/event.php | 187 ++++++++++++ include/identity.php | 18 +- mod/cal.php | 279 ++++++++++++++++++ mod/events.php | 147 ++------- view/templates/event_head.tpl | 12 +- view/theme/frio/templates/event_head.tpl | 14 +- view/theme/frost-mobile/js/theme.js | 10 +- .../frost-mobile/templates/event_head.tpl | 2 + view/theme/frost/js/theme.js | 12 +- view/theme/frost/templates/event_head.tpl | 2 + 10 files changed, 542 insertions(+), 141 deletions(-) create mode 100644 mod/cal.php diff --git a/include/event.php b/include/event.php index c5e5ff18d7..df9b958570 100644 --- a/include/event.php +++ b/include/event.php @@ -1,7 +1,12 @@ $firstDay, + "Sun" => t("Sun"), + "Mon" => t("Mon"), + "Tue" => t("Tue"), + "Wed" => t("Wed"), + "Thu" => t("Thu"), + "Fri" => t("Fri"), + "Sat" => t("Sat"), + "Sunday" => t("Sunday"), + "Monday" => t("Monday"), + "Tuesday" => t("Tuesday"), + "Wednesday" => t("Wednesday"), + "Thursday" => t("Thursday"), + "Friday" => t("Friday"), + "Saturday" => t("Saturday"), + "Jan" => t("Jan"), + "Feb" => t("Feb"), + "Mar" => t("Mar"), + "Apr" => t("Apr"), + "May" => t("May"), + "Jun" => t("Jun"), + "Jul" => t("Jul"), + "Aug" => t("Aug"), + "Sep" => t("Sept"), + "Oct" => t("Oct"), + "Nov" => t("Nov"), + "Dec" => t("Dec"), + "January" => t("January"), + "February" => t("February"), + "March" => t("March"), + "April" => t("April"), + "May" => t("May"), + "June" => t("June"), + "July" => t("July"), + "August" => t("August"), + "September" => t("September"), + "October" => t("October"), + "November" => t("November"), + "December" => t("December"), + "today" => t("today"), + "month" => t("month"), + "week" => t("week"), + "day" => t("day"), + ); + + return $i18n; +} + +/** + * @brief Get an event by its event ID + * + * @param type $owner_uid The User ID of the owner of the event + * @param type $event_params An assoziative array with + * int 'event_id' => The ID of the event in the event table + * @param type $sql_extra + * @return array Query result + */ +function event_by_id($owner_uid = 0, $event_params, $sql_extra = '') { + // ownly allow events if there is a valid owner_id + if($owner_uid == 0) + return; + + // query for the event by event id + $r = q("SELECT `event`.*, `item`.`id` AS `itemid`,`item`.`plink`, + `item`.`author-name`, `item`.`author-avatar`, `item`.`author-link` FROM `event` + LEFT JOIN `item` ON `item`.`event-id` = `event`.`id` AND `item`.`uid` = `event`.`uid` + WHERE `event`.`uid` = %d AND `event`.`id` = %d $sql_extra", + intval($owner_uid), + intval($event_params["event_id"]) + ); + + if(count($r)) + return $r; + +} + +/** + * @brief Get all events in a specific timeframe + * + * @param int $owner_uid The User ID of the owner of the events + * @param array $event_params An assoziative array with + * int 'ignored' => + * string 'start' => Start time of the timeframe + * string 'finish' => Finish time of the timeframe + * string 'adjust_start' => + * string 'adjust_start' => + * + * @param string $sql_extra Additional sql conditions (e.g. permission request) + * @return array Query results + */ +function events_by_date($owner_uid = 0, $event_params, $sql_extra = '') { + // ownly allow events if there is a valid owner_id + if($owner_uid == 0) + return; + + // query for the event by date + $r = q("SELECT `event`.*, `item`.`id` AS `itemid`,`item`.`plink`, + `item`.`author-name`, `item`.`author-avatar`, `item`.`author-link` FROM `event` + LEFT JOIN `item` ON `item`.`event-id` = `event`.`id` AND `item`.`uid` = `event`.`uid` + WHERE `event`.`uid` = %d AND event.ignore = %d + AND ((`adjust` = 0 AND (`finish` >= '%s' OR (nofinish AND start >= '%s')) AND `start` <= '%s') + OR (`adjust` = 1 AND (`finish` >= '%s' OR (nofinish AND start >= '%s')) AND `start` <= '%s')) + $sql_extra ", + intval($owner_uid), + intval($event_params["ignored"]), + dbesc($event_params["start"]), + dbesc($event_params["start"]), + dbesc($event_params["finish"]), + dbesc($event_params["adjust_start"]), + dbesc($event_params["adjust_start"]), + dbesc($event_params["adjust_finish"]) + ); + + if(count($r)) + return $r; +} + +/** + * @brief Convert an array query results in an arry which could be used by the events template + * + * @param array $arr Event query array + * @return array Event array for the template + */ +function process_events ($arr) { + $events=array(); + + $last_date = ''; + $fmt = t('l, F j'); + if (count($arr)) { + foreach($arr as $rr) { + + $j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'j') : datetime_convert('UTC','UTC',$rr['start'],'j')); + $d = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], $fmt) : datetime_convert('UTC','UTC',$rr['start'],$fmt)); + $d = day_translate($d); + + $start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'c') : datetime_convert('UTC','UTC',$rr['start'],'c')); + if ($rr['nofinish']){ + $end = null; + } else { + $end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['finish'], 'c') : datetime_convert('UTC','UTC',$rr['finish'],'c')); + } + + + $is_first = ($d !== $last_date); + + $last_date = $d; + $edit = ((! $rr['cid']) ? array(App::get_baseurl().'/events/event/'.$rr['id'],t('Edit event'),'','') : null); + $title = strip_tags(html_entity_decode(bbcode($rr['summary']),ENT_QUOTES,'UTF-8')); + if(! $title) { + list($title, $_trash) = explode("$rr['id'], + 'start'=> $start, + 'end' => $end, + 'allDay' => false, + 'title' => $title, + + 'j' => $j, + 'd' => $d, + 'is_first'=>$is_first, + 'item'=>$rr, + 'html'=>$html, + 'plink' => array($rr['plink'],t('link to source'),'',''), + ); + } + } + + return $events; +} diff --git a/include/identity.php b/include/identity.php index 48a6c5bbf7..136452e787 100644 --- a/include/identity.php +++ b/include/identity.php @@ -740,8 +740,8 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){ ), ); - if ($is_owner){ - if ($a->theme_events_in_profile) + // the calendar link for the full featured events calendar + if ($is_owner && $a->theme_events_in_profile) { $tabs[] = array( 'label' => t('Events'), 'url' => $a->get_baseurl() . '/events', @@ -750,6 +750,20 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){ 'id' => 'events-tab', 'accesskey' => 'e', ); + // if the user is not the owner of the calendar we only show a calendar + // with the public events of the calendar owner + } elseif (! $is_owner) { + $tabs[] = array( + 'label' => t('Events'), + 'url' => $a->get_baseurl() . '/cal/' . $nickname, + 'sel' =>((!isset($tab)&&$a->argv[0]=='cal')?'active':''), + 'title' => t('Events and Calendar'), + 'id' => 'events-tab', + 'accesskey' => 'e', + ); + } + + if ($is_owner){ $tabs[] = array( 'label' => t('Personal Notes'), 'url' => $a->get_baseurl() . '/notes', diff --git a/mod/cal.php b/mod/cal.php new file mode 100644 index 0000000000..0cde2a6ece --- /dev/null +++ b/mod/cal.php @@ -0,0 +1,279 @@ +argc > 1) + auto_redir($a, $a->argv[1]); + + if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) { + return; + } + + nav_set_selected('events'); + + $o = ''; + + if($a->argc > 1) { + $nick = $a->argv[1]; + $user = q("SELECT * FROM `user` WHERE `nickname` = '%s' AND `blocked` = 0 LIMIT 1", + dbesc($nick) + ); + + if(! count($user)) + return; + + $a->data['user'] = $user[0]; + $a->profile_uid = $user[0]['uid']; + + $profile = get_profiledata_by_nick($nick, $a->profile_uid); + + if((intval($profile['page-flags']) == PAGE_COMMUNITY) || (intval($profile['page-flags']) == PAGE_PRVGROUP)) + $account_type = t('Forum'); + else + $account_type = ""; + + $tpl = get_markup_template("vcard-widget.tpl"); + + $vcard_widget .= replace_macros($tpl, array( + '$name' => $profile['name'], + '$photo' => $profile['photo'], + '$addr' => (($profile['addr'] != "") ? $profile['addr'] : ""), + '$account_type' => $account_type, + '$pdesc' => (($profile['pdesc'] != "") ? $profile['pdesc'] : ""), + )); + + if(! x($a->page,'aside')) + $a->page['aside'] = ''; + + $a->page['aside'] .= $vcard_widget; + } + + return; +} + +function cal_content(&$a) { + nav_set_selected('events'); + + $editselect = 'none'; + if( feature_enabled(local_user(), 'richtext') ) + $editselect = 'textareas'; + + // First day of the week (0 = Sunday) + $firstDay = get_pconfig(local_user(),'system','first_day_of_week'); + if ($firstDay === false) $firstDay=0; + + // get the translation strings for the callendar + $i18n = get_event_strings(); + + $htpl = get_markup_template('event_head.tpl'); + $a->page['htmlhead'] .= replace_macros($htpl,array( + '$baseurl' => $a->get_baseurl(), + '$module_url' => '/cal/' . $a->data['user']['nickname'], + '$modparams' => 2, + '$i18n' => $i18n, + '$editselect' => $editselect + )); + + $etpl = get_markup_template('event_end.tpl'); + $a->page['end'] .= replace_macros($etpl,array( + '$baseurl' => $a->get_baseurl(), + '$editselect' => $editselect + )); + + $o =""; + + $mode = 'view'; + $y = 0; + $m = 0; + $ignored = ((x($_REQUEST,'ignored')) ? intval($_REQUEST['ignored']) : 0); + + // + // Setup permissions structures + // + + $contact = null; + $remote_contact = false; + $contact_id = 0; + + $owner_uid = $a->data['user']['uid']; + + if(is_array($_SESSION['remote'])) { + foreach($_SESSION['remote'] as $v) { + if($v['uid'] == $a->profile['profile_uid']) { + $contact_id = $v['cid']; + break; + } + } + } + if($contact_id) { + $groups = init_groups_visitor($contact_id); + $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", + intval($contact_id), + intval($a->profile['profile_uid']) + ); + if(count($r)) { + $contact = $r[0]; + $remote_contact = true; + } + } + if(! $remote_contact) { + if(local_user()) { + $contact_id = $_SESSION['cid']; + $contact = $a->contact; + } + } + $is_owner = ((local_user()) && (local_user() == $a->profile['profile_uid']) ? true : false); + + if($a->profile['hidewall'] && (! $is_owner) && (! $remote_contact)) { + notice( t('Access to this profile has been restricted.') . EOL); + return; + } + + $sql_extra = item_permissions_sql($owner_uid,$remote_contact,$groups); + + // get the tab navigation bar + $tabs .= profile_tabs($a,false, $a->data['user']['nickname']); + + // The view mode part is similiar to /mod/events.php + if($mode == 'view') { + + + $thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y'); + $thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m'); + if(! $y) + $y = intval($thisyear); + if(! $m) + $m = intval($thismonth); + + // Put some limits on dates. The PHP date functions don't seem to do so well before 1900. + // An upper limit was chosen to keep search engines from exploring links millions of years in the future. + + if($y < 1901) + $y = 1900; + if($y > 2099) + $y = 2100; + + $nextyear = $y; + $nextmonth = $m + 1; + if($nextmonth > 12) { + $nextmonth = 1; + $nextyear ++; + } + + $prevyear = $y; + if($m > 1) + $prevmonth = $m - 1; + else { + $prevmonth = 12; + $prevyear --; + } + + $dim = get_dim($y,$m); + $start = sprintf('%d-%d-%d %d:%d:%d',$y,$m,1,0,0,0); + $finish = sprintf('%d-%d-%d %d:%d:%d',$y,$m,$dim,23,59,59); + + + if ($a->argv[2] === 'json'){ + if (x($_GET,'start')) $start = date("Y-m-d h:i:s", $_GET['start']); + if (x($_GET,'end')) $finish = date("Y-m-d h:i:s", $_GET['end']); + } + + $start = datetime_convert('UTC','UTC',$start); + $finish = datetime_convert('UTC','UTC',$finish); + + $adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start); + $adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish); + + // put the event parametes in an array so we can better transmit them + $event_params = array( + 'event_id' => (x($_GET,'id') ? $_GET["id"] : 0), + 'start' => $start, + 'finish' => $finish, + 'adjust_start' => $adjust_start, + 'adjust_finish' => $adjust_finish, + 'ignored' => $ignored, + ); + + // get events by id or by date + if (x($_GET,'id')){ + $r = event_by_id($owner_uid, $event_params, $sql_extra); + } else { + $r = events_by_date($owner_uid, $event_params, $sql_extra); + } + + $links = array(); + + if(count($r)) { + $r = sort_by_date($r); + foreach($r as $rr) { + $j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'j') : datetime_convert('UTC','UTC',$rr['start'],'j')); + if(! x($links,$j)) + $links[$j] = $a->get_baseurl() . '/' . $a->cmd . '#link-' . $j; + } + } + + + $events=array(); + + // transform the event in a usable array + if(count($r)) + $r = sort_by_date($r); + $events = process_events($r); + + if ($a->argv[2] === 'json'){ + echo json_encode($events); killme(); + } + + // links: array('href', 'text', 'extra css classes', 'title') + if (x($_GET,'id')){ + $tpl = get_markup_template("event.tpl"); + } else { +// if (get_config('experimentals','new_calendar')==1){ + $tpl = get_markup_template("events-js.tpl"); +// } else { +// $tpl = get_markup_template("events.tpl"); +// } + } + + // Get rid of dashes in key names, Smarty3 can't handle them + foreach($events as $key => $event) { + $event_item = array(); + foreach($event['item'] as $k => $v) { + $k = str_replace('-','_',$k); + $event_item[$k] = $v; + } + $events[$key]['item'] = $event_item; + } + + $o = replace_macros($tpl, array( + '$baseurl' => $a->get_baseurl(), + '$tabs' => $tabs, + '$title' => t('Events'), + '$view' => t('View'), + '$previus' => array($a->get_baseurl()."/events/$prevyear/$prevmonth",t('Previous'),'',''), + '$next' => array($a->get_baseurl()."/events/$nextyear/$nextmonth",t('Next'),'',''), + '$calendar' => cal($y,$m,$links, ' eventcal'), + + '$events' => $events, + + "today" => t("today"), + "month" => t("month"), + "week" => t("week"), + "day" => t("day"), + + + )); + + if (x($_GET,'id')){ echo $o; killme(); } + + return $o; + } +} diff --git a/mod/events.php b/mod/events.php index e4526ac594..617627ac4c 100644 --- a/mod/events.php +++ b/mod/events.php @@ -1,5 +1,8 @@ $firstDay, - "Sun" => t("Sun"), - "Mon" => t("Mon"), - "Tue" => t("Tue"), - "Wed" => t("Wed"), - "Thu" => t("Thu"), - "Fri" => t("Fri"), - "Sat" => t("Sat"), - "Sunday" => t("Sunday"), - "Monday" => t("Monday"), - "Tuesday" => t("Tuesday"), - "Wednesday" => t("Wednesday"), - "Thursday" => t("Thursday"), - "Friday" => t("Friday"), - "Saturday" => t("Saturday"), - "Jan" => t("Jan"), - "Feb" => t("Feb"), - "Mar" => t("Mar"), - "Apr" => t("Apr"), - "May" => t("May"), - "Jun" => t("Jun"), - "Jul" => t("Jul"), - "Aug" => t("Aug"), - "Sep" => t("Sept"), - "Oct" => t("Oct"), - "Nov" => t("Nov"), - "Dec" => t("Dec"), - "January" => t("January"), - "February" => t("February"), - "March" => t("March"), - "April" => t("April"), - "May" => t("May"), - "June" => t("June"), - "July" => t("July"), - "August" => t("August"), - "September" => t("September"), - "October" => t("October"), - "November" => t("November"), - "December" => t("December"), - "today" => t("today"), - "month" => t("month"), - "week" => t("week"), - "day" => t("day"), - ); + // get the translation strings for the callendar + $i18n = get_event_strings(); $htpl = get_markup_template('event_head.tpl'); $a->page['htmlhead'] .= replace_macros($htpl,array( '$baseurl' => $a->get_baseurl(), + '$module_url' => '/events', + '$modparams' => 1, '$i18n' => $i18n, '$editselect' => $editselect )); @@ -284,6 +242,7 @@ function events_content(&$a) { } } + // The view mode part is similiar to /mod/cal.php if($mode == 'view') { @@ -333,31 +292,21 @@ function events_content(&$a) { $adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start); $adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish); + // put the event parametes in an array so we can better transmit them + $event_params = array( + 'event_id' => (x($_GET,'id') ? $_GET["id"] : 0), + 'start' => $start, + 'finish' => $finish, + 'adjust_start' => $adjust_start, + 'adjust_finish' => $adjust_finish, + 'ignored' => $ignored, + ); + // get events by id or by date if (x($_GET,'id')){ - $r = q("SELECT `event`.*, `item`.`id` AS `itemid`,`item`.`plink`, - `item`.`author-name`, `item`.`author-avatar`, `item`.`author-link` FROM `event` - LEFT JOIN `item` ON `item`.`event-id` = `event`.`id` AND `item`.`uid` = `event`.`uid` - WHERE `event`.`uid` = %d AND `event`.`id` = %d", - intval(local_user()), - intval($_GET['id']) - ); + $r = event_by_id(local_user(), $event_params); } else { - $r = q("SELECT `event`.*, `item`.`id` AS `itemid`,`item`.`plink`, - `item`.`author-name`, `item`.`author-avatar`, `item`.`author-link` FROM `event` - LEFT JOIN `item` ON `item`.`event-id` = `event`.`id` AND `item`.`uid` = `event`.`uid` - WHERE `event`.`uid` = %d and event.ignore = %d - AND ((`adjust` = 0 AND (`finish` >= '%s' OR (nofinish AND start >= '%s')) AND `start` <= '%s') - OR (`adjust` = 1 AND (`finish` >= '%s' OR (nofinish AND start >= '%s')) AND `start` <= '%s')) ", - intval(local_user()), - intval($ignored), - dbesc($start), - dbesc($start), - dbesc($finish), - dbesc($adjust_start), - dbesc($adjust_start), - dbesc($adjust_finish) - ); + $r = events_by_date(local_user(), $event_params); } $links = array(); @@ -371,60 +320,12 @@ function events_content(&$a) { } } - $events=array(); - $last_date = ''; - $fmt = t('l, F j'); - - if(count($r)) { + // transform the event in a usable array + if(count($r)) $r = sort_by_date($r); - foreach($r as $rr) { - - - $j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'j') : datetime_convert('UTC','UTC',$rr['start'],'j')); - $d = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], $fmt) : datetime_convert('UTC','UTC',$rr['start'],$fmt)); - $d = day_translate($d); - - $start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'c') : datetime_convert('UTC','UTC',$rr['start'],'c')); - if ($rr['nofinish']){ - $end = null; - } else { - $end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['finish'], 'c') : datetime_convert('UTC','UTC',$rr['finish'],'c')); - } - - - $is_first = ($d !== $last_date); - - $last_date = $d; - $edit = ((! $rr['cid']) ? array($a->get_baseurl().'/events/event/'.$rr['id'],t('Edit event'),'','') : null); - $title = strip_tags(html_entity_decode(bbcode($rr['summary']),ENT_QUOTES,'UTF-8')); - if(! $title) { - list($title, $_trash) = explode("$rr['id'], - 'start'=> $start, - 'end' => $end, - 'allDay' => false, - 'title' => $title, - - 'j' => $j, - 'd' => $d, - 'edit' => $edit, - 'is_first'=>$is_first, - 'item'=>$rr, - 'html'=>$html, - 'plink' => array($rr['plink'],t('link to source'),'',''), - ); - - - } - } + $events = process_events($r); if ($a->argv[1] === 'json'){ echo json_encode($events); killme(); diff --git a/view/templates/event_head.tpl b/view/templates/event_head.tpl index 01c69b8b31..99a320a895 100644 --- a/view/templates/event_head.tpl +++ b/view/templates/event_head.tpl @@ -6,7 +6,7 @@ diff --git a/view/theme/frost/js/theme.js b/view/theme/frost/js/theme.js index 038f83e0e5..eb8bb51cc2 100644 --- a/view/theme/frost/js/theme.js +++ b/view/theme/frost/js/theme.js @@ -149,7 +149,7 @@ $(document).ready(function() { if(window.aclType == "event_head") { $('#events-calendar').fullCalendar({ - events: baseurl + '/events/json/', + events: baseurl + window.eventModuleUrl +'/json/', header: { left: 'prev,next today', center: 'title', @@ -202,10 +202,12 @@ $(document).ready(function() { // center on date var args=location.href.replace(baseurl,"").split("/"); - if (args.length>=4) { + if (args.length>=5 && window.eventModeParams == 2) { + $("#events-calendar").fullCalendar('gotoDate',args[3] , args[4]-1); + } else if (args.length>=4 && window.eventModeParams == 1) { $("#events-calendar").fullCalendar('gotoDate',args[2] , args[3]-1); - } - + } + // show event popup var hash = location.hash.split("-") if (hash.length==2 && hash[0]=="#link") showEvent(hash[1]); @@ -352,7 +354,7 @@ if(typeof window.photoEdit != 'undefined') { function showEvent(eventid) { $.get( - baseurl + '/events/?id='+eventid, + baseurl + window.eventModuleUrl + '/?id=' + eventid, function(data){ $.colorbox({html:data}); $.colorbox.resize(); diff --git a/view/theme/frost/templates/event_head.tpl b/view/theme/frost/templates/event_head.tpl index f33f7fce23..47efb56ae9 100644 --- a/view/theme/frost/templates/event_head.tpl +++ b/view/theme/frost/templates/event_head.tpl @@ -4,5 +4,7 @@