'd-m-Y H:i (e.g. '.$now->format('d-m-Y H:i').')', 'Y-m-d H:i' => 'Y-m-d H:i (e.g. '.$now->format('Y-m-d H:i').')', 'm/d/Y h:i a' => 'm/d/Y h:i (e.g. '.$now->format('m/d/Y h:i a').')', 'H:i d-m-Y' => 'H:i d-m-Y (e.g. '.$now->format('H:i d-m-Y').')', 'h:i a m/d/Y' => 'h:i a m/d/Y (e.g. '.$now->format('h:i a m/d/Y').')', ]; $default_format = self::getGrav()['config']->get('system.pages.dateformat.default'); if ($default_format) { $date_formats = array_merge([$default_format => $default_format.' (e.g. '.$now->format($default_format).')'], $date_formats); } return $date_formats; } /** * Truncate text by number of characters but can cut off words. * * @param string $string * @param int $limit Max number of characters. * @param bool $up_to_break truncate up to breakpoint after char count * @param string $break Break point. * @param string $pad Appended padding to the end of the string. * @return string */ public static function truncate($string, $limit = 150, $up_to_break = false, $break = " ", $pad = "…") { // return with no change if string is shorter than $limit if (mb_strlen($string) <= $limit) { return $string; } // is $break present between $limit and the end of the string? if ($up_to_break && false !== ($breakpoint = mb_strpos($string, $break, $limit))) { if ($breakpoint < mb_strlen($string) - 1) { $string = mb_substr($string, 0, $breakpoint) . $break; } } else { $string = mb_substr($string, 0, $limit) . $pad; } return $string; } /** * Truncate text by number of characters in a "word-safe" manor. * * @param $string * @param int $limit * @return string */ public static function safeTruncate($string, $limit = 150) { return static::truncate($string, $limit, true); } /** * Truncate HTML by number of characters. not "word-safe"! * * @param string $text * @param int $length * * @return string */ public static function truncateHtml($text, $length = 100) { return Truncator::truncate($text, $length, array('length_in_chars' => true)); } /** * Truncate HTML by number of characters in a "word-safe" manor. * * @param string $text * @param int $length * * @return string */ public static function safeTruncateHtml($text, $length = 100) { return Truncator::truncate($text, $length, array('length_in_chars' => true, 'word_safe' => true)); } /** * Generate a random string of a given length * * @param int $length * * @return string */ public static function generateRandomString($length = 5) { return substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, $length); } /** * Provides the ability to download a file to the browser * * @param $file the full path to the file to be downloaded * @param bool $force_download as opposed to letting browser choose if to download or render */ public static function download($file, $force_download = true) { if (file_exists($file)) { // fire download event self::getGrav()->fireEvent('onBeforeDownload', new Event(['file' => $file])); $file_parts = pathinfo($file); $filesize = filesize($file); // check if this function is available, if so use it to stop any timeouts if (function_exists('set_time_limit')) { set_time_limit(0); } ignore_user_abort(false); if ($force_download) { header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . $file_parts['basename']); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); } else { header("Content-Type: " . Utils::getMimeType($file_parts['extension'])); } header('Content-Length: ' . $filesize); // 8kb chunks for now $chunk = 8 * 1024; $fh = fopen($file, "rb"); if ($fh === false) { return; } // Repeat reading until EOF while (!feof($fh)) { echo fread($fh, $chunk); ob_flush(); // flush output flush(); } exit; } } /** * Return the mimetype based on filename * * @param $extension Extension of file (eg .txt) * * @return string */ public static function getMimeType($extension) { $extension = strtolower($extension); $config = self::getGrav()['config']->get('media'); if (isset($config[$extension])) { return $config[$extension]['mime']; } return 'application/octet-stream'; } /** * Normalize path by processing relative `.` and `..` syntax and merging path * * @param $path * * @return string */ public static function normalizePath($path) { $root = ($path[0] === '/') ? '/' : ''; $segments = explode('/', trim($path, '/')); $ret = array(); foreach ($segments as $segment) { if (($segment == '.') || empty($segment)) { continue; } if ($segment == '..') { array_pop($ret); } else { array_push($ret, $segment); } } return $root . implode('/', $ret); } public static function timezones() { $timezones = \DateTimeZone::listIdentifiers(\DateTimeZone::ALL); $offsets = []; $testDate = new \DateTime; foreach ($timezones as $zone) { $tz = new \DateTimeZone($zone); $offsets[$zone] = $tz->getOffset($testDate); } asort($offsets); $timezone_list = array(); foreach ($offsets as $timezone => $offset) { $offset_prefix = $offset < 0 ? '-' : '+'; $offset_formatted = gmdate('H:i', abs($offset)); $pretty_offset = "UTC${offset_prefix}${offset_formatted}"; $timezone_list[$timezone] = "(${pretty_offset}) $timezone"; } return $timezone_list; } public static function arrayFilterRecursive(Array $source, $fn) { $result = array(); foreach ($source as $key => $value) { if (is_array($value)) { $result[$key] = static::arrayFilterRecursive($value, $fn); continue; } if ($fn($key, $value)) { $result[$key] = $value; // KEEP continue; } } return $result; } public static function pathPrefixedByLangCode($string) { $languages_enabled = self::getGrav()['config']->get('system.languages.supported', []); if ($string[0] == '/' && $string[3] == '/' && in_array(substr($string, 1, 2), $languages_enabled)) { return true; } return false; } public static function date2timestamp($date) { $config = self::getGrav()['config']; $default_dateformat = $config->get('system.pages.dateformat.default'); // try to use DateTime and default format if ($default_dateformat) { $datetime = DateTime::createFromFormat($default_dateformat, $date); } else { $datetime = new DateTime($date); } // fallback to strtotime if DateTime approach failed if ($datetime !== false) { return $datetime->getTimestamp(); } else { return strtotime($date); } } /** * Checks if a value is positive * * @param string $value * * @return boolean */ public static function isPositive($value) { return in_array($value, [true, 1, '1', 'yes', 'on', 'true'], true); } }