/** * Получение данных из суперглобальных массивов $_GET, $_POST, $_COOKIE или $_REQUEST. * * Описание методов см. в комментарии к этому классу. * * Суть: парсим запрошенный метод. Если совпадает с тем, что мы поддерживаем, подключаемся к нужному массиву. * По заданному количеству параметров функции пытаемся вернуть требуемое значение. В частности в методе приведения * к типу ожидаем имя ключа в массиве, а при регулярке еще один параметр - шаблон регулярного выражения. * * Прим: параметры в этот метод попадают в виде неассоциативного массива, приходится по порядку ключей разбирать. * * Если вызов неправильный, кидаем исключение. Если значение в массиве не найдено (или регулярке не отвечает) - NULL * * @param string $method имя метода * @param array $params параметры метода * @return mixed * @throws \RuntimeException * @throws \LogicException */ public static function __callStatic($method, $params) { if (preg_match('/^(?<verb>get|post|request|cookie)(As(?<type>Int|Bool|Regexp|Enum))?$/', $method, $m)) { $verb = $m['verb']; $type = isset($m['type']) ? $m['type'] : null; } else { throw new \RuntimeException('Неизвестный метод ' . __NAMESPACE__ . "\\Request::{$method}()"); } // Прим.: нельзя использовать переменные переменных в данном случае. Поэтому - через условие. // {@see http://php.net/manual/ru/language.variables.variable.php}, внизу варнинг. switch ($verb) { case 'get': $arr =& $_GET; break; case 'post': $arr =& $_POST; break; case 'cookie': $arr =& $_COOKIE; break; case 'request': $arr =& $_REQUEST; break; default: $arr = []; } if (!$params) { if ($type) { $secondParam = $type == 'Regexp' ? ', $pattern' : ($type == 'Enum' ? ', $expect' : ''); throw new \RuntimeException("Пропущен обязательный параметр функции: имя ключа в массиве \$_{$verb}" . PHP_EOL . "Сигнатура вызова: {$method}(\$key{$secondParam})"); } return $arr; } $key =& $params[0]; $val = utils\Arrays::getValue($arr, $key); if (!$type || $val == '') { return $val; } if (is_array($val)) { throw new \LogicException('Для массива данных проверки содержимого невозможны. Полученное значение:' . utils\Dumper::dumpAsString($val)); } switch ($type) { case 'Int': return preg_match('~^-?\\d+$~', $val) ? intval($val) : null; case 'Bool': return preg_match('~^true|1|on|yes|checked$~i', $val) ? true : (preg_match('~^false|0|off|no|unchecked$~i', $val) ? false : null); case 'Regexp': if (!isset($params[1])) { throw new \RuntimeException('Пропущен обязательный параметр функции: шаблон регулярного выражения.' . PHP_EOL . "Сигнатура вызова: {$verb}AsRegexp(\$key, \$pattern)"); } $pattern =& $params[1]; return preg_match($pattern, $val) ? $val : null; case 'Enum': if (!isset($params[1])) { throw new \RuntimeException('Пропущен обязательный параметр функции: массив допустимых значений.' . PHP_EOL . "Сигнатура вызова: {$verb}AsEnum(\$key, \$expect)"); } return in_array($val, $params[1]) ? $val : null; default: return null; } }
/** * Пробуем пробить валидаторы * * Результаты можно получить несколькими способами, аналогично с self::test_validate() * * Прим.: пересоздаем модель формы, т.к. ее повторное использование не предусмотрено. */ public function test_invalid_data() { self::setUpBeforeClass(); $form = self::$form; $data = ['app_path' => '\\valid\\path\\tooLong', 'app_namespace' => null, 'email' => '*****@*****.**', 'db' => ['switch' => 'on', 'base' => [' my_base ', 'base2']], 'modules' => ' user ']; $result = $form->load($data)->validate(); $this->assertFalse($result, 'Валидация не прошла'); $this->assertFalse($form->isValid(), 'Результат проведенной валидации - неверные данные'); $this->assertTrue($form->hasErrors(), 'Есть ошибки валидации'); $errorsByField = Arrays::array_filter_recursive($form->getErrorsAsString()); $this->assertEquals(5, count($errorsByField), 'Есть ошибки по 5 полям'); }
/** * Получение всех ошибок по каждому полю, склееных в строку. * * Если контракт - сложный многомерный массив, то ошибки склеиваются из всех подмассивов для каждого старшего ключа. * На выходе всегда получается простой ассоциативный массив [поле => ошибки]. В случае сложного контракта полями * будут его старшие ключи. * * @param null $key ключ в массиве данных. Возможно составной ключ типа "['lvl1' => ['lvl2' => 'param1']]". * @param string $glue клей между соседними элементами одного массива * @param string $eol клей между соседними подмассивами * @return array */ public function getErrorsAsString($key = null, $glue = ' ', $eol = '') { $errors = $this->getErrors($key); foreach ($errors as &$v) { if (is_array($v)) { $v = Arrays::implode_recursive($v, $glue, $eol); } } return $errors; }
public function test_getValue() { $arr = ['path' => ['app' => ['level1' => '/home', 'level2' => '/www']]]; $expect = Arrays::getValue($arr, ['path' => ['app' => 'level2']]); $this->assertEquals($expect, '/www', 'Получение значения массива по заданной цепочке ключей'); }