setText($text); $this->setFromDate($from_date); $this->setUntilDate($until_date); } private function __clone() { } public function __unserialize(array $data) : void { // __unserialize() must have public visibility throw new \Exception("Cannot unserialize a singleton."); } // __wakeup() is deprecated from PHP 8.5. // "The __wakeup() serialization magic method has been deprecated. Implement __unserialize() // instead (or in addition, if support for old PHP versions is necessary)". // __unserialize() is only available from PHP 7.4.0 public function __wakeup() { // __wakeup() must have public visibility throw new \Exception("Cannot unserialize a singleton."); } public static function getInstance(string $text = '', string $from_date = '', string $until_date = ''): Message { if (!isset(self::$instance)) { self::$instance = new self($text, $from_date, $until_date); } return self::$instance; } // Loads a message from the database public function load() : void { $sql = "SELECT variable_content FROM " . _tbl('variables') . " WHERE variable_name='message' LIMIT 1"; $res = db()->query_array($sql); $message = (count($res) === 0) ? [] : json_decode($res[0], true); $this->setText($message['text'] ?? ''); $this->setFrom($message['from'] ?? ''); $this->setUntil($message['until'] ?? ''); } // Saves a message to the database public function save() : bool { $sql_params = array(); $data = array( 'variable_name' => 'message', 'variable_content' => json_encode([ 'text' => $this->text, 'from' => $this->from, 'until' => $this->until ]) ); $sql = db()->syntax_upsert($data, _tbl('variables'), $sql_params, 'variable_name', ['id'], true); return (0 < db()->command($sql, $sql_params)); } // Gets the message text public function getText() : string { return $this->text; } public function getEscapedText() : string { global $message_allowed_tags; if (empty($message_allowed_tags)) { return escape_html($this->text); } return self::stripTags($this->text, $message_allowed_tags); } // Gets the message end date public function getFromDate() : string { if ($this->from === '') { return ''; } if (false === ($date = DateTime::createFromFormat(self::FORMAT_DATETIME, $this->from))) { return ''; } return $date->format(self::FORMAT_DATE); } // Gets the message end date public function getUntilDate() : string { if ($this->until === '') { return ''; } if (false === ($date = DateTime::createFromFormat(self::FORMAT_DATETIME, $this->until))) { return ''; } return $date->modify('-1 day')->format(self::FORMAT_DATE); } // Gets the message start timestamp public function getFromTimestamp() : ?int { if ($this->from === '') { return null; } if (false === ($date = DateTime::createFromFormat(self::FORMAT_DATETIME, $this->from))) { return null; } return $date->getTimestamp(); } // Gets the message end timestamp public function getUntilTimestamp() : ?int { if ($this->until === '') { return null; } if (false === ($date = DateTime::createFromFormat(self::FORMAT_DATETIME, $this->until))) { return null; } return $date->getTimestamp(); } // Get the message start time as a string in the user's locale public function getFromLocalString() : ?string { global $datetime_formats; $timestamp = $this->getFromTimestamp(); if (!isset($timestamp)) { return null; } return datetime_format($datetime_formats['date_and_time'], $timestamp); } // Get the message end time as a string in the user's locale public function getUntilLocalString() : ?string { global $datetime_formats; $timestamp = $this->getUntilTimestamp(); if (!isset($timestamp)) { return null; } return datetime_format($datetime_formats['date_and_time'], $timestamp); } // Sets the message text public function setText(string $text) : void { $this->text = $text; } // Sets the message end date public function setFromDate(string $from_date) : void { if ($from_date !== '') { // Set the date to the beginning of the day and save it with a time. // This allows a time to be added to the form in the future. // Note that the time is without timezone, so will be the time in the // timezone of the area that the message will be displayed in. $date = DateTime::createFromFormat(self::FORMAT_DATE, $from_date); if ($date === false) { trigger_error("Could not create date from '$from_date'; expecting format '" . self::FORMAT_DATE . "'.", E_USER_WARNING); $this->setFrom(''); } else { $date->setTime(0, 0); $this->setFrom($date->format(self::FORMAT_DATETIME)); } } } // Sets the message end date public function setUntilDate(string $until_date) : void { if ($until_date !== '') { // Set the date to the beginning of the next day and save it with a time. // This allows a time to be added to the form in the future. // Note that the time is without timezone, so will be the time in the // timezone of the area that the message will be displayed in. $date = DateTime::createFromFormat(self::FORMAT_DATE, $until_date); if ($date === false) { trigger_error("Could not create date from '$until_date'; expecting format '" . self::FORMAT_DATE . "'.", E_USER_WARNING); $this->setUntil(''); } else { $date->setTime(0, 0)->modify('+1 day'); $this->setUntil($date->format(self::FORMAT_DATETIME)); } } } // Determines whether there is a message that should be displayed, ie // the message exists and the expiry date hasn't passed. public function hasSomethingToDisplay() : bool { $text = $this->getText(); if ($text === '') { return false; } $from_timestamp = $this->getFromTimestamp(); $until_timestamp = $this->getUntilTimestamp(); // Check to see whether we're in the time interval in which to display the message return ((!isset($from_timestamp) || (time() >= $from_timestamp)) && (!isset($until_timestamp) || (time() < $until_timestamp))); } private function setFrom(string $date_time_string) : void { $this->from = $date_time_string; } private function setUntil(string $date_time_string) : void { $this->until = $date_time_string; } // Wrapper for PHP's strip_tags() function which converts $allowed tags to a string // if PHP < 7.4.0 private static function stripTags(string $string, array $allowed_tags) : string { assert(version_compare(MRBS_MIN_PHP_VERSION, '7.4.0', '<'), "This method is now redundant."); if (version_compare(PHP_VERSION, '7.4.0', '>=')) { return strip_tags($string, $allowed_tags); } $tag_string = ''; foreach ($allowed_tags as $tag) { $tag_string .= "<$tag>"; } return strip_tags($string, $tag_string); } }