diff --git a/misuzu.php b/misuzu.php index 53e43b38..964cf30b 100644 --- a/misuzu.php +++ b/misuzu.php @@ -223,7 +223,7 @@ MIG; tpl_add_path(__DIR__ . '/templates'); - if ($app->getConfig()->get('Auth', 'lockdown', 'bool', false)) { + if ($app->underLockdown()) { http_response_code(503); echo tpl_render('auth/lockdown'); exit; diff --git a/public/auth.php b/public/auth.php index 701bd13b..7962646f 100644 --- a/public/auth.php +++ b/public/auth.php @@ -7,8 +7,6 @@ use Misuzu\Users\Session; require_once __DIR__ . '/../misuzu.php'; -$config = $app->getConfig(); - $usernameValidationErrors = [ 'trim' => 'Your username may not start or end with spaces!', 'short' => sprintf('Your username is too short, it has to be at least %d characters!', MSZ_USERNAME_MIN_LENGTH), @@ -18,7 +16,7 @@ $usernameValidationErrors = [ ]; $authMode = $_GET['m'] ?? 'login'; -$preventRegistration = $config->get('Auth', 'prevent_registration', 'bool', false); +$preventRegistration = $app->disableRegistration(); tpl_vars([ 'prevent_registration' => $preventRegistration, @@ -203,10 +201,7 @@ If you weren't the person who requested this reset, please send a reply to this MSG; $message = (new Swift_Message('Flashii Password Reset')) - ->setFrom([ - $config->get('Mail', 'sender_email', 'string', 'sys@misuzu.lh') => - $config->get('Mail', 'sender_name', 'string', 'Misuzu') - ]) + ->setFrom($app->getMailSender()) ->setTo([$forgotUser['email'] => $forgotUser['username']]) ->setBody($messageBody); diff --git a/public/index.php b/public/index.php index cff7fede..77218fd5 100644 --- a/public/index.php +++ b/public/index.php @@ -5,17 +5,7 @@ use Misuzu\Database; require_once __DIR__ . '/../misuzu.php'; -$config = $app->getConfig(); - -if ($config->get('Site', 'embed_linked_data', 'bool', false)) { - tpl_vars([ - 'embed_linked_data' => true, - 'embed_name' => $config->get('Site', 'name'), - 'embed_url' => $config->get('Site', 'url'), - 'embed_logo' => $config->get('Site', 'external_logo'), - 'embed_same_as' => explode(',', $config->get('Site', 'social_media')), - ]); -} +tpl_vars($app->getLinkedData()); $news = Database::query(' SELECT diff --git a/public/profile.php b/public/profile.php index 950aeb1e..3274661f 100644 --- a/public/profile.php +++ b/public/profile.php @@ -9,10 +9,7 @@ $mode = (string)($_GET['m'] ?? 'view'); switch ($mode) { case 'avatar': - $avatar_filename = $app->getPath( - $app->getConfig()->get('Avatar', 'default_path', 'string', 'public/images/no-avatar.png') - ); - + $avatar_filename = $app->getDefaultAvatar(); $user_avatar = "{$user_id}.msz"; $cropped_avatar = $app->getStore('avatars/200x200')->filename($user_avatar); diff --git a/public/settings.php b/public/settings.php index f3b0877c..e773a419 100644 --- a/public/settings.php +++ b/public/settings.php @@ -66,11 +66,9 @@ if (!array_key_exists($settingsMode, $settingsModes)) { $settingsErrors = []; -$disableAccountOptions = !$app->inDebugMode() && $app->getConfig()->get('Auth', 'prevent_registration', 'bool', false); +$disableAccountOptions = !$app->inDebugMode() && $app->disableRegistration(); $avatarFileName = "{$app->getUserId()}.msz"; -$avatarWidthMax = $app->getConfig()->get('Avatar', 'max_width', 'int', 4000); -$avatarHeightMax = $app->getConfig()->get('Avatar', 'max_height', 'int', 4000); -$avatarFileSizeMax = $app->getConfig()->get('Avatar', 'max_filesize', 'int', 1000000); +$avatarProps = $app->getAvatarProps(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!tmp_csrf_verify($_POST['csrf'] ?? '')) { @@ -123,9 +121,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $avatarErrorStrings['upload'][$_FILES['avatar']['error']['file']] ?? $avatarErrorStrings['upload']['default'], $_FILES['avatar']['error']['file'], - byte_symbol($avatarFileSizeMax, true), - $avatarWidthMax, - $avatarHeightMax + byte_symbol($avatarProps['max_filesize'], true), + $avatarProps['max_width'], + $avatarProps['max_height'] ); break; } @@ -140,9 +138,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $avatarErrorStrings['set'][$setAvatar] ?? $avatarErrorStrings['set']['default'], $setAvatar, - byte_symbol($avatarFileSizeMax, true), - $avatarWidthMax, - $avatarHeightMax + byte_symbol($avatarProps['max_filesize'], true), + $avatarProps['max_width'], + $avatarProps['max_height'] ); } break; @@ -309,9 +307,9 @@ switch ($settingsMode) { tpl_vars([ 'avatar_user_id' => $app->getUserId(), - 'avatar_max_width' => $avatarWidthMax, - 'avatar_max_height' => $avatarHeightMax, - 'avatar_max_filesize' => $avatarFileSizeMax, + 'avatar_max_width' => $avatarProps['max_width'], + 'avatar_max_height' => $avatarProps['max_height'], + 'avatar_max_filesize' => $avatarProps['max_filesize'], 'user_has_avatar' => $userHasAvatar, 'settings_profile_fields' => $profileFields, 'settings_profile_values' => $userFields, diff --git a/src/Application.php b/src/Application.php index 0dfbe45d..ebf30ba7 100644 --- a/src/Application.php +++ b/src/Application.php @@ -2,7 +2,6 @@ namespace Misuzu; use Carbon\Carbon; -use Misuzu\Config\ConfigManager; use Misuzu\IO\Directory; use Misuzu\IO\DirectoryDoesNotExistException; use Misuzu\Users\Session; @@ -12,6 +11,7 @@ use Swift_Mailer; use Swift_NullTransport; use Swift_SmtpTransport; use Swift_SendmailTransport; +use GeoIp2\Database\Reader as GeoIP; /** * Handles the set up procedures. @@ -50,11 +50,7 @@ class Application extends ApplicationBase */ private $currentUserId = 0; - /** - * ConfigManager instance. - * @var \Misuzu\Config\ConfigManager - */ - private $configInstance = null; + private $config = []; /** * TemplatingEngine instance. @@ -64,6 +60,8 @@ class Application extends ApplicationBase private $mailerInstance = null; + private $geoipInstance = null; + private $startupTime = 0; /** @@ -76,14 +74,18 @@ class Application extends ApplicationBase $this->startupTime = microtime(true); parent::__construct(); $this->debugMode = $debug; - $this->configInstance = new ConfigManager($configFile); + $this->config = parse_ini_file($configFile, true, INI_SCANNER_TYPED); + + if ($this->config === false) { + throw new UnexpectedValueException('Failed to parse configuration.'); + } // only use this error handler in prod mode, dev uses Whoops now if (!$debug) { ExceptionHandler::register( false, - $this->configInstance->get('Exceptions', 'report_url', 'string', null), - $this->configInstance->get('Exceptions', 'hash_key', 'string', null) + $this->config['Exceptions']['report_url'] ?? null, + $this->config['Exceptions']['hash_key'] ?? null ); } } @@ -93,21 +95,6 @@ class Application extends ApplicationBase return microtime(true) - $this->startupTime; } - /** - * Gets instance of the config manager. - * @return ConfigManager - */ - public function getConfig(): ConfigManager - { - if (is_null($this->configInstance)) { - throw new UnexpectedValueException( - 'Internal ConfigManager instance is null, how did you even manage to do this?' - ); - } - - return $this->configInstance; - } - /** * Gets whether we're in debug mode or not. * @return bool @@ -143,7 +130,7 @@ class Application extends ApplicationBase if (starts_with($append, '/')) { $path = $append; } else { - $path = $this->getConfig()->get('Storage', 'path', 'string', __DIR__ . '/../store'); + $path = $this->config['Storage']['path'] ?? __DIR__ . '/../store'; if (!empty($append)) { $path .= '/' . $append; @@ -164,9 +151,9 @@ class Application extends ApplicationBase { $override_key = 'override_' . str_replace('/', '_', $purpose); - if ($this->configInstance->contains('Storage', $override_key)) { + if (array_key_exists('Storage', $this->config)) { try { - return new Directory($this->configInstance->get('Storage', $override_key)); + return new Directory($this->config['Storage'][$override_key]); } catch (DirectoryDoesNotExistException $ex) { // fall through and just get the default path. } @@ -235,7 +222,13 @@ class Application extends ApplicationBase throw new UnexpectedValueException('Database has already been started.'); } - new Database($this->configInstance, self::DATABASE_CONNECTIONS[0]); + $connections = []; + + foreach (self::DATABASE_CONNECTIONS as $name) { + $connections[$name] = $this->config["Database.{$name}"] ?? []; + } + + new Database($connections, self::DATABASE_CONNECTIONS[0]); } /** @@ -248,11 +241,11 @@ class Application extends ApplicationBase } new Cache( - $this->configInstance->get('Cache', 'host', 'string', null), - $this->configInstance->get('Cache', 'port', 'int', null), - $this->configInstance->get('Cache', 'database', 'int', null), - $this->configInstance->get('Cache', 'password', 'string', null), - $this->configInstance->get('Cache', 'prefix', 'string', '') + $this->config['Cache']['host'] ?? null, + $this->config['Cache']['port'] ?? null, + $this->config['Cache']['database'] ?? null, + $this->config['Cache']['password'] ?? null, + $this->config['Cache']['prefix'] ?? '' ); } @@ -270,10 +263,10 @@ class Application extends ApplicationBase ]); tpl_var('globals', [ - 'site_name' => $this->configInstance->get('Site', 'name', 'string', 'Flashii'), - 'site_description' => $this->configInstance->get('Site', 'description'), - 'site_twitter' => $this->configInstance->get('Site', 'twitter'), - 'site_url' => $this->configInstance->get('Site', 'url'), + 'site_name' => $this->config['Site']['name'] ?? 'Flashii', + 'site_description' => $this->config['Site']['description'] ?? '', + 'site_twitter' => $this->config['Site']['twitter'] ?? '', + 'site_url' => $this->config['Site']['url'] ?? '', ]); tpl_add_function('json_decode', true); @@ -309,8 +302,8 @@ class Application extends ApplicationBase return; } - if ($this->configInstance->contains('Mail')) { - $method = mb_strtolower($this->configInstance->get('Mail', 'method')); + if (array_key_exists('Mail', $this->config) && array_key_exists('method', $this->config['Mail'])) { + $method = mb_strtolower($this->config['Mail']['method'] ?? ''); } if (empty($method) || !array_key_exists($method, self::MAIL_TRANSPORT)) { @@ -322,27 +315,25 @@ class Application extends ApplicationBase switch ($method) { case 'sendmail': - if ($this->configInstance->contains('Mail', 'command')) { - $transport->setCommand( - $this->configInstance->get('Mail', 'command') - ); + if (array_key_exists('command', $this->config['Mail'])) { + $transport->setCommand($this->config['Mail']['command']); } break; case 'smtp': - $transport->setHost($this->configInstance->get('Mail', 'host')); - $transport->setPort($this->configInstance->get('Mail', 'port', 'int', 25)); + $transport->setHost($this->config['Mail']['host'] ?? ''); + $transport->setPort(intval($this->config['Mail']['port'] ?? 25)); - if ($this->configInstance->contains('Mail', 'encryption')) { - $transport->setEncryption($this->configInstance->get('Mail', 'encryption')); + if (array_key_exists('encryption', $this->config['Mail'])) { + $transport->setEncryption($this->config['Mail']['encryption']); } - if ($this->configInstance->contains('Mail', 'username')) { - $transport->setUsername($this->configInstance->get('Mail', 'username')); + if (array_key_exists('username', $this->config['Mail'])) { + $transport->setUsername($this->config['Mail']['username']); } - if ($this->configInstance->contains('Mail', 'password')) { - $transport->setPassword($this->configInstance->get('Mail', 'password')); + if (array_key_exists('password', $this->config['Mail'])) { + $transport->setPassword($this->config['Mail']['password']); } break; } @@ -363,4 +354,73 @@ class Application extends ApplicationBase { return self::getInstance()->getMailer(); } + + public function getMailSender(): array + { + return [ + ($this->config['Mail']['sender_email'] ?? 'sys@msz.lh') => ($this->config['Mail']['sender_name'] ?? 'Misuzu System') + ]; + } + + public function startGeoIP(): void + { + if (!empty($this->geoipInstance)) { + return; + } + + $this->geoipInstance = new GeoIP($this->config['GeoIP']['database_path'] ?? ''); + } + + public function getGeoIP(): GeoIP + { + if (empty($this->geoipInstance)) { + $this->startGeoIP(); + } + + return $this->geoipInstance; + } + + public static function geoip(): GeoIP + { + return self::getInstance()->getGeoIP(); + } + + public function getAvatarProps(): array + { + return [ + 'max_width' => intval($this->config['Avatar']['max_width'] ?? 4000), + 'max_height' => intval($this->config['Avatar']['max_height'] ?? 4000), + 'max_filesize' => intval($this->config['Avatar']['max_filesize'] ?? 1000000), + ]; + } + + public function underLockdown(): bool + { + return boolval($this->config['Auth']['lockdown'] ?? false); + } + + public function disableRegistration(): bool + { + return $this->underLockdown() || boolval($this->config['Auth']['prevent_registration'] ?? false); + } + + public function getLinkedData(): array + { + if (!($this->config['Site']['embed_linked_data'] ?? false)) { + return ['embed_linked_data' => false]; + } + + return [ + 'embed_linked_data' => true, + 'embed_name' => $this->config['Site']['name'] ?? 'Flashii', + 'embed_url' => $this->config['Site']['url'] ?? '', + 'embed_logo' => $this->config['Site']['external_logo'] ?? '', + 'embed_same_as' => explode(',', $this->config['Site']['social_media'] ?? '') + ]; + } + + public function getDefaultAvatar(): string + { + return $this->getPath($this->config['Avatar']['default_path'] ?? 'public/images/no-avatar.png'); + } } diff --git a/src/Cache.php b/src/Cache.php index 4f19aaf5..c4a371b6 100644 --- a/src/Cache.php +++ b/src/Cache.php @@ -1,7 +1,6 @@ - */ -class ConfigManager -{ - /** - * Holds the key collection pairs for the sections. - * @var array - */ - private $collection = []; - - private $filename = null; - - /** - * Creates a file object with the given path and reloads the context. - * @param string|null $filename - */ - public function __construct(?string $filename = null) - { - if (empty($filename)) { - return; - } - - $this->filename = $filename; - - if (File::exists($this->filename)) { - $this->load(); - } - } - - /** - * Checks if a section or key exists in the config. - * @param string $section - * @param string $key - * @return bool - */ - public function contains(string $section, ?string $key = null): bool - { - if ($key !== null) { - return $this->contains($section) && array_key_exists($key, $this->collection[$section]); - } - - return array_key_exists($section, $this->collection); - } - - /** - * Removes a section or key and saves. - * @param string $section - * @param string $key - */ - public function remove(string $section, ?string $key = null): void - { - if ($key !== null && $this->contains($section, $key)) { - if (count($this->collection[$section]) < 2) { - $this->remove($section); - return; - } - - unset($this->collection[$section][$key]); - } elseif ($this->contains($section)) { - unset($this->collection[$section]); - } - } - - /** - * Gets a value from a section in the config. - * @param string $section - * @param string $key - * @param string $type - * @param string $fallback - * @return mixed - */ - public function get(string $section, string $key, string $type = 'string', ?string $fallback = null) - { - $value = null; - - if (!$this->contains($section, $key)) { - $this->set($section, $key, $fallback); - return $fallback; - } - - $raw = $this->collection[$section][$key]; - - switch (strtolower($type)) { - case "bool": - case "boolean": - $value = mb_strlen($raw) > 0 && ($raw[0] === '1' || mb_strtolower($raw) === "true"); - break; - - case "int": - case "integer": - $value = intval($raw); - break; - - case "float": - case "double": - $value = floatval($raw); - break; - - default: - $value = $raw; - break; - } - - return $value; - } - - /** - * Sets a configuration value and immediately saves it. - * @param string $section - * @param string $key - * @param mixed $value - */ - public function set(string $section, string $key, $value): void - { - $type = gettype($value); - $store = null; - - switch (mb_strtolower($type)) { - case 'boolean': - $store = $value ? '1' : '0'; - break; - - default: - $store = (string)$value; - break; - } - - if (!$this->contains($section)) { - $this->collection[$section] = []; - } - - $this->collection[$section][$key] = $store; - } - - /** - * Writes the serialised config to file. - */ - public function save(): void - { - if (!empty($this->filename)) { - static::write($this->filename, $this->collection); - } - } - - /** - * Calls for a parse of the contents of the config file. - */ - public function load(): void - { - if (!empty($this->filename)) { - $this->collection = static::read($this->filename); - } - } - - /** - * Serialises the $this->collection array to the human managable config format. - * @param string $filename - * @param array $collection - * @throws \Misuzu\IO\FileDoesNotExistException - * @throws \Misuzu\IO\IOException - */ - public static function write(string $filename, array $collection): void - { - $file = new FileStream($filename, FileStream::MODE_TRUNCATE, true); - $file->write(sprintf('; Saved on %s%s', date('Y-m-d H:i:s e'), PHP_EOL)); - - foreach ($collection as $name => $entries) { - if (count($entries) < 1) { - continue; - } - - $file->write(sprintf('%1$s[%2$s]%1$s', PHP_EOL, $name)); - - foreach ($entries as $key => $value) { - $file->write(sprintf('%s = %s%s', $key, $value, PHP_EOL)); - } - } - - $file->flush(); - $file->close(); - } - - /** - * Parses the config file. - * @param string $filename - * @return array - * @throws \Misuzu\IO\FileDoesNotExistException - * @throws \Misuzu\IO\IOException - */ - private static function read(string $filename): array - { - $collection = []; - $section = null; - $key = null; - $value = null; - - $file = new FileStream($filename, FileStream::MODE_READ); - $lines = explode("\n", $file->read($file->length)); - $file->close(); - - foreach ($lines as $line) { - $line = trim($line, "\r\n"); - $length = mb_strlen($line); - - if ($length < 1 - || starts_with($line, '#') - || starts_with($line, ';') - || starts_with($line, '//') - ) { - continue; - } - - if (starts_with($line, '[') && ends_with($line, ']')) { - $section = rtrim(ltrim($line, '['), ']'); - - if (!isset($collection[$section])) { - $collection[$section] = []; - } - continue; - } - - if (mb_strpos($line, '=') !== false) { - $split = explode('=', $line, 2); - - if (count($split) < 2) { - continue; - } - - $key = trim($split[0]); - $value = trim($split[1]); - - if (mb_strlen($key) > 0 && mb_strlen($value) > 0) { - $collection[$section][$key] = $value; - } - } - } - - return $collection; - } -} diff --git a/src/Database.php b/src/Database.php index 81b89281..8c1f90fc 100644 --- a/src/Database.php +++ b/src/Database.php @@ -1,7 +1,6 @@ default = $default; - $this->configManager = $config; + + foreach ($connections as $name => $info) { + $this->addConnection($info, $name); + } } public static function connection(?string $name = null): PDO @@ -110,21 +107,17 @@ final class Database return $this->connections[$name] ?? $this->addConnection($name); } - public function addConnection(string $name): PDO + public function addConnection(array $info, string $name): PDO { - $section = "Database.{$name}"; - - if (!$this->configManager->contains($section, 'driver')) { + if (!array_key_exists('driver', $info)) { throw new InvalidArgumentException('Config section not found!'); } - $driver = $this->configManager->get($section, 'driver'); - - if (!in_array($driver, self::SUPPORTED)) { + if (!in_array($info['driver'], self::SUPPORTED)) { throw new InvalidArgumentException('Unsupported driver.'); } - $dsn = $driver . ':'; + $dsn = $info['driver'] . ':'; $options = [ PDO::ATTR_CASE => PDO::CASE_NATURAL, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, @@ -133,40 +126,29 @@ final class Database PDO::ATTR_EMULATE_PREPARES => false, ]; - switch ($driver) { + switch ($info['driver']) { case 'sqlite': - if ($this->configManager->get($section, 'memory', 'bool', false)) { + if ($info['memory']) { $dsn .= ':memory:'; } else { - $databasePath = realpath( - $this->configManager->get($section, 'database', 'string', __DIR__ . '/../store/misuzu.db') - ); + $databasePath = realpath($info['database'] ?? __DIR__ . '/../store/misuzu.db'); if ($databasePath === false) { - throw new \UnexpectedValueException("Database does not exist."); + throw new UnexpectedValueException("Database does not exist."); } - - $dsn .= $databasePath . ';'; } break; case 'mysql': - $is_unix_socket = $this->configManager->contains($section, 'unix_socket'); - - if ($is_unix_socket) { - $dsn .= 'unix_socket=' . $this->configManager->get($section, 'unix_socket', 'string') . ';'; + if ($info['unix_socket'] ?? false) { + $dsn .= 'unix_socket=' . $info['unix_socket'] . ';'; } else { - $dsn .= 'host=' . $this->configManager->get($section, 'host', 'string', self::DEFAULT_HOST) . ';'; - $dsn .= 'port=' . $this->configManager->get($section, 'port', 'int', self::DEFAULT_PORT_MYSQL) . ';'; + $dsn .= 'host=' . ($info['host'] ?? self::DEFAULT_HOST) . ';'; + $dsn .= 'port=' . intval($info['port'] ?? self::DEFAULT_PORT_MYSQL) . ';'; } - $dsn .= 'charset=' . ( - $this->configManager->contains($section, 'charset') - ? $this->configManager->get($section, 'charset', 'string') - : 'utf8mb4' - ) . ';'; - - $dsn .= 'dbname=' . $this->configManager->get($section, 'database', 'string', 'misuzu') . ';'; + $dsn .= 'charset=' . ($info['charset'] ?? 'utf8mb4') . ';'; + $dsn .= 'dbname=' . ($info['database'] ?? 'misuzu') . ';'; $options[PDO::MYSQL_ATTR_INIT_COMMAND] = " SET SESSION @@ -178,8 +160,8 @@ final class Database $connection = new PDO( $dsn, - $this->configManager->get($section, 'username', 'string', null), - $this->configManager->get($section, 'password', 'string', null), + ($info['username'] ?? null), + ($info['password'] ?? null), $options ); diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php deleted file mode 100644 index cc56f102..00000000 --- a/tests/ConfigTest.php +++ /dev/null @@ -1,67 +0,0 @@ -assertInstanceOf(ConfigManager::class, $config); - - $config->set('TestCat', 'string_val', 'test', 'string'); - $config->set('TestCat', 'int_val', 25, 'int'); - $config->set('TestCat', 'bool_val', true, 'bool'); - - $this->assertEquals('test', $config->get('TestCat', 'string_val', 'string')); - $this->assertEquals(25, $config->get('TestCat', 'int_val', 'int')); - $this->assertEquals(true, $config->get('TestCat', 'bool_val', 'bool')); - } - - public function testConfigCreateSet() - { - $config = new ConfigManager(CONFIG_FILE); - $this->assertInstanceOf(ConfigManager::class, $config); - - $config->set('TestCat', 'string_val', 'test', 'string'); - $config->set('TestCat', 'int_val', 25, 'int'); - $config->set('TestCat', 'bool_val', true, 'bool'); - - $this->assertEquals('test', $config->get('TestCat', 'string_val', 'string')); - $this->assertEquals(25, $config->get('TestCat', 'int_val', 'int')); - $this->assertEquals(true, $config->get('TestCat', 'bool_val', 'bool')); - - $config->save(); - } - - public function testConfigReadGet() - { - $config = new ConfigManager(CONFIG_FILE); - $this->assertInstanceOf(ConfigManager::class, $config); - - $this->assertEquals('test', $config->get('TestCat', 'string_val', 'string')); - $this->assertEquals(25, $config->get('TestCat', 'int_val', 'int')); - $this->assertEquals(true, $config->get('TestCat', 'bool_val', 'bool')); - } - - public function testConfigRemove() - { - $config = new ConfigManager(CONFIG_FILE); - $this->assertInstanceOf(ConfigManager::class, $config); - - $this->assertTrue($config->contains('TestCat', 'string_val')); - $config->remove('TestCat', 'string_val'); - - $config->save(); - $config->load(); - - $this->assertFalse($config->contains('TestCat', 'string_val')); - - // tack this onto here, deletes the entire file because we're done with it - \Misuzu\IO\File::delete(CONFIG_FILE); - } -} diff --git a/utility.php b/utility.php index af12a8ae..28662a20 100644 --- a/utility.php +++ b/utility.php @@ -1,12 +1,12 @@ getConfig(); - - if ($config === null) { - return $fallback; - } - - $database_path = $config->get('GeoIP', 'database_path'); - - if ($database_path === null) { - return $fallback; - } - - $_msz_geoip = new \GeoIp2\Database\Reader($database_path); - } - - $record = $_msz_geoip->country($ipAddr); - - return $record->country->isoCode; + return \Misuzu\Application::geoip()->country($ipAddr)->country->isoCode ?? $fallback; } catch (\Exception $e) { // report error? } @@ -186,7 +165,7 @@ function crop_image_centred(Imagick $image, int $target_width, int $target_heigh function running_on_windows(): bool { - return starts_with(strtolower(PHP_OS), 'win'); + return starts_with(mb_strtolower(PHP_OS), 'win'); } function first_paragraph(string $text, string $delimiter = "\n"): string @@ -227,7 +206,7 @@ function parse_bbcode(string $text): string function is_local_url(string $url): bool { - $length = strlen($url); + $length = mb_strlen($url); if ($length < 1) { return false; @@ -243,7 +222,7 @@ function is_local_url(string $url): bool function parse_text(string $text, string $parser): string { - switch (strtolower($parser)) { + switch (mb_strtolower($parser)) { case 'md': case 'markdown': return \Misuzu\Parsers\MarkdownParser::instance()->parseText($text); @@ -259,7 +238,7 @@ function parse_text(string $text, string $parser): string function parse_line(string $line, string $parser): string { - switch (strtolower($parser)) { + switch (mb_strtolower($parser)) { case 'md': case 'markdown': return \Misuzu\Parsers\MarkdownParser::instance()->parseLine($line); @@ -285,7 +264,7 @@ function render_info(?string $message, int $httpCode, string $template = 'errors try { tpl_var('http_code', $httpCode); - if (strlen($message)) { + if (mb_strlen($message)) { tpl_var('message', $message); } @@ -322,7 +301,7 @@ function html_link(string $url, ?string $content = null, $attributes = []): stri ['href' => $url] ); - if (strpos($url, '://') !== false) { + if (mb_strpos($url, '://') !== false) { $attributes['target'] = '_blank'; $attributes['rel'] = 'noreferrer noopener'; } @@ -362,7 +341,7 @@ function url_construct(string $path, array $query = [], string $host = ''): stri $url = $host . $path; if (count($query)) { - $url .= strpos($path, '?') !== false ? '&' : '?'; + $url .= mb_strpos($path, '?') !== false ? '&' : '?'; foreach ($query as $key => $value) { if ($value) { @@ -371,12 +350,12 @@ function url_construct(string $path, array $query = [], string $host = ''): stri } } - return substr($url, 0, -1); + return mb_substr($url, 0, -1); } function camel_to_snake(string $camel): string { - return trim(strtolower(preg_replace('#([A-Z][a-z]+)#', '$1_', $camel)), '_'); + return trim(mb_strtolower(preg_replace('#([A-Z][a-z]+)#', '$1_', $camel)), '_'); } function snake_to_camel(string $snake): string