Skip to content

Commit

Permalink
Add strict types
Browse files Browse the repository at this point in the history
  • Loading branch information
carry0987 committed Jul 21, 2024
1 parent f6711da commit ddd7208
Show file tree
Hide file tree
Showing 13 changed files with 113 additions and 73 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# exclude files from the generated tarball
.git* export-ignore
cache/ export-ignore
lang/ export-ignore
example.php export-ignore
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

.DS_Store
cache/*.php
vendor/*
composer.lock
/vendor/
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"keywords": ["i18n", "php-i18n", "language"],
"type": "library",
"require": {
"php": ">=8.0"
"php": ">=8.0",
"carry0987/utils": "^1.0"
},
"license": "MIT",
"autoload": {
Expand Down
60 changes: 60 additions & 0 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions src/Cache/CacheManager.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<?php
declare(strict_types=1);

namespace carry0987\I18n\Cache;

use carry0987\I18n\I18n;
use carry0987\I18n\Exception\IOException;
use carry0987\Utils\Utils;

class CacheManager
{
Expand All @@ -26,7 +28,7 @@ public function isCacheValid(string $directory, string $cacheFile): bool
}

$cachedTime = filemtime($cacheFile);
$files = glob($directory.I18n::DIR_SEP.'*.json');
$files = glob($directory.Utils::DIR_SEP.'*.json');
foreach ($files as $file) {
if (filemtime($file) > $cachedTime) {
return false;
Expand All @@ -38,7 +40,7 @@ public function isCacheValid(string $directory, string $cacheFile): bool

public function generateCache(string $cacheFileName): void
{
if (!I18n::makePath(dirname($cacheFileName))) {
if (!Utils::makePath(dirname($cacheFileName))) {
throw new IOException('Unable to create cache directory for file {'.$cacheFileName.'}.');
}

Expand Down
8 changes: 5 additions & 3 deletions src/Config/Config.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<?php
declare(strict_types=1);

namespace carry0987\I18n\Config;

use carry0987\I18n\I18n;
use carry0987\I18n\Exception\InvalidLanguageCodeException;
use carry0987\Utils\Utils;

class Config
{
Expand Down Expand Up @@ -31,8 +33,8 @@ public static function setOptions(array $options): void
$options = array_merge(self::$defaultOptions, $options);
self::$config['useAutoDetect'] = $options['useAutoDetect'];
self::$config['defaultLang'] = $options['defaultLang'];
self::$config['langFilePath'] = isset($options['langFilePath']) ? I18n::trimPath($options['langFilePath']) : null;
self::$config['cachePath'] = isset($options['cachePath']) ? I18n::trimPath($options['cachePath']) : null;
self::$config['langFilePath'] = isset($options['langFilePath']) ? Utils::trimPath($options['langFilePath']) : null;
self::$config['cachePath'] = isset($options['cachePath']) ? Utils::trimPath($options['cachePath']) : null;
self::$config['separator'] = $options['separator'];
self::$config['autoSearch'] = $options['autoSearch'];
self::$config['countryCodeUpperCase'] = $options['countryCodeUpperCase'];
Expand Down
2 changes: 2 additions & 0 deletions src/Cookie/CookieService.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);

namespace carry0987\I18n\Cookie;

use carry0987\I18n\Config\Config;
Expand Down
2 changes: 2 additions & 0 deletions src/Exception/IOException.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);

namespace carry0987\I18n\Exception;

class IOException extends \Exception {}
2 changes: 2 additions & 0 deletions src/Exception/InitializationException.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);

namespace carry0987\I18n\Exception;

class InitializationException extends \Exception {}
2 changes: 2 additions & 0 deletions src/Exception/InvalidLanguageCodeException.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);

namespace carry0987\I18n\Exception;

class InvalidLanguageCodeException extends \InvalidArgumentException {}
68 changes: 15 additions & 53 deletions src/I18n.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);

namespace carry0987\I18n;

use carry0987\I18n\Language\LanguageLoader;
Expand All @@ -7,20 +9,22 @@
use carry0987\I18n\Cookie\CookieService;
use carry0987\I18n\Exception\InitializationException;
use carry0987\I18n\Exception\IOException;
use carry0987\Utils\Utils;

class I18n
{
private $languageLoader;
private $languageCodeValidator;
private $config;
private $cookieService;

private $currentLang;
private $initialized = false;
// Class properties
private LanguageLoader $languageLoader;
private LanguageCodeValidator $languageCodeValidator;
private Config $config;
private CookieService $cookieService;

private static $option;
// Instance properties
private string $currentLang;
private bool $initialized = false;

const DIR_SEP = DIRECTORY_SEPARATOR;
// Options
private static array $option;

public function __construct(array $options = [])
{
Expand All @@ -40,7 +44,7 @@ public function __construct(array $options = [])
return $this;
}

public function initialize(string $language = null)
public function initialize(string $language = null): void
{
if ($this->initialized) {
throw new InitializationException('The I18n class has already been initialized');
Expand Down Expand Up @@ -114,53 +118,11 @@ public function fetchCurrentLang(): string

private function validateLanguageFolder(string $folder): string
{
$folderPath = self::$option['langFilePath'].self::DIR_SEP.$folder;
$folderPath = self::$option['langFilePath'].Utils::DIR_SEP.$folder;
if (!is_dir($folderPath)) {
throw new IOException('Language folder does not exist: {'.$folder.'}');
}

return $folder;
}

public static function trimPath(string $path): string
{
return str_replace(array('/', '\\', '//', '\\\\'), self::DIR_SEP, $path);
}

public static function makePath(string $path): bool
{
$path = self::trimPath($path); // Ensure path format is consistent.
$isAbsolute = (strpos($path, self::DIR_SEP) === 0); // Determine if it's an absolute path.
$currentPath = $isAbsolute ? self::DIR_SEP : ''; // Handle both absolute and relative paths.
$parts = array_filter(explode(self::DIR_SEP, $path), 'strlen'); // Split the path into individual parts.
$pathStack = [];

// Loop through parts to create directories.
foreach ($parts as $part) {
if ($part === '..') {
// If it's a parent directory indicator, pop the last element from the stack
// unless the stack is empty which means we are at the root for absolute paths.
if (!empty($pathStack)) {
array_pop($pathStack);
} elseif (!$isAbsolute) {
// Append .. parts to stack if path is relative.
$pathStack[] = $part;
}
// If the path is absolute and the stack is empty, no action is needed since we are at the root.
} elseif ($part !== '.') {
// Skip the current directory indicator '.' as it has no effect on the path.
$pathStack[] = $part; // Push the current part to the stack.
}
}

// Reconstruct path from the stack.
$currentPath .= implode(self::DIR_SEP, $pathStack);

// Ensure the directory exists.
if (!is_dir($currentPath) && !mkdir($currentPath, 0755, true)) {
throw new IOException('Unable to create directory '.$currentPath);
}

return true; // Return true if the directory has been successfully created or already exists.
}
}
6 changes: 4 additions & 2 deletions src/Language/LanguageCodeValidator.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<?php
declare(strict_types=1);

namespace carry0987\I18n\Language;

use carry0987\I18n\I18n;
use carry0987\I18n\Config\Config;
use carry0987\I18n\Exception\IOException;
use carry0987\I18n\Exception\InvalidLanguageCodeException;
use carry0987\Utils\Utils;

class LanguageCodeValidator
{
Expand Down Expand Up @@ -66,7 +68,7 @@ public function getLanguageList(): array
throw new IOException('Language directory does not exist: {'.$langDir.'}');
}

$directories = glob($langDir.I18n::DIR_SEP.'*', GLOB_ONLYDIR);
$directories = glob($langDir.Utils::DIR_SEP.'*', GLOB_ONLYDIR);
$langList = [];
foreach ($directories as $dir) {
$langCode = basename($dir);
Expand Down
20 changes: 11 additions & 9 deletions src/Language/LanguageLoader.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<?php
declare(strict_types=1);

namespace carry0987\I18n\Language;

use carry0987\I18n\I18n;
use carry0987\I18n\Config\Config;
use carry0987\I18n\Cache\CacheManager;
use carry0987\I18n\Exception\IOException;
use carry0987\Utils\Utils;

class LanguageLoader
{
Expand Down Expand Up @@ -48,14 +50,14 @@ public function loadLanguageFile(string $filePath, string $fileName): void

public function loadLanguageData(): void
{
$directory = $this->langFilePath.I18n::DIR_SEP.self::$currentLang;
$directory = $this->langFilePath.Utils::DIR_SEP.self::$currentLang;
if (!is_dir($directory)) {
throw new IOException('Language folder does not exist: {'.$directory.'}');
}

if ($this->cachePath) {
$cacheManager = new CacheManager();
$cacheFile = $this->cachePath.I18n::DIR_SEP.self::$currentLang.'.php';
$cacheFile = $this->cachePath.Utils::DIR_SEP.self::$currentLang.'.php';
if ($cacheManager->isCacheValid($directory, $cacheFile)) {
$this->languageData = include $cacheFile;
} else {
Expand Down Expand Up @@ -89,7 +91,7 @@ public function getValue(string $lang, string $key): string
$translationKey = implode('.', $keys); // Combine the remaining key path

// Try to load the language data for the corresponding file first
$filePath = $this->langFilePath.I18n::DIR_SEP.$lang.I18n::DIR_SEP.$fileKey.'.json';
$filePath = $this->langFilePath.Utils::DIR_SEP.$lang.Utils::DIR_SEP.$fileKey.'.json';
if (isset($this->languageData[$fileKey], $this->languageData[$fileKey][$translationKey])) {
// If the language data has already been loaded, get the translation directly from the data structure
return $this->languageData[$fileKey][$translationKey];
Expand All @@ -111,8 +113,8 @@ public function getAllValues(array $fileList): array
if (empty($fileList)) {
if (empty($this->allowedFiles)) {
// Load all files in the language directory
$directory = $this->langFilePath.I18n::DIR_SEP.self::$currentLang;
$files = glob($directory.I18n::DIR_SEP.'*.json');
$directory = $this->langFilePath.Utils::DIR_SEP.self::$currentLang;
$files = glob($directory.Utils::DIR_SEP.'*.json');
foreach ($files as $file) {
$fileName = basename($file, '.json');
$fileList[] = $fileName;
Expand All @@ -128,7 +130,7 @@ public function getAllValues(array $fileList): array

$allData = [];
foreach ($fileList as $fileName) {
$filePath = $this->langFilePath.I18n::DIR_SEP.self::$currentLang.I18n::DIR_SEP.$fileName.'.json';
$filePath = $this->langFilePath.Utils::DIR_SEP.self::$currentLang.Utils::DIR_SEP.$fileName.'.json';
if (isset($this->languageData[$fileName])) {
// If the language data has already been loaded, use it directly
$allData[$fileName] = $this->languageData[$fileName];
Expand All @@ -147,8 +149,8 @@ public function getAllValues(array $fileList): array

private function loadAllLanguageFiles(): void
{
$directory = $this->langFilePath.I18n::DIR_SEP.self::$currentLang;
$files = glob($directory.I18n::DIR_SEP.'*.json');
$directory = $this->langFilePath.Utils::DIR_SEP.self::$currentLang;
$files = glob($directory.Utils::DIR_SEP.'*.json');
foreach ($files as $file) {
$fileName = basename($file, '.json');
if (substr_count($fileName, '.') > 0) {
Expand Down

0 comments on commit ddd7208

Please sign in to comment.