diff options
author | redmatrix <git@macgirvin.com> | 2016-02-24 18:54:52 -0800 |
---|---|---|
committer | redmatrix <git@macgirvin.com> | 2016-02-24 18:54:52 -0800 |
commit | c95d7c69eb3135f137390323a09eb105776ce29c (patch) | |
tree | 5183b1d8e9fde8ff9e7628ad0160c0b78bd35f30 | |
parent | 6300f47cdcd921141b8f98b71d373d53aa3d80f2 (diff) | |
download | volse-hubzilla-c95d7c69eb3135f137390323a09eb105776ce29c.tar.gz volse-hubzilla-c95d7c69eb3135f137390323a09eb105776ce29c.tar.bz2 volse-hubzilla-c95d7c69eb3135f137390323a09eb105776ce29c.zip |
issue #216 - calendar sharing
-rw-r--r-- | include/conversation.php | 20 | ||||
-rw-r--r-- | include/security.php | 18 | ||||
-rwxr-xr-x | mod/cal.php | 343 | ||||
-rwxr-xr-x | mod/events.php | 7 | ||||
-rw-r--r-- | view/pdl/mod_cal.pdl | 3 | ||||
-rwxr-xr-x | view/tpl/event_cal.tpl | 14 | ||||
-rwxr-xr-x | view/tpl/event_head.tpl | 13 | ||||
-rwxr-xr-x | view/tpl/events_cal-js.tpl | 17 |
8 files changed, 425 insertions, 10 deletions
diff --git a/include/conversation.php b/include/conversation.php index 1ade8ed3a..e2dfccac9 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1595,8 +1595,17 @@ function profile_tabs($a, $is_owner = false, $nickname = null){ if (is_null($nickname)) $nickname = $channel['channel_address']; + $uid = (($a->profile['profile_uid']) ? $a->profile['profile_uid'] : local_channel()); + if($uid == local_channel()) { + $cal_link = '/events'; + } + else { + $cal_link = '/cal/' . $nickname; + } + + if (get_pconfig($uid, 'system', 'noprofiletabs')) return; @@ -1644,6 +1653,17 @@ function profile_tabs($a, $is_owner = false, $nickname = null){ ); } + if($p['view_stream']) { + $tabs[] = array( + 'label' => t('Events'), + 'url' => $a->get_baseurl() . $cal_link, + 'sel' => ((argv(0) == 'cal' || argv(0) == 'events') ? 'active' : ''), + 'title' => t('Events'), + 'id' => 'event-tab', + ); + } + + if ($p['chat']) { require_once('include/chat.php'); $has_chats = chatroom_list_count($uid); diff --git a/include/security.php b/include/security.php index ee94dba82..215cc92cb 100644 --- a/include/security.php +++ b/include/security.php @@ -148,7 +148,7 @@ function change_channel($change_channel) { * @return string additional SQL where statement */ -function permissions_sql($owner_id, $remote_observer = null) { +function permissions_sql($owner_id, $remote_observer = null, $table = '') { $local_channel = local_channel(); @@ -158,10 +158,14 @@ function permissions_sql($owner_id, $remote_observer = null) { * default permissions - anonymous user */ - $sql = " AND allow_cid = '' - AND allow_gid = '' - AND deny_cid = '' - AND deny_gid = '' + if($table) + $table .= '.'; + + + $sql = " AND {$table}allow_cid = '' + AND {$table}allow_gid = '' + AND {$table}deny_cid = '' + AND {$table}deny_gid = '' "; /** @@ -193,8 +197,8 @@ function permissions_sql($owner_id, $remote_observer = null) { } $regexop = db_getfunc('REGEXP'); $sql = sprintf( - " AND ( NOT (deny_cid like '%s' OR deny_gid $regexop '%s') - AND ( allow_cid like '%s' OR allow_gid $regexop '%s' OR ( allow_cid = '' AND allow_gid = '') ) + " AND ( NOT ({$table}deny_cid like '%s' OR {$table}deny_gid $regexop '%s') + AND ( {$table}allow_cid like '%s' OR {$table}allow_gid $regexop '%s' OR ( {$table}allow_cid = '' AND {$table}allow_gid = '') ) ) ", dbesc(protect_sprintf( '%<' . $observer . '>%')), diff --git a/mod/cal.php b/mod/cal.php new file mode 100755 index 000000000..9899b33b0 --- /dev/null +++ b/mod/cal.php @@ -0,0 +1,343 @@ +<?php + +require_once('include/conversation.php'); +require_once('include/bbcode.php'); +require_once('include/datetime.php'); +require_once('include/event.php'); +require_once('include/items.php'); +require_once('Contact.php'); + + +function cal_init(&$a) { + if((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) { + return; + } + + $o = ''; + + if(argc() > 1) { + $nick = argv(1); + + profile_load($a,$nick); + + $channelx = channelx_by_nick($nick); + + if(! $channelx) + return; + + $a->data['channel'] = $channelx; + + $observer = $a->get_observer(); + $a->data['observer'] = $observer; + + $observer_xchan = (($observer) ? $observer['xchan_hash'] : ''); + + head_set_icon($a->data['channel']['xchan_photo_s']); + + $a->page['htmlhead'] .= "<script> var ispublic = '" . t('everybody') . "'; var profile_uid = " . (($a->data['channel']) ? $a->data['channel']['channel_id'] : 0) . "; </script>" ; + + } + + return; +} + + + +function cal_content(&$a) { + + $channel = null; + + if(argc() > 1) { + $channel = channelx_by_nick(argv(1)); + } + + + if(! $channel) { + notice( t('Channel not found.') . EOL); + return; + } + + // since we don't currently have an event permission - use the stream permission + + if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_stream')) { + notice( t('Permissions denied.') . EOL); + return; + } + + $sql_extra = permissions_sql($channel['channel_id'],get_observer_hash(),'event'); + + $first_day = get_pconfig(local_channel(),'system','cal_first_day'); + $first_day = (($first_day) ? $first_day : 0); + + $htpl = get_markup_template('event_head.tpl'); + $a->page['htmlhead'] .= replace_macros($htpl,array( + '$baseurl' => $a->get_baseurl(), + '$module_url' => '/cal/' . $channel['channel_address'], + '$modparams' => 2, + '$lang' => $a->language, + '$first_day' => $first_day + )); + + $o = ''; + + $mode = 'view'; + $y = 0; + $m = 0; + $ignored = ((x($_REQUEST,'ignored')) ? " and ignored = " . intval($_REQUEST['ignored']) . " " : ''); + +logger('args: ' . print_r($a->argv,true)); + + if(argc() > 3 && intval(argv(2)) && intval(argv(3))) { + $mode = 'view'; + $y = intval(argv(2)); + $m = intval(argv(3)); + } + if(argc() <= 3) { + $mode = 'view'; + $event_id = argv(2); + } + + if($mode == 'view') { + + /* edit/create form */ + if($event_id) { + $r = q("SELECT * FROM `event` WHERE event_hash = '%s' AND `uid` = %d LIMIT 1", + dbesc($event_id), + intval($channel['channel_id']) + ); + if(count($r)) + $orig_event = $r[0]; + } + + + // Passed parameters overrides anything found in the DB + if(!x($orig_event)) + $orig_event = array(); + + + + $tz = date_default_timezone_get(); + if(x($orig_event)) + $tz = (($orig_event['adjust']) ? date_default_timezone_get() : 'UTC'); + + $syear = datetime_convert('UTC', $tz, $sdt, 'Y'); + $smonth = datetime_convert('UTC', $tz, $sdt, 'm'); + $sday = datetime_convert('UTC', $tz, $sdt, 'd'); + $shour = datetime_convert('UTC', $tz, $sdt, 'H'); + $sminute = datetime_convert('UTC', $tz, $sdt, 'i'); + + $stext = datetime_convert('UTC',$tz,$sdt); + $stext = substr($stext,0,14) . "00:00"; + + $fyear = datetime_convert('UTC', $tz, $fdt, 'Y'); + $fmonth = datetime_convert('UTC', $tz, $fdt, 'm'); + $fday = datetime_convert('UTC', $tz, $fdt, 'd'); + $fhour = datetime_convert('UTC', $tz, $fdt, 'H'); + $fminute = datetime_convert('UTC', $tz, $fdt, 'i'); + + $ftext = datetime_convert('UTC',$tz,$fdt); + $ftext = substr($ftext,0,14) . "00:00"; + + $type = ((x($orig_event)) ? $orig_event['type'] : 'event'); + + $f = get_config('system','event_input_format'); + if(! $f) + $f = 'ymd'; + + $catsenabled = feature_enabled($channel['channel_id'],'categories'); + + + $show_bd = perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts'); + if(! $show_bd) { + $sql_extra .= " and event.type != 'birthday' "; + } + + + $category = ''; + + $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 (argv(2) === 'json'){ + if (x($_GET,'start')) $start = $_GET['start']; + if (x($_GET,'end')) $finish = $_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); + + if (x($_GET,'id')){ + $r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan + from event left join item on resource_id = event_hash where resource_type = 'event' and event.uid = %d and event.id = %d $sql_extra limit 1", + intval($channel['channel_id']), + intval($_GET['id']) + ); + } + else { + // fixed an issue with "nofinish" events not showing up in the calendar. + // There's still an issue if the finish date crosses the end of month. + // Noting this for now - it will need to be fixed here and in Friendica. + // Ultimately the finish date shouldn't be involved in the query. + + $r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan + from event left join item on event_hash = resource_id + where resource_type = 'event' and event.uid = %d $ignored + AND (( adjust = 0 AND ( finish >= '%s' or nofinish = 1 ) AND start <= '%s' ) + OR ( adjust = 1 AND ( finish >= '%s' or nofinish = 1 ) AND start <= '%s' )) $sql_extra ", + intval($channel['channel_id']), + dbesc($start), + dbesc($finish), + dbesc($adjust_start), + dbesc($adjust_finish) + ); + + } + + $links = array(); + + if($r) { + xchan_query($r); + $r = fetch_post_tags($r,true); + + $r = sort_by_date($r); + } + + if($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(); + + $last_date = ''; + $fmt = t('l, F j'); + + if($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 = false; + + $drop = false; + + $title = strip_tags(html_entity_decode(bbcode($rr['summary']),ENT_QUOTES,'UTF-8')); + if(! $title) { + list($title, $_trash) = explode("<br",bbcode($rr['desc']),2); + $title = strip_tags(html_entity_decode($title,ENT_QUOTES,'UTF-8')); + } + $html = format_event_html($rr); + $rr['desc'] = bbcode($rr['desc']); + $rr['location'] = bbcode($rr['location']); + $events[] = array( + 'id'=>$rr['id'], + 'hash' => $rr['event_hash'], + 'start'=> $start, + 'end' => $end, + 'drop' => $drop, + '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'),'',''), + ); + + + } + } + + if (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_cal.tpl"); + } + else { + $tpl = get_markup_template("events_cal-js.tpl"); + } + + $nick = $channel['channel_address']; + + $o = replace_macros($tpl, array( + '$baseurl' => $a->get_baseurl(), + '$new_event' => array($a->get_baseurl().'/cal',(($event_id) ? t('Edit Event') : t('Create Event')),'',''), + '$previus' => array($a->get_baseurl()."/cal/$nick/$prevyear/$prevmonth",t('Previous'),'',''), + '$next' => array($a->get_baseurl()."/cal/$nick/$nextyear/$nextmonth",t('Next'),'',''), + '$export' => array($a->get_baseurl()."/cal/$nick/$y/$m/export",t('Export'),'',''), + '$calendar' => cal($y,$m,$links, ' eventcal'), + '$events' => $events, + '$upload' => t('Import'), + '$submit' => t('Submit'), + '$prev' => t('Previous'), + '$next' => t('Next'), + '$today' => t('Today'), + '$form' => $form, + '$expandform' => ((x($_GET,'expandform')) ? true : false), + )); + + if (x($_GET,'id')){ echo $o; killme(); } + + return $o; + } + +} diff --git a/mod/events.php b/mod/events.php index b07ffa184..be39902aa 100755 --- a/mod/events.php +++ b/mod/events.php @@ -283,6 +283,8 @@ function events_content(&$a) { $htpl = get_markup_template('event_head.tpl'); $a->page['htmlhead'] .= replace_macros($htpl,array( '$baseurl' => $a->get_baseurl(), + '$module_url' => '/events', + '$modparams' => 1, '$lang' => $a->language, '$first_day' => $first_day )); @@ -296,6 +298,11 @@ function events_content(&$a) { $m = 0; $ignored = ((x($_REQUEST,'ignored')) ? " and ignored = " . intval($_REQUEST['ignored']) . " " : ''); + +logger('args: ' . print_r($a->argv,true)); + + + if(argc() > 1) { if(argc() > 2 && argv(1) === 'add') { $mode = 'add'; diff --git a/view/pdl/mod_cal.pdl b/view/pdl/mod_cal.pdl new file mode 100644 index 000000000..f12bf39c3 --- /dev/null +++ b/view/pdl/mod_cal.pdl @@ -0,0 +1,3 @@ +[region=aside] +[widget=fullprofile][/widget] +[/region] diff --git a/view/tpl/event_cal.tpl b/view/tpl/event_cal.tpl new file mode 100755 index 000000000..61458b263 --- /dev/null +++ b/view/tpl/event_cal.tpl @@ -0,0 +1,14 @@ +{{foreach $events as $event}} + <div class="event-wrapper"> + <div class="event"> + <div class="event-owner"> + {{if $event.item.author.xchan_name}}<a href="{{$event.item.author.xchan_url}}" ><img src="{{$event.item.author.xchan_photo_s}}">{{$event.item.author.xchan_name}}</a>{{/if}} + </div> + {{$event.html}} + <div class="event-buttons"> + {{if $event.item.plink}}<a href="{{$event.plink.0}}" title="{{$event.plink.1}}" class="plink-event-link"><i class="icon-external-link btn btn-default" ></i></a>{{/if}} + </div> + <div class="clear"></div> + </div> + </div> +{{/foreach}} diff --git a/view/tpl/event_head.tpl b/view/tpl/event_head.tpl index dc98d14b3..5083c5835 100755 --- a/view/tpl/event_head.tpl +++ b/view/tpl/event_head.tpl @@ -6,7 +6,7 @@ <script> function showEvent(eventid) { $.get( - '{{$baseurl}}/events/?id='+eventid, + '{{$baseurl}}{{$module_url}}/?id='+eventid, function(data){ $.colorbox({ scrolling: false, html: data, onComplete: function() { $.colorbox.resize(); }}); } @@ -36,7 +36,7 @@ $(document).ready(function() { $('#events-calendar').fullCalendar({ - events: '{{$baseurl}}/events/json', + events: '{{$baseurl}}{{$module_url}}/json', header: false, lang: '{{$lang}}', firstDay: {{$first_day}}, @@ -109,10 +109,17 @@ }); // center on date + // @fixme does not work for cal/$nick module_url var args=location.href.replace(baseurl,"").split("/"); + {{if $modparams == 2}} + if (args.length>=5) { + $("#events-calendar").fullCalendar('gotoDate',args[3] , args[4]-1); + } + {{else}} if (args.length>=4) { $("#events-calendar").fullCalendar('gotoDate',args[2] , args[3]-1); - } + } + {{/if}} // show event popup var hash = location.hash.split("-") diff --git a/view/tpl/events_cal-js.tpl b/view/tpl/events_cal-js.tpl new file mode 100755 index 000000000..b3c7ff03b --- /dev/null +++ b/view/tpl/events_cal-js.tpl @@ -0,0 +1,17 @@ +<div class="generic-content-wrapper"> + <div class="section-title-wrapper"> + <div class="pull-right"> + <div class="btn-group"> + <button class="btn btn-default btn-xs" onclick="changeView('prev', false);" title="{{$prev}}"><i class="icon-backward"></i></button> + <button id="events-spinner" class="btn btn-default btn-xs" onclick="changeView('today', false);" title="{{$today}}"><i class="icon-bullseye"></i></button> + <button class="btn btn-default btn-xs" onclick="changeView('next', false);" title="{{$next}}"><i class="icon-forward"></i></button> + </div> + </div> + <h2 id="title"></h2> + <div class="clear"></div> + </div> + <div class="clear"></div> + <div class="section-content-wrapper-np"> + <div id="events-calendar"></div> + </div> +</div> |