aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorredmatrix <git@macgirvin.com>2016-02-24 18:54:52 -0800
committerredmatrix <git@macgirvin.com>2016-02-24 18:54:52 -0800
commitc95d7c69eb3135f137390323a09eb105776ce29c (patch)
tree5183b1d8e9fde8ff9e7628ad0160c0b78bd35f30
parent6300f47cdcd921141b8f98b71d373d53aa3d80f2 (diff)
downloadvolse-hubzilla-c95d7c69eb3135f137390323a09eb105776ce29c.tar.gz
volse-hubzilla-c95d7c69eb3135f137390323a09eb105776ce29c.tar.bz2
volse-hubzilla-c95d7c69eb3135f137390323a09eb105776ce29c.zip
issue #216 - calendar sharing
-rw-r--r--include/conversation.php20
-rw-r--r--include/security.php18
-rwxr-xr-xmod/cal.php343
-rwxr-xr-xmod/events.php7
-rw-r--r--view/pdl/mod_cal.pdl3
-rwxr-xr-xview/tpl/event_cal.tpl14
-rwxr-xr-xview/tpl/event_head.tpl13
-rwxr-xr-xview/tpl/events_cal-js.tpl17
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>