1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16: namespace TokenReflection;
17:
18: use TokenReflection\Exception;
19:
20: 21: 22:
23: class ReflectionNamespace implements IReflectionNamespace
24: {
25: 26: 27: 28: 29: 30: 31:
32: const NO_NAMESPACE_NAME = 'no-namespace';
33:
34: 35: 36: 37: 38:
39: private $name;
40:
41: 42: 43: 44: 45:
46: private $classes = array();
47:
48: 49: 50: 51: 52:
53: private $constants = array();
54:
55: 56: 57: 58: 59:
60: private $functions = array();
61:
62: 63: 64: 65: 66:
67: private $broker;
68:
69: 70: 71: 72: 73: 74:
75: public function __construct($name, Broker $broker)
76: {
77: $this->name = $name;
78: $this->broker = $broker;
79: }
80:
81: 82: 83: 84: 85:
86: public function getName()
87: {
88: return $this->name;
89: }
90:
91: 92: 93: 94: 95: 96: 97:
98: public function isInternal()
99: {
100: return false;
101: }
102:
103: 104: 105: 106: 107: 108: 109:
110: public function isUserDefined()
111: {
112: return true;
113: }
114:
115: 116: 117: 118: 119:
120: public function isTokenized()
121: {
122: return true;
123: }
124:
125: 126: 127: 128: 129: 130:
131: public function hasClass($className)
132: {
133: $className = ltrim($className, '\\');
134: if (false === strpos($className, '\\') && self::NO_NAMESPACE_NAME !== $this->getName()) {
135: $className = $this->getName() . '\\' . $className;
136: }
137:
138: return isset($this->classes[$className]);
139: }
140:
141: 142: 143: 144: 145: 146: 147:
148: public function getClass($className)
149: {
150: $className = ltrim($className, '\\');
151: if (false === strpos($className, '\\') && self::NO_NAMESPACE_NAME !== $this->getName()) {
152: $className = $this->getName() . '\\' . $className;
153: }
154:
155: if (!isset($this->classes[$className])) {
156: throw new Exception\RuntimeException(sprintf('Class "%s" does not exist.', $className), Exception\RuntimeException::DOES_NOT_EXIST, $this);
157: }
158:
159: return $this->classes[$className];
160: }
161:
162: 163: 164: 165: 166:
167: public function getClasses()
168: {
169: return $this->classes;
170: }
171:
172: 173: 174: 175: 176:
177: public function getClassNames()
178: {
179: return array_keys($this->classes);
180: }
181:
182: 183: 184: 185: 186:
187: public function getClassShortNames()
188: {
189: return array_map(function(IReflectionClass $class) {
190: return $class->getShortName();
191: }, $this->classes);
192: }
193:
194: 195: 196: 197: 198: 199:
200: public function hasConstant($constantName)
201: {
202: $constantName = ltrim($constantName, '\\');
203: if (false === strpos($constantName, '\\') && self::NO_NAMESPACE_NAME !== $this->getName()) {
204: $constantName = $this->getName() . '\\' . $constantName;
205: }
206:
207: return isset($this->constants[$constantName]);
208: }
209:
210: 211: 212: 213: 214: 215: 216:
217: public function getConstant($constantName)
218: {
219: $constantName = ltrim($constantName, '\\');
220: if (false === strpos($constantName, '\\') && self::NO_NAMESPACE_NAME !== $this->getName()) {
221: $constantName = $this->getName() . '\\' . $constantName;
222: }
223:
224: if (!isset($this->constants[$constantName])) {
225: throw new Exception\RuntimeException(sprintf('Constant "%s" does not exist.', $constantName), Exception\RuntimeException::DOES_NOT_EXIST, $this);
226: }
227:
228: return $this->constants[$constantName];
229: }
230:
231: 232: 233: 234: 235:
236: public function getConstants()
237: {
238: return $this->constants;
239: }
240:
241: 242: 243: 244: 245:
246: public function getConstantNames()
247: {
248: return array_keys($this->constants);
249: }
250:
251: 252: 253: 254: 255:
256: public function getConstantShortNames()
257: {
258: return array_map(function(IReflectionConstant $constant) {
259: return $constant->getShortName();
260: }, $this->constants);
261: }
262:
263: 264: 265: 266: 267: 268:
269: public function hasFunction($functionName)
270: {
271: $functionName = ltrim($functionName, '\\');
272: if (false === strpos($functionName, '\\') && self::NO_NAMESPACE_NAME !== $this->getName()) {
273: $functionName = $this->getName() . '\\' . $functionName;
274: }
275:
276: return isset($this->functions[$functionName]);
277: }
278:
279: 280: 281: 282: 283: 284: 285:
286: public function getFunction($functionName)
287: {
288: $functionName = ltrim($functionName, '\\');
289: if (false === strpos($functionName, '\\') && self::NO_NAMESPACE_NAME !== $this->getName()) {
290: $functionName = $this->getName() . '\\' . $functionName;
291: }
292:
293: if (!isset($this->functions[$functionName])) {
294: throw new Exception\RuntimeException(sprintf('Function "%s" does not exist.', $functionName), Exception\RuntimeException::DOES_NOT_EXIST, $this);
295: }
296:
297: return $this->functions[$functionName];
298: }
299:
300: 301: 302: 303: 304:
305: public function getFunctions()
306: {
307: return $this->functions;
308: }
309:
310: 311: 312: 313: 314:
315: public function getFunctionNames()
316: {
317: return array_keys($this->functions);
318: }
319:
320: 321: 322: 323: 324:
325: public function getFunctionShortNames()
326: {
327: return array_map(function(IReflectionFunction $function) {
328: return $function->getShortName();
329: }, $this->functions);
330: }
331:
332: 333: 334: 335: 336:
337: public function getPrettyName()
338: {
339: return $this->name;
340: }
341:
342: 343: 344: 345: 346:
347: public function __toString()
348: {
349: $buffer = '';
350: $count = 0;
351: foreach ($this->getClasses() as $class) {
352: $string = "\n " . trim(str_replace("\n", "\n ", $class->__toString()), ' ');
353: $string = str_replace(" \n - Parameters", "\n - Parameters", $string);
354:
355: $buffer .= $string;
356: $count++;
357: }
358: $classes = sprintf("\n\n - Classes [%d] {\n%s }", $count, ltrim($buffer, "\n"));
359:
360: $buffer = '';
361: $count = 0;
362: foreach ($this->getConstants() as $constant) {
363: $buffer .= ' ' . $constant->__toString();
364: $count++;
365: }
366: $constants = sprintf("\n\n - Constants [%d] {\n%s }", $count, $buffer);
367:
368: $buffer = '';
369: $count = 0;
370: foreach ($this->getFunctions() as $function) {
371: $string = "\n " . trim(str_replace("\n", "\n ", $function->__toString()), ' ');
372: $string = str_replace(" \n - Parameters", "\n - Parameters", $string);
373:
374: $buffer .= $string;
375: $count++;
376: }
377: $functions = sprintf("\n\n - Functions [%d] {\n%s }", $count, ltrim($buffer, "\n"));
378:
379: return sprintf(
380: "Namespace [ <user> namespace %s ] { %s%s%s\n}\n",
381: $this->getName(),
382: $classes,
383: $constants,
384: $functions
385: );
386: }
387:
388: 389: 390: 391: 392: 393: 394: 395: 396:
397: public static function export(Broker $broker, $namespace, $return = false)
398: {
399: $namespaceName = $namespace;
400:
401: $namespace = $broker->getNamespace($namespaceName);
402: if (null === $namespace) {
403: throw new Exception\RuntimeException(sprintf('Namespace %s does not exist.', $namespaceName), Exception\RuntimeException::DOES_NOT_EXIST);
404: }
405:
406: if ($return) {
407: return $namespace->__toString();
408: }
409:
410: echo $namespace->__toString();
411: }
412:
413: 414: 415: 416: 417: 418: 419:
420: public function addFileNamespace(ReflectionFileNamespace $namespace)
421: {
422: $errors = array();
423:
424: foreach ($namespace->getClasses() as $className => $reflection) {
425: if ($reflection instanceof Invalid\ReflectionClass) {
426: $errors = array_merge($errors, $reflection->getReasons());
427: }
428:
429: if (isset($this->classes[$className])) {
430: if (!$this->classes[$className] instanceof Invalid\ReflectionClass) {
431: $this->classes[$className] = new Invalid\ReflectionClass($className, $this->classes[$className]->getFileName(), $this->getBroker());
432: }
433:
434: $error = new Exception\RuntimeException(
435: sprintf('Class %s was redeclared (previously declared in file %s).', $className, $this->classes[$className]->getFileName()),
436: Exception\RuntimeException::ALREADY_EXISTS,
437: $reflection
438: );
439: $errors[] = $error;
440: $this->classes[$className]->addReason($error);
441:
442: if ($reflection instanceof Invalid\ReflectionClass) {
443: foreach ($reflection->getReasons() as $reason) {
444: $this->classes[$className]->addReason($reason);
445: }
446: }
447: } else {
448: $this->classes[$className] = $reflection;
449: }
450: }
451:
452: foreach ($namespace->getFunctions() as $functionName => $reflection) {
453: if ($reflection instanceof Invalid\ReflectionFunction) {
454: $errors = array_merge($errors, $reflection->getReasons());
455: }
456:
457: if (isset($this->functions[$functionName])) {
458: if (!$this->functions[$functionName] instanceof Invalid\ReflectionFunction) {
459: $this->functions[$functionName] = new Invalid\ReflectionFunction($functionName, $this->functions[$functionName]->getFileName(), $this->getBroker());
460: }
461:
462: $error = new Exception\RuntimeException(
463: sprintf('Function %s was redeclared (previousy declared in file %s).', $functionName, $this->functions[$functionName]->getFileName()),
464: Exception\RuntimeException::ALREADY_EXISTS,
465: $reflection
466: );
467: $errors[] = $error;
468: $this->functions[$functionName]->addReason($error);
469:
470: if ($reflection instanceof Invalid\ReflectionFunction) {
471: foreach ($reflection->getReasons() as $reason) {
472: $this->functions[$functionName]->addReason($reason);
473: }
474: }
475: } else {
476: $this->functions[$functionName] = $reflection;
477: }
478: }
479:
480: foreach ($namespace->getConstants() as $constantName => $reflection) {
481: if ($reflection instanceof Invalid\ReflectionConstant) {
482: $errors = array_merge($errors, $reflection->getReasons());
483: }
484:
485: if (isset($this->constants[$constantName])) {
486: if (!$this->constants[$constantName] instanceof Invalid\ReflectionConstant) {
487: $this->constants[$constantName] = new Invalid\ReflectionConstant($constantName, $this->constants[$constantName]->getFileName(), $this->getBroker());
488: }
489:
490: $error = new Exception\RuntimeException(
491: sprintf('Constant %s was redeclared (previuosly declared in file %s).', $constantName, $this->constants[$constantName]->getFileName()),
492: Exception\RuntimeException::ALREADY_EXISTS,
493: $reflection
494: );
495: $errors[] = $error;
496: $this->constants[$constantName]->addReason($error);
497:
498: if ($reflection instanceof Invalid\ReflectionConstant) {
499: foreach ($reflection->getReasons() as $reason) {
500: $this->constants[$constantName]->addReason($reason);
501: }
502: }
503: } else {
504: $this->constants[$constantName] = $reflection;
505: }
506: }
507:
508: if (!empty($errors)) {
509: throw new Exception\FileProcessingException($errors, null);
510: }
511:
512: return $this;
513: }
514:
515: 516: 517: 518: 519: 520: 521:
522: public function getSource()
523: {
524: throw new Exception\RuntimeException('Cannot export source code of a namespace.', Exception\RuntimeException::UNSUPPORTED, $this);
525: }
526:
527: 528: 529: 530: 531:
532: public function getBroker()
533: {
534: return $this->broker;
535: }
536:
537: 538: 539: 540: 541: 542:
543: final public function __get($key)
544: {
545: return ReflectionElement::get($this, $key);
546: }
547:
548: 549: 550: 551: 552: 553:
554: final public function __isset($key)
555: {
556: return ReflectionElement::exists($this, $key);
557: }
558: }