create formatted output for calendar component VFREEBUSY object instance

@author Kjell-Inge Gustafsson <ical@kigkonsult.se>
@since 2.3.1 - 2007-11-19
@param array $xcaldecl
@return string
971825
function createComponent( &$xcaldecl ) {
    $objectname = $this->_createFormat();
    $component  = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
    $component .= $this->createUid();
    $component .= $this->createDtstamp();
    $component .= $this->createAttendee();
    $component .= $this->createComment();
    $component .= $this->createContact();
    $component .= $this->createDtend();
    $component .= $this->createDtstart();
    $component .= $this->createDuration();
    $component .= $this->createFreebusy();
    $component .= $this->createOrganizer();
    $component .= $this->createRequestStatus();
    $component .= $this->createUrl();
    $component .= $this->createXprop();
    $component .= $this->componentEnd1.$objectname.$this->componentEnd2;
    if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
      foreach( $this->xcaldecl as $localxcaldecl )
        $xcaldecl[] = $localxcaldecl;
    }
    return $component;
  }
1340903
private function writeCalendar(array $events)
    {
        $date = new \Datetime();
        $tz = $date->getTimezone();

        return $this->container->get('templating')->render(
            'ClarolineAgendaBundle:tool:export_ics_calendar.ics.twig',
            [
                'tzName' => $tz->getName(),
                'events' => $events,
            ]
        );
    }
1200819
private static function parseCompexDecl($decl) {
        $left = null;
        $right = null;
        $combinator = '';
        if (substr($decl, 0, 1) === '(') {
            $regex = '(^(\(((?>[^()]+)|(?1))*\)))';
            $match = [];
            if (preg_match($regex, $decl, $match)) {
                $sub = (string) $match[0];
                $left = self::fromDecl(substr($sub, 1, -1));
                if ($sub === $decl) {
                    return $left;
                }
                $decl = substr($decl, strlen($sub));
            } else {
                throw new \RuntimeException("Unmatched braces?");
            }
            if (!in_array(substr($decl, 0, 1), ['|', '&'])) {
                throw new \RuntimeException("Unknown position of combinator: $decl");
            }
            $right = self::fromDecl(substr($decl, 1));
            $combinator = substr($decl, 0, 1);
        } else {
            $orPos = strpos($decl, '|');
            $andPos = strpos($decl, '&');
            $pos = 0;
            if ($orPos === false && $andPos !== false) {
                $pos = $andPos;
            } elseif ($orPos !== false && $andPos === false) {
                $pos = $orPos;
            } elseif ($orPos !== false && $andPos !== false) {
                $pos = min($orPos, $andPos);
            } else {
                throw new \RuntimeException("No combinator found: $decl");
            }
            if ($pos === 0) {
                throw new \RuntimeException("Unknown position of combinator: $decl");
            }
            $left = self::fromDecl(substr($decl, 0, $pos));
            $right = self::fromDecl(substr($decl, $pos + 1));
            $combinator = substr($decl, $pos, 1);
        }
        if ($combinator === '|') {
            return new Type(Type::TYPE_UNION, [$left, $right]);
        } elseif ($combinator === '&') {
            return new Type(Type::TYPE_INTERSECTION, [$left, $right]);
        }
        throw new \RuntimeException("Unknown combinator $combinator");
    }
407898
private function createMessage(): string
    {
        $message = '';
        foreach (libxml_get_errors() as $error) {
            $message .= trim($error->message) . (($error->file) ? (' in file ' . $error->file) : ('')) . ' on line ' . $error->line . ' in column ' . $error->column . "\n";
        }

        libxml_clear_errors();
        if (strlen($message) === 0) {
            return 'Transformation failed: unknown error.';
        }

        return $message;
    }
434958
public function render($output = true)
    {
        //Add header
        $ics = 'BEGIN:VCALENDAR
METHOD:PUBLISH
VERSION:2.0
X-WR-CALNAME:' . $this->calendarName . '
PRODID:-//hacksw/handcal//NONSGML v1.0//EN';

        //Add events
        foreach ($this->events as $event) {
            $ics .= '
BEGIN:VEVENT
UID:' . $event['uid'] . '
DTSTAMP:' . gmdate('Ymd') . 'T' . gmdate('His') . 'Z
DTSTART:' . $event['start'] . '
DTEND:' . $event['end'] . '
SUMMARY:' . str_replace("\n", "\\n", $event['summary']) . '
DESCRIPTION:' . str_replace("\n", "\\n", $event['description']) . '
URL;VALUE=URI:' . $event['url'] . '
END:VEVENT';
        }

        //Add footer
        $ics .= '
END:VCALENDAR';

        if ($output) {
            //Output
            $filename = $this->calendarName;
            //Filename needs quoting if it contains spaces
            if (strpos($filename, ' ') !== false) {
                $filename = '"'.$filename.'"';
            }
            header('Content-type: text/calendar; charset=utf-8');
            header('Content-Disposition: inline; filename=' . $filename . '.ics');
            echo $ics;
        }
        return $ics;
    }
1085033
public static function builtInFormatCode($pIndex)
	{
		// Clean parameter
		$pIndex = intval($pIndex);

		// Ensure built-in format codes are available
		self::fillBuiltInFormatCodes();

		// Lookup format code
		if (isset(self::$_builtInFormats[$pIndex])) {
			return self::$_builtInFormats[$pIndex];
		}

		return '';
	}
24903
public static function fromDecl($decl) {
        if ($decl instanceof Type) {
            return $decl;
        } elseif (!is_string($decl)) {
            throw new \LogicException("Should never happen");
        } elseif (empty($decl)) {
            throw new \RuntimeException("Empty declaration found");
        }
        if ($decl[0] === '\\') {
            $decl = substr($decl, 1);
        } elseif ($decl[0] === '?') {
            $decl = substr($decl, 1);
            $type = Type::fromDecl($decl);
            return (new Type(Type::TYPE_UNION, [
                $type,
                new Type(Type::TYPE_NULL)
            ]))->simplify();
        }
        switch (strtolower($decl)) {
            case 'boolean':
            case 'bool':
            case 'false':
            case 'true':
                return new Type(Type::TYPE_BOOLEAN);
            case 'integer':
            case 'int':
                return new Type(Type::TYPE_LONG);
            case 'double':
            case 'real':
            case 'float':
                return new Type(Type::TYPE_DOUBLE);
            case 'string':
                return new Type(Type::TYPE_STRING);
            case 'array':
                return new Type(Type::TYPE_ARRAY);
            case 'callable':
                return new Type(Type::TYPE_CALLABLE);
            case 'null':
            case 'void':
                return new Type(Type::TYPE_NULL);
            case 'numeric':
                return Type::fromDecl('int|float');
        }
        // TODO: parse | and & and ()
        if (strpos($decl, '|') !== false || strpos($decl, '&') !== false || strpos($decl, '(') !== false) {
            return self::parseCompexDecl($decl)->simplify();
        }
        if (substr($decl, -2) === '[]') {
            $type = Type::fromDecl(substr($decl, 0, -2));
            return new Type(Type::TYPE_ARRAY, [$type]);
        }
        $regex = '(^([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\\\)*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$)';
        if (!preg_match($regex, $decl)) {
            throw new \RuntimeException("Unknown type declaration found: $decl");
        }
        return new Type(Type::TYPE_OBJECT, [], $decl);
    }
739846
protected static function objectOutput(\stdClass $object, \DOMDocument $dom, \DOMElement $parentUL)
    {
        foreach($object as $k=>$v)
        {
            $li = $dom->createElement('li');
            $parentUL->appendChild($li);
            $strong = $dom->createElement('strong', $k);
            $li->appendChild($strong);
            if ($v instanceof \stdClass)
            {
                $ul = $dom->createElement('ul');
                $li->appendChild($ul);
                self::objectOutput($v, $dom, $ul);
            }
            else if (is_array($v))
            {
                $ul = $dom->createElement('ul');
                $li->appendChild($ul);
                self::arrayOutput($v, $dom, $ul);
            }
            else if (is_bool($v))
            {
                switch($v)
                {
                    case true: $li->appendChild($dom->createTextNode(' TRUE')); break;
                    case false: $li->appendChild($dom->createTextNode(' FALSE')); break;
                }
            }
            else if (is_scalar($v))
            {
                $span = $dom->createElement('span');
                $span->appendChild($dom->createTextNode(' '.strval($v)));
                $li->appendChild($span);
            }
        }
        return $dom;
    }
1195180
protected function getDatePatternFormatter($datetype, $timetype, $calendar = \IntlDateFormatter::GREGORIAN)
    {
        return \IntlDateFormatter::create(
            \Locale::getDefault(),
            is_int($datetype) ? $datetype : \IntlDateFormatter::NONE,
            is_int($timetype) ? $timetype : \IntlDateFormatter::NONE,
            \IntlTimeZone::getGMT(),
            $calendar
        );
    }
5845
private function _serializeCallback( $callback )
    {
        $retVal = $callback;

        if ( is_array( $callback ) && 2 === count( $callback ) )
        {
            $retVal = get_class( $callback[ 0 ] ) . '/' . $callback[ 1 ];
        }

        return $retVal;
    }
1118358
private function serializeComponents(array $components): string
    {
        return implode('|', array_map(function ($name, $value) {
            return sprintf('%s:%s', $name, $value);
        }, array_keys($components), $components));
    }
1002243
public static function _printCallback($callback)
    {
        if (is_array($callback)) {
            if (is_object($callback[0])) {
                $className = get_class($callback[0]);
            } else {
                $className = strval($callback[0]);
            }
            $functionName = $className . '::' . strval($callback[1]);
        }
        else {
            $functionName = strval($callback);
        }
        return $functionName;
    }
723486
public function export($doImmediateOutput = false){
        //setup exporter
        $calendarExport = new CalendarExport(new CalendarStream, new Formatter());
        $calendarExport->addCalendar($this);

        //set exporter to send items directly to output instead of storing in memory
        $calendarExport->getStreamObject()->setDoImmediateOutput($doImmediateOutput);

        //output .ics formatted text
        return $calendarExport->getStream();
    }
754730
public function getHolidayListInICalendarFormat(HolidayList $holidayList, TranslatorInterface $translator = null, DateHelper $dateHelper = null)
    {
        $calendarFormatter = new ICalendarFormatter($translator, $dateHelper);
        $content = [];
        $content[] = $calendarFormatter->getHeader();
        $content = array_merge($content, $calendarFormatter->formatList($holidayList));
        $content[] = $calendarFormatter->getFooter();

        return implode(ICalendarFormatter::LINE_ENDING, $content).ICalendarFormatter::LINE_ENDING;
    }
1229376
function _createFormat() {
    $objectname                   = null;
    switch( $this->format ) {
      case 'xcal':
        $objectname               = ( isset( $this->timezonetype )) ?
                                 strtolower( $this->timezonetype )  :  strtolower( $this->objName );
        $this->componentStart1    = $this->elementStart1 = '<';
        $this->componentStart2    = $this->elementStart2 = '>';
        $this->componentEnd1      = $this->elementEnd1   = '</';
        $this->componentEnd2      = $this->elementEnd2   = '>'.$this->nl;
        $this->intAttrDelimiter   = '<!-- -->';
        $this->attributeDelimiter = $this->nl;
        $this->valueInit          = null;
        break;
      default:
        $objectname               = ( isset( $this->timezonetype )) ?
                                 strtoupper( $this->timezonetype )  :  strtoupper( $this->objName );
        $this->componentStart1    = 'BEGIN:';
        $this->componentStart2    = null;
        $this->componentEnd1      = 'END:';
        $this->componentEnd2      = $this->nl;
        $this->elementStart1      = null;
        $this->elementStart2      = null;
        $this->elementEnd1        = null;
        $this->elementEnd2        = $this->nl;
        $this->intAttrDelimiter   = '<!-- -->';
        $this->attributeDelimiter = ';';
        $this->valueInit          = ':';
        break;
    }
    return $objectname;
  }
129335
protected function getFormatterDay($locale) {
		if (! isset($this->formattersDay[$locale])) {
			$this->formattersDay[$locale] = new IntlDateFormatter($locale, IntlDateFormatter::MEDIUM, IntlDateFormatter::NONE);
		}
		
		return $this->formattersDay[$locale];
	}
580662
public function getOutput() {
    	$this->lines = array();
    
		$this->addLine('BEGIN:VCALENDAR');
		$this->addLine('VERSION:2.0');
    	
		if( is_null($this->prodid) ) {
			$this->addLine("PRODID:" . '-//'.$this->host.'//NONSGML v1.0//EN');
		} 
		elseif( !is_null($this->prodid) ) {
			$this->addLine("PRODID:" . $this->prodid);
		}
		
    	$upcomingEvents = $this->calendar->UpcomingEvents($this->limit); /* @var $upcomingEvents DataObjectSet */
    	foreach($upcomingEvents as $dateTime) { /* @var $event CalendarDateTime */
    		$this->addDateTime($dateTime);
    	}
    	
		$this->addLine('END:VCALENDAR');
		
		return implode("\r\n", $this->lines);
    }