1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Tester;
9:
10:
11: 12: 13: 14: 15:
16: class DataProvider
17: {
18:
19: 20: 21: 22:
23: public static function loadCurrent()
24: {
25: if (isset($_SERVER['argv'][2])) {
26: list(, $query, $file) = $_SERVER['argv'];
27:
28: } else {
29: $trace = debug_backtrace();
30: $file = $trace[count($trace) - 1]['file'];
31: $annotations = Helpers::parseDocComment(file_get_contents($file));
32: if (!isset($annotations['dataprovider'])) {
33: throw new \Exception('Missing annotation @dataProvider.');
34: }
35: $provider = (array) $annotations['dataprovider'];
36: list($file, $query) = self::parseAnnotation($provider[0], $file);
37: }
38: $data = self::load($file, $query);
39: return reset($data);
40: }
41:
42:
43: public static function load($file, $query = NULL)
44: {
45: if (!is_file($file)) {
46: throw new \Exception("Missing data-provider file '$file'.");
47: }
48:
49: $data = @parse_ini_file($file, TRUE);
50: if ($data === FALSE) {
51: throw new \Exception("Cannot parse data-provider file '$file'.");
52: }
53:
54: foreach ($data as $key => $value) {
55: if (!self::testQuery($key, $query)) {
56: unset($data[$key]);
57: }
58: }
59:
60: if (!$data) {
61: throw new \Exception("No records in data-provider file '$file'" . ($query ? " for query '$query'" : '') . '.');
62: }
63: return $data;
64: }
65:
66:
67: public static function testQuery($input, $query)
68: {
69: static $replaces = array('' => '=', '=>' => '>=', '=<' => '<=');
70: $tokens = preg_split('#\s+#', $input);
71: preg_match_all('#\s*,?\s*(<=|=<|<|==|=|!=|<>|>=|=>|>)?\s*([^\s,]+)#A', $query, $queryParts, PREG_SET_ORDER);
72: foreach ($queryParts as $queryPart) {
73: list(, $operator, $operand) = $queryPart;
74: $operator = isset($replaces[$operator]) ? $replaces[$operator] : $operator;
75: $token = array_shift($tokens);
76: $res = preg_match('#^[0-9.]+\z#', $token)
77: ? version_compare($token, $operand, $operator)
78: : self::compare($token, $operator, $operand);
79: if (!$res) {
80: return FALSE;
81: }
82: }
83: return TRUE;
84: }
85:
86:
87: private static function compare($l, $operator, $r)
88: {
89: switch ($operator) {
90: case '>':
91: return $l > $r;
92: case '=>':
93: case '>=':
94: return $l >= $r;
95: case '<':
96: return $l < $r;
97: case '=<':
98: case '<=':
99: return $l <= $r;
100: case '=':
101: case '==':
102: return $l == $r;
103: case '!':
104: case '!=':
105: case '<>':
106: return $l != $r;
107: }
108: throw new \InvalidArgumentException("Unknown operator $operator.");
109: }
110:
111:
112: 113: 114: 115:
116: public static function parseAnnotation($annotation, $file)
117: {
118: if (!preg_match('#^(\??)\s*([^,\s]+)\s*,?\s*(\S.*)?()#', $annotation, $m)) {
119: throw new \Exception("Invalid @dataProvider value '$annotation'.");
120: }
121: return array(dirname($file) . DIRECTORY_SEPARATOR . $m[2], $m[3], (bool) $m[1]);
122: }
123:
124: }
125: