$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]); }, 'error' => self::translate($attribute) . ' est obligatoire' ]; break; case 'sometimes': $validators[] = [ 'type' => $rule, 'validate' => function () use ($data, $attribute) { return true; }, 'error' => self::translate($attribute) . ' est falcutatif' ]; break; case 'int': $validators[] = [ 'type' => $rule, 'validate' => function () use ($data, $attribute) { return \is_int($data[$attribute]); }, 'error' => self::translate($attribute) . ' doit être un entier' ]; break; case 'string': $validators[] = [ 'type' => $rule, 'validate' => function () use ($data, $attribute) { return \is_string($data[$attribute]); }, 'error' => self::translate($attribute) . ' doit être une chaine de charactères' ]; break; case 'bool': $validators[] = [ 'type' => $rule, 'validate' => function () use ($data, $attribute) { return \is_bool($data[$attribute]); }, 'error' => self::translate($attribute) . ' doit être un booléen' ]; break; case 'min': $validators[] = [ 'type' => $rule, 'validate' => function () use ($data, $attribute, $rParams) { return \is_string($data[$attribute]) and \strlen($data[$attribute]) >= (int)$rParams[0]; }, 'error' => self::translate($attribute) . " doit avoir au moins $rParams[0] caratères" ]; break; case 'max': $validators[] = [ 'type' => $rule, 'validate' => function () use ($data, $attribute, $rParams) { return \is_string($data[$attribute]) and \strlen($data[$attribute]) <= (int)$rParams[0]; }, 'error' => self::translate($attribute) . " doit avoir plus ou $rParams[0] caratères" ]; break; case 'uuid': $validators[] = [ 'type' => $rule, 'validate' => function () use ($data, $attribute) { return Validator::uuid()->validate($data[$attribute]); }, '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) { return \preg_match('/[^a-zA-Z0-9]/', $data[$attribute]); }, // phpcs:ignore Generic.Files.LineLength.TooLong 'error' => self::translate($attribute) . ' doit contenir au moins un caractère spécial comme une virgule par exemple' ]; break; case 'date': $validators[] = [ 'type' => $rule, 'validate' => function () use ($data, $attribute) { return Validator::dateTime()->validate($data[$attribute]); }, 'error' => self::translate($attribute) . ' doit être une date valide' ]; break; case 'date_format': $validators[] = [ 'type' => $rule, 'validate' => function () use ($data, $attribute, $rParams) { return Validator::dateTime($rParams[0])->validate($data[$attribute]); }, 'error' => self::translate($attribute) . " doit être une date au format $rParams[0]" ]; break; case 'email': $validators[] = [ 'type' => $rule, 'validate' => function () use ($data, $attribute) { return Validator::email()->validate($data[$attribute]); }, 'error' => self::translate($attribute) . ' doit être un email valide' ]; break; case 'array': $validators[] = [ 'type' => $rule, 'validate' => function () use ($data, $attribute) { return Validator::arrayType()->validate($data[$attribute]); }, 'error' => self::translate($attribute) . ' doit être un email valide' ]; break; case 'closure': $validators[] = [ 'type' => $rule, 'validate' => function () use ($data, $attribute, $closure, $closureFail) { $closure($attribute, $data[$attribute], $closureFail); return true; }, 'error' => self::translate($attribute) . ' doit être validé' ]; break; default: throw new \Exception("Unknown validation rule $rule " . implode(': ', $rParams)); } } } return function () use ($validators) { foreach ($validators as $validator) { if (!$validator['validate']()) { throw new ValidationException($validator['error']); } } }; } /** * 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; } /** * Translation a string using php file lang * * @param string $key * @param string $lang * @return string */ 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]; } } } /** * Write log using syslog * It also write log using \Illuminate\Support\Facades\Log * if it is present * * @param string $message The message is prefixed with "LDC CRM:" * @param \LDC\LDCCRM\Enums\LogLevel $level The log level to apply * @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); } }