-
}
-
-
/**
-
- Display a button to close one of multiple calendars shown
-
-
- Necessare to eg. close the calendar of a contact
-
-
-
@param string $uid calendar to close
-
*/
-
private function close_button($uid)
-
{
-
return Api\Html::a_href(Api\Html::image('phpgwapi', 'close.button', 'Close','style="width: 12px; padding-top: 1px;"'), array(
-
'menuaction' => 'calendar.calendar_uiviews.index',
-
'close' => $uid,
-
));
}
/**
@@ -827,811 +814,6 @@
}
/**
-
- Calculates the vertical position based on the time
-
-
- workday start- and end-time, is taken into account, as well as timeGrids px_m - minutes per pixel param
-
-
-
@param int $time in minutes
-
-
@return float position in percent
-
*/
-
function time2pos($time)
-
{
-
if ($this->scroll_to_wdstart) // we display the complete day - thought only workday is visible without scrolling
-
{
-
return $this->rowHeight * (1 + $this->extraRows + $time/$this->granularity_m);
-
}
-
// time before workday => condensed in the first $this->extraRows rows
-
if ($this->wd_start > 0 && $time < $this->wd_start)
-
{
-
$pos = (($this->extraRows - $this->extraRowsOriginal + 1) + ($time / $this->wd_start * ($this->extraRowsOriginal - 1))) * $this->rowHeight;
-
}
-
// time after workday => condensed in the last row
-
elseif ($this->wd_end < 24*60 && $time > $this->wd_end+1*$this->granularity_m)
-
{
-
$pos = 100 - (($this->extraRows - $this->remBotExtraRows) * $this->rowHeight * (1 - ($time - $this->wd_end) / (24*60 - $this->wd_end)));
-
}
-
// time during the workday => 2. row on (= + granularity)
-
else
-
{
-
$pos = $this->rowHeight * (1+$this->extraRows+($time-$this->wd_start)/$this->granularity_m);
-
}
-
$pos = round($pos,1);
-
-
if ($this->debug > 3) $this->bo->debug_message('uiviews::time2pos(%1)=%2',False,$time,$pos);
-
-
return $pos;
-
}
-
-
/**
-
- Calculates the height of a difference between 2 times
-
-
- workday start- and end-time, is taken into account, as well as timeGrids px_m - minutes per pixel param
-
-
-
@param int $start time in minutes
-
-
@param int $end time in minutes
-
-
@return float height in percent
-
*/
-
function times2height($start,$end)
-
{
-
$minimum = $this->rowHeight;
-
$height = $this->time2pos($end) - $this->time2pos($start);
-
-
if ($this->debug > 3) $this->bo->debug_message('uiviews::times2height(%1,%2,min=%3)=%4',False,$start,$end,$minimum,$height);
-
-
return $height >= $minimum ? $height : $minimum;
-
}
-
-
/**
-
- Creates a grid with rows for the time, columns for (multiple) days containing events
-
-
- Uses the dayColWidget to display each day.
-
-
-
@param $daysEvents array with subarrays of events for each day to show, day as YYYYMMDD as key
-
-
@param int $granularity_m = 30 granularity in minutes of the rows
-
-
@param int $height = 400 height of the widget
-
-
@param string $indent = ‘’ string for correct indention
-
-
@param string $title = ‘’ title of the time-grid
-
-
@param int/array $owner = 0 owner of the calendar (default 0 = $this->owner) or array with owner for each column
-
-
@param boolean $last = true last timeGrid displayed, default true
-
*/
-
function &timeGridWidget($daysEvents,$granularity_m=30,$height=400,$indent=’’,$title=’’,$owner=0,$last=true)
-
{
-
if ($this->debug > 1 || $this->debug==='timeGridWidget') $this->bo->debug_message('uiviews::timeGridWidget(events=%1,granularity_m=%2,height=%3,,title=%4)',True,$daysEvents,$granularity_m,$height,$title);
-
-
// determine if the browser supports scrollIntoView: IE4+, firefox1.0+ and safari2.0+ does
-
// then show all hours in a div of the size of the workday and scroll to the workday start
-
// still disabled, as things need to be re-aranged first, to that the column headers are not scrolled
-
$this->scroll_to_wdstart = false;/*$this->use_time_grid && (Api\Header\UserAgent::type() == 'msie' ||
-
Api\Header\UserAgent::type() == 'mozilla' && Api\Html::ua_version >= 5.0 ||
-
Api\Header\UserAgent::type() == 'safari' && Api\Html::ua_version >= 2.0);*/
-
-
if ($this->scroll_to_wdstart)
-
{
-
$this->extraRows = 0; // no extra rows necessary
-
$this->remBotExtraRows = 0;
-
$overflow = 'overflow: scroll;';
-
}
-
$this->granularity_m = $granularity_m;
-
$this->display_start = $this->wd_start - ($this->extraRows * $this->granularity_m);
-
$this->display_end = $this->wd_end + (($this->extraRows - $this->remBotExtraRows) * $this->granularity_m);
-
-
if (!$this->wd_end) $this->wd_end = 1440;
-
$totalDisplayMinutes = $this->wd_end - $this->wd_start;
-
$this->rowsToDisplay = ($totalDisplayMinutes/$granularity_m)+2+2*$this->extraRows - $this->remBotExtraRows;
-
$this->rowHeight = round(100/$this->rowsToDisplay,1);
-
-
// ensure a minimum height of each row
-
if ($height < ($this->rowsToDisplay+1) * 12)
-
{
-
$height = ($this->rowsToDisplay+1) * 12;
-
}
-
$html = $indent.'<div class="calendar_calTimeGrid" style="height: '.$height.'px;'.$overflow.'">'."\n";
-
-
$html .= $indent."\t".'<div class="calendar_calGridHeader" style="height: '.
-
$this->rowHeight.'%;">'.$title."</div>\n";
-
-
if ($this->use_time_grid)
-
{
-
$off = false; // Off-row means a different bgcolor
-
$add_links = count($daysEvents) == 1;
-
-
// the hour rows
-
for($t = $this->scroll_to_wdstart ? 0 : $this->wd_start,$i = 1+$this->extraRows;
-
$t <= $this->wd_end || $this->scroll_to_wdstart && $t < 24*60;
-
$t += $this->granularity_m,++$i)
-
{
-
$set_id = '';
-
if ($t == $this->wd_start)
-
{
-
list($id) = @each($daysEvents);
-
if (is_numeric($id))
-
{
-
$id = 'wd_start_'.$id;
-
$set_id = ' id="'.$id.'"';
-
}
-
}
-
$html .= $indent."\t".'<div'.$set_id.' class="calendar_calTimeRow'.($off ? 'Off row_off' : ' row_on').
-
'" style="height: '.$this->rowHeight.'%; top:'. $i*$this->rowHeight .'%;">'."\n";
-
// show time for full hours, allways for 45min interval and at least on every 3 row
-
$time = '';
-
static $show = array(
-
5 => array(0,15,30,45),
-
10 => array(0,30),
-
15 => array(0,30),
-
45 => array(0,15,30,45),
-
);
-
if (!isset($show[$this->granularity_m]) ? $t % 60 == 0 : in_array($t % 60,$show[$this->granularity_m]))
-
{
-
$time = common::formattime(sprintf('%02d',$t/60),sprintf('%02d',$t%60));
-
}
-
if ($add_links) $time = $this->add_link($time,$this->date,(int) ($t/60),$t%60);
-
$html .= $indent."\t\t".'<div class="calendar_calTimeRowTime">'.$time."</div>\n";
-
$html .= $indent."\t</div>\n"; // calendar_calTimeRow
-
$off = !$off;
-
}
-
}
-
if (is_array($daysEvents) && count($daysEvents))
-
{
-
$numberOfDays = count($daysEvents);
-
$dayColWidth = 100/$numberOfDays;
-
-
$dayCols_width = $width - $this->timeRow_width - 1;
-
-
$html .= $indent."\t".'<div id="calendar_calDayCols" class="calendar_calDayCols'.
-
($this->use_time_grid ? ($this->bo->common_prefs['timeformat'] == 12 ? '12h' : '') : 'NoTime').'">'."\n";
-
-
if (Api\Header\UserAgent::type() == 'msie') // necessary IE hack - stupid thing ...
-
{
-
// Lars Kneschke 2005-08-28
-
// why do we use a div in a div which has the same height and width???
-
// To make IE6 happy!!! Without the second div you can't use
-
// style="left: 50px; right: 0px;"
-
//$html .= '<div style="width=100%; height: 100%;">'."\n";
-
-
// Ralf Becker 2006-06-19
-
// Lars original typo "width=100%; height: 100%;" is important ;-)
-
// means you width: 100% does NOT work, you need no width!
-
$html .= '<div style="height: 100%;">'."\n";
-
}
-
$dayCol_width = $dayCols_width / count($daysEvents);
-
$n = 0;
-
foreach($daysEvents as $day => $events)
-
{
-
$this->wholeDayPosCounter=1;
-
$short_title = count($daysEvents) > 1;
-
$col_owner = $owner;
-
if (!is_numeric($day))
-
{
-
$short_title = $day;
-
$day = $this->date;
-
$col_owner = $owner[$n];
-
}
-
$html .= $this->dayColWidget($day,$events,$n*$dayColWidth,
-
$dayColWidth,$indent."\t\t",$short_title,++$on_off & 1,$col_owner);
-
++$n;
-
}
-
if (Api\Header\UserAgent::type() == 'msie') $html .= "</div>\n";
-
-
$html .= $indent."\t</div>\n"; // calendar_calDayCols
-
}
-
$html .= $indent."</div>\n"; // calendar_calTimeGrid
-
-
if ($this->scroll_to_wdstart)
-
{
-
$html .= "<script>\n\tdocument.getElementById('$id').scrollIntoView();\n";
-
if ($last) // last timeGrid --> scroll whole document back up
-
{
-
$html .= "\tdocument.getElementById('divMain').scrollIntoView();\n";
-
}
-
$html .= "</script>\n";
-
}
-
-
return $html;
-
}
-
-
/**
-
- Sorts the events of a day into columns with non-overlapping events, the events
-
- are already sorted by start-time
-
-
-
@param string/int $day_ymd date as Ymd
-
-
@param array &$events events to split into non-overlapping groups
-
*/
-
function getEventCols($day_ymd, &$events)
-
{
-
$day_start = $this->bo->date2ts((string)$day_ymd);
-
-
// if daylight saving is switched on or off, correct $day_start
-
// gives correct times after 2am, times between 0am and 2am are wrong
-
if(($daylight_diff = $day_start + 12*HOUR_s - ($this->bo->date2ts($day_ymd."T120000"))))
-
{
-
$day_start -= $daylight_diff;
-
}
-
-
$eventCols = $col_ends = array();
-
foreach($events as $event)
-
{
-
$event['multiday'] = False;
-
$event['start_m'] = ($event['start'] - $day_start) / 60;
-
if ($event['start_m'] < 0)
-
{
-
$event['start_m'] = 0;
-
$event['multiday'] = True;
-
}
-
$event['end_m'] = ($event['end'] - $day_start) / 60;
-
if ($event['end_m'] >= 24*60)
-
{
-
$event['end_m'] = 24*60-1;
-
$event['multiday'] = True;
-
}
-
if ($this->use_time_grid && !$event['whole_day_on_top'])
-
{
-
for($c = 0; $event['start_m'] < $col_ends[$c]; ++$c);
-
$col_ends[$c] = $event['end_m'];
-
}
-
else
-
{
-
$c = 0; // without grid we only use one column
-
}
-
$eventCols[$c][] = $event;
-
}
-
return $eventCols;
-
}
-
-
/**
-
- Creates (if necessary multiple) columns for the events of a day
-
-
- Uses the eventColWidget to display each column.
-
-
-
@param string/int $day_ymd date as Ymd
-
-
@param array $events of events to show
-
-
@param int $pleft start of the widget
-
-
@param int $pwidth width of the widget
-
-
@param string $indent string for correct indention
-
-
@param boolean/string $short_title = True should we add a label (weekday, day) with link to the day-view above each day or string with title
-
-
@param boolean $on_off = false start with row_on or row_off, default false=row_off
-
-
@param int $owner = 0 if != 0 owner to add to the add-event link
-
*/
-
function dayColWidget($day_ymd,$events,$pleft,$pwidth,$indent,$short_title=True,$on_off=False,$owner=0)
-
{
-
if ($this->debug > 1 || $this->debug==='dayColWidget') $this->bo->debug_message('uiviews::dayColWidget(%1,%2,left=%3,width=%4,)',False,$day_ymd,$events,$pleft,$pwidth);
-
-
$html = $indent.'<div id="calColumn'.$this->calColumnCounter++.'" class="calendar_calDayCol" '.'data-sortable-id="'.$owner.'" style="left: '.$pleft.
-
'%;width: '.$pwidth.'%;">'."\n";
-
-
// Creation of the header-column with date, evtl. holiday-names and a matching background-color
-
$ts = $this->bo->date2ts((string)$day_ymd);
-
$title = !is_bool($short_title) ? $short_title :
-
($short_title ? lang(adodb_date('l',$ts)).' '.adodb_date('d.',$ts) : $this->bo->long_date($ts,0,false,true));
-
-
$day_view = array(
-
'menuaction' => 'calendar.calendar_uiviews.day',
-
'date' => $day_ymd,
-
);
-
$this->_day_class_holiday($day_ymd,$class,$holidays);
-
// the weekday and date
-
if (!$short_title && $holidays) $title .= Api\Html::htmlspecialchars(': '.$holidays);
-
-
if ($short_title === true)
-
{
-
if ($this->allowEdit)
-
{
-
$title = Api\Html::a_href($title,$day_view,'',
-
!isset($this->holidays[$day_ymd])?' title="'.$this->bo->long_date($ts,0,false,true).'"':'');
-
}
-
}
-
elseif ($short_title === false)
-
{
-
// add arrows to go to the previous and next day (dayview only)
-
$day_view['date'] = $this->bo->date2string($ts -= 12*HOUR_s);
-
if ($this->allowEdit)
-
{
-
$title = Api\Html::a_href(Api\Html::image('phpgwapi','left',$this->bo->long_date($ts)),$day_view).' <span> '.$title;
-
}
-
else
-
{
-
$title = $day_view.' <span> '.$title;
-
}
-
$day_view['date'] = $this->bo->date2string($ts += 48*HOUR_s);
-
if ($this->allowEdit)
-
{
-
$title .= ' </span> '.Api\Html::a_href(Api\Html::image('phpgwapi','right',$this->bo->long_date($ts)),$day_view);
-
}
-
else
-
{
-
$title .= ' </span> '.$day_view;
-
}
-
}
-
if (is_bool($short_title) || ($short_title != "")) {
-
$html .= $indent."\t".'<div style="height: '. $this->rowHeight .'%;" class="calendar_calDayColHeader '.$class.'"'.
-
($holidays ? ' title="'.Api\Html::htmlspecialchars($holidays).'"':'').'>'.$title."</div>\n";
-
}
-
-
if ($this->use_time_grid)
-
{
-
// drag and drop: check if the current user has EDIT permissions on the grid
-
if($owner)
-
{
-
$dropPermission = $this->bo->check_perms(Acl::EDIT,0,$owner);
-
}
-
else
-
{
-
$dropPermission = true;
-
}
-
-
// adding divs to click on for each row / time-span
-
for($t = $this->scroll_to_wdstart ? 0 : $this->wd_start,$i = 1 + $this->extraRows;
-
$t <= $this->wd_end || $this->scroll_to_wdstart && $t < 24*60;
-
$t += $this->granularity_m,++$i)
-
{
-
$linkData = array(
-
'menuaction' =>'calendar.calendar_uiforms.edit',
-
'date' => $day_ymd,
-
'hour' => sprintf("%02d",floor($t / 60)),
-
'minute' => sprintf("%02d",floor($t % 60)),
-
);
-
if ($owner) $linkData['owner'] = $owner;
-
-
$droppableDateTime = $linkData['date'] . "T" . $linkData['hour'] . $linkData['minute'];
-
$droppableID='drop_'.$droppableDateTime.'_O'.($owner<0?str_replace('-','group',$owner):$owner);
-
-
$html .= $indent."\t".'<div id="' . $droppableID . '" style="height:'. $this->rowHeight .'%; top: '. $i*$this->rowHeight .
-
'%;" class="calendar_calAddEvent"';
-
if ($this->allowEdit)
-
{
-
$html .= ' data-date=' .$linkData['date'].'|'.$linkData['hour'].'|'.$linkData['minute'];
-
}
-
if($dropPermission && $owner)
-
{
-
$html .= ' data-owner ='.$owner;
-
-
}
-
$html .= '></div>'."\n";
-
-
}
-
}
-
-
$eventCols = $this->getEventCols($day_ymd,$events);
-
// displaying all event columns of the day
-
foreach($eventCols as $n => $eventCol)
-
{
-
// equal sized columns
-
//$width = 95.0 / count($eventCols);
-
//$left = 2.5 + $n * $width;
-
// alternative overlapping columns
-
$left = 2.5 + (1.5 * 100 / $pwidth);
-
if (count($eventCols) == 1)
-
{
-
$width = 100 - $left;
-
}
-
else
-
{
-
$width = !$n ? 70 : 50;
-
$left += $n * (100.0-$left) / count($eventCols);
-
}
-
if ($left + $width > 100.0) $width = 100.0 - $left;
-
//echo "<p>count(\$eventCols)=".count($eventCols).", n=$n, pWidth=$pwidth, pLeft=$pleft, width=$width, left=$left</p>\n";
-
$html .= $this->eventColWidget($eventCol,$left,$width,$indent."\t",
-
$owner ? $owner : $this->user, 20+10*$n);
-
}
-
$html .= $indent."</div>\n"; // calendar_calDayCol
-
-
return $html;
-
}
-
-
/**
-
- get the CSS class and holidays for a given day
-
-
-
@param string $day_ymd date
-
-
@param string &$class class to use
-
-
@param string &$holidays commaseparted holidays or empty if none
-
-
@param boolean $only_weekend = false show only the weekend in header-color, otherwise every second days is shown too
-
-
@param boolean $show_bdays = true If available, also show birthdays (or hide Bdays)
-
-
-
-
*/
-
function _day_class_holiday($day_ymd,&$class,&$holidays,$only_weekend=false,$show_bdays=true)
-
{
-
$class = $holidays = '';
-
$bday = false;
-
if (isset($this->holidays[$day_ymd]))
-
{
-
$h = array();
-
foreach($this->holidays[$day_ymd] as $holiday)
-
{
-
if (isset($holiday['birthyear']))
-
{
-
if ($show_bdays)
-
{
-
$bday = true;
-
-
//If the birthdays are already displayed as event, don't
-
//show them in the caption
-
if (!$this->display_holiday_event_types['bdays'])
-
{
-
$h[] = $holiday['name'];
-
}
-
}
-
}
-
else
-
{
-
$class = 'calendar_calHoliday';
-
-
//If the birthdays are already displayed as event, don't
-
//show them in the caption
-
if (!$this->display_holiday_event_types['hdays'])
-
{
-
$h[] = $holiday['name'];
-
}
-
}
-
}
-
$holidays = implode(', ',$h);
-
}
-
if (!$class)
-
{
-
if ($day_ymd == $this->bo->date2string($this->bo->now_su))
-
{
-
$class = 'calendar_calToday';
-
}
-
else
-
{
-
$day = (int) date('w',$this->bo->date2ts((string) $day_ymd));
-
-
if ($only_weekend)
-
{
-
$class = $day == 0 || $day == 6 ? 'th' : 'row_off';
-
}
-
else
-
{
-
$class = $day & 1 ? 'row_on' : 'th';
-
}
-
}
-
}
-
if ($bday) $class .= ' calendar_calBirthday';
-
}
-
-
/**
-
- Creates colunm for non-overlaping (!) events
-
-
- Uses the eventWidget to display each event.
-
-
-
@param array $events of events to show
-
-
@param int $left start of the widget
-
-
@param int $width width of the widget
-
-
@param string $indent string for correct indention
-
-
@param int $owner owner of the eventCol
-
*/
-
function eventColWidget($events,$left,$width,$indent,$owner,$z_index=null)
-
{
-
if ($this->debug > 1 || $this->debug==='eventColWidget') $this->bo->debug_message('uiviews::eventColWidget(%1,left=%2,width=%3,)',False,$events,$left,$width);
-
-
$html = $indent.'<div class="calendar_calEventCol" style="left: '.$left.'%; width:'.$width.'%;'.
-
// the "calendar_calEventCol" spans across a whole column (as the name suggests) - setting the
-
// z-index here would give the whole invisible column a z-index and thus the underlying
-
// regions are not clickable anymore. The z_index has now moved the the eventWidget
-
// function.
-
//(!is_null($z_index) ? ' z-index:'.$z_index.';' : '').
-
(!$this->use_time_grid ? ' top: '.$this->rowHeight.'%;' : '').'">'."\n";
-
foreach($events as $event)
-
{
-
$html .= $this->eventWidget($event,$width,$indent."\t",$owner,false,'event_widget',$z_index);
-
}
-
$html .= $indent."</div>\n";
-
-
return $html;
-
}
-
-
/**
-
-
-
- The display of the event and it’s tooltip is done via the event_widget.tpl template
-
-
-
@param $event array with the data of event to show
-
-
@param $width int width of the widget
-
-
@param string $indent string for correct indention
-
-
@param int $owner owner of the calendar the event is in
-
-
@param boolean $return_array = false should an array with keys(tooltip,popup,Api\Html) be returned or the complete widget as string
-
-
@param string $block = ‘event_widget’ template used the render the widget
-
-
@param int $z_index is the z-index of the drag-drobable outer box of the event.
-
-
*/
-
function eventWidget($event,$width,$indent,$owner,$return_array=false,$block=‘event_widget’,$z_index=null)
-
{
-
if ($this->debug > 1 || $this->debug==='eventWidget') $this->bo->debug_message('uiviews::eventWidget(%1,width=%2)',False,$event,$width);
-
-
if($this->use_time_grid && $event['whole_day_on_top']) $block = 'event_widget_wholeday_on_top';
-
-
static $tpl = False;
-
if (!$tpl)
-
{
-
$tpl = new Framework\Template(Framework\Template::get_dir('calendar'));
-
-
$tpl->set_file('event_widget_t','event_widget.tpl');
-
$tpl->set_block('event_widget_t','event_widget');
-
$tpl->set_block('event_widget_t','event_widget_wholeday_on_top');
-
$tpl->set_block('event_widget_t','event_tooltip');
-
$tpl->set_block('event_widget_t','planner_event');
-
}
-
if (($return_array || $event['start_m'] == 0) && $event['end_m'] >= 24*60-1)
-
{
-
if ($return_array && $event['end_m'] > 24*60)
-
{
-
$timespan = $this->bo->format_date($event['start'],false).' - '.$this->bo->format_date($event['end']);
-
}
-
else
-
{
-
$timespan = lang('all day');
-
}
-
}
-
else
-
{
-
$timespan = $this->bo->timespan($event['start_m'],$event['end_m']);
-
}
-
$icons = array();
-
if(!(int)$event['id'] && preg_match('/^([a-z_-]+)([0-9]+)$/i',$event['id'],$matches))
-
{
-
$app = $matches[1];
-
$app_id = $matches[2];
-
if (($is_private = calendar_bo::integration_get_private($app,$app_id,$event)))
-
{
-
$icons[] = Api\Html::image('calendar','private');
-
}
-
else
-
{
-
$icons = self::integration_get_icons($app,$app_id,$event);
-
}
-
}
-
elseif($event['id'])
-
{
-
if (($is_private = !$this->bo->check_perms(Acl::READ,$event)))
-
{
-
$icons = array(Api\Html::image('calendar','private'));
-
}
-
else
-
{
-
$icons = $this->event_icons($event);
-
}
-
}
-
$cats = $this->bo->categories($this->categories->check_list(Acl::READ, $event['category']),$color);
-
// these values control varius aspects of the geometry of the eventWidget
-
$small_trigger_width = 120 + 20*count($icons);
-
$corner_radius=$width > $small_trigger_width ? 10 : 5;
-
$header_height=$width > $small_trigger_width ? 19 : 12; // multi_3 icon has a height of 19=16+2*1padding+1border !
-
if (!$return_array)
-
{
-
$height = $this->times2height($event['start_m'],$event['end_m'],$header_height);
-
}
-
//$body_height = max(0,$height - $header_height - $corner_radius);
-
$border=1;
-
$headerbgcolor = $color ? $color : '#808080';
-
$headercolor = self::brightness($headerbgcolor) > 128 ? 'black' : 'white';
-
// the body-colors (gradient) are calculated from the headercolor, which depends on the cat of an event
-
$bodybgcolor1 = $this->brighter($headerbgcolor,$headerbgcolor == '#808080' ? 100 : 170);
-
$bodybgcolor2 = $this->brighter($headerbgcolor,220);
-
-
// mark event as invitation, by NOT using category based background color, but plain white
-
if ($event['participants'][$this->user][0] == 'U')
-
{
-
$bodybgcolor1 = $bodybgcolor2 = 'white';
-
}
-
-
// get status class of event: calendar_calEventAllAccepted, calendar_calEventAllAnswered or calendar_calEventSomeUnknown
-
$status_class = 'calendar_calEventAllAccepted';
-
foreach($event['participants'] as $id => $status)
-
{
-
if ($id < 0) continue; // as we cant accept/reject groups, we dont care about them here
-
-
calendar_so::split_status($status,$quantity,$role);
-
-
switch ($status)
-
{
-
case 'A':
-
case '': // app without status
-
break;
-
case 'U':
-
$status_class = 'calendar_calEventSomeUnknown';
-
break 2; // break foreach
-
default:
-
$status_class = 'calendar_calEventAllAnswered';
-
break;
-
}
-
}
-
// seperate each participant types
-
$part_array = array();
-
if ($this->allowEdit)
-
{
-
foreach($this->bo->participants($event) as $part_key => $participant)
-
{
-
if(is_numeric($part_key))
-
{
-
$part_array[lang('Participants')][$part_key] = $participant;
-
}
-
elseif(isset($this->bo->resources[$part_key[0]]))
-
{
-
$part_array[((isset($this->bo->resources[$part_key[0]]['participants_header'])) ? $this->bo->resources[$part_key[0]]['participants_header'] : lang($this->bo->resources[$part_key[0]]['app']))][$part_key] = $participant;
-
}
-
}
-
foreach($part_array as $part_group => $participant)
-
{
-
$participants .= $this->add_nonempty($participant,$part_group,True,False,false);
-
}
-
}
-
// as we only deal with percentual widht, we consider only the full dayview (1 colum) as NOT small
-
$small = $this->view != 'day' || $width < 50;
-
// $small = $width <= $small_trigger_width
-
-
$small_height = $this->use_time_grid && ( $event['end_m']-$event['start_m'] < 2*$this->granularity_m ||
-
$event['end_m'] <= $this->wd_start || $event['start_m'] >= $this->wd_end);
-
-
$tpl->set_var(array(
-
// event-content, some of it displays only if it really has content or is needed
-
'owner' => Api\Accounts::username($event['owner']),
-
'header_icons' => $small ? '' : implode("",$icons),
-
'body_icons' => $small ? implode("\n",$icons) : '',
-
'icons' => implode('',$icons),
-
'timespan' => $timespan,
-
'title' => ($title = !$is_private ? Api\Html::htmlspecialchars($event['title']) : lang('private')),
-
'header' => $small_height ? $title : $timespan,
-
'description' => !$is_private ? nl2br(Api\Html::htmlspecialchars($event['description'])) : '',
-
'location' => !$is_private ? $this->add_nonempty($event['location'],lang('Location')) : '',
-
'participants' => $participants,
-
'times' => !$event['multiday'] ? $this->add_nonempty($this->bo->timespan($event['start_m'],$event['end_m'],true),lang('Time')) :
-
$this->add_nonempty($this->bo->format_date($event['start']),lang('Start')).
-
$this->add_nonempty($this->bo->format_date($event['end']),lang('End')),
-
'multidaytimes' => !$event['multiday'] ? '' :
-
$this->add_nonempty($this->bo->format_date($event['start']),lang('Start')).
-
$this->add_nonempty($this->bo->format_date($event['end']),lang('End')),
-
'category' => !$is_private ? $this->add_nonempty($cats,lang('Category')) : '',
-
// the tooltip is based on the content of the actual widget, this way it takes no extra bandwidth/volum
-// ‘tooltip’ => Api\Html::tooltip(False,False,array(‘BorderWidth’=>0,‘Padding’=>0)),
-
// Add event description to cal event view body if the event is long enough (ATM 3 times longer than interval)
-
// to be able to show some lines of description text
-
if ($event['whole_day'] || ($event['end'] - $event['start']) > ($this->cal_prefs['interval'] * 3 * 60))
-
{
-
$tpl->set_var('bodydescription', !$is_private ? nl2br(Api\Html::htmlspecialchars($event['description'])) : '');
-
}
-
// set the bodydescription to empty if it is not visible
-
else
-
{
-
$tpl->set_var('bodydescription', '');
-
}
-
-
$tooltip = $tpl->fp('tooltip','event_tooltip');
-
$html = $tpl->fp('out',$block);
-
-
if ($is_private || !$this->allowEdit)
-
{
-
$popup = '';
-
}
-
elseif($app && $app_id)
-
{
-
$popup = $this->integration_get_popup($app,$app_id);
-
}
-
else
-
{
-
if ($event['recur_type'] != MCAL_RECUR_NONE)
-
{
-
$popup = $event['id']."|r";
-
}
-
else
-
{
-
$popup = $event['id']."|n";
-
}
-
}
-
$tooltip = Api\Html::htmlspecialchars($tooltip, true); // true=need double-encoding, as it is transported as attribute!
-
//_debug_array($event);
-
-
if ($return_array)
-
{
-
return array(
-
'tooltip' => $tooltip,
-
'popup' => $popup,
-
'html' => $html,
-
'private' => $is_private,
-
'color' => $color,
-
);
-
}
-
-
$draggableID = $event['id'].'_O'.$event['owner'].'_C'.($owner<0?str_replace('-','group',$owner):$owner);
-
-
if ($this->use_time_grid)
-
{
-
if($event['whole_day_on_top'])
-
{
-
$style = 'top: '.($this->rowHeight*$this->wholeDayPosCounter).'%; height: '.$this->rowHeight.'%;';
-
$this->wholeDayPosCounter++;
-
}
-
else
-
{ $view_link = $GLOBALS['egw']->link('/index.php',array('menuaction'=>'calendar.calendar_uiforms.edit','cal_id'=>$event['id'],'date'=>$this->bo->date2string($event['start'])));
-
-
$style = 'top: '.$this->time2pos($event['start_m']).'%; height: '.$height.'%;';
-
}
-
}
-
else
-
{
-
$style = 'position: relative; margin-top: 3px;';
-
}
-
-
$prefix_icon = isset($event['prepend_icon']) ? $event['prepend_icon'] : '';
-
-
$z_index = is_null($z_index) ? 20 : (int)$z_index;
-
-
if ($this->use_time_grid &&
-
((int)$event['id'] || substr($event['id'],0,7) == 'infolog') && $this->bo->check_perms(Acl::EDIT,$event))
-
{
-
if (!$event['whole_day_on_top'] &&
-
!$event['whole_day'] &&
-
!$event['recur_type'])
-
{
-
$draggableID = 'drag_'.$event['id'].'_O'.$event['owner'].'_C'.($owner<0?str_replace('-','group',$owner):$owner);
-
}
-
else
-
{
-
$draggableID = 'drag_'.$event['id'].'_O'.$event['owner'].'_C'.($owner<0?str_replace('-','group',$owner):$owner);
-
-
}
-
}
-
if (!$event['whole_day_on_top'] &&
-
!$event['whole_day'])
-
{
-
// S represents Series
-
// '' represents Single
-
$eventTypeTag = $event['recur_type']?'S':'';
-
}
-
else if (!$event['recur_type'])
-
{
-
// WD represents Whole Day
-
$eventTypeTag = 'WD';
-
}
-
else
-
{
-
// WDS represents Whole Day Series (recurrent whole day event)
-
$eventTypeTag = 'WDS';
-
}
-
// Helps client-side to bind handler to events with specific types tag
-
$resizableHelper = $this->bo->date2string($event['start']). '|' .$this->bo->format_date($event['start'],false) . '|' . $this->cal_prefs['interval'].'|'.$eventTypeTag;
-
-
$html = $indent.'<div id="'.$draggableID.'" data-tooltip ="'.$tooltip .'" data-resize="'.$resizableHelper.'" class="calendar_calEvent'.($is_private ? 'Private' : '').' '.$status_class.
-
'" style="'.$style.' border-color: '.$headerbgcolor.'; background: '.$background.'; z-index: '.$z_index.';"'.
-
'>'.$prefix_icon."\n".$html."\n".
-
$indent."</div>"."\n";
-
-
return $html;
- }
-
- /**
- Get onclick attribute to open integration item for edit
-
- Name of the attribute is ‘edit_link’ and it should be an array with values for keys:
@@ -1710,839 +892,6 @@
$icons += (array)ExecMethod2($app_data,$id,$event);
}
return $icons;
- }
-
- function add_nonempty($content,$label,$one_per_line=False,$space = True,$htmlspecialchars=true)
- {
-
if (is_array($content))
-
{
-
if($space)
-
{
-
$content = implode($one_per_line ? ",\n" : ', ',$content);
-
}
-
else
-
{
-
$content = implode($one_per_line ? "\n" : ', ',$content);
-
}
-
}
-
if (!empty($content))
-
{
-
return '<span class="calendar_calEventLabel">'.$label.'</span>:'.
-
($one_per_line ? '<br>' : ' ').
-
nl2br($htmlspecialchars?html::htmlspecialchars($content):$content).'<br>';
-
}
-
return '';
- }
-
- /**
-
- Calculates a brighter color for a given color
-
-
-
@param $rgb string color as #rrggbb value
-
-
@param $decr int value to add to each component, default 64
-
-
@return string the brighter color
- */
- static function brighter($rgb,$decr=64)
- {
-
if (!preg_match('/^#?([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})$/',$rgb,$components))
-
{
-
return '#ffffff';
-
}
-
$brighter = '#';
-
for ($i = 1; $i <=3; ++$i)
-
{
-
$val = hexdec($components[$i]) + $decr;
-
if ($val > 255) $val = 255;
-
$brighter .= sprintf('%02x',$val);
-
}
-
//echo "brighter($rgb=".print_r($components,True).")=$brighter</p>\n";
-
return $brighter;
- }
-
- /**
-
- Calculates the brightness of a hexadecimal rgb color (median of the r, g and b components)
-
-
-
@param string $rgb eg. #808080
-
-
@return int between 0 and 255
- */
- static function brightness($rgb)
- {
-
if ($rgb[0] != '#' || strlen($rgb) != 7)
-
{
-
return 128; // no rgb color, return some default
-
}
-
$dec = hexdec(substr($rgb,1));
-
for($i = 0; $i < 24; $i += 8)
-
{
-
$sum += ($dec >> $i) & 255;
-
}
-
return (int)round($sum / 3.0, 0);
- }
-
- /**
-
- Number of month to display in yearly planner
- */
- const YEARLY_PLANNER_NUM_MONTH = 12;
-
- /**
-
- Creates a planner view: grid with columns for the time and rows for categories or users
-
-
- Uses the plannerRowWidget to display rows
-
-
-
@param array $events events to show
-
-
@param mixed $start start-time of the grid
-
-
@param mixed $end end-time of the grid
-
-
@param string|int $by_cat rows by sub-categories of $by_cat (cat_id or 0 for upmost level) or by ‘user’ or ‘month’
-
-
@param string $indent = ‘’ string for correct indention
-
-
@return string with widget
- */
- function &plannerWidget(&$events,$start,$end,$by_cat=0,$indent=’’)
- {
-
$content = $indent.'<div class="calendar_plannerWidget">'."\n";
-
-
// display the header, containing a headerTitle and multiple headerRows with the scales
-
$content .= $indent."\t".'<div class="calendar_plannerHeader">'."\n";
-
-
// display the headerTitle, and get sort2labels
-
switch($by_cat)
-
{
-
case 'user':
-
$title = lang('User');
-
$sort2label = $this->_get_planner_users();
-
break;
-
case 'month':
-
$title = lang('Month');
-
$sort2label = array();
-
$time = new Api\DateTime($start);
-
for($n = 0; $n < self::YEARLY_PLANNER_NUM_MONTH; ++$n)
-
{
-
$sort2label[$time->format('Y-m')] = lang($time->format('F')).' '.$time->format('Y');
-
$time->modify('+1 month');
-
}
-
break;
-
default:
-
$title = lang('Category');
-
$sort2label = array();
-
break;
-
}
-
$content .= $indent."\t\t".'<div class="calendar_plannerHeaderTitle th">'.$title."</div>\n";
-
-
// display the headerRows with the scales
-
$content .= $indent."\t\t".'<div class="calendar_plannerHeaderRows">'."\n";
-
// set start & end to timestamp and first & last to timestamp of 12h midday, to avoid trouble with daylight saving
-
foreach(array('start' => 'first','end' => 'last') as $t => $v)
-
{
-
$$t = $this->bo->date2ts($$t);
-
$$v = $this->bo->date2array($$t);
-
unset(${$v}['raw']);
-
${$v}['hour'] = 12;
-
${$v}['minute'] = ${$v}['second'] = 0;
-
${$v} = $this->bo->date2ts($$v);
-
}
-
if ($by_cat === 'month')
-
{
-
$content .= $this->plannerDayOfMonthScale($indent."\t\t\t");
-
}
-
else
-
{
-
$days = 1 + (int) round(($last - $first) / DAY_s); // we have to use round to get the right number if daylight saving changes
-
if ($days >= 28) // display the month scale
-
{
-
$content .= $this->plannerMonthScale($first,$days,$indent."\t\t\t");
-
}
-
if ($days >= 5) // display the week scale
-
{
-
$content .= $this->plannerWeekScale($first,$days,$indent."\t\t\t");
-
}
-
$content .= $this->plannerDayScale($first,$days,$indent."\t\t\t"); // day-scale, always displayed
-
if ($days <= 7) // display the hour scale
-
{
-
$content .= $this->plannerHourScale($start,$days,$indent."\t\t\t");
-
}
-
}
-
$content .= $indent."\t\t</div>\n"; // end of the plannerHeaderRows
-
$content .= $indent."\t</div>\n"; // end of the plannerHeader
-
-
// sort the events after user or category
-
$rows = array();
-
if (!is_array($events)) $events = array();
-
-
if ($by_cat === 'user') // planner by user
-
{
-
// convert filter to allowed status
-
switch($this->filter)
-
{
-
case 'unknown':
-
$status_to_show = array('U','G'); break;
-
case 'accepted':
-
$status_to_show = array('A'); break;
-
case 'tentative':
-
$status_to_show = array('T'); break;
-
case 'rejected':
-
$status_to_show = array('R'); break;
-
case 'delegated':
-
$status_to_show = array('D'); break;
-
case 'all':
-
$status_to_show = array('U','A','T','D','G','R'); break;
-
default:
-
$status_to_show = array('U','A','T','D','G'); break;
-
}
-
}
-
foreach($events as $key => $event)
-
{
-
if ($by_cat === 'user') // planner by user
-
{
-
foreach($event['participants'] as $sort => $status)
-
{
-
calendar_so::split_status($status,$nul,$nul);
-
// only show if participant with status visible with current filter
-
if (isset($sort2label[$sort]) && (in_array($status,$status_to_show) ||
-
$this->filter == 'owner' && $event['owner'] == $sort)) // owner too additionally uses owner
-
{
-
$rows[$sort][] =& $events[$key];
-
}
-
}
-
}
-
elseif ($by_cat === 'month') // planner by month / yearly planner
-
{
-
$sort = date('Y-m',$event['start']);
-
$rows[$sort][] =& $events[$key];
-
// end in a different month?
-
if ($sort != ($end_sort = date('Y-m',$event['end'])))
-
{
-
while($sort != $end_sort)
-
{
-
list($y,$m) = explode('-',$sort);
-
if (++$m > 12)
-
{
-
++$y;
-
$m = 1;
-
}
-
$sort = sprintf('%04d-%02d',$y,$m);
-
$rows[$sort][] =& $events[$key];
-
}
-
}
-
}
-
else // planner by cat
-
{
-
foreach($this->_get_planner_cats($event['category'],$sort2label,$sort2color) as $sort)
-
{
-
if (!is_array($rows[$sort])) $rows[$sort] = array();
-
-
$rows[$sort][] =& $events[$key];
-
}
-
}
-
}
-
$owners = explode(',',$this->owner);
-
// display a plannerRowWidget for each row (user or category)
-
foreach($sort2label as $sort => $label)
-
{
-
if (!isset($rows[$sort]) && (!$this->cal_prefs['planner_show_empty_rows'] ||
-
$by_cat === 'user' && $this->cal_prefs['planner_show_empty_rows'] == 'cat' ||
-
is_int($by_cat) && $this->cal_prefs['planner_show_empty_rows'] == 'user'))
-
{
-
continue; // dont show empty Api\Categories or user rows
-
}
-
$class = $class == 'row_on' ? 'row_off' : 'row_on';
-
if ($by_cat === 'month')
-
{
-
$time = new Api\DateTime($sort.'-01');
-
$start = $time->format('ts');
-
$time->modify('+1month -1second');
-
$end = $time->format('ts');
-
}
-
// display close button only for directly set users, eg. not group-members (as we cant unset them!)
-
if ($by_cat === 'user' && in_array($sort, $owners))
-
{
-
$label .= $this->close_button($sort);
-
}
-
$content .= $this->plannerRowWidget(isset($rows[$sort]) ? $rows[$sort] : array(),$start,$end,$label,$class,$indent."\t");
-
}
-
$content .= $indent."</div>\n"; // end of the plannerWidget
-
-
return $content;
- }
-
- /**
-
- get all users to display in the planner_by_user
-
-
-
@param boolean $enum_groups = true should groups be returned as there members (eg. planner) or not (day & week)
-
-
@return array with uid => label pairs, first all users alphabetically sorted, then all resources
- */
- function _get_planner_users($enum_groups=true)
- {
-
$users = $resources = array();
-
foreach(explode(',',$this->owner) as $user)
-
{
-
if($user === '0')
-
{
-
// 0 means current user
-
$user = $this->user;
-
}
-
if (!is_numeric($user)) // resources
-
{
-
$resources[$user] = $this->bo->participant_name($user);
-
}
-
elseif ($enum_groups && $GLOBALS['egw']->accounts->get_type($user) == 'g') // groups
-
{
-
foreach((array) $GLOBALS['egw']->accounts->members($user, true) as $user)
-
{
-
if ($this->bo->check_perms(Acl::READ | calendar_bo::ACL_FREEBUSY,0,$user))
-
{
-
$users[$user] = $this->bo->participant_name($user);
-
}
-
}
-
}
-
else // users
-
{
-
$users[$user] = $this->bo->participant_name($user);
-
}
-
}
-
// Only sort users in planner views
-
if ($enum_groups)
-
{
-
asort($users);
-
asort($resources);
-
}
-
-
return $users+$resources;
- }
-
- /**
-
- get all Api\Categories used as sort criteria for the planner by category
-
-
- the returned cat is as direct sub-category of $this->cat_id or a main (level 1) category if !$this->cat_id
-
-
-
@param string $cats comma-delimited cat_id’s or empty for no cat
-
-
@param array &$sort2label labels for the returned cats
-
-
@return array with cat_id’s
- */
- function _get_planner_cats($cats,&$sort2label)
- {
-
static $cat2sort;
-
-
if (!is_array($cat2sort))
-
{
-
$cat2sort = array();
-
$cat_filter = $this->cat_id ? (array)$this->cat_id : array();
-
foreach((array)$this->categories->return_sorted_array(0,false,'','','',true) as $data)
-
{
-
if (in_array($data['parent'], $cat_filter) || in_array($data['id'], $cat_filter) ||
-
!$data['parent'] && !$cat_filter) // cat is a direct sub of $this->cat_id
-
{
-
$cat2sort[$data['id']] = $data['id'];
-
$sort2label[$data['id']] = stripslashes($data['name']);
-
}
-
elseif(isset($cat2sort[$data['parent']])) // parent is already in the array => add us with same target
-
{
-
$cat2sort[$data['id']] = $cat2sort[$data['parent']];
-
}
-
}
-
}
-
$ret = array();
-
foreach(!is_array($cats) ? explode(',',$cats) : $cats as $cat)
-
{
-
if (isset($cat2sort[$cat]) && !in_array($cat2sort[$cat],$ret))
-
{
-
$ret[] = $cat2sort[$cat];
-
}
-
}
-
if (!count($ret))
-
{
-
$sort2label[0] = lang('none');
-
$ret[] = 0;
-
}
-
//echo "<p>uiviews::_get_planner_cats($cats=".$this->categories->id2name($cats).") (this->cat_id=$this->cat_id) = ".print_r($ret,true).'='.$this->categories->id2name($ret[0])."</p>\n";
-
return $ret;
- }
-
- /**
-
- Creates month scale for the planner
-
-
-
@param int $start start-time (12h) of the scale
-
-
@param int $days number of days to display
-
-
@param string $indent = ‘’ string for correct indention
-
-
@return string with scale
- */
- function plannerMonthScale($start,$days,$indent)
- {
-
$day_width = round(100 / $days,2);
-
-
$content .= $indent.'<div class="calendar_plannerScale">'."\n";
-
for($t = $start,$left = 0,$i = 0; $i < $days; $t += $days_in_month*DAY_s,$left += $days_in_month*$day_width,$i += $days_in_month)
-
{
-
$t_arr = $this->bo->date2array($t);
-
unset($t_arr['raw']); // force recalculation
-
unset($t_arr['full']);
-
$days_in_month = $this->datetime->days_in_month($t_arr['month'],$t_arr['year']) - ($t_arr['day']-1);
-
if ($i + $days_in_month > $days)
-
{
-
$days_in_month = $days - $i;
-
}
-
if ($days_in_month > 10)
-
{
-
$title = lang(date('F',$t)).' '.$t_arr['year'];
-
// previous links
-
$prev = $t_arr;
-
$prev['day'] = 1;
-
if ($prev['month']-- <= 1)
-
{
-
$prev['month'] = 12;
-
$prev['year']--;
-
}
-
if ($this->bo->date2ts($prev) < $start-20*DAY_s)
-
{
-
$prev['day'] = $this->day;
-
$full = $this->bo->date2string($prev);
-
if ($this->day >= 15) $prev = $t_arr; // we stay in the same month
-
$prev['day'] = $this->day < 15 ? 15 : 1;
-
$half = $this->bo->date2string($prev);
-
$title = Api\Html::a_href(Api\Html::image('phpgwapi','first',lang('back one month'),$options=' alt="<<"'),array(
-
'menuaction' => $this->view_menuaction,
-
'date' => $full,
-
))