1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13:
14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
25: class Jyxo_Svn_Result implements Countable, SeekableIterator
26: {
27:
28: 29: 30: 31: 32:
33: const OK = 'OK';
34:
35: 36: 37: 38: 39:
40: const KO = 'KO';
41:
42: 43: 44: 45: 46:
47: const ADD = 'A';
48:
49: 50: 51: 52: 53:
54: const DELETE = 'D';
55:
56: 57: 58: 59: 60:
61: const UPDATE = 'U';
62:
63: 64: 65: 66: 67:
68: const CONFLICT = 'C';
69:
70: 71: 72: 73: 74:
75: const MODIFIED = 'M';
76:
77: 78: 79: 80: 81:
82: const MERGE = 'G';
83:
84: 85: 86: 87: 88:
89: const EXTERNALS = 'X';
90:
91: 92: 93: 94: 95:
96: const IGNORED = 'I';
97:
98: 99: 100: 101: 102:
103: const LOCKED = 'L';
104:
105: 106: 107: 108: 109:
110: const NOT_VERSIONED = '?';
111:
112: 113: 114: 115: 116:
117: const MISSING = '!';
118:
119: 120: 121: 122: 123: 124:
125: const DIR_FILE_SWITCH = '~';
126:
127: 128: 129: 130: 131:
132: const SCHEDULED = '+';
133:
134: 135: 136: 137: 138:
139: const SWITCHED = 'S';
140:
141: 142: 143: 144: 145:
146: const NEW_VERSION_EXISTS = '*';
147:
148: 149: 150: 151: 152:
153: protected $statusTable = array(
154: self::ADD => 'A',
155: self::DELETE => 'D',
156: self::UPDATE => 'U',
157: self::CONFLICT => 'C',
158: self::MODIFIED => 'M',
159: self::MERGE => 'G',
160: self::EXTERNALS => 'X',
161: self::IGNORED => 'I',
162: self::LOCKED => 'L',
163: self::NOT_VERSIONED => '?',
164: self::MISSING => '!',
165: self::DIR_FILE_SWITCH => '',
166: self::SCHEDULED => '+',
167: self::SWITCHED => 'S',
168: self::NEW_VERSION_EXISTS => '*',
169: );
170:
171: 172: 173: 174: 175:
176: protected $revision;
177:
178: 179: 180: 181: 182:
183: protected $error = '';
184:
185: 186: 187: 188: 189:
190: protected $status;
191:
192: 193: 194: 195: 196:
197: protected $items = array();
198:
199: 200: 201: 202: 203:
204: protected $pointer = 0;
205:
206: 207: 208: 209: 210: 211: 212:
213: public function __construct($action, $input, $returnCode = 1)
214: {
215: $this->items = $this->parse($action, $input);
216: $this->status = $returnCode === 0 ? self::OK : self::KO;
217: $this->error = $returnCode === 0 ? '' : $input;
218: }
219:
220: 221: 222: 223: 224: 225: 226:
227: protected function parse($action, $input)
228: {
229: switch ($action) {
230: case 'add':
231: case 'status':
232: return $this->parseStatus($input);
233: case 'commit':
234: return $this->parseCommit($input);
235: case 'update':
236: return $this->parseUpdate($input);
237: default:
238:
239: return array();
240: }
241: }
242:
243: 244: 245: 246: 247: 248:
249: protected function parseStatus($input)
250: {
251: $array = explode("\n", (string) $input);
252: foreach ($array as $key => &$line) {
253:
254: $line = trim($line);
255:
256: if (empty($line)) {
257: unset($array[$key]);
258: continue;
259: }
260:
261: $tmp = $line;
262: $line = array();
263:
264: if ($tmp{0} !== ' ') {
265: $line['status'] = $tmp{0};
266: }
267: if ($tmp{1} !== ' ') {
268: $line['properties'] = $tmp{1};
269: }
270: if ($tmp{2} !== ' ') {
271: $line['lock'] = $tmp{2};
272: }
273: if ($tmp{3} !== ' ') {
274: $line['history'] = $tmp{3};
275: }
276: if ($tmp{4} !== ' ') {
277: $line['switch'] = $tmp{4};
278: }
279: $line['file'] = substr($tmp, 7);
280:
281: }
282: return $array;
283: }
284:
285: 286: 287: 288: 289: 290:
291: protected function parseCommit($input)
292: {
293: $array = explode("\n", (string) $input);
294: foreach ($array as $key => &$line) {
295:
296: $line = trim($line);
297:
298: if (empty($line)) {
299: unset($array[$key]);
300: continue;
301: }
302:
303: if (preg_match('/Committed revision ([0-9]+)\./i', $line, $matches)) {
304: $this->revision = (int) $matches[1];
305: unset($array[$key]);
306: continue;
307: }
308:
309: if (!preg_match('/Sending.*/', $line)) {
310: unset($array[$key]);
311: continue;
312: }
313:
314: }
315:
316: return $array;
317: }
318:
319: 320: 321: 322: 323: 324:
325: protected function parseUpdate($input)
326: {
327: $array = explode("\n", (string) $input);
328: foreach ($array as $key => &$line) {
329:
330: $line = trim($line);
331:
332: if (empty($line)) {
333: unset($array[$key]);
334: continue;
335: }
336:
337: if (preg_match('/At revision ([0-9]+)\./i', $line, $matches)) {
338: $this->revision = (int) $matches[1];
339: unset($array[$key]);
340: continue;
341: }
342:
343: }
344:
345: return $array;
346: }
347:
348: 349: 350: 351: 352: 353:
354: public function __get($prop)
355: {
356: return isset($this->$prop) ? $this->$prop : null;
357: }
358:
359: 360: 361: 362: 363: 364: 365:
366: public function seek($position)
367: {
368: $position = (int) $position;
369: if ($position < 0 || $position > count($this->items)) {
370: throw new Jyxo_Svn_Exception(sprintf('Illegal index %d', $position));
371: }
372: $this->pointer = $position;
373:
374: return $this;
375: }
376:
377: 378: 379: 380: 381:
382: public function current()
383: {
384: if ($this->valid()) {
385: return $this->items[$this->pointer];
386: }
387:
388: return null;
389: }
390:
391: 392: 393: 394: 395:
396: public function next()
397: {
398: return ++$this->pointer < count($this->items);
399: }
400:
401: 402: 403: 404: 405:
406: public function rewind()
407: {
408: $this->pointer = 0;
409:
410: return $this;
411: }
412:
413: 414: 415: 416: 417:
418: public function key()
419: {
420: return $this->items[$this->pointer];
421: }
422:
423: 424: 425: 426: 427:
428: public function valid()
429: {
430: return $this->pointer < count($this->items);
431: }
432:
433: 434: 435: 436: 437:
438: public function count()
439: {
440: return count($this->items);
441: }
442: }
443: