Your IP : 216.73.216.240


Current Path : /home/juvelize/saulnois/libraries/ic_library/Vendor/Icalcreator/src/Traits/
Upload File :
Current File : /home/juvelize/saulnois/libraries/ic_library/Vendor/Icalcreator/src/Traits/TRIGGERtrait.php

<?php
/**
 * iCalcreator, the PHP class package managing iCal (rfc2445/rfc5445) calendar information.
 *
 * This file is a part of iCalcreator.
 *
 * @author    Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
 * @copyright 2007-2024 Kjell-Inge Gustafsson, kigkonsult AB, All rights reserved
 * @link      https://kigkonsult.se
 * @license   Subject matter of licence is the software iCalcreator.
 *            The above copyright, link, package and version notices,
 *            this licence notice and the invariant [rfc5545] PRODID result use
 *            as implemented and invoked in iCalcreator shall be included in
 *            all copies or substantial portions of the iCalcreator.
 *
 *            iCalcreator is free software: you can redistribute it and/or modify
 *            it under the terms of the GNU Lesser General Public License as
 *            published by the Free Software Foundation, either version 3 of
 *            the License, or (at your option) any later version.
 *
 *            iCalcreator is distributed in the hope that it will be useful,
 *            but WITHOUT ANY WARRANTY; without even the implied warranty of
 *            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *            GNU Lesser General Public License for more details.
 *
 *            You should have received a copy of the GNU Lesser General Public License
 *            along with iCalcreator. If not, see <https://www.gnu.org/licenses/>.
 */
declare( strict_types = 1 );
namespace Kigkonsult\Icalcreator\Traits;

use DateTimeInterface;
use DateInterval;
use Exception;
use InvalidArgumentException;
use Kigkonsult\Icalcreator\Formatter\Property\DurDates;
use Kigkonsult\Icalcreator\Pc;
use Kigkonsult\Icalcreator\Util\DateIntervalFactory;
use Kigkonsult\Icalcreator\Util\DateTimeFactory;
use Kigkonsult\Icalcreator\Util\DateTimeZoneFactory;
use Kigkonsult\Icalcreator\Util\StringFactory;
use Kigkonsult\Icalcreator\Util\Util;

use function strtoupper;
use function substr;

/**
 *    rfc5545 : DURATION
 *    Format Definition:  This value type is defined by the following notation:
 *
 *    dur-value  = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
 *
 *    dur-date   = dur-day [dur-time]
 *    dur-time   = "T" (dur-hour / dur-minute / dur-second)
 *    dur-week   = 1*DIGIT "W"
 *    dur-hour   = 1*DIGIT "H" [dur-minute]
 *    dur-minute = 1*DIGIT "M" [dur-second]
 *    dur-second = 1*DIGIT "S"
 *    dur-day    = 1*DIGIT "D"
 */
/**
 * TRIGGER property functions
 *
 * @since 2.41.85 2024-01-18
 */
trait TRIGGERtrait
{
    /**
     * @var null|Pc component property TRIGGER value
     */
    protected ? Pc $trigger = null;

    /**
     * @var string  iCal TRIGGER param keywords
     * @since  2.26.8 - 2019-03-08
     * @deprecated
     */
    public static string $RELATEDSTART = 'relatedStart';
    public static string $BEFORE       = 'before';

    /**
     * Return formatted output for calendar component property trigger
     *
     * @return string
     * @throws Exception
     * @since 2.41.55 2022-08-13
     */
    public function createTrigger() : string
    {
        return DurDates::format(
            self::TRIGGER,
            $this->trigger,
            $this->getConfig( self::ALLOWEMPTY )
        );
    }

    /**
     * Delete calendar component property trigger
     *
     * @return bool
     * @since  2.27.1 - 2018-12-15
     */
    public function deleteTrigger() : bool
    {
        $this->trigger = null;
        return true;
    }

    /**
     * Get calendar component property trigger
     *
     * @param null|bool   $inclParam
     * @return bool|string|DateTimeInterface|DateInterval|Pc
     * @throws Exception
     * @since 2.41.85 2024-01-18
     */
    public function getTrigger( ? bool $inclParam = false ) :bool|string|DateInterval|DateTimeInterface|Pc
    {
        if( empty( $this->trigger )) {
            return false;
        }
        return $inclParam ? clone $this->trigger : $this->trigger->getValue();
    }

    /**
     * Return bool true if set (and ignore empty property)
     *
     * @return bool
     * @since 2.41.88 2024-01-19
     */
    public function isTriggerSet() : bool
    {
        return self::isPropSet( $this->trigger );
    }

    /**
     * Set calendar component property trigger
     *
     * @param null|string|Pc|DateTimeInterface|DateInterval $value
     * @param null|mixed[] $params
     * @return static
     * @throws Exception
     * @throws InvalidArgumentException
     * @since 2.41.85 2024-01-18
     * @todo ?? "If the trigger is set relative to START, then the "DTSTART"
     *        property MUST be present in the associated "VEVENT" or "VTODO"
     *        calendar component.  If an alarm is specified for an event with
     *        the trigger set relative to the END, then the "DTEND" property or
     *        the "DTSTART" and "DURATION " properties MUST be present in the
     *        associated "VEVENT" calendar component.  If the alarm is specified
     *        for a to-do with a trigger set relative to the END, then either
     *        the "DUE" property or the "DTSTART" and "DURATION " properties
     *        MUST be present in the associated "VTODO" calendar component."
     */
    public function setTrigger(
        null|string|Pc|DateTimeInterface|DateInterval $value = null,
        ? array $params = []
    ) : static
    {
        static $FMTERRPROPFMT = 'Invalid %s input format (%s)';
        $pc      = Pc::factory( $value, $params );
        $pcValue = $pc->getValue();
        if( empty( $pcValue )) {
            $this->assertEmptyValue( self::$SP0, self::TRIGGER );
            $this->trigger = $pc->setEmpty();
            return $this;
        }
        $isParamsDateTimeSet = $pc->hasParamValue( self::DATE_TIME );
        $pc->addParamValue( self::DURATION, false ); // default
        if( $pc->hasParamKey( self::RELATED )) {
            $pc->addParam( self::RELATED, strtoupper( $pc->getParams( self::RELATED )));
        } // end if
        switch( true ) {
            // duration DateInterval
            case ( ! $isParamsDateTimeSet && ( $pcValue instanceof DateInterval )) :
                return $this->setTriggerDateIntervalValue( $pc );
            // datetime DateTimeInterface
            case ( $pcValue instanceof DateTimeInterface ) :
                $pc->addParamValue( self::DATE_TIME ); // force date-time...
                return $this->setTriggerDateTimeValue(
                    $pc->setValue( DateTimeFactory::toDateTime( $pcValue ))
                );
            // duration in a string
            case ( ! $isParamsDateTimeSet && DateIntervalFactory::isStringAndDuration( $pcValue )) :
                return $this->setTriggerStringDurationValue( $pc );
            // date in a string
            case( $isParamsDateTimeSet && DateTimeFactory::isStringAndDate( $pcValue )) :
                return $this->setTriggerStringDateValue( $pc );
        } // end switch
        throw new InvalidArgumentException(
            sprintf( $FMTERRPROPFMT, self::TRIGGER, var_export( $pcValue, true ))
        );
    }

    /**
     * Set trigger DateInterval value
     *
     * @param Pc $value
     * @return static
     * @throws Exception
     * @since 2.41.85 2024-01-18
     */
    private function setTriggerDateIntervalValue( Pc $value ) : static
    {
        $dateInterval = DateIntervalFactory::conformDateInterval( $value->getValue());
        if( true !== self::isDurationRelatedEnd( $value->params )) {
            $value->removeParam(self::RELATED ); // remove default
        }
        $value->removeParam(self::VALUE ); // remove default
        $this->trigger = $value->setValue( $dateInterval );
        return $this;
    }

    /**
     * Set trigger DateTime value
     *
     * @param Pc $value
     * @return static
     * @throws Exception
     * @since 2.41.85 2024-01-18
     */
    private function setTriggerDateTimeValue( Pc $value ) : static
    {
        $value->removeParam( self::RELATED ); // n.a. for date-time
        $this->trigger = $value->setValue(
            DateTimeFactory::setDateTimeTimeZone( $value->getValue(), self::UTC )
        );
        return $this;
    }

    /**
     * Set trigger string duration value
     *
     * @param Pc  $value
     * @return static
     * @throws Exception
     * @since 2.41.85 2024-01-18
     */
    private function setTriggerStringDurationValue( Pc $value ) : static
    {
        $pcValue = $value->getValue();
        $before  = ( StringFactory::$MINUS === $pcValue[0] );
        if( DateIntervalFactory::$P !== $pcValue[0] ) {
            $pcValue = substr( $pcValue, 1 );
        }
        $dateInterval1 = new DateInterval( $pcValue );
        $dateInterval1->invert = ( $before ) ? 1 : 0;
        $dateInterval  = DateIntervalFactory::conformDateInterval( $dateInterval1 );
        if( true !== self::isDurationRelatedEnd( $value->getParams())) {
            $value->removeParam( self::RELATED ); // remove default
        }
        $value->removeParam( self::VALUE ); // remove default
        $this->trigger = $value->setValue( $dateInterval );
        return $this;
    }

    /**
     * Set trigger string date value
     *
     * @param Pc   $value
     * @return static
     * @throws Exception
     * @since 2.41.85 2024-01-18
     */
    private function setTriggerStringDateValue( Pc $value ) : static
    {
        [ $dateStr, $timezonePart ] =
            DateTimeFactory::splitIntoDateStrAndTimezone( $value->getValue());
        $tmpDate = DateTimeFactory::getDateTimeWithTimezoneFromString(
            $dateStr,
            $timezonePart,
            self::UTC,
            true
        );
        if( ! DateTimeZoneFactory::isUTCtimeZone(
            $tmpDate->getTimezone()->getName(),
            $tmpDate->format( DateTimeFactory::$YmdTHis ))
        ) {
            $tmpDate = DateTimeFactory::setDateTimeTimeZone( $tmpDate, self::UTC );
        }
        $value->removeParam(self::RELATED ); // n.a. for date-time
        $this->trigger = $value->setValue( $tmpDate );
        return $this;
    }

    /**
     * Return bool true if duration is related END
     *
     * @param string[] $params
     * @return bool
     * @since  2.26.7 - 2018-12-01
     */
    private static function isDurationRelatedEnd( array $params ) : bool
    {
        return Util::issetKeyAndEquals( $params, self::RELATED, self::END );
    }
}