* * @param array $options contains a list of parameters passed to the plugin at the wiki-page * @param array pages the wiki-pages to read the data from * @param default_date if year ist omitted it is taken from this date. * so you can write "31.07." for a birthdate which shows up every year */ function read_pages_into_calendar(&$options,&$pages,$default_date) { global $gCal_data; # this array receives all the date-entries # reset data-array $gCal_data = array(); # memory for wiki-pages allready read to avoid duplicates $pages_allready_read = array(); foreach($pages as $page_key=>$page) { list($page_name,$page_list) = explode("(",$page,2); $page_list = substr($page_list,0,-1); if($page_list != ""){ $page_list = explode("|",$page_list); }else{ $page_list = array($page_name); } # expand namespaces (i.e. ":wiki:*") expands to all files in that ns # if option 'nested' is given, this is done recursive (all subnamespaces) $page_list = expand_ns($page_list,isset($options['nested'])); foreach($page_list as $wikipage) { # split section from wikipage list($wikipage,$section)=explode('#',$wikipage,2); $wikipage=cleanID($wikipage); # skip pages allready read, except if allowed with option: "showdup" if(!isset($options["showdup"]) && in_array($wikipage,$pages_allready_read)) continue; $pages_allready_read[] = $wikipage; # check if user is allowed to see this page $perm = auth_quickaclcheck(cleanID($wikipage)); if ($perm < AUTH_READ) continue; # to next page # if we have more than one page to include or option pagelinks is set to 'show', # generate a link to the wiki page, except option pagelinks is set to 'hide'. if( ($options["pagelinks"]=="show") || (($options["pagelinks"]!="hide") && count($page_list)>1) ) { $pagelink = " ".noNS($wikipage).""; }else{ $pagelink=""; } # now read this page into the calendar-array read_wikipage_into_calendar($options,$page_key,$wikipage,$section,$pagelink,$default_date); } } } /** * read a page into the gCal_data-array * * @author Frank Hinkel * * @param array $options contains a list of parameters passed to the plugin at the wiki-page * @param array page_key the column number where the data is stored into the gCal_data-array * @param string wikipage the wiki-page to read the data from * @param string section optionally given section inside the wikipage to read from * @param default_date if year ist omitted it is taken from this date. * so you can write "31.07." for a birthdate which shows every year * */ function read_wikipage_into_calendar(&$options,$page_key,$wikipage,$section,$pagelink,$default_date) { global $gCal_data; # this array contains all the date-entries global $conf; # read categorypattern from config $match_category = $conf['gCal_match_category']; if(!is_array($match_category)) return; # read eventpattern from config. $match_event = $conf['gCal_match_event']; if(!is_array($match_event)) return; # find path to actual wiki-page. skip if file not exists $filepath = wikiFN($wikipage); if(!file_exists($filepath)) return; # read data from wiki-page $handle = fopen ($filepath, "r"); while (!feof($handle)) { $buffer = trim(fgets($handle, 4096)); # check line against all category-patterns. see user/conf.php foreach($match_category as $pattern) { if(preg_match($pattern, $buffer, $subpattern)) { $category = strtoupper($subpattern[1]); break; } } if(is_string($section) && strlen($section)>0 && (strtoupper($section)!=$category)) continue; # check line against all event-patterns. see user/conf.php foreach($match_event as $pattern) { if(preg_match($pattern, $buffer, $subpattern)) { $buffer = $subpattern[1]; # grab date- and time-spans from the beginning of each line $start_date = $end_date = fetch_date($buffer,$default_date); $end_time = ""; $start_time = fetch_time($buffer); # check for time-spans indicated by a dash if($buffer{0}=="-") { $buffer = trim(substr($buffer,1)); # remove dash $end_date = fetch_date($buffer,$default_date); # end_date equals start_date by default if ( strlen($end_date)==0 ) $end_date = $start_date; $end_time = fetch_time($buffer); } $cat = strtoupper(trim($category." ".fetch_inline_category($buffer))); # insert the event into the whole date-range for($d=$start_date ; $d <= $end_date ; $d++) { $entry = $buffer; # initialize event with event-source $event = array("source"=>$subpattern[1]); # set the category, even when there is no event-text $event["categories"] = $cat; # generate an event, when event-text or start-time or end-time is given if(($entry!="") || ($start_time!="") || ($end_time!="")) { # special character ">" will be suppressed, when it is the first character # of the event-text. can be used to force an event-icon without text if($entry{0}==">") $buffer=substr($entry,1); # apply basic rendering like bold, italic, links, etc. $entry = fast_p_render($entry); # add the backlink to the original wikipage $entry .= $pagelink; # attach start_time at start_date and end_time at end_date. I hope this is allways logical? if(is_array($end_time) && ($d==$end_date) ) { $entry = "- ".$end_time[0]. " ".$entry; $event["end_time"] = $end_time[1]; } if(is_array($start_time) && ($d==$start_date)) { $entry = $start_time[0]." ".$entry; $event["start_time"] = $start_time[1]; } # write the event-entry to global array $cat_classes = 'gCal_cat_'.implode(' gCal_cat_',explode(' ',$cat))." "; $event["content"] = "".$entry.""; } $gCal_data[$page_key][$d][] = $event; } break; } } } fclose($handle); } # ================================================================================================= # Utility-functions # ================================================================================================= /* * returns date at the beginning of the text. if date found it is removed from the text. */ function fetch_date(&$text,$default_date) { global $conf; if($text=="") return; # '#^' --> # string has to start with the pattern. # '(?=($|\D))#' --> # look-ahead => any non-digit or end-of-string terminates pattern if(preg_match('#^'.$conf['gCal_date_dmy'].'(?=($|\D))#',$text,$match)) { $d=$match[1];$m=$match[2];$y=$match[3]; }elseif(preg_match('#^'.$conf['gCal_date_mdy'].'(?=($|\D))#',$text,$match)) { $d=$match[2];$m=$match[1];$y=$match[3]; }elseif(preg_match('#^'.$conf['gCal_date_ymd'].'(?=($|\D))#',$text,$match)) { $d=$match[3];$m=$match[2];$y=$match[1]; }else{ return; } if(strlen($d)==1) $d='0'.$d; if(strlen($m)==1) $m='0'.$m; if(strlen($y)==0) $y=date('Y',$default_date); if(strlen($y)==2) $y='20'.$y; $text=trim(substr($text,strlen($match[0]))); return $y.$m.$d; // return format yyyymmdd } /* * returns time at the beginning of the text */ function fetch_time(&$text) { global $conf; if($text=="") return; # allowed formats are: 1:23 , 01:23, 01:23am. 1:23 Am, etc. $pattern = '([0-9]{1,2})\:([0-9]{2})\s*(am|pm|)'; $pattern = '#^'.$pattern; # string has to start with the pattern $pattern .= '(?=($|\\D))#i'; # look-ahead => any non-digit or end-of-string terminates pattern if(preg_match($pattern,$text, $match)) { $text=trim(substr($text,strlen($match[0]))); $time = str_replace(array('##','#h','#m','#r'),$match,$conf['gCal_time']); if(strlen($match[1])==1) $match[1] = '0'.$match[1]; if(strtolower($match[3])=='pm') $match[1] += 12; $euro = $match[1].":".$match[2]; return array($time,$euro); } } /* * returns the inline-category */ function fetch_inline_category(&$text) { global $conf; if($text=="") return; # get the preg-expr from $conf. sting has to start with this pattern $pattern = '#'.$conf['gCal_inline_Category_visible'].'#i'; if(preg_match($pattern,$text, $match)) { $text=trim($match[1].substr($text,strlen($match[0]))); return strtoupper($match[1]); } $pattern = '#'.$conf['gCal_inline_Category_hidden'].'#i'; if(preg_match($pattern,$text, $match)) { $text=trim(substr($text,strlen($match[0]))); return strtoupper($match[1]); } } /** * Expand namespaces in the form :namespace:* to every wiki-page in this ns. * * @author Frank Hinkel * * @param array page_list on input : array of pages and namespaces * @param array page_list on output : array of pages (namespaces are expanded) * @param boolean nested if true -> subnamespaces are also expanded into single-pages * */ function expand_ns($page_list,$nested=false) { global $conf; $pl = array(); foreach($page_list as $page) { if(substr($page,-1)=="*") { # when page ends with *, expand namespace $start = noNS($conf['start']); $dir = wikiFN(substr($page,0,-1).$start); $dir = substr($dir,0,-(strlen($start)+4)); # strip filename - only the dir is needed if(!@$handle=opendir($dir)) continue; while ($file = readdir ($handle)) { if($file == "." || $file == ".." || trim($file)=="") continue; if(is_file($dir.$file)) { $pl[] = substr($page,0,-1).substr($file,0,-4); }elseif($nested && is_dir($dir.$file)){ $subNS[] = substr($page,0,-2).':'.cleanID($file).':*'; } } closedir($handle); }else{ # leave page as it is $pl[] = $page; } } # if $nested is true, add all files of all subnamespaces to the list if(is_array($subNS)) { $subNS = expand_ns($subNS,$nested,false); $pl = array_merge($pl,$subNS); } return $pl; } /** * quick rendering, where not all the power of p_render is needed * do basic formatting and linking. returns the rendered string * * @author Frank Hinkel * @param string $text text to be rendered * * @todo : add more rendering */ function fast_p_render($text) { global $conf; # do some fundamental-rendering: bold, italic, underline, ... $text = preg_replace('#\*\*(.*)\*\*#sU', '\1', $text); $text = preg_replace('#(?\1', $text); $text = preg_replace('#\_\_(.*)\_\_#sU', '\1', $text); $text = preg_replace('#\'\'(.*)\'\'#sU', '\1', $text); $text = preg_replace('#\\\\\\\\(\s+|$)#m', '
', $text); $text = str_replace('=>','⇒',$text); $text = str_replace('<=','⇐',$text); $text = str_replace('->','→',$text); $text = str_replace('<-','←',$text); # some methods of the class 'Doku_Renderer_xhtml' needed here static $drx; if(!isset($drx)) $drx = new Doku_Renderer_xhtml; # process all links enclosed in double square brackets preg_match_all("=\[\[.+\]\]=sU",$text,$wiki_links); foreach($wiki_links[0] as $wl) { # reset rendered content $drx->doc = ''; list($link,$name)=explode("|",substr($wl,2,strlen($wl)-4),2); if ( preg_match('/^[a-zA-Z\.]+>{1}.*$/u',$link )) { // Interwiki if(count($drx->interwiki)==0) $drx->interwiki = getInterwiki(); list($wikiname,$wikiuri) = preg_split('/>/u',$link,2); $drx->interwikilink('',$name,strtolower($wikiname),$wikiuri); }elseif ( preg_match('/^\\\\\\\\[\w.:?\-;,]+?\\\\/u',$link) ) { // Windows Share $drx->windowssharelink($link,$name); }elseif ( preg_match('#^([a-z0-9\-\.+]+?)://#i',$link) ) { // external link (accepts all protocols) $drx->externallink($link,$name); }elseif ( preg_match('#([a-z0-9\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)#i',$link) ) { // email-link $drx->emaillink($link,$name); }elseif ( preg_match('!^#.+!',$link) ){ // local link $drx->locallink($link,$name); }else { $drx->internallink($link,$name); } $text=str_replace($wl,$drx->doc,$text); } # remove all html-tags which are not explicitly allowed return strip_tags($text,$conf['gCal_allowed_tags']); }