|
1 <?php |
|
2 |
|
3 /* |
|
4 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com> |
|
5 * |
|
6 * Licensed under the Apache License, Version 2.0 (the "License"); |
|
7 * you may not use this file except in compliance with the License. |
|
8 * You may obtain a copy of the License at |
|
9 * |
|
10 * http://www.apache.org/licenses/LICENSE-2.0 |
|
11 * |
|
12 * Unless required by applicable law or agreed to in writing, software |
|
13 * distributed under the License is distributed on an "AS IS" BASIS, |
|
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
15 * See the License for the specific language governing permissions and |
|
16 * limitations under the License. |
|
17 */ |
|
18 |
|
19 namespace Metadata; |
|
20 |
|
21 use Metadata\Cache\CacheInterface; |
|
22 |
|
23 use Metadata\Driver\DriverInterface; |
|
24 |
|
25 final class MetadataFactory implements MetadataFactoryInterface |
|
26 { |
|
27 private $driver; |
|
28 private $cache; |
|
29 private $loadedMetadata = array(); |
|
30 private $loadedClassMetadata = array(); |
|
31 private $hierarchyMetadataClass; |
|
32 private $debug; |
|
33 |
|
34 public function __construct(DriverInterface $driver, $hierarchyMetadataClass = 'Metadata\ClassHierarchyMetadata', $debug = false) |
|
35 { |
|
36 $this->driver = $driver; |
|
37 $this->hierarchyMetadataClass = $hierarchyMetadataClass; |
|
38 $this->debug = $debug; |
|
39 } |
|
40 |
|
41 public function setCache(CacheInterface $cache) |
|
42 { |
|
43 $this->cache = $cache; |
|
44 } |
|
45 |
|
46 public function getMetadataForClass($className) |
|
47 { |
|
48 if (isset($this->loadedMetadata[$className])) { |
|
49 return $this->loadedMetadata[$className]; |
|
50 } |
|
51 |
|
52 $metadata = new $this->hierarchyMetadataClass; |
|
53 foreach ($this->getClassHierarchy($className) as $class) { |
|
54 if (isset($this->loadedClassMetadata[$name = $class->getName()])) { |
|
55 $metadata->addClassMetadata($this->loadedClassMetadata[$name]); |
|
56 continue; |
|
57 } |
|
58 |
|
59 // check the cache |
|
60 if (null !== $this->cache |
|
61 && (null !== $classMetadata = $this->cache->loadClassMetadataFromCache($class))) { |
|
62 if ($this->debug && !$classMetadata->isFresh()) { |
|
63 $this->cache->evictClassMetadataFromCache($classMetadata->reflection); |
|
64 } else { |
|
65 $this->loadedClassMetadata[$name] = $classMetadata; |
|
66 $metadata->addClassMetadata($classMetadata); |
|
67 continue; |
|
68 } |
|
69 } |
|
70 |
|
71 // load from source |
|
72 if (null !== $classMetadata = $this->driver->loadMetadataForClass($class)) { |
|
73 $this->loadedClassMetadata[$name] = $classMetadata; |
|
74 $metadata->addClassMetadata($classMetadata); |
|
75 |
|
76 if (null !== $this->cache) { |
|
77 $this->cache->putClassMetadataInCache($classMetadata); |
|
78 } |
|
79 |
|
80 continue; |
|
81 } |
|
82 } |
|
83 |
|
84 if (!$metadata->classMetadata) { |
|
85 return null; |
|
86 } |
|
87 |
|
88 return $this->loadedMetadata[$className] = $metadata; |
|
89 } |
|
90 |
|
91 private function getClassHierarchy($class) |
|
92 { |
|
93 $classes = array(); |
|
94 $refl = new \ReflectionClass($class); |
|
95 |
|
96 do { |
|
97 $classes[] = $refl; |
|
98 } while (false !== $refl = $refl->getParentClass()); |
|
99 |
|
100 return array_reverse($classes, false); |
|
101 } |
|
102 } |