<?php
+
/**
* Shaarli utilities
*/
/**
- * Logs a message to a text file
+ * Format log using provided data.
*
- * The log format is compatible with fail2ban.
+ * @param string $message the message to log
+ * @param string|null $clientIp the client's remote IPv4/IPv6 address
*
- * @param string $logFile where to write the logs
- * @param string $clientIp the client's remote IPv4/IPv6 address
- * @param string $message the message to log
+ * @return string Formatted message to log
*/
-function logm($logFile, $clientIp, $message)
+function format_log(string $message, string $clientIp = null): string
{
- file_put_contents(
- $logFile,
- date('Y/m/d H:i:s').' - '.$clientIp.' - '.strval($message).PHP_EOL,
- FILE_APPEND
- );
+ $out = $message;
+
+ if (!empty($clientIp)) {
+ // Note: we keep the first dash to avoid breaking fail2ban configs
+ $out = '- ' . $clientIp . ' - ' . $out;
+ }
+
+ return $out;
}
/**
*
* @param mixed $input Data to escape: a single string or an array of strings.
*
- * @return string escaped.
+ * @return string|array escaped.
*/
function escape($input)
{
- if (is_bool($input)) {
+ if (null === $input) {
+ return null;
+ }
+
+ if (is_bool($input) || is_int($input) || is_float($input) || $input instanceof DateTimeInterface) {
return $input;
}
if (is_array($input)) {
- $out = array();
+ $out = [];
foreach ($input as $key => $value) {
- $out[$key] = escape($value);
+ $out[escape($key)] = escape($value);
}
return $out;
}
*
* @return string $referer - final referer.
*/
-function generateLocation($referer, $host, $loopTerms = array())
+function generateLocation($referer, $host, $loopTerms = [])
{
- $finalReferer = '?';
+ $finalReferer = './?';
// No referer if it contains any value in $loopCriteria.
foreach (array_filter($loopTerms) as $value) {
function autoLocale($headerLocale)
{
// Default if browser does not send HTTP_ACCEPT_LANGUAGE
- $locales = array('en_US', 'en_US.utf8', 'en_US.UTF-8');
+ $locales = ['en_US', 'en_US.utf8', 'en_US.UTF-8'];
if (! empty($headerLocale)) {
if (preg_match_all('/([a-z]{2,3})[-_]?([a-z]{2})?,?/i', $headerLocale, $matches, PREG_SET_ORDER)) {
$attempts = [];
* Requires php-intl to display international datetimes,
* otherwise default format '%c' will be returned.
*
- * @param DateTime $date to format.
- * @param bool $time Displays time if true.
- * @param bool $intl Use international format if true.
+ * @param DateTimeInterface $date to format.
+ * @param bool $time Displays time if true.
+ * @param bool $intl Use international format if true.
*
* @return bool|string Formatted date, or false if the input is invalid.
*/
function format_date($date, $time = true, $intl = true)
{
- if (! $date instanceof DateTime) {
+ if (! $date instanceof DateTimeInterface) {
return false;
}
IntlDateFormatter::LONG,
$time ? IntlDateFormatter::LONG : IntlDateFormatter::NONE
);
+ $formatter->setTimeZone($date->getTimezone());
return $formatter->format($date);
}
+/**
+ * Format the date month according to the locale.
+ *
+ * @param DateTimeInterface $date to format.
+ *
+ * @return bool|string Formatted date, or false if the input is invalid.
+ */
+function format_month(DateTimeInterface $date)
+{
+ if (! $date instanceof DateTimeInterface) {
+ return false;
+ }
+
+ return strftime('%B', $date->getTimestamp());
+}
+
+
/**
* Check if the input is an integer, no matter its real type.
*
return $val;
}
$val = trim($val);
- $last = strtolower($val[strlen($val)-1]);
+ $last = strtolower($val[strlen($val) - 1]);
$val = intval(substr($val, 0, -1));
switch ($last) {
case 'g':
$val *= 1024;
+ // do no break in order 1024^2 for each unit
case 'm':
$val *= 1024;
+ // do no break in order 1024^2 for each unit
case 'k':
$val *= 1024;
}
* Wrapper function for translation which match the API
* of gettext()/_() and ngettext().
*
- * @param string $text Text to translate.
- * @param string $nText The plural message ID.
- * @param int $nb The number of items for plural forms.
- * @param string $domain The domain where the translation is stored (default: shaarli).
+ * @param string $text Text to translate.
+ * @param string $nText The plural message ID.
+ * @param int $nb The number of items for plural forms.
+ * @param string $domain The domain where the translation is stored (default: shaarli).
+ * @param array $variables Associative array of variables to replace in translated text.
+ * @param bool $fixCase Apply `ucfirst` on the translated string, might be useful for strings with variables.
*
* @return string Text translated.
*/
-function t($text, $nText = '', $nb = 1, $domain = 'shaarli')
+function t($text, $nText = '', $nb = 1, $domain = 'shaarli', $variables = [], $fixCase = false)
+{
+ $postFunction = $fixCase ? 'ucfirst' : function ($input) {
+ return $input;
+ };
+
+ return $postFunction(dn__($domain, $text, $nText, $nb, $variables));
+}
+
+/**
+ * Converts an exception into a printable stack trace string.
+ */
+function exception2text(Throwable $e): string
{
- return dn__($domain, $text, $nText, $nb);
+ return $e->getMessage() . PHP_EOL . $e->getFile() . $e->getLine() . PHP_EOL . $e->getTraceAsString();
}