2021-08-09 09:18:46 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace LDC\LDCCRM;
|
|
|
|
|
|
|
|
|
|
use Dotenv\Dotenv;
|
|
|
|
|
use LDC\LDCCRM\Enums\HttpMethods;
|
2021-09-14 13:44:03 +02:00
|
|
|
use LDC\LDCCRM\Enums\LogLevel;
|
2021-08-13 10:24:57 +02:00
|
|
|
use LDC\LDCCRM\Exceptions\ValidationException;
|
2021-08-09 09:18:46 +02:00
|
|
|
use LDC\LDCCRM\Transport\Request;
|
2021-08-13 10:24:57 +02:00
|
|
|
use Respect\Validation\Validator;
|
2021-08-09 09:18:46 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This is the LDCCRM utility class
|
|
|
|
|
*
|
|
|
|
|
* @category Utility
|
|
|
|
|
* @uses \LDC\LDCCRM\Enums\HttpMethods
|
|
|
|
|
* @uses \LDC\LDCCRM\Transport\Request
|
|
|
|
|
*
|
|
|
|
|
* @package LDCCrmClient
|
|
|
|
|
* @subpackage utilities
|
|
|
|
|
*/
|
|
|
|
|
class Utils
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Package infos
|
|
|
|
|
*
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
|
|
|
|
private static $packageInfos;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The env config
|
|
|
|
|
*
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
|
|
|
|
private static $config;
|
|
|
|
|
|
2021-08-17 09:51:02 +02:00
|
|
|
/**
|
|
|
|
|
* Loaded translations
|
|
|
|
|
*
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
|
|
|
|
private static $translations = [];
|
|
|
|
|
|
2021-08-09 09:18:46 +02:00
|
|
|
/**
|
|
|
|
|
* Create a new Validator instance.
|
|
|
|
|
*
|
|
|
|
|
* @param array $data
|
|
|
|
|
* @param array $rules
|
|
|
|
|
* @param array $messages
|
|
|
|
|
* @param array $customAttributes
|
|
|
|
|
* @return \Illuminate\Validation\Validator
|
|
|
|
|
*/
|
2021-08-17 09:51:02 +02:00
|
|
|
// phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
|
2021-08-09 09:18:46 +02:00
|
|
|
public static function makeValidator(
|
|
|
|
|
array $data,
|
2021-08-13 10:24:57 +02:00
|
|
|
array $rules
|
|
|
|
|
): object {
|
|
|
|
|
foreach ($rules as $attribute => $attrRules) {
|
|
|
|
|
$validators = [];
|
|
|
|
|
if (\is_string($attrRules)) {
|
|
|
|
|
$attrRules = \explode('|', $attrRules);
|
|
|
|
|
}
|
|
|
|
|
foreach ($attrRules as $rule) {
|
|
|
|
|
$closureFail = function ($message) {
|
|
|
|
|
throw new ValidationException($message);
|
|
|
|
|
};
|
|
|
|
|
$closure = null;
|
|
|
|
|
$rParams = [];
|
|
|
|
|
if (\is_callable($rule) and !is_string($rule)) {
|
|
|
|
|
$closure = $rule;
|
|
|
|
|
$rule = 'closure';
|
|
|
|
|
} elseif (\strpos($rule, ':') !== false) {
|
|
|
|
|
$rParams = \explode(':', $rule, 2);
|
|
|
|
|
$rule = \array_shift($rParams);
|
|
|
|
|
}
|
|
|
|
|
switch ($rule) {
|
|
|
|
|
case 'required':
|
|
|
|
|
$validators[] = [
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute) {
|
|
|
|
|
return isset($data[$attribute]);
|
|
|
|
|
},
|
2021-08-17 09:51:02 +02:00
|
|
|
'error' => self::translate($attribute) . ' est obligatoire'
|
2021-08-13 10:24:57 +02:00
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'sometimes':
|
|
|
|
|
$validators[] = [
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute) {
|
|
|
|
|
return true;
|
|
|
|
|
},
|
2021-08-17 09:51:02 +02:00
|
|
|
'error' => self::translate($attribute) . ' est falcutatif'
|
2021-08-13 10:24:57 +02:00
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'int':
|
|
|
|
|
$validators[] =
|
|
|
|
|
[
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute) {
|
|
|
|
|
return \is_int($data[$attribute]);
|
|
|
|
|
},
|
2021-08-17 09:51:02 +02:00
|
|
|
'error' => self::translate($attribute) . ' doit être un entier'
|
2021-08-13 10:24:57 +02:00
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'string':
|
|
|
|
|
$validators[] =
|
|
|
|
|
[
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute) {
|
|
|
|
|
return \is_string($data[$attribute]);
|
|
|
|
|
},
|
2021-08-17 09:51:02 +02:00
|
|
|
'error' => self::translate($attribute) . ' doit être une chaine de charactères'
|
2021-08-13 10:24:57 +02:00
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'bool':
|
|
|
|
|
$validators[] =
|
|
|
|
|
[
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute) {
|
|
|
|
|
return \is_bool($data[$attribute]);
|
|
|
|
|
},
|
2021-08-17 09:51:02 +02:00
|
|
|
'error' => self::translate($attribute) . ' doit être un booléen'
|
2021-08-13 10:24:57 +02:00
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'min':
|
|
|
|
|
$validators[] = [
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute, $rParams) {
|
|
|
|
|
return \is_string($data[$attribute]) and
|
|
|
|
|
\strlen($data[$attribute]) >= (int)$rParams[0];
|
|
|
|
|
},
|
2021-08-17 09:51:02 +02:00
|
|
|
'error' => self::translate($attribute) . " doit avoir moins ou $rParams[0] caratères"
|
2021-08-13 10:24:57 +02:00
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'max':
|
|
|
|
|
$validators[] = [
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute, $rParams) {
|
|
|
|
|
return \is_string($data[$attribute]) and
|
|
|
|
|
\strlen($data[$attribute]) <= (int)$rParams[0];
|
|
|
|
|
},
|
2021-08-17 09:51:02 +02:00
|
|
|
'error' => self::translate($attribute) . " doit avoir plus ou $rParams[0] caratères"
|
2021-08-13 10:24:57 +02:00
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'uuid':
|
|
|
|
|
$validators[] = [
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute) {
|
|
|
|
|
return Validator::uuid()->validate($data[$attribute]);
|
|
|
|
|
},
|
2021-08-17 09:51:02 +02:00
|
|
|
'error' => self::translate($attribute) . ' doit être un uuid'
|
|
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'mixedCase':
|
|
|
|
|
$validators[] = [
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute) {
|
|
|
|
|
return \preg_match('/[a-z]/', $data[$attribute]) and
|
|
|
|
|
\preg_match('/[A-Z]/', $data[$attribute]);
|
|
|
|
|
},
|
|
|
|
|
'error' => self::translate($attribute) . ' doit contenir des lettre minuscules et majuscules'
|
|
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'containDigit':
|
|
|
|
|
$validators[] = [
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute) {
|
|
|
|
|
return \preg_match('/[0-9]/', $data[$attribute]);
|
|
|
|
|
},
|
|
|
|
|
'error' => self::translate($attribute) . ' doit contenir au moins un chiffre'
|
|
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'containSymbol':
|
|
|
|
|
$validators[] = [
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute) {
|
2021-09-07 14:41:16 +02:00
|
|
|
return \preg_match('/[^a-zA-Z0-9]/', $data[$attribute]);
|
2021-08-17 09:51:02 +02:00
|
|
|
},
|
|
|
|
|
// phpcs:ignore Generic.Files.LineLength.TooLong
|
|
|
|
|
'error' => self::translate($attribute) . ' doit contenir au moins un caractère spécial comme une virgule par exemple'
|
2021-08-13 10:24:57 +02:00
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'date':
|
|
|
|
|
$validators[] = [
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute) {
|
|
|
|
|
return Validator::dateTime()->validate($data[$attribute]);
|
|
|
|
|
},
|
2021-08-17 09:51:02 +02:00
|
|
|
'error' => self::translate($attribute) . ' doit être une date valide'
|
2021-08-13 10:24:57 +02:00
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'date_format':
|
|
|
|
|
$validators[] = [
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute, $rParams) {
|
|
|
|
|
return Validator::dateTime($rParams[0])->validate($data[$attribute]);
|
|
|
|
|
},
|
2021-08-17 09:51:02 +02:00
|
|
|
'error' => self::translate($attribute) . " doit être une date au format $rParams[0]"
|
2021-08-13 10:24:57 +02:00
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'email':
|
|
|
|
|
$validators[] = [
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute) {
|
|
|
|
|
return Validator::email()->validate($data[$attribute]);
|
|
|
|
|
},
|
2021-08-17 09:51:02 +02:00
|
|
|
'error' => self::translate($attribute) . ' doit être un email valide'
|
2021-08-13 10:24:57 +02:00
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
case 'closure':
|
|
|
|
|
$validators[] = [
|
|
|
|
|
'type' => $rule,
|
|
|
|
|
'validate' => function () use ($data, $attribute, $closure, $closureFail) {
|
|
|
|
|
$closure($attribute, $data[$attribute], $closureFail);
|
|
|
|
|
return true;
|
|
|
|
|
},
|
2021-08-17 09:51:02 +02:00
|
|
|
'error' => self::translate($attribute) . ' doit être validé'
|
2021-08-13 10:24:57 +02:00
|
|
|
];
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw new \Exception("Unknown validation rule $rule " . implode(': ', $rParams));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return function () use ($validators) {
|
|
|
|
|
foreach ($validators as $validator) {
|
|
|
|
|
if (!$validator['validate']()) {
|
2021-08-17 09:51:02 +02:00
|
|
|
throw new ValidationException($validator['error']);
|
2021-08-13 10:24:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2021-08-09 09:18:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get config
|
|
|
|
|
*
|
|
|
|
|
* @param string $key
|
|
|
|
|
* @param string $default
|
|
|
|
|
* @return string|null
|
|
|
|
|
* @throws \Dotenv\Exception\InvalidPathException|\Dotenv\Exception\InvalidEncodingException|\Dotenv\Exception\InvalidFileException
|
|
|
|
|
*/
|
|
|
|
|
public static function getConfig(string $key, string $default = null): ?string
|
|
|
|
|
{
|
|
|
|
|
$value = null;
|
|
|
|
|
if (function_exists('config')) {
|
|
|
|
|
$value = \config($key, $default);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (!self::$config) {
|
|
|
|
|
$dotenv = Dotenv::createImmutable(__DIR__ . '/..');
|
|
|
|
|
self::$config = $dotenv->load();
|
|
|
|
|
}
|
|
|
|
|
} catch (\Dotenv\Exception\InvalidPathException $e) {
|
|
|
|
|
return $value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isset(self::$config[$key])) {
|
|
|
|
|
$value = self::$config[$key];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Generate a Request from the route name
|
|
|
|
|
*
|
|
|
|
|
* @param string $routeName
|
|
|
|
|
* @param array $query params to pass on to the route
|
|
|
|
|
* @param array $data http body params
|
|
|
|
|
* @return Request
|
|
|
|
|
*/
|
|
|
|
|
public static function getResquest(string $routeName, array $query = [], array $data = []): Request
|
|
|
|
|
{
|
|
|
|
|
// convert bool to integer
|
|
|
|
|
$query = \array_map(function ($v) {
|
|
|
|
|
return is_bool($v) ? (int)$v : $v;
|
|
|
|
|
}, $query);
|
|
|
|
|
$data = \array_map(function ($v) {
|
|
|
|
|
return is_bool($v) ? (int)$v : $v;
|
|
|
|
|
}, $data);
|
|
|
|
|
|
|
|
|
|
$routes = \json_decode(\file_get_contents(__DIR__ . '/routes.json'), true);
|
|
|
|
|
if (!isset($routes[$routeName])) {
|
|
|
|
|
throw new \Exception("Unknown route $routeName from the crm");
|
|
|
|
|
}
|
|
|
|
|
$route = $routes[$routeName];
|
|
|
|
|
$matches = [];
|
|
|
|
|
$matchedIndex = [];
|
|
|
|
|
\preg_match_all('/{([\w-]*)}/', $route['uri'], $matches);
|
|
|
|
|
if (\count($matches[0])) {
|
|
|
|
|
foreach ($matches[0] as $k => $match) {
|
|
|
|
|
if (!isset($query[$matches[1][$k]])) {
|
|
|
|
|
throw new \Exception(sprintf('Missing required parameter %s', $matches[1][$k]));
|
|
|
|
|
}
|
|
|
|
|
$route['uri'] = str_replace($match, $query[$matches[1][$k]], $route['uri']);
|
|
|
|
|
$matchedIndex[$matches[1][$k]] = $query[$matches[1][$k]];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$query = \array_flip($query);
|
|
|
|
|
foreach ($matchedIndex as $key) {
|
|
|
|
|
unset($query[$key]);
|
|
|
|
|
}
|
|
|
|
|
$query = \array_flip($query);
|
|
|
|
|
if (count($query)) {
|
|
|
|
|
$route['uri'] = sprintf('%s?%s', $route['uri'], \http_build_query($query));
|
|
|
|
|
}
|
|
|
|
|
return new Request(HttpMethods::make($route['methods'][0]), $route['uri'], [], $data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get composer.json infos
|
|
|
|
|
*
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public static function getPackageInfo(): array
|
|
|
|
|
{
|
|
|
|
|
if (!static::$packageInfos) {
|
|
|
|
|
static::$packageInfos = \json_decode(\file_get_contents(__DIR__ . '/../composer.json'), true);
|
|
|
|
|
}
|
|
|
|
|
return static::$packageInfos;
|
|
|
|
|
}
|
2021-08-17 09:51:02 +02:00
|
|
|
|
2021-09-14 14:23:18 +02:00
|
|
|
/**
|
|
|
|
|
* Translation a string using php file lang
|
|
|
|
|
*
|
|
|
|
|
* @param string $key
|
|
|
|
|
* @param string $lang
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2021-08-17 09:51:02 +02:00
|
|
|
public static function translate(string $key, string $lang = 'fr'): string
|
|
|
|
|
{
|
|
|
|
|
try {
|
|
|
|
|
if (!array_key_exists($lang, self::$translations)) {
|
|
|
|
|
self::$translations = require __DIR__ . "/../resources/lang/$lang.php";
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
if (!isset(self::$translations['validation'][$key])) {
|
|
|
|
|
return $key;
|
|
|
|
|
} else {
|
|
|
|
|
return self::$translations['validation'][$key];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-09-14 13:44:03 +02:00
|
|
|
|
|
|
|
|
/**
|
2021-09-14 14:23:18 +02:00
|
|
|
* Write log using syslog
|
|
|
|
|
* It also write log using \Illuminate\Support\Facades\Log
|
|
|
|
|
* if it is present
|
2021-09-14 13:44:03 +02:00
|
|
|
*
|
2021-09-14 14:23:18 +02:00
|
|
|
* @param string $message The message is prefixed with "LDC CRM:"
|
|
|
|
|
* @param \LDC\LDCCRM\Enums\LogLevel $level The log level to apply
|
2021-09-14 13:44:03 +02:00
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public static function log(string $message, LogLevel $level)
|
|
|
|
|
{
|
|
|
|
|
$message = "LDC CRM: $message";
|
|
|
|
|
if (\class_exists('\Illuminate\Support\Facades\Log')) {
|
|
|
|
|
switch ($level) {
|
|
|
|
|
case LogLevel::EMERG():
|
|
|
|
|
\Illuminate\Support\Facades\Log::emergency($message);
|
|
|
|
|
break;
|
|
|
|
|
case LogLevel::ALERT():
|
|
|
|
|
\Illuminate\Support\Facades\Log::alert($message);
|
|
|
|
|
break;
|
|
|
|
|
case LogLevel::CRIT():
|
|
|
|
|
\Illuminate\Support\Facades\Log::critical($message);
|
|
|
|
|
break;
|
|
|
|
|
case LogLevel::ERR():
|
|
|
|
|
\Illuminate\Support\Facades\Log::error($message);
|
|
|
|
|
break;
|
|
|
|
|
case LogLevel::WARNING():
|
|
|
|
|
\Illuminate\Support\Facades\Log::warning($message);
|
|
|
|
|
break;
|
|
|
|
|
case LogLevel::NOTICE():
|
|
|
|
|
\Illuminate\Support\Facades\Log::notice($message);
|
|
|
|
|
break;
|
|
|
|
|
case LogLevel::INFO():
|
|
|
|
|
\Illuminate\Support\Facades\Log::info($message);
|
|
|
|
|
break;
|
|
|
|
|
case LogLevel::DEBUG():
|
|
|
|
|
\Illuminate\Support\Facades\Log::debug($message);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
\Illuminate\Support\Facades\Log::warning($message);
|
|
|
|
|
}
|
|
|
|
|
\syslog(\constant($level), $message);
|
|
|
|
|
}
|
2021-08-09 09:18:46 +02:00
|
|
|
}
|