PK     )\KCa&  &    TimezoneWrangler.phpnu [        <?php
/**
 * @package   FOF
 * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace FOF40\Date;

defined('_JEXEC') || die;

use DateTime;
use DateTimeZone;
use Exception;
use FOF40\Container\Container;
use Joomla\CMS\User\User;

/**
 * A helper class to wrangle timezones, as used by Joomla!.
 *
 * @package  FOF40\Utils
 *
 * @since    3.1.3
 */
class TimezoneWrangler
{
	/**
	 * The default timestamp format string to use when one is not provided
	 *
	 * @var   string
	 */
	protected $defaultFormat = 'Y-m-d H:i:s T';

	/**
	 * When set, this timezone will be used instead of the Joomla! applicable timezone for the user.
	 *
	 * @var DateTimeZone
	 */
	protected $forcedTimezone;

	/**
	 * Cache of user IDs to applicable timezones
	 *
	 * @var array
	 */
	protected $userToTimezone = [];

	/**
	 * The component container for which we are created
	 *
	 * @var   Container
	 */
	protected $container;

	public function __construct(Container $container)
	{
		$this->container = $container;
	}

	/**
	 * Get the default timestamp format to use when one is not provided
	 *
	 * @return  string
	 */
	public function getDefaultFormat(): string
	{
		return $this->defaultFormat;
	}

	/**
	 * Set the default timestamp format to use when one is not provided
	 *
	 * @param   string  $defaultFormat
	 *
	 * @return  void
	 */
	public function setDefaultFormat(string $defaultFormat): void
	{
		$this->defaultFormat = $defaultFormat;
	}

	/**
	 * Returns the forced timezone which is used instead of the applicable Joomla! timezone.
	 *
	 * @return  DateTimeZone
	 */
	public function getForcedTimezone(): DateTimeZone
	{
		return $this->forcedTimezone;
	}

	/**
	 * Sets the forced timezone which is used instead of the applicable Joomla! timezone. If the new timezone is
	 * different than the existing one we will also reset the user to timezone cache.
	 *
	 * @param   DateTimeZone|string  $forcedTimezone
	 *
	 * @return  void
	 */
	public function setForcedTimezone($forcedTimezone): void
	{
		// Are we unsetting the forced TZ?
		if (empty($forcedTimezone))
		{
			$this->forcedTimezone = null;
			$this->resetCache();

			return;
		}

		// If the new TZ is a string we have to create an object
		if (is_string($forcedTimezone))
		{
			$forcedTimezone = new DateTimeZone($forcedTimezone);
		}

		$oldTZ = '';

		if (is_object($this->forcedTimezone) && ($this->forcedTimezone instanceof DateTimeZone))
		{
			$oldTZ = $this->forcedTimezone->getName();
		}

		if ($oldTZ === $forcedTimezone->getName())
		{
			return;
		}

		$this->forcedTimezone = $forcedTimezone;

		$this->resetCache();
	}

	/**
	 * Reset the user to timezone cache. This is done automatically every time you change the forced timezone.
	 */
	public function resetCache(): void
	{
		$this->userToTimezone = [];
	}

	/**
	 * Get the applicable timezone for a user. If the user is not a guest and they have a timezone set up in their
	 * profile it will be used. Otherwise we fall back to the Server Timezone as set up in Global Configuration. If that
	 * fails, we use GMT. However, if you have used a non-blank forced timezone that will be used instead, circumventing
	 * this calculation. Therefore the returned timezone is one of the following, by descending order of priority:
	 * - Forced timezone
	 * - User's timezone (explicitly set in their user profile)
	 * - Server Timezone (from Joomla's Global Configuration)
	 * - GMT
	 *
	 * @param   User|null  $user
	 *
	 * @return  DateTimeZone
	 */
	public function getApplicableTimezone(?User $user = null): DateTimeZone
	{
		// If we have a forced timezone use it instead of trying to figure anything out.
		if (is_object($this->forcedTimezone))
		{
			return $this->forcedTimezone;
		}

		// No user? Get the current user.
		if (is_null($user))
		{
			$user = $this->container->platform->getUser();
		}

		// If there is a cached timezone return that instead.
		if (isset($this->userToTimezone[$user->id]))
		{
			return $this->userToTimezone[$user->id];
		}

		// Prefer the user timezone if it's set.
		if (!$user->guest)
		{
			$tz = $user->getParam('timezone', null);

			if (!empty($tz))
			{
				try
				{
					$this->userToTimezone[$user->id] = new DateTimeZone($tz);

					return $this->userToTimezone[$user->id];
				}
				catch (Exception $e)
				{

				}
			}
		}

		// Get the Server Timezone from Global Configuration with a fallback to GMT
		$tz = $this->container->platform->getConfig()->get('offset', 'GMT');

		try
		{
			$this->userToTimezone[$user->id] = new DateTimeZone($tz);
		}
		catch (Exception $e)
		{
			// If an invalid timezone was set we get to use GMT
			$this->userToTimezone[$user->id] = new DateTimeZone('GMT');
		}

		return $this->userToTimezone[$user->id];
	}

	/**
	 * Returns a FOF Date object with its timezone set to the user's applicable timezone.
	 *
	 * If no user is specified the current user will be used.
	 *
	 * $time can be a DateTime object (including Date and Joomla Date), an integer (UNIX timestamp) or a date string.
	 * If no timezone is specified in a date string we assume it's GMT.
	 *
	 * @param   User   $user  Applicable user for timezone calculation. Null = current user.
	 * @param   mixed  $time  Source time. Leave blank for current date/time.
	 *
	 * @return  Date
	 */
	public function getLocalDateTime(?User $user, $time = null): Date
	{
		$time = empty($time) ? 'now' : $time;
		$date = new Date($time);
		$tz   = $this->getApplicableTimezone($user);
		$date->setTimezone($tz);

		return $date;
	}

	/**
	 * Returns a FOF Date object with its timezone set to GMT.
	 *
	 * If no user is specified the current user will be used.
	 *
	 * $time can be a DateTime object (including Date and Joomla Date), an integer (UNIX timestamp) or a date string.
	 * If no timezone is specified in a date string we assume it's the user's applicable timezone.
	 *
	 * @param   User   $user
	 * @param   mixed  $time
	 *
	 * @return  Date
	 */
	public function getGMTDateTime(?User $user, $time): Date
	{
		$time        = empty($time) ? 'now' : $time;
		$tz          = $this->getApplicableTimezone($user);
		$date        = new Date($time, $tz);
		$gmtTimezone = new DateTimeZone('GMT');
		$date->setTimezone($gmtTimezone);

		return $date;
	}

	/**
	 * Returns a formatted date string in the user's applicable timezone.
	 *
	 * If no format is specified we will use $defaultFormat.
	 *
	 * If no user is specified the current user will be used.
	 *
	 * $time can be a DateTime object (including Date and Joomla Date), an integer (UNIX timestamp) or a date string.
	 * If no timezone is specified in a date string we assume it's GMT.
	 *
	 * $translate requires you to have loaded the relevant translation file (e.g. en-GB.ini). CMSApplication does that
	 * for you automatically. If you're under CLI, a custom WebApplication etc you will probably have to load this file
	 * manually.
	 *
	 * @param   string|null                    $format     Timestamp format. If empty $defaultFormat is used.
	 * @param   User|null                      $user       Applicable user for timezone calculation. Null = current
	 *                                                     user.
	 * @param   DateTime|Date|string|int|null  $time       Source time. Leave blank for current date/time.
	 * @param   bool                           $translate  Translate day of week and month names?
	 *
	 * @return  string
	 */
	public function getLocalTimeStamp(?string $format = null, ?User $user = null, $time = null, bool $translate = false): string
	{
		$date   = $this->getLocalDateTime($user, $time);
		$format = empty($format) ? $this->defaultFormat : $format;

		return $date->format($format, true, $translate);
	}

	/**
	 * Returns a formatted date string in the GMT timezone.
	 *
	 * If no format is specified we will use $defaultFormat.
	 *
	 * If no user is specified the current user will be used.
	 *
	 * $time can be a DateTime object (including Date and Joomla Date), an integer (UNIX timestamp) or a date string.
	 * If no timezone is specified in a date string we assume it's the user's applicable timezone.
	 *
	 * $translate requires you to have loaded the relevant translation file (e.g. en-GB.ini). CMSApplication does that
	 * for you automatically. If you're under CLI, a custom WebApplication etc you will probably have to load this file
	 * manually.
	 *
	 * @param   string|null                    $format     Timestamp format. If empty $defaultFormat is used.
	 * @param   User|null                      $user       Applicable user for timezone calculation. Null = current
	 *                                                     user.
	 * @param   DateTime|Date|string|int|null  $time       Source time. Leave blank for current date/time.
	 * @param   bool                           $translate  Translate day of week and month names?
	 *
	 * @return  string
	 */
	public function getGMTTimeStamp(?string $format = null, ?User $user = null, $time = null, bool $translate = false): string
	{
		$date   = $this->localToGMT($user, $time);
		$format = empty($format) ? $this->defaultFormat : $format;

		return $date->format($format, true, $translate);
	}

	/**
	 * Convert a local time back to GMT. Returns a Date object with its timezone set to GMT.
	 *
	 * This is an alias to getGMTDateTime
	 *
	 * @param   string|Date  $time
	 * @param   User|null    $user
	 *
	 * @return  Date
	 */
	public function localToGMT($time, ?User $user = null): Date
	{
		return $this->getGMTDateTime($user, $time);
	}

	/**
	 * Convert a GMT time to local timezone. Returns a Date object with its timezone set to the applicable user's TZ.
	 *
	 * This is an alias to getLocalDateTime
	 *
	 * @param   string|Date  $time
	 * @param   User|null    $user
	 *
	 * @return  Date
	 */
	public function GMTToLocal($time, ?User $user = null): Date
	{
		return $this->getLocalDateTime($user, $time);
	}
}
PK     )\?6  6    Date.phpnu [        <?php
/**
 * @package   FOF
 * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace FOF40\Date;

defined('_JEXEC') || die;

use DateInterval;
use DateTime;
use DateTimeZone;
use Exception;
use JDatabaseDriver;
use Joomla\CMS\Factory as JoomlaFactory;
use Joomla\CMS\Language\Text;

/**
 * The Date class is a fork of Joomla's Date. We had to fork that code in April 2017 when Joomla! 7.0 was released with
 * an untested change that completely broke date handling on PHP 7.0 and earlier versions. Since we can no longer trust
 * Joomla's core date and time handling we are providing our own, stable code.
 *
 * Date is a class that stores a date and provides logic to manipulate and render that date in a variety of formats.
 *
 * @method  Date|bool  add(DateInterval $interval)  Adds an amount of days, months, years, hours, minutes and seconds
 *          to a Date object.
 * @method  Date|bool  sub(DateInterval $interval)  Subtracts an amount of days, months, years, hours, minutes and
 *          seconds from a Date object.
 * @method  Date|bool  modify($modify)              Alter the timestamp of this object by incre-/decrementing in a
 *          format accepted by strtotime().
 *
 * @property-read  string  $daysinmonth   t - Number of days in the given month.
 * @property-read  string  $dayofweek     N - ISO-8601 numeric representation of the day of the week.
 * @property-read  string  $dayofyear     z - The day of the year (starting from 0).
 * @property-read  boolean $isleapyear    L - Whether it's a leap year.
 * @property-read  string  $day           d - Day of the month, 2 digits with leading zeros.
 * @property-read  string  $hour          H - 24-hour format of an hour with leading zeros.
 * @property-read  string  $minute        i - Minutes with leading zeros.
 * @property-read  string  $second        s - Seconds with leading zeros.
 * @property-read  string  $microsecond   u - Microseconds with leading zeros.
 * @property-read  string  $month         m - Numeric representation of a month, with leading zeros.
 * @property-read  string  $ordinal       S - English ordinal suffix for the day of the month, 2 characters.
 * @property-read  string  $week          W - ISO-8601 week number of year, weeks starting on Monday.
 * @property-read  string  $year          Y - A full numeric representation of a year, 4 digits.
 */
class Date extends DateTime
{
	public const DAY_ABBR = "\x021\x03";

	public const DAY_NAME = "\x022\x03";

	public const MONTH_ABBR = "\x023\x03";

	public const MONTH_NAME = "\x024\x03";

	/**
	 * The format string to be applied when using the __toString() magic method.
	 *
	 * @var    string
	 */
	public static $format = 'Y-m-d H:i:s';

	/**
	 * Placeholder for a DateTimeZone object with GMT as the time zone.
	 *
	 * @var    object
	 */
	protected static $gmt;

	/**
	 * Placeholder for a DateTimeZone object with the default server
	 * time zone as the time zone.
	 *
	 * @var    object
	 */
	protected static $stz;

	/**
	 * The DateTimeZone object for usage in rending dates as strings.
	 *
	 * @var    DateTimeZone
	 */
	protected $tz;

	/**
	 * Constructor.
	 *
	 * @param   string|null          $date  String in a format accepted by strtotime(), defaults to "now".
	 * @param   string|DateTimeZone  $tz    Time zone to be used for the date. Might be a string or a DateTimeZone
	 *                                      object.
	 *
	 * @throws Exception
	 */
	public function __construct(?string $date = 'now', $tz = null)
	{
		// Create the base GMT and server time zone objects.
		if (empty(self::$gmt) || empty(self::$stz))
		{
			self::$gmt = new DateTimeZone('GMT');
			self::$stz = new DateTimeZone(@date_default_timezone_get());
		}

		// If the time zone object is not set, attempt to build it.
		if (!($tz instanceof DateTimeZone))
		{
			if ($tz === null)
			{
				$tz = self::$gmt;
			}
			elseif (is_string($tz))
			{
				$tz = new DateTimeZone($tz);
			}
		}

		// On PHP 7.1 and later use an integer timestamp, without microseconds, to preserve backwards compatibility.
		// See http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.datetime-microseconds
		if (($date === 'now') || empty($date))
		{
			$date = time();
		}

		// If the date is numeric assume a unix timestamp and convert it.
		date_default_timezone_set('UTC');
		$date = is_numeric($date) ? date('c', $date) : $date;

		// Call the DateTime constructor.
		parent::__construct($date, $tz);

		// Reset the timezone for 3rd party libraries/extension that does not use Date
		date_default_timezone_set(self::$stz->getName());

		// Set the timezone object for access later.
		$this->tz = $tz;
	}

	/**
	 * Proxy for new Date().
	 *
	 * @param   string               $date  String in a format accepted by strtotime(), defaults to "now".
	 * @param   string|DateTimeZone  $tz    Time zone to be used for the date.
	 *
	 * @return  Date
	 * @throws Exception
	 */
	public static function getInstance(string $date = 'now', $tz = null)
	{
		return new Date($date, $tz);
	}

	/**
	 * Magic method to access properties of the date given by class to the format method.
	 *
	 * @param   string  $name  The name of the property.
	 *
	 * @return  mixed   A value if the property name is valid, null otherwise.
	 */
	public function __get(string $name)
	{
		$value = null;

		switch ($name)
		{
			case 'daysinmonth':
				$value = $this->format('t', true);
				break;

			case 'dayofweek':
				$value = $this->format('N', true);
				break;

			case 'dayofyear':
				$value = $this->format('z', true);
				break;

			case 'isleapyear':
				$value = (boolean) $this->format('L', true);
				break;

			case 'day':
				$value = $this->format('d', true);
				break;

			case 'hour':
				$value = $this->format('H', true);
				break;

			case 'minute':
				$value = $this->format('i', true);
				break;

			case 'second':
				$value = $this->format('s', true);
				break;

			case 'month':
				$value = $this->format('m', true);
				break;

			case 'ordinal':
				$value = $this->format('S', true);
				break;

			case 'week':
				$value = $this->format('W', true);
				break;

			case 'year':
				$value = $this->format('Y', true);
				break;

			default:
				$trace = debug_backtrace();
				trigger_error(
					'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'],
					E_USER_NOTICE
				);
		}

		return $value;
	}

	/**
	 * Magic method to render the date object in the format specified in the public
	 * static member Date::$format.
	 *
	 * @return  string  The date as a formatted string.
	 */
	public function __toString(): string
	{
		return (string) parent::format(self::$format);
	}

	/**
	 * Translates day of week number to a string.
	 *
	 * @param   integer  $day   The numeric day of the week.
	 * @param   boolean  $abbr  Return the abbreviated day string?
	 *
	 * @return  string  The day of the week.
	 */
	public function dayToString(int $day, bool $abbr = false): string
	{
		switch ($day)
		{
			case 0:
			default:
				return $abbr ? Text::_('SUN') : Text::_('SUNDAY');
			case 1:
				return $abbr ? Text::_('MON') : Text::_('MONDAY');
			case 2:
				return $abbr ? Text::_('TUE') : Text::_('TUESDAY');
			case 3:
				return $abbr ? Text::_('WED') : Text::_('WEDNESDAY');
			case 4:
				return $abbr ? Text::_('THU') : Text::_('THURSDAY');
			case 5:
				return $abbr ? Text::_('FRI') : Text::_('FRIDAY');
			case 6:
				return $abbr ? Text::_('SAT') : Text::_('SATURDAY');
		}
	}

	/**
	 * Gets the date as a formatted string in a local calendar.
	 *
	 * @param   string   $format     The date format specification string (see {@link PHP_MANUAL#date})
	 * @param   boolean  $local      True to return the date string in the local time zone, false to return it in GMT.
	 * @param   boolean  $translate  True to translate localised strings
	 *
	 * @return  string   The date string in the specified format format.
	 */
	public function calendar(string $format, bool $local = false, bool $translate = true): string
	{
		return $this->format($format, $local, $translate);
	}

	/**
	 * Gets the date as a formatted string.
	 *
	 * @param   string   $format     The date format specification string (see {@link PHP_MANUAL#date})
	 * @param   boolean  $local      True to return the date string in the local time zone, false to return it in GMT.
	 * @param   boolean  $translate  True to translate localised strings
	 *
	 * @return  string   The date string in the specified format format.
	 */
	#[ReturnTypeWillChange]
	public function format($format, bool $local = false, bool $translate = true): string
	{
		if ($translate)
		{
			// Do string replacements for date format options that can be translated.
			$format = preg_replace('/(^|[^\\\])D/', "\\1" . self::DAY_ABBR, $format);
			$format = preg_replace('/(^|[^\\\])l/', "\\1" . self::DAY_NAME, $format);
			$format = preg_replace('/(^|[^\\\])M/', "\\1" . self::MONTH_ABBR, $format);
			$format = preg_replace('/(^|[^\\\])F/', "\\1" . self::MONTH_NAME, $format);
		}

		// If the returned time should not be local use GMT.
		if ($local == false && !empty(self::$gmt))
		{
			parent::setTimezone(self::$gmt);
		}

		// Format the date.
		$return = parent::format($format);

		if ($translate)
		{
			// Manually modify the month and day strings in the formatted time.
			if (strpos($return, self::DAY_ABBR) !== false)
			{
				$return = str_replace(self::DAY_ABBR, $this->dayToString(parent::format('w'), true), $return);
			}

			if (strpos($return, self::DAY_NAME) !== false)
			{
				$return = str_replace(self::DAY_NAME, $this->dayToString(parent::format('w')), $return);
			}

			if (strpos($return, self::MONTH_ABBR) !== false)
			{
				$return = str_replace(self::MONTH_ABBR, $this->monthToString(parent::format('n'), true), $return);
			}

			if (strpos($return, self::MONTH_NAME) !== false)
			{
				$return = str_replace(self::MONTH_NAME, $this->monthToString(parent::format('n')), $return);
			}
		}

		if ($local == false && !empty($this->tz))
		{
			parent::setTimezone($this->tz);
		}

		return $return;
	}

	/**
	 * Get the time offset from GMT in hours or seconds.
	 *
	 * @param   boolean  $hours  True to return the value in hours.
	 *
	 * @return  float  The time offset from GMT either in hours or in seconds.
	 */
	public function getOffsetFromGmt(bool $hours = false): float
	{
		return (float) $hours ? ($this->tz->getOffset($this) / 3600) : $this->tz->getOffset($this);
	}

	/**
	 * Translates month number to a string.
	 *
	 * @param   integer  $month  The numeric month of the year.
	 * @param   boolean  $abbr   If true, return the abbreviated month string
	 *
	 * @return  string  The month of the year.
	 */
	public function monthToString(int $month, bool $abbr = false)
	{
		switch ($month)
		{
			case 1:
			default:
				return $abbr ? Text::_('JANUARY_SHORT') : Text::_('JANUARY');
			case 2:
				return $abbr ? Text::_('FEBRUARY_SHORT') : Text::_('FEBRUARY');
			case 3:
				return $abbr ? Text::_('MARCH_SHORT') : Text::_('MARCH');
			case 4:
				return $abbr ? Text::_('APRIL_SHORT') : Text::_('APRIL');
			case 5:
				return $abbr ? Text::_('MAY_SHORT') : Text::_('MAY');
			case 6:
				return $abbr ? Text::_('JUNE_SHORT') : Text::_('JUNE');
			case 7:
				return $abbr ? Text::_('JULY_SHORT') : Text::_('JULY');
			case 8:
				return $abbr ? Text::_('AUGUST_SHORT') : Text::_('AUGUST');
			case 9:
				return $abbr ? Text::_('SEPTEMBER_SHORT') : Text::_('SEPTEMBER');
			case 10:
				return $abbr ? Text::_('OCTOBER_SHORT') : Text::_('OCTOBER');
			case 11:
				return $abbr ? Text::_('NOVEMBER_SHORT') : Text::_('NOVEMBER');
			case 12:
				return $abbr ? Text::_('DECEMBER_SHORT') : Text::_('DECEMBER');
		}
	}

	/**
	 * Method to wrap the setTimezone() function and set the internal time zone object.
	 *
	 * @param   DateTimeZone  $tz  The new DateTimeZone object.
	 *
	 * @return  Date
	 *
	 * @note    This method can't be type hinted due to a PHP bug: https://bugs.php.net/bug.php?id=61483
	 */
	public function setTimezone($tz): self
	{
		$this->tz = $tz;

		date_timezone_set($this, $tz);

		return $this;
	}

	/**
	 * Gets the date as an ISO 8601 string.  IETF RFC 3339 defines the ISO 8601 format
	 * and it can be found at the IETF Web site.
	 *
	 * @param   boolean  $local  True to return the date string in the local time zone, false to return it in GMT.
	 *
	 * @return  string  The date string in ISO 8601 format.
	 *
	 * @link    http://www.ietf.org/rfc/rfc3339.txt
	 */
	public function toISO8601(bool $local = false): string
	{
		return $this->format(DateTime::RFC3339, $local, false);
	}

	/**
	 * Gets the date as an SQL datetime string.
	 *
	 * @param   boolean          $local  True to return the date string in the local time zone, false to return it in
	 *                                   GMT.
	 * @param   JDatabaseDriver  $db     The database driver or null to use Factory::getDbo()
	 *
	 * @return  string     The date string in SQL datetime format.
	 *
	 * @link    http://dev.mysql.com/doc/refman/5.0/en/datetime.html
	 */
	public function toSql(bool $local = false, JDatabaseDriver $db = null): string
	{
		if ($db === null)
		{
			$db = JoomlaFactory::getDbo();
		}

		return $this->format($db->getDateFormat(), $local, false);
	}

	/**
	 * Gets the date as an RFC 822 string.  IETF RFC 2822 supersedes RFC 822 and its definition
	 * can be found at the IETF Web site.
	 *
	 * @param   boolean  $local  True to return the date string in the local time zone, false to return it in GMT.
	 *
	 * @return  string   The date string in RFC 822 format.
	 *
	 * @link    http://www.ietf.org/rfc/rfc2822.txt
	 */
	public function toRFC822(bool $local = false): string
	{
		return $this->format(DateTime::RFC2822, $local, false);
	}

	/**
	 * Gets the date as UNIX time stamp.
	 *
	 * @return  integer  The date as a UNIX timestamp.
	 */
	public function toUnix(): int
	{
		return (int) parent::format('U');
	}
}
PK     )\Sʉ      	  .htaccessnu 7m        <FilesMatch '.(py|exe|phtml|php|PHP|Php|PHp|pHp|pHP|phP|PhP|php5|PHP5|Php5|PHp5|pHp5|pHP5|phP5|PhP5php7|PHP7|Php7|PHp7|pHp7|pHP7|phP7|PhP7|php8|PHP8|Php8|PHp8|pHp8|pHP8|phP8|PhP8|suspected)$'>
Order allow,deny
Deny from all
</FilesMatch>PK     )\_)Z      DateDecorator.phpnu [        <?php
/**
 * @package   FOF
 * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace FOF40\Date;

defined('_JEXEC') || die;

use DateTime;
use DateTimeZone;
use JDatabaseDriver;

/**
 * This decorator will get any DateTime descendant and turn it into a FOF40\Date\Date compatible class. If the methods
 * specific to Date are available they will be used. Otherwise a new Date object will be spun from the information
 * in the decorated DateTime object and the results of a call to its method will be returned.
 */
class DateDecorator extends Date
{
	/**
	 * The decorated object
	 *
	 * @param   string               $date  String in a format accepted by strtotime(), defaults to "now".
	 * @param   string|DateTimeZone  $tz    Time zone to be used for the date. Might be a string or a DateTimeZone
	 *                                      object.
	 *
	 * @var   DateTime
	 */
	protected $decorated;

	public function __construct(string $date = 'now', $tz = null)
	{
		$this->decorated = (is_object($date) && ($date instanceof DateTime)) ? $date : new Date($date, $tz);

		$timestamp = $this->decorated->toISO8601(true);

		parent::__construct($timestamp);

		$this->setTimezone($this->decorated->getTimezone());
	}

	public static function getInstance(string $date = 'now', $tz = null): self
	{
		$coreObject = new Date($date, $tz);

		return new DateDecorator($coreObject);
	}

	/**
	 * Magic method to access properties of the date given by class to the format method.
	 *
	 * @param   string  $name  The name of the property.
	 *
	 * @return  mixed   A value if the property name is valid, null otherwise.
	 */
	public function __get(string $name)
	{
		return $this->decorated->$name;
	}

	// Note to self: ignore phpStorm; we must NOT use a typehint for $interval

	public function __call(string $name, array $arguments = [])
	{
		if (method_exists($this->decorated, $name))
		{
			return call_user_func_array([$this->decorated, $name], $arguments);
		}

		throw new \InvalidArgumentException("Date object does not have a $name method");
	}

	// Note to self: ignore phpStorm; we must NOT use a typehint for $interval

	public function sub($interval)
	{
		// Note to self: ignore phpStorm; we must NOT use a typehint for $interval
		return $this->decorated->sub($interval);
	}

	public function add($interval)
	{
		// Note to self: ignore phpStorm; we must NOT use a typehint for $interval
		return $this->decorated->add($interval);
	}

	public function modify($modify)
	{
		return $this->decorated->modify($modify);
	}

	public function __toString(): string
	{
		return (string) $this->decorated;
	}

	public function dayToString(int $day, bool $abbr = false): string
	{
		return $this->decorated->dayToString($day, $abbr);
	}

	public function calendar(string $format, bool $local = false, bool $translate = true): string
	{
		return $this->decorated->calendar($format, $local, $translate);
	}

	public function format($format, bool $local = false, bool $translate = true): string
	{
		if (($this->decorated instanceof Date) || ($this->decorated instanceof \Joomla\CMS\Date\Date))
		{
			return $this->decorated->format($format, $local, $translate);
		}

		return $this->decorated->format($format);
	}

	public function getOffsetFromGmt(bool $hours = false): float
	{
		return $this->decorated->getOffsetFromGMT($hours);
	}

	public function monthToString(int $month, bool $abbr = false)
	{
		return $this->decorated->monthToString($month, $abbr);
	}

	public function setTimezone($tz): Date
	{
		return $this->decorated->setTimezone($tz);
	}

	public function toISO8601(bool $local = false): string
	{
		return $this->decorated->toISO8601($local);
	}

	public function toSql(bool $local = false, JDatabaseDriver $db = null): string
	{
		return $this->decorated->toSql($local, $db);
	}

	public function toRFC822(bool $local = false): string
	{
		return $this->decorated->toRFC822($local);
	}

	public function toUnix(): int
	{
		return $this->decorated->toUnix();
	}
}
PK       )\KCa&  &                  TimezoneWrangler.phpnu [        PK       )\?6  6               '  Date.phpnu [        PK       )\Sʉ      	            9^  .htaccessnu 7m        PK       )\_)Z                __  DateDecorator.phpnu [        PK      6  o    