/** * Returns matcher closure by $pattern * * @param array $pattern * * @return \Closure * * @see https://github.com/ptrofimov/matchmaker - ultra-fresh PHP matching functions * @author Petr Trofimov <*****@*****.**> */ function key_catcher(array $pattern, $context) { $keys = []; foreach ($pattern as $k => $v) { $chars = ['?' => [0, 1], '*' => [0, PHP_INT_MAX], '!' => [1, 1]]; if (isset($chars[$last = substr($k, -1)])) { $keys[$k = substr($k, 0, -1)] = $chars[$last]; } elseif ($last == '}') { list($k, $range) = explode('{', $k); $range = explode(',', rtrim($range, '}')); $keys[$k] = count($range) == 1 ? [$range[0], $range[0]] : [$range[0] === '' ? 0 : $range[0], $range[1] === '' ? PHP_INT_MAX : $range[1]]; } else { $keys[$k] = $chars[$k[0] == ':' ? '*' : '!']; } array_push($keys[$k], $v, 0); } return function ($key = null, $value = null) use(&$keys, $context) { if (is_null($key)) { foreach ($keys as $count) { if ($count[3] < $count[0] || $count[3] > $count[1]) { return false; } } } else { foreach ($keys as $k => &$count) { if (catcher($key, $k)) { if (!catches($value, $count[2], $context . '.' . $key)) { return false; } $count[3]++; } } } return true; }; }
function catches($value, $pattern, $context = '') { require_once 'key_catcher.php'; if (is_array($pattern)) { if (!is_array($value) && !$value instanceof \Traversable) { return false; } $keyCatcher = key_catcher($pattern, $context); foreach ($value as $key => $item) { if (!$keyCatcher($key, $item)) { throw new \Exception("validation error: invalid key '" . $context . '.' . $key . "'"); } if ($keyCatcher($key)) { throw new \Exception("validation error: key '" . $context . '.' . $key . "' not found in schema"); } } if (!$keyCatcher()) { return false; } } elseif (!catcher($value, $pattern)) { return false; } return true; }
<?php def_printfer('p', "%s\n"); p(1); catcher('warning', function () { echo "warning!\n"; }); noise('warning'); p(2); catcher('warning', function () { echo "error!\n"; }); noise('warning'); p(3); ?> --- 1 warning! 2 error! 3
<?php def_printfer('p', "%s\n"); p(1); noise('warning'); p(2); catcher('warning', function () { echo "warning!\n"; }); noise('warning'); p(3); ?> --- 1 2 warning! 3
<?php catcher('warning', function ($one, $two, $three) { echo $one . $two . $three; }); noise('warning', 1, 2, 3); ?> --- 123