/** * parse component unparsed data into properties * * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**> * @since 2.20.3 - 2015-03-05 * @param mixed $unparsedtext strict rfc2445 formatted, single property string or array of strings * @uses calendarComponent::getConfig() * @uses iCalUtilityFunctions::convEolChar() * @uses calendarComponent::$unparsed * @uses calendarComponent::$components * @uses calendarComponent::copy() * @uses iCalUtilityFunctions::_splitContent() * @uses calendarComponent::setProperty() * @uses iCalUtilityFunctions::_strunrep() * @uses calendarComponent::parse() * @return bool FALSE if error occurs during parsing */ function parse($unparsedtext = null) { $nl = $this->getConfig('nl'); if (!empty($unparsedtext)) { if (is_array($unparsedtext)) { $unparsedtext = implode('\\n' . $nl, $unparsedtext); } $unparsedtext = iCalUtilityFunctions::convEolChar($unparsedtext, $nl); } elseif (!isset($this->unparsed)) { $unparsedtext = array(); } else { $unparsedtext = $this->unparsed; } /* skip leading (empty/invalid) lines */ foreach ($unparsedtext as $lix => $line) { if (FALSE !== ($pos = stripos($line, 'BEGIN:'))) { $unparsedtext[$lix] = substr($unparsedtext[$lix], $pos); break; } $tst = trim($line); if ('\\n' == $tst || empty($tst)) { unset($unparsedtext[$lix]); } } $this->unparsed = array(); $comp =& $this; $config = $this->getConfig(); $compsync = $subsync = 0; foreach ($unparsedtext as $lix => $line) { if ('END:VALARM' == strtoupper(substr($line, 0, 10))) { if (1 != $subsync) { return FALSE; } $this->components[] = $comp->copy(); $subsync--; } elseif ('END:DAYLIGHT' == strtoupper(substr($line, 0, 12))) { if (1 != $subsync) { return FALSE; } $this->components[] = $comp->copy(); $subsync--; } elseif ('END:STANDARD' == strtoupper(substr($line, 0, 12))) { if (1 != $subsync) { return FALSE; } array_unshift($this->components, $comp->copy()); $subsync--; } elseif ('END:' == strtoupper(substr($line, 0, 4))) { // end:<component> if (1 != $compsync) { return FALSE; } if (0 < $subsync) { $this->components[] = $comp->copy(); } $compsync--; break; /* skip trailing empty lines */ } elseif ('BEGIN:VALARM' == strtoupper(substr($line, 0, 12))) { $comp = new valarm($config); $subsync++; } elseif ('BEGIN:STANDARD' == strtoupper(substr($line, 0, 14))) { $comp = new vtimezone('standard', $config); $subsync++; } elseif ('BEGIN:DAYLIGHT' == strtoupper(substr($line, 0, 14))) { $comp = new vtimezone('daylight', $config); $subsync++; } elseif ('BEGIN:' == strtoupper(substr($line, 0, 6))) { // begin:<component> $compsync++; } else { $comp->unparsed[] = $line; } } if (0 < $subsync) { $this->components[] = $comp->copy(); } unset($config); /* concatenate property values spread over several lines */ $lastix = -1; $propnames = array('action', 'attach', 'attendee', 'categories', 'comment', 'completed', 'contact', 'class', 'created', 'description', 'dtend', 'dtstart', 'dtstamp', 'due', 'duration', 'exdate', 'exrule', 'freebusy', 'geo', 'last-modified', 'location', 'organizer', 'percent-complete', 'priority', 'rdate', 'recurrence-id', 'related-to', 'repeat', 'request-status', 'resources', 'rrule', 'sequence', 'status', 'summary', 'transp', 'trigger', 'tzid', 'tzname', 'tzoffsetfrom', 'tzoffsetto', 'tzurl', 'uid', 'url', 'x-'); $proprows = array(); for ($i = 0; $i < count($this->unparsed); $i++) { // concatenate lines $line = rtrim($this->unparsed[$i], $nl); while (isset($this->unparsed[$i + 1]) && !empty($this->unparsed[$i + 1]) && ' ' == $this->unparsed[$i + 1][0]) { $line .= rtrim(substr($this->unparsed[++$i], 1), $nl); } $proprows[] = $line; } /* parse each property 'line' */ foreach ($proprows as $line) { if ('\\n' == substr($line, -2)) { $line = substr($line, 0, -2); } /* get propname */ $propname = null; $cix = 0; while (isset($line[$cix])) { if (in_array($line[$cix], array(':', ';'))) { break; } else { $propname .= $line[$cix]; } $cix++; } if ('x-' == substr($propname, 0, 2) || 'X-' == substr($propname, 0, 2)) { $propname2 = $propname; $propname = 'X-'; } if (!in_array(strtolower($propname), $propnames)) { // skip non standard property names continue; } /* rest of the line is opt.params and value */ $line = substr($line, $cix); /* separate attributes from value */ iCalUtilityFunctions::_splitContent($line, $propAttr); /* call setProperty( $propname.. . */ switch (strtoupper($propname)) { case 'ATTENDEE': foreach ($propAttr as $pix => $attr) { if (!in_array(strtoupper($pix), array('MEMBER', 'DELEGATED-TO', 'DELEGATED-FROM'))) { continue; } $attr2 = explode(',', $attr); if (1 < count($attr2)) { $propAttr[$pix] = $attr2; } } $this->setProperty($propname, $line, $propAttr); break; case 'CATEGORIES': case 'RESOURCES': if (FALSE !== strpos($line, ',')) { $content = array(0 => ''); $cix = $lix = 0; while (FALSE !== substr($line, $lix, 1)) { if (',' == $line[$lix] && "\\" != $line[$lix - 1]) { $cix++; $content[$cix] = ''; } else { $content[$cix] .= $line[$lix]; } $lix++; } if (1 < count($content)) { $content = array_values($content); foreach ($content as $cix => $contentPart) { $content[$cix] = iCalUtilityFunctions::_strunrep($contentPart); } $this->setProperty($propname, $content, $propAttr); break; } else { $line = reset($content); } } case 'COMMENT': case 'CONTACT': case 'DESCRIPTION': case 'LOCATION': case 'SUMMARY': if (empty($line)) { $propAttr = null; } $this->setProperty($propname, iCalUtilityFunctions::_strunrep($line), $propAttr); break; case 'REQUEST-STATUS': $values = explode(';', $line, 3); $values[1] = !isset($values[1]) ? null : iCalUtilityFunctions::_strunrep($values[1]); $values[2] = !isset($values[2]) ? null : iCalUtilityFunctions::_strunrep($values[2]); $this->setProperty($propname, $values[0], $values[1], $values[2], $propAttr); break; case 'FREEBUSY': $fbtype = isset($propAttr['FBTYPE']) ? $propAttr['FBTYPE'] : ''; // force setting default, if missing unset($propAttr['FBTYPE']); $values = explode(',', $line); foreach ($values as $vix => $value) { $value2 = explode('/', $value); if (1 < count($value2)) { $values[$vix] = $value2; } } $this->setProperty($propname, $fbtype, $values, $propAttr); break; case 'GEO': $value = explode(';', $line, 2); if (2 > count($value)) { $value[1] = null; } $this->setProperty($propname, $value[0], $value[1], $propAttr); break; case 'EXDATE': $values = !empty($line) ? explode(',', $line) : null; $this->setProperty($propname, $values, $propAttr); break; case 'RDATE': if (empty($line)) { $this->setProperty($propname, $line, $propAttr); break; } $values = explode(',', $line); foreach ($values as $vix => $value) { $value2 = explode('/', $value); if (1 < count($value2)) { $values[$vix] = $value2; } } $this->setProperty($propname, $values, $propAttr); break; case 'EXRULE': case 'RRULE': $values = explode(';', $line); $recur = array(); foreach ($values as $value2) { if (empty($value2)) { continue; } // ;-char in ending position ??? $value3 = explode('=', $value2, 2); $rulelabel = strtoupper($value3[0]); switch ($rulelabel) { case 'BYDAY': $value4 = explode(',', $value3[1]); if (1 < count($value4)) { foreach ($value4 as $v5ix => $value5) { $value6 = array(); $dayno = $dayname = null; $value5 = trim((string) $value5); if (ctype_alpha(substr($value5, -1)) && ctype_alpha(substr($value5, -2, 1))) { $dayname = substr($value5, -2, 2); if (2 < strlen($value5)) { $dayno = substr($value5, 0, strlen($value5) - 2); } } if ($dayno) { $value6[] = $dayno; } if ($dayname) { $value6['DAY'] = $dayname; } $value4[$v5ix] = $value6; } } else { $value4 = array(); $dayno = $dayname = null; $value5 = trim((string) $value3[1]); if (ctype_alpha(substr($value5, -1)) && ctype_alpha(substr($value5, -2, 1))) { $dayname = substr($value5, -2, 2); if (2 < strlen($value5)) { $dayno = substr($value5, 0, strlen($value5) - 2); } } if ($dayno) { $value4[] = $dayno; } if ($dayname) { $value4['DAY'] = $dayname; } } $recur[$rulelabel] = $value4; break; default: $value4 = explode(',', $value3[1]); if (1 < count($value4)) { $value3[1] = $value4; } $recur[$rulelabel] = $value3[1]; break; } // end - switch $rulelabel } // end - foreach( $values.. . $this->setProperty($propname, $recur, $propAttr); break; case 'X-': $propname = isset($propname2) ? $propname2 : $propname; unset($propname2); case 'ACTION': case 'CLASSIFICATION': case 'STATUS': case 'TRANSP': case 'UID': case 'TZID': case 'RELATED-TO': case 'TZNAME': $line = iCalUtilityFunctions::_strunrep($line); default: $this->setProperty($propname, $line, $propAttr); break; } // end switch( $propname.. . } // end - foreach( $proprows.. . unset($unparsedtext, $this->unparsed, $proprows); if (isset($this->components) && is_array($this->components) && 0 < count($this->components)) { $ckeys = array_keys($this->components); foreach ($ckeys as $ckey) { if (!empty($this->components[$ckey]) && !empty($this->components[$ckey]->unparsed)) { $this->components[$ckey]->parse(); } } } return TRUE; }
/** * function csv2iCal * * Convert csv file to iCal format and send file to browser (default) or save Ical file to disk * Definition iCal : rcf2445, http://kigkonsult.se/downloads/index.php#rfc2445 * Definition csv : http://en.wikipedia.org/wiki/Comma-separated_values * Using iCalcreator: http://kigkonsult.se/downloads/index.php#iCalcreator * csv directory/file read/write * * @author Kjell-Inge Gustafsson <*****@*****.**> * @since 3.0 - 2011-12-21 * @return bool return FALSE when error */ public function csv2iCal() { $timeexec = array('start' => microtime(TRUE)); if ($this->log) { $this->log->log(' ********** START **********', PEAR_LOG_NOTICE); } $conf = array(); foreach ($this->config as $key => $value) { if (in_array(strtolower($key), array('inputdirectory', 'outputdirectory', 'inputfilename', 'outputfilename', 'inputurl', 'backup', 'save', 'skip'))) { continue; } if (in_array($key, array('del', 'sep', 'nl'))) { $conf[$key] = "{$value}"; } else { $conf[strtoupper($value)] = strtoupper($key); // flip map names if ($this->log) { $this->log->log("{$value} mapped to {$key}", PEAR_LOG_DEBUG); } } } $fp = false; $string_to_parse = $this->getConfig('string_to_parse'); if ($string_to_parse) { $fp = fopen('php://temp/maxmemory:' . 1024 * 1024, 'rw'); fputs($fp, $string_to_parse); fseek($fp, 0); } else { /** check input/output directory and filename */ $inputdirFile = $outputdirFile = ''; $inputFileParts = $outputFileParts = array(); $remoteInput = $remoteOutput = FALSE; if (FALSE === $this->_fixIO('input', 'csv', $inputdirFile, $inputFileParts, $remoteInput)) { if ($this->log) { $this->log->log(number_format(microtime(TRUE) - $timeexec['start'], 5) . ' sec', PEAR_LOG_ERR); $this->log->log("ERROR 2, invalid input ({$inputdirFile})", PEAR_LOG_ERR); $this->log->flush(); } return FALSE; } if (FALSE === $this->_fixIO('output', FALSE, $outputdirFile, $outputFileParts, $remoteOutput)) { if (FALSE === $this->setConfig('outputfilename', $inputFileParts['filename'] . '.ics')) { if ($this->log) { $this->log->log(number_format(microtime(TRUE) - $timeexec['start'], 5) . ' sec', PEAR_LOG_ERR); $this->log->log('ERROR 3,invalid output (' . $inputFileParts['filename'] . '.csv)', PEAR_LOG_ERR); $this->log->flush(); } return FALSE; } $outputdirFile = $this->getConfig('outputdirectory') . DIRECTORY_SEPARATOR . $inputFileParts['filename'] . '.ics'; $outputFileParts = pathinfo($outputdirFile); if ($this->log) { $this->log->log("output set to '{$outputdirFile}'", PEAR_LOG_NOTICE); } } if ($this->log) { $this->log->log("INPUT..FILE:{$inputdirFile}", PEAR_LOG_NOTICE); $this->log->log("OUTPUT.FILE:{$outputdirFile}", PEAR_LOG_NOTICE); } /** read csv file into input array */ ini_set('auto_detect_line_endings', true); $fp = fopen($inputdirFile, "r"); if (FALSE === $fp) { if ($this->log) { $this->log->log("ERROR 4, unable to read file: '{$inputdirFile}'", PEAR_LOG_ERR); $this->log->log(number_format(microtime(TRUE) - $timeexec['start'], 5) . ' sec', PEAR_LOG_DEBUG); $this->log->flush(); } return FALSE; } } $rows = array(); while (FALSE !== ($row = fgetcsv($fp, FALSE, $conf['sep'], $conf['del']))) { $rows[] = $row; } fclose($fp); ini_set('auto_detect_line_endings', false); $cntrows = count($rows); /** iCalcreator checks when setting directory and filename */ $calendar = new vcalendar(); if (FALSE !== ($unique_id = $this->getConfig('unique_id'))) { $calendar->setConfig('unique_id', $unique_id); } if (!$this->getConfig('outputobj')) { if ($remoteOutput) { if (FALSE === $calendar->setConfig('url', $outputdirFile)) { if ($this->log) { $this->log->log("ERROR 5, iCalcreator: invalid url: '{$outputdirFile}'", PEAR_LOG_ERR); $this->log->log(number_format(microtime(TRUE) - $timeexec['start'], 5) . ' sec', PEAR_LOG_DEBUG); $this->log->flush(); } return FALSE; } } else { if (FALSE === $calendar->setConfig('directory', $outputFileParts['dirname'])) { if ($this->log) { $this->log->log("ERROR 6, INPUT FILE:'{$inputdirFile}' iCalcreator: invalid directory: '" . $outputFileParts['dirname'] . "'", PEAR_LOG_ERR); $this->log->log(number_format(microtime(TRUE) - $timeexec['start'], 5) . ' sec', PEAR_LOG_DEBUG); $this->log->flush(); } return FALSE; } if (FALSE === $calendar->setConfig('filename', $outputFileParts['basename'])) { if ($this->log) { $this->log->log("ERROR 7, INPUT FILE:'{$inputdirFile}' iCalcreator: invalid filename: '" . $outputFileParts['basename'] . "'", PEAR_LOG_ERR); $this->log->log(number_format(microtime(TRUE) - $timeexec['start'], 5) . ' sec', PEAR_LOG_DEBUG); $this->log->flush(); } return FALSE; } } } $timeexec['fileOk'] = microtime(TRUE); /** info rows */ $actrow = 0; for ($row = $actrow; $row < $cntrows; $row++) { if (empty($rows[$row]) || 1 >= count($rows[$row]) || '' >= $rows[$row][1] || 'iCal' == substr($rows[$row][0], 0, 4) || 'kigkonsult.se' == $rows[$row][0]) { continue; } elseif ('TYPE' == strtoupper($rows[$row][0])) { $actrow = $row; break; } elseif ('CALSCALE' == strtoupper($rows[$row][0])) { $calendar->setProperty('CALSCALE', $rows[$row][1]); } elseif ('METHOD' == strtoupper($rows[$row][0])) { $calendar->setProperty('METHOD', $rows[$row][1]); } elseif ('X-' == substr($rows[$row][0], 0, 2)) { $calendar->setProperty($rows[$row][0], $rows[$row][1]); } elseif (2 >= count($rows[$row])) { continue; } else { $actrow = $row; break; } } $timeexec['infoOk'] = microtime(TRUE); $cntprops = 0; $proporder = array(); /** fix opt. vtimezone */ if ($actrow < $cntrows && (in_array('tzid', $rows[$actrow]) || in_array('TZID', $rows[$actrow]))) { foreach ($rows[$actrow] as $key => $header) { $header = strtoupper($header); if (isset($conf[$header])) { $proporder[$conf[$header]] = $key; // check map of userfriendly name to iCal property name if ($this->log) { $this->log->log("header row ix:{$key} => {$header}, replaced by " . $conf[$header], PEAR_LOG_DEBUG); } } else { $proporder[$header] = $key; } } if ($this->log) { $this->log->log("comp proporder=" . implode(',', array_flip($proporder)), PEAR_LOG_DEBUG); } $allowedProps = array('VTIMEZONE' => array('TZID', 'LAST-MODIFIED', 'TZURL'), 'STANDARD' => array('DTSTART', 'TZOFFSETTO', 'TZOFFSETFROM', 'COMMENT', 'RDATE', 'RRULE', 'TZNAME'), 'DAYLIGHT' => array('DTSTART', 'TZOFFSETTO', 'TZOFFSETFROM', 'COMMENT', 'RDATE', 'RRULE', 'TZNAME')); $actrow++; $comp = $subcomp = $actcomp = FALSE; for ($row = $actrow; $row < $cntrows; $row++) { if (empty($rows[$row]) || 1 >= count($rows[$row])) { continue; } $compname = strtoupper($rows[$row][0]); if ('TYPE' == $compname) { // next header $actrow = $row; break; } if ($comp && $subcomp) { $comp->setComponent($subcomp); $subcomp = FALSE; } if ('VTIMEZONE' == $compname) { if ($comp) { $calendar->setComponent($comp); } $comp = new vtimezone(); $actcomp =& $comp; $cntprops += 1; } elseif ('STANDARD' == $compname) { $subcomp = new vtimezone('STANDARD'); $actcomp =& $subcomp; } elseif ('DAYLIGHT' == $compname) { $subcomp = new vtimezone('DAYLIGHT'); $actcomp =& $subcomp; } else { if ($this->log) { $this->log->log("skipped {$compname}", PEAR_LOG_WARNING); } continue; } foreach ($proporder as $propName => $col) { // insert all properties into component if (2 > $col || 'ORDER' == strtoupper($propName)) { continue; } $propName = strtoupper($propName); if ('X-' != substr($propName, 0, 2) && !in_array($propName, $allowedProps[$compname])) { // check if allowed property for the component if ($this->log) { $this->log->log("skipped {$compname}: {$propName}", PEAR_LOG_DEBUG); } continue; } if (isset($rows[$row][$col]) && !empty($rows[$row][$col])) { $rows[$row][$col] = str_replace(array("\r\n", "\n\r", "\n", "\r"), $conf['nl'], $rows[$row][$col]); $value = FALSE !== strpos($rows[$row][$col], $conf['nl']) ? explode($conf['nl'], $rows[$row][$col]) : array($rows[$row][$col]); foreach ($value as $val) { if (empty($val) && '0' != $val) { continue; } $del = FALSE !== strpos($val, ':') ? ';' : ':'; if (FALSE !== $actcomp->parse("{$propName}{$del}{$val}")) { if ($this->log) { $this->log->log("iCalcreator->parse( '{$propName} {$val}' )", PEAR_LOG_DEBUG); } } elseif ($this->log) { $this->log->log("ERROR 8, INPUT FILE:'{$inputdirFile}' iCalcreator: parse error: '{$propName}{$del}{$val}'", PEAR_LOG_ERR); } } // end foreach( $value } // end if( isset } // end foreach( $proporder } // end for( $row = $actrow if ($comp && $subcomp) { $comp->setComponent($subcomp); } if ($comp) { $calendar->setComponent($comp); } $comp = $subcomp = $actcomp = FALSE; } $timeexec['zoneOk'] = microtime(TRUE); /** fix data */ $proporder = array(); if ($actrow < $cntrows && isset($rows[$actrow][0]) && 'TYPE' == strtoupper($rows[$actrow][0])) { foreach ($rows[$actrow] as $key => $header) { $header = strtoupper($header); if (isset($conf[$header])) { $proporder[$conf[$header]] = $key; // check map of user friendly name to iCal property name if ($this->log) { $this->log->log("header row ix:'{$key} => {$header}', mapped to '" . $conf[$header] . "'", PEAR_LOG_DEBUG); } } else { $proporder[$header] = $key; } } if ($this->log) { $this->log->log("comp proporder=" . implode(',', array_flip($proporder)), PEAR_LOG_DEBUG); } $allowedProps = array('VEVENT' => array('ATTACH', 'ATTENDEE', 'CATEGORIES', 'CLASS', 'COMMENT', 'CONTACT', 'CREATED', 'DESCRIPTION', 'DTEND', 'DTSTAMP', 'DTSTART', 'DURATION', 'EXDATE', 'RXRULE', 'GEO', 'LAST-MODIFIED', 'LOCATION', 'ORGANIZER', 'PRIORITY', 'RDATE', 'RECURRENCE-ID', 'RELATED-TO', 'RESOURCES', 'RRULE', 'REQUEST-STATUS', 'SEQUENCE', 'STATUS', 'SUMMARY', 'TRANSP', 'UID', 'URL'), 'VTODO' => array('ATTACH', 'ATTENDEE', 'CATEGORIES', 'CLASS', 'COMMENT', 'COMPLETED', 'CONTACT', 'CREATED', 'DESCRIPTION', 'DTSTAMP', 'DTSTART', 'DUE', 'DURATION', 'EXDATE', 'EXRULE', 'GEO', 'LAST-MODIFIED', 'LOCATION', 'ORGANIZER', 'PERCENT', 'PRIORITY', 'RDATE', 'RECURRENCE-ID', 'RELATED-TO', 'RESOURCES', 'RRULE', 'REQUEST-STATUS', 'SEQUENCE', 'STATUS', 'SUMMARY', 'UID', 'URL'), 'VJOURNAL' => array('ATTACH', 'ATTENDEE', 'CATEGORIES', 'CLASS', 'COMMENT', 'CONTACT', 'CREATED', 'DESCRIPTION', 'DTSTAMP', 'DTSTART', 'EXDATE', 'EXRULE', 'LAST-MODIFIED', 'ORGANIZER', 'RDATE', 'RECURRENCE-ID', 'RELATED-TO', 'RRULE', 'REQUEST-STATUS', 'SEQUENCE', 'STATUS', 'SUMMARY', 'UID', 'URL'), 'VFREEBUSY' => array('ATTENDEE', 'COMMENT', 'CONTACT', 'DTEND', 'DTSTAMP', 'DTSTART', 'DURATION', 'FREEBUSY', 'ORGANIZER', 'UID', 'URL'), 'VALARM' => array('ACTION', 'ATTACH', 'ATTENDEE', 'DESCRIPTION', 'DURATION', 'REPEAT', 'SUMMARY', 'TRIGGER')); $actrow++; $comp = $subcomp = $actcomp = FALSE; $allowedComps = array('VEVENT', 'VTODO', 'VJOURNAL', 'VFREEBUSY'); for ($row = $actrow; $row < $cntrows; $row++) { if (empty($rows[$row]) || 1 >= count($rows[$row])) { continue; } if ($comp && $subcomp) { $comp->setComponent($subcomp); $subcomp = FALSE; } $compname = strtoupper($rows[$row][0]); if ($this->log) { $this->log->log("'{$compname}' START", PEAR_LOG_NOTICE); } if (in_array($compname, $allowedComps)) { if ($comp) { $calendar->setComponent($comp); } $comp = new $rows[$row][0](); $actcomp =& $comp; $cntprops += 1; } elseif ('VALARM' == $compname) { $subcomp = new valarm(); $actcomp =& $subcomp; } else { if ($this->log) { $this->log->log("skipped {$compname}", PEAR_LOG_WARNING); } continue; } foreach ($proporder as $propName => $col) { // insert all properties into component if (2 > $col || 'ORDER' == strtoupper($propName)) { continue; } $propName = strtoupper($propName); if ($this->log) { $this->log->log("{$compname} {$propName} START (col={$col})", PEAR_LOG_DEBUG); } if ('X-' != substr($propName, 0, 2) && !in_array($propName, $allowedProps[$compname])) { // check if allowed property for the component if ($this->log) { $this->log->log("skipped {$compname} {$propName}", PEAR_LOG_NOTICE); } continue; } if (isset($rows[$row][$col]) && !empty($rows[$row][$col]) || 'SEQUENCE' == $propName && '0' == $rows[$row][$col]) { $rows[$row][$col] = str_replace(array("\r\n", "\n\r", "\n", "\r"), $conf['nl'], $rows[$row][$col]); $value = FALSE !== strpos($rows[$row][$col], $conf['nl']) ? explode($conf['nl'], $rows[$row][$col]) : array($rows[$row][$col]); $ctests = array('://', 'fax:', 'cid:', 'sms:', 'tel:', 'urn:', 'crid:', 'news:', 'pres:', 'mailto:', 'MAILTO:'); foreach ($value as $val) { if (empty($val) && '0' != $val && 0 != $val) { continue; } if ('GEO' == $propName) { $parseval = FALSE !== strpos($val, ':') ? "GEO{$val}" : "GEO:{$val}"; if (FALSE === $actcomp->parse($parseval)) { if ($this->log) { $this->log->log("ERROR 11, INPUT FILE:'{$inputdirFile}' iCalcreator: parse error: '{$parseval}'", PEAR_LOG_ERR); } } } elseif ('REQUEST-STATUS' == $propName) { // 'REQUEST-STATUS' without any parameters.. . if (FALSE === $actcomp->parse("{$propName}:{$val}")) { if ($this->log) { $this->log->log("ERROR 12, INPUT FILE:'{$inputdirFile}' iCalcreator: parse error: '{$propName}:{$val}'", PEAR_LOG_ERR); } } } $cntm = $pos = 0; foreach ($ctests as $tst) { $cntm += substr_count($val, $tst); } $cntc = substr_count($val, ':'); $cntq = substr_count($val, '='); $cnts = substr_count($val, ';'); if (0 == $cntq && 0 == $cnts) { // no parameters $del = ':'; } elseif (1 == $cntc && $cntq + 1 == $cnts) { // parameters and colon $del = ';'; } elseif ($cntc == $cntm + 1) { $del = ';'; } else { $del = 1 > $cntm && 0 < $cntc ? ';' : ':'; } if ('X-' == substr($propName, 0, 2) || in_array($propName, array('CATEGORIES', 'COMMENT', 'CONTACT', 'DESCRIPTION', 'LOCATION', 'RESOURCES', 'SUMMARY'))) { $val = str_replace(',', '\\,', $val); if (FALSE !== ($pos = strpos($del . $val, ':'))) { while (FALSE !== ($pos2 = strpos($val, ';', $pos + 1))) { $val = substr($val, 0, $pos2) . '\\;' . substr($val, $pos2 + 1); if ($this->log) { $this->log->log("pos={$pos} pos2={$pos2} val='{$val}'", PEAR_LOG_DEBUG); } $pos = $pos2 + 1; } } } if (FALSE === $actcomp->parse("{$propName}{$del}{$val}")) { if ($this->log) { $this->log->log("ERROR 13, INPUT FILE:'{$inputdirFile}' iCalcreator: parse error: '{$propName}{$del}{$val}'", PEAR_LOG_ERR); } } elseif ($this->log) { $this->log->log("iCalcreator->parse( '{$propName}{$del}{$val}' )", PEAR_LOG_DEBUG); } } // end foreach( $value as $val } // end if( isset( $rows[$row][$col] } // end foreach( $proporder } // end for( $row = $actrow; if ($comp && $subcomp) { $comp->setComponent($subcomp); } if ($comp) { $calendar->setComponent($comp); } } $save = $this->getConfig('save'); if ($this->log) { $timeexec['exit'] = microtime(TRUE); $msg = "INPUT '{$inputdirFile}'"; $msg .= ' fileOk:' . number_format($timeexec['fileOk'] - $timeexec['start'], 5); $msg .= ' infoOk:' . number_format($timeexec['infoOk'] - $timeexec['fileOk'], 5); $msg .= ' zoneOk:' . number_format($timeexec['zoneOk'] - $timeexec['infoOk'], 5); $msg .= ' compOk:' . number_format($timeexec['exit'] - $timeexec['zoneOk'], 5); $msg .= ' total:' . number_format($timeexec['exit'] - $timeexec['start'], 5) . ' sec'; $this->log->log($msg, PEAR_LOG_DEBUG); $msg = "'{$inputdirFile}' (" . $cntprops . ' components) start:' . date('H:i:s', $timeexec['start']); $msg .= ' total:' . number_format($timeexec['exit'] - $timeexec['start'], 5) . ' sec'; if ($save) { $msg .= " -> '{$outputdirFile}'"; } $this->log->log($msg, PEAR_LOG_NOTICE); } /** return calendar, save or send the file */ if ($this->getConfig('outputobj')) { if ($this->log) { $this->log->log("INPUT FILE:'{$inputdirFile}' returning iCalcreator vcalendar instance", PEAR_LOG_NOTICE); $this->log->flush(); } return $calendar; exit; } $d = $calendar->getConfig('directory'); $f = $calendar->getConfig('filename'); $df = $d . DIRECTORY_SEPARATOR . $f; if ($save) { if (FALSE !== $calendar->saveCalendar()) { if ($this->log) { $this->log->log("INPUT FILE:'{$inputdirFile}' saved '{$df}'", PEAR_LOG_NOTICE); $this->log->flush(); } return TRUE; } else { // ?? if ($this->log) { $this->log->log("ERROR 16, INPUT FILE:'{$inputdirFile}' can't write to output file : '{$df}'", PEAR_LOG_ERR); $this->log->flush(); } return FALSE; } } else { if ($this->log) { $this->log->log("INPUT FILE:'{$inputdirFile}' returning : '{$f}'", PEAR_LOG_NOTICE); $this->log->flush(); } $output = $calendar->createCalendar(); $filesize = strlen($output); if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) { $output = gzencode($output, 9); $filesize = strlen($output); header('Content-Encoding: gzip'); header('Vary: *'); } header('Content-Type: text/calendar; charset=utf-8'); header("Content-Disposition: attachment; filename='{$f}'"); header('Cache-Control: max-age=10'); header('Content-Length: ' . $filesize); echo $output; } return TRUE; }
$e->setComponent($a); // add alarm component to event component as subcomponent $v->setComponent($e); // add event component to calendar /* alt. production */ // $v->returnCalendar(); // generate and redirect output to user browser /* alt. dev. and test */ $str = $v->createCalendar(); // generate and get output in string, for testing? echo $str; echo "<br />\n\n"; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* define timezone */ $v = new vcalendar(); // initiate new CALENDAR $t = new vtimezone(); // initiate TIMEZONE $t->setProperty('tzid', 'US-Eastern'); $t->setProperty('last-modified', 1987, 1, 1); $ts = new vtimezone('standard'); $ts->setProperty('dtstart', 1997, 10, 26, 2); $rdate1 = array('year' => 1997, 'month' => 10, 'day' => 26, 'hour' => 02, 'min' => 0, 'sec' => 0); $ts->setProperty('rdate', array($rdate1)); $ts->setProperty('tzoffsetfrom', '-0400'); $ts->setProperty('tzoffsetto', '-0500'); $ts->setProperty('tzname', 'EST'); $t->setComponent($ts); $td = new vtimezone('daylight'); $td->setProperty('dtstart', 1997, 10, 26, 2); $rdate1 = array('year' => 1997, 'month' => 4, 'day' => 6, 'hour' => 02, 'min' => 0, 'sec' => 0); $td->setProperty('rdate', array($rdate1));
/** * Prepare output in icalendar format a la RFC2445 * http://www.ietf.org/rfc/rfc2445.txt * * @return string */ public function icalendar() { $s = 'EJURI3ia8aj#912IKa'; $r = '#'; $e = 'aAEah38a;a33'; // ------------------------------------- // Some dummy tagdata we'll hand off to events() // ------------------------------------- $vars = array('event_title' => 'title', 'event_id' => 'id', 'event_summary' => 'summary', 'event_location' => 'location', 'event_start_date format="%Y"' => 'start_year', 'event_start_date format="%m"' => 'start_month', 'event_start_date format="%d"' => 'start_day', 'event_start_date format="%H"' => 'start_hour', 'event_start_date format="%i"' => 'start_minute', 'event_end_date format="%Y"' => 'end_year', 'event_end_date format="%m"' => 'end_month', 'event_end_date format="%d"' => 'end_day', 'event_end_date format="%H"' => 'end_hour', 'event_end_date format="%i"' => 'end_minute', 'event_calendar_tz_offset' => 'tz_offset', 'event_calendar_timezone' => 'timezone'); $rvars = array('rule_type', 'rule_start_date', 'rule_repeat_years', 'rule_repeat_months', 'rule_repeat_days', 'rule_repeat_weeks', 'rule_days_of_week', 'rule_relative_dow', 'rule_days_of_month', 'rule_months_of_year', 'rule_stop_by', 'rule_stop_after'); $evars = array('exception_start_date format="%Y%m%dT%H%i00"'); $ovars = array('occurrence_start_date format="%Y%m%dT%H%i00"', 'occurrence_end_date format="%Y%m%dT%H%i00"'); //ee()->TMPL->log_item('Calendar: Preparing tagdata'); $summary_field = ee()->TMPL->fetch_param('summary_field', 'event_title'); ee()->TMPL->tagdata = implode($s, array(LD . $summary_field . RD, LD . 'event_id' . RD, LD . 'if event_summary' . RD . LD . 'event_summary' . RD . LD . '/if' . RD, LD . 'if event_location' . RD . LD . 'event_location' . RD . LD . '/if' . RD, LD . 'event_start_date format="%Y"' . RD, LD . 'event_start_date format="%m"' . RD, LD . 'event_start_date format="%d"' . RD, LD . 'event_start_date format="%H"' . RD, LD . 'event_start_date format="%i"' . RD, LD . 'event_end_date format="%Y"' . RD, LD . 'event_end_date format="%m"' . RD, LD . 'event_end_date format="%d"' . RD, LD . 'event_end_date format="%H"' . RD, LD . 'event_end_date format="%i"' . RD, LD . 'event_calendar_tz_offset' . RD, LD . 'event_calendar_timezone' . RD, 'RULES' . LD . 'if event_has_rules' . RD . LD . 'rules' . RD . LD . implode(RD . $r . LD, $rvars) . RD . '|' . LD . T_SLASH . 'rules' . RD . LD . '/if' . RD, 'OCCURRENCES' . LD . 'if event_has_occurrences' . RD . LD . 'occurrences' . RD . LD . implode(RD . $r . LD, $ovars) . RD . '|' . LD . T_SLASH . 'occurrences' . RD . LD . '/if' . RD, 'EXCEPTIONS' . LD . 'if event_has_exceptions' . RD . LD . 'exceptions' . RD . LD . implode(RD . $r . LD, $evars) . RD . '|' . LD . T_SLASH . 'exceptions' . RD . LD . '/if' . RD, $e)); $tvars = ee()->functions->assign_variables(ee()->TMPL->tagdata); ee()->TMPL->var_single = $tvars['var_single']; ee()->TMPL->var_pair = $tvars['var_pair']; ee()->TMPL->tagdata = ee()->functions->prep_conditionals(ee()->TMPL->tagdata, array_keys($vars)); // ------------------------------------- // Fire up events() // ------------------------------------- //ee()->TMPL->log_item('Calendar: Firing up Events()'); $tagdata = ee()->TMPL->advanced_conditionals($this->events()); // ------------------------------------- // Collect the events // ------------------------------------- //ee()->TMPL->log_item('Calendar: Collecting events'); $events = explode($e, $tagdata); // ------------------------------------- // Fire up iCalCreator // ------------------------------------- //ee()->TMPL->log_item('Calendar: Starting iCalCreator'); if (!class_exists('vcalendar')) { require_once 'libraries/icalcreator/iCalcreator.class.php'; } $ICAL = new vcalendar(); //we are setting this manually because we need individual ones for each event for this to work //$ICAL->setConfig('unique_id', parse_url(ee()->config->item('site_url'), PHP_URL_HOST)); $host = parse_url(ee()->config->item('site_url'), PHP_URL_HOST); $vars = array_values($vars); //ee()->TMPL->log_item('Calendar: Iterating through the events'); foreach ($events as $key => $event) { if (trim($event) == '') { continue; } $E = new vevent(); $event = explode($s, $event); $rules = ''; $occurrences = ''; $exceptions = ''; foreach ($event as $k => $v) { if (isset($vars[$k])) { //-------------------------------------------- // Makes the local vars from above, if available: // $title, $summary, $location, // $start_year, $start_month, $start_day, // $start_hour, $start_minute, $end_year, // $end_month, $end_day, $end_hour, // $end_minute, $tz_offset, $timezone //-------------------------------------------- ${$vars}[$k] = $v; } elseif (substr($v, 0, 5) == 'RULES') { $rules = substr($v, 5); } elseif (substr($v, 0, 11) == 'OCCURRENCES') { $occurrences = substr($v, 11); } elseif (substr($v, 0, 10) == 'EXCEPTIONS') { $exceptions = substr($v, 10); } } // ------------------------------------- // Set the timezone for this calendar based on the first event's info // ------------------------------------- if ($key == 0) { // ------------------------------------- // Convert calendar_name to calendar_id // ------------------------------------- if ($this->P->value('calendar_id') == '' and $this->P->value('calendar_name') != '') { $ids = $this->data->get_calendar_id_from_name($this->P->value('calendar_name'), NULL, $this->P->params['calendar_name']['details']['not']); $this->P->set('calendar_id', implode('|', $ids)); } //-------------------------------------------- // lets try to get the timezone from the // passed calendar ID if there is one //-------------------------------------------- $cal_timezone = FALSE; $cal_tz_offset = FALSE; if ($this->P->value('calendar_id') != '') { $sql = "SELECT \ttz_offset, timezone\n\t\t\t\t\t\t\tFROM\texp_calendar_calendars\n\t\t\t\t\t\t\tWHERE \tcalendar_id\n\t\t\t\t\t\t\tIN \t\t(" . ee()->db->escape_str(implode(',', explode('|', $this->P->value('calendar_id')))) . ")\n\t\t\t\t\t\t\tLIMIT\t1"; $cal_tz_query = ee()->db->query($sql); if ($cal_tz_query->num_rows() > 0) { $cal_timezone = $cal_tz_query->row('timezone'); $cal_tz_offset = $cal_tz_query->row('tz_offset'); } } //last resort, we get it from the current event $T = new vtimezone(); $T->setProperty('tzid', $cal_timezone ? $cal_timezone : $timezone); $T->setProperty('tzoffsetfrom', '+0000'); $tzoffsetto = $cal_tz_offset ? $cal_tz_offset : $tz_offset; if ($tzoffsetto === '0000') { $tzoffsetto = '+0000'; } $T->setProperty('tzoffsetto', $tzoffsetto); $ICAL->setComponent($T); } $title = strip_tags($title); $description = strip_tags(trim($summary)); $location = strip_tags(trim($location)); // ------------------------------------- // Occurrences? // ------------------------------------- $occurrences = explode('|', rtrim($occurrences, '|')); $odata = array(); foreach ($occurrences as $k => $occ) { $occ = trim($occ); if ($occ == '') { continue; } $occ = explode($r, $occ); $odata[$k][] = $occ[0]; $odata[$k][] = $occ[1]; } // ------------------------------------- // Exceptions? // ------------------------------------- $exceptions = explode('|', rtrim($exceptions, '|')); $exdata = array(); foreach ($exceptions as $k => $exc) { $exc = trim($exc); if ($exc == '') { continue; } $exdata[] = $exc; } // ------------------------------------- // Rules? // ------------------------------------- $add_rules = FALSE; $erules = array(); $rules = explode('|', rtrim($rules, '|')); foreach ($rules as $rule) { $temp = explode($r, $rule); $rule = array(); foreach ($temp as $k => $v) { if ($v != FALSE) { $add_rules = TRUE; } $rule[substr($rvars[$k], 5)] = $v; } if ($add_rules === TRUE) { $temp = array(); if ($rule['repeat_years'] > 0) { $temp['FREQ'] = 'YEARLY'; if ($rule['repeat_years'] > 1) { $temp['INTERVAL'] = $rule['repeat_years']; } } elseif ($rule['repeat_months'] > 0) { $temp['FREQ'] = 'MONTHLY'; if ($rule['repeat_months'] > 1) { $temp['INTERVAL'] = $rule['repeat_months']; } } elseif ($rule['repeat_weeks'] > 0) { $temp['FREQ'] = 'WEEKLY'; if ($rule['repeat_weeks'] > 1) { $temp['INTERVAL'] = $rule['repeat_weeks']; } } elseif ($rule['repeat_days'] > 0) { $temp['FREQ'] = 'DAILY'; if ($rule['repeat_days'] > 1) { $temp['INTERVAL'] = $rule['repeat_days']; } } if ($rule['months_of_year'] > 0) { //this flips keys to make 'c' => 12, etc $m = array_flip(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C')); if (strlen($rule['months_of_year'] > 1)) { $months = str_split($rule['months_of_year']); foreach ($months as $month) { $temp['BYMONTH'][] = $m[$month] + 1; } } else { $temp['BYMONTH'] = $m[$month] + 1; } } if ($rule['days_of_month'] > '') { //this flips keys to make 'v' => 30, etc $d = array_flip(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V')); if (strlen($rule['days_of_month']) > 1) { $days = str_split($rule['days_of_month']); foreach ($days as $day) { $temp['BYMONTHDAY'][] = $d[$day] + 1; } } else { $temp['BYMONTHDAY'] = $d[$rule['days_of_month']] + 1; } } if ($rule['days_of_week'] != '' or $rule['days_of_week'] > 0) { $d = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'); $d_letter = array('U', 'M', 'T', 'W', 'R', 'F', 'S'); $dows = str_split($rule['days_of_week']); if ($rule['relative_dow'] > 0) { $rels = str_split($rule['relative_dow']); foreach ($dows as $dow) { foreach ($rels as $rel) { if ($rel == 6) { $rel = -1; } $temp['BYDAY'][] = $rel . $d[array_search($dow, $d_letter)]; } } } else { foreach ($dows as $dow) { $temp['BYDAY'][] = $d[array_search($dow, $d_letter)]; } } } if ($rule['stop_after'] > 0) { $temp['COUNT'] = $rule['stop_after']; } elseif ($rule['stop_by'] > 0) { // TODO: Add time // TODO: The "+1" below is because the ical standard treats // UNTIL as "less than", not "less than or equal to" (which // is how Calendar treats stop_by). Double check that a simple // "+1" accurately addresses this difference. $temp['UNTIL'] = $rule['stop_by'] + 1; } $erules[] = $temp; } } // ------------------------------------- // Put it together // ------------------------------------- //if this is all day we need to add the dates as params to the dstart and end items if ($this->_is_all_day($start_hour, $start_minute, $end_hour, $end_minute)) { $E->setProperty("dtstart", array('year' => $start_year, 'month' => $start_month, 'day' => $start_day), array('VALUE' => 'DATE')); //-------------------------------------------- // we need CDT so we can add a day // gcal, and ical are ok with this being the same day // stupid damned outlook barfs, hence the +1 // the +1 doesnt affect g/ical //-------------------------------------------- if (!isset($this->CDT) or !is_object($this->CDT)) { $this->load_calendar_datetime(); } $this->CDT->change_date($end_year, $end_month, $end_day); $this->CDT->add_day(); $E->setProperty("dtend", array('year' => $this->CDT->year, 'month' => $this->CDT->month, 'day' => $this->CDT->day), array('VALUE' => 'DATE')); } else { $E->setProperty('dtstart', $start_year, $start_month, $start_day, $start_hour, $start_minute, 00); $E->setProperty('dtend', $end_year, $end_month, $end_day, $end_hour, $end_minute, 00); } $E->setProperty('summary', $title); if (!empty($erules)) { foreach ($erules as $rule) { $E->setProperty('rrule', $rule); } } $extras = array(); $edits = array(); if (!empty($odata)) { $query = ee()->db->query("SELECT *\n\t\t\t\t\t FROM\texp_calendar_events_occurrences\n\t\t\t\t\t WHERE\tevent_id = " . ee()->db->escape_str($id)); foreach ($query->result_array() as $row) { //fix blank times $row['start_time'] = $row['start_time'] == 0 ? '0000' : $row['start_time']; $row['end_time'] = $row['end_time'] == 0 ? '2400' : $row['end_time']; //looks like an edited occurrence //edits without rules arent really edits. if ($row['event_id'] != $row['entry_id'] and empty($rules)) { $edits[] = $row; } else { $extras[] = $row; } } } if (!empty($exdata)) { $E->setProperty('exdate', $exdata); } if ($description != '') { $E->setProperty('description', $description); } if ($location != '') { $E->setProperty('location', $location); } $E->setProperty("uid", $this->make_uid() . '@' . $host); $ICAL->setComponent($E); //-------------------------------------------- // remove rules for subsequent items //-------------------------------------------- while ($E->deleteProperty("RRULE")) { continue; } //edits must come right after if (!empty($edits)) { foreach ($edits as $edit) { $edit_date = array("year" => $edit['start_year'], "month" => $edit['start_month'], "day" => $edit['start_day'], "hour" => substr($edit['start_time'], 0, 2), "min" => substr($edit['start_time'], 2, 2)); //if this is all day we need to add the dates as params to the dstart and end items if ($this->_is_all_day(substr($edit['start_time'], 0, 2), substr($edit['start_time'], 2, 2), substr($edit['end_time'], 0, 2), substr($edit['end_time'], 2, 2))) { $E->setProperty("dtstart", array('year' => $edit['start_year'], 'month' => $edit['start_month'], 'day' => $edit['start_day']), array('VALUE' => 'DATE')); //-------------------------------------------- // we need CDT so we can add a day // gcal, and ical are ok with this being the same day // stupid damned outlook barfs, hence the +1 // the +1 doesnt affect g/ical //-------------------------------------------- if (!isset($this->CDT) or !is_object($this->CDT)) { $this->load_calendar_datetime(); } $this->CDT->change_date($edit['end_year'], $edit['end_month'], $edit['end_day']); $this->CDT->add_day(); $E->setProperty("dtend", array('year' => $this->CDT->year, 'month' => $this->CDT->month, 'day' => $this->CDT->day), array('VALUE' => 'DATE')); } else { $E->setProperty('dtstart', $edit_date['year'], $edit_date['month'], $edit_date['day'], $edit_date['hour'], $edit_date['min'], 00); $E->setProperty('dtend', $edit['end_year'], $edit['end_month'], $edit['end_day'], substr($edit['end_time'], 0, 2), substr($edit['end_time'], 2, 2), 00); } $E->setProperty("RECURRENCE-ID", $edit_date); $E->setProperty("uid", $this->make_uid() . '@' . $host); $ICAL->setComponent($E); } //cleanup $E->deleteProperty("RECURRENCE-ID"); $E->setProperty('dtstart', $start_year, $start_month, $start_day, $start_hour, $start_minute, 00); $E->setProperty('dtend', $end_year, $end_month, $end_day, $end_hour, $end_minute, 00); } // these random ass add-in dates are non-standard to most cal creation // and need to be treated seperately as lumping don't work, dog if (!empty($extras)) { foreach ($extras as $extra) { //if this is all day we need to add the dates as params to the dstart and end items if ($this->_is_all_day(substr($extra['start_time'], 0, 2), substr($extra['start_time'], 2, 2), substr($extra['end_time'], 0, 2), substr($extra['end_time'], 2, 2))) { $E->setProperty("dtstart", array('year' => $extra['start_year'], 'month' => $extra['start_month'], 'day' => $extra['start_day']), array('VALUE' => 'DATE')); //-------------------------------------------- // we need CDT so we can add a day // gcal, and ical are ok with this being the same day // stupid damned outlook barfs, hence the +1 // the +1 doesnt affect g/ical //-------------------------------------------- if (!isset($this->CDT) or !is_object($this->CDT)) { $this->load_calendar_datetime(); } $this->CDT->change_date($extra['end_year'], $extra['end_month'], $extra['end_day']); $this->CDT->add_day(); $E->setProperty("dtend", array('year' => $this->CDT->year, 'month' => $this->CDT->month, 'day' => $this->CDT->day), array('VALUE' => 'DATE')); } else { $E->setProperty('dtstart', $extra['start_year'], $extra['start_month'], $extra['start_day'], substr($extra['start_time'], 0, 2), substr($extra['start_time'], 2, 2), 00); $E->setProperty('dtend', $extra['end_year'], $extra['end_month'], $extra['end_day'], substr($extra['end_time'], 0, 2), substr($extra['end_time'], 2, 2), 00); } $E->setProperty("uid", $this->make_uid() . '@' . $host); $ICAL->setComponent($E); } //clean in case we need to add more later $E->setProperty('dtstart', $start_year, $start_month, $start_day, $start_hour, $start_minute, 00); $E->setProperty('dtend', $end_year, $end_month, $end_day, $end_hour, $end_minute, 00); } } //return $ICAL->createCalendar(); return $ICAL->returnCalendar(); }
$tsY = date('Y', $ts); $tsm = date('m', $ts); $tsd = date('d', $ts); $tsH = date('H', $ts); $tsi = date('i', $ts); $tss = date('s', $ts); require_once 'inc/iCalcreator.class.php'; /* new vcalendar with name of the timezone, name of the calendar */ $v = new vcalendar(); $v->setProperty("method", "PUBLISH"); $v->setProperty('X-WR-TIMEZONE', 'Europe/Berlin'); $v->setProperty("x-wr-calname", "Filmstarts Deutschland"); $v->setProperty("calscale", "GREGORIAN"); //$v->setConfig( "filename", "filmstarts_de.ics" ); /* define timezone */ $timezone = new vtimezone(); $timezone->setProperty("Tzid", "Europe/Berlin"); /* $timezonedaylight = new vtimezone( "daylight" ); $timezonedaylight->setProperty( "tzoffsetfrom", "+0100" ); $timezonedaylight->setProperty('dtstart', 2006, 8, 11, 7, 30, 1); $timezonedaylight->setProperty( "tzname", "GMT+02:00" ); $timezonedaylight->setProperty( "tzoffsetto", "+0200" ); $timezonedaylight->setProperty( "rrule", array("freq" => "YEARLY", "bymonth" => 3, "byday" => array( array(-1, "DAY" => "SU" ))) ); */ $timezonestandard = new vtimezone("standard"); $timezonestandard->setProperty("tzoffsetfrom", "+0200"); $timezonestandard->setProperty('dtstart', 2006, 8, 11, 7, 30, 1); $timezonestandard->setProperty("tzname", "GMT+01:00"); $timezonestandard->setProperty("tzoffsetto", "+0100"); $timezonestandard->setProperty("rrule", array("freq" => "YEARLY", "bymonth" => 10, "byday" => array(array(-1, "DAY" => "SU"))));
/** * Save client event * @param web request $request */ public function executeUpdateEvent($request) { $sf_user = $this->getUser(); $sf_user_id = $sf_user->getGuardUser()->getId(); $client_id = $request->getParameter('id'); $client_profile = ProfilePeer::retrieveByPK($client_id); $sfguard_user_profile = $sf_user->getProfile(); $sfguard_fullname = $sfguard_user_profile->getFullname(); $sfguard_email = $sfguard_user_profile->getEmail(); $start_hour = $request->getParameter('start_hour'); $start_min = $request->getParameter('start_min'); $time_mode = $request->getParameter('start_mn'); $client_branch_id = BranchUsersPeer::getUserBranchId($client_profile->getUserId()); $hour = sfConfig::get('mod_client_outlook_shour'); $sc_hour = sfConfig::get('mod_client_secondhalf_shhour'); if ($request->isMethod('post')) { $event_id = $this->getRequestParameter('event_id'); $event_details = ''; if ($event_id) { $event_details = pmProjectObjectsPeer::retrieveByPK($event_id); $this->form = new ClientEventForm($event_details); } else { $this->form = new ClientEventForm(); } $event_data = $request->getParameter('pm_project_objects'); if ($time_mode == 'AM') { $start_hour_value = $start_hour == 11 ? '00' : $hour[$start_hour]; $date_field_1 = $event_data['date_field_1'] . ' ' . $start_hour_value . ':' . $start_min . ':00'; } elseif ($time_mode == 'PM') { $start_hour_value = $start_hour == 11 ? $hour[$start_hour] : $sc_hour[$start_hour]; $date_field_1 = $event_data['date_field_1'] . ' ' . $start_hour_value . ':' . $start_min . ':00'; } $event_data['module'] = 'client event'; $event_data['tree_left'] = $client_branch_id; $event_data['tree_right'] = $sf_user_id; $event_data['integer_field_2'] = $client_id; $event_data['date_field_1'] = $date_field_1; $event_data['contract_id'] = $request->getParameter('contract_id'); $event_data['created_by_id'] = $sf_user_id; $event_data['updated_by_id'] = $sf_user_id; $this->form->bind($event_data); if ($this->form->isValid()) { $client_event = $this->form->save(); $client_event->setParentId($client_event->getId()); $client_event->setUpdatedAt($date_field_1); $client_event->save(); // create instance of event class and add client event in event table $event = ''; $c = new Criteria(); $c->add(EventPeer::CEVENT_ID, $event_id); $event = EventPeer::doSelectOne($c); if (!$event) { $event = new Event(); } $event_start_date = $client_event->getDateField1(); $client_full_name = $client_profile->getFname() . ' ' . $client_profile->getLname(); $event->setUserId($client_profile->getUserId()); $event->setSubject($client_full_name . ': ' . $client_event->getName() . ': ' . $client_event->getBody()); $event->setBody($client_event->getName() . ': ' . $client_event->getBody()); $event->setEventType('client event'); $event->setStartTime($date_field_1); $event->setEndTime($date_field_1); $event->setCeventId($client_event->getId()); $event->setCalendarId(calendarsPeer::getCalendarIdByUserId($sf_user_id)); $event->save(); $ical = $this->getICalData($event); $event->setUri($ical->filename); $event->setIcsData($ical->createCalendar()); $event->setCreatedById($sf_user_id); $event->save(); $events = $event; if ($time_mode == 'PM') { $hour = sfConfig::get('mod_client_outlook_shour'); } else { $hour = sfConfig::get('mod_client_outlook_shour'); } $start_time = strtotime($event_start_date); $end_time = strtotime($event_start_date); $hour_start = $hour[$start_hour]; //set default 9:00am $minute_start = $start_min; $end_hr = $start_min; // star time $start = array('year' => date('Y', $start_time), 'month' => date('m', $start_time), 'day' => date('d', $start_time), 'hour' => $hour_start, 'min' => $minute_start, 'sec' => date('s', $start_time)); $outlook_start = date('d-m-Y', $start_time); $metting_start_time = $hour_start . ':' . $minute_start . ':' . '00'; $mode = $time_mode == 'PM' ? ' PM' : ' AM'; $metting_start_time = $metting_start_time . $mode; sfConfig::set('sf_web_debug', false); $description = get_partial('message_data', array()); $sender = str_replace('sender', "{$client_full_name}", $description); $topic = str_replace('topic', "{$client_event->getName()}", $sender); $time = str_replace('start', "{$outlook_start}", $topic); $s_t = str_replace('s_t', "{$metting_start_time}", $time); $place = str_replace('place', "{$client_event->getVarcharField1()}", $s_t); $subject = str_replace('subject', "{$client_event->getBody()}", $place); $involved_user = $client_event->getContractId(); $c = new Criteria(); $c->add(ProfilePeer::USER_ID, $involved_user); $involved_user_profile = ProfilePeer::doSelectOne($c); $organizer = $involved_user_profile->getEmail(); if ($time_mode == 'PM') { $outlook_hour = sfConfig::get('mod_client_soutlook_dhour'); } else { $outlook_hour = sfConfig::get('mod_client_secoutlook_sechour'); } $time_start = array('year' => date('Y', $start_time), 'month' => date('m', $start_time), 'day' => date('d', $start_time), 'hour' => $outlook_hour[$hour_start], 'min' => $minute_start, 'sec' => date('s', $start_time)); $v_event = new vevent(); $v_event->setProperty("organizer", 'MAILTO:' . $organizer); //$v_event->setProperty("recurrence-id", $start); $v_event->setProperty('uid', md5($events->getId())); $v_event->setProperty('dtstamp', $events->getCreatedAt()); $v_event->setProperty('dtstart', $time_start); $v_event->setProperty('location', $client_event->getVarcharField1()); $v_event->setProperty('dtend', $time_start); $v_event->setProperty('summary', $events->getSubject()); $v_event->setProperty('description', $subject); $v_event->setProperty("status", "CONFIRMED"); $v_timezone = new vtimezone(); $v_timezone->setProperty("tzid", "Pacific/Auckland"); $v_event->setComponent($v_timezone); $cal_events[] = $v_event; $v_alarm = new valarm(); $v_alarm->setProperty('trigger', 'PT15M'); $v_alarm->setProperty('action', 'display'); $v_alarm->setProperty('Description', "Reminder: " . $subject); $v_event->setComponent($v_alarm); $calendar_events = $cal_events; $config = array('unique_id' => 'ravebuild.com'); $v_calendar = new vcalendar(); $v_calendar->setProperty("method", "REQUEST"); $mail_data = $this->setIcalEvents($v_calendar, $calendar_events); $all_events = $v_calendar->createCalendar(); $send_mail = new mailSend(); $send_mail->sendInvitationToUser($organizer, null, $all_events); $event_type = $event_id ? 'updated' : 'added'; $modification_message = $event_id ? 'Update Client Event' : 'Add Client Event'; $client_user_id = $client_profile->getUserId(); $this->saveHistory($modification_message, $client_user_id); $sf_user->setFlash('notice', 'The Event "' . $client_event->getBody() . '" has been ' . $event_type . ' successfully.'); $this->redirect($request->getReferer()); } } }