@@ -65,6 +65,11 @@ class DocumentParser
6565 */
6666 private $ properties = [];
6767
68+ /**
69+ * @var array Local cache for documents
70+ */
71+ private $ documents = [];
72+
6873 /**
6974 * @param Reader $reader Used for reading annotations.
7075 * @param DocumentFinder $finder Used for resolving namespaces.
@@ -81,40 +86,50 @@ public function __construct(Reader $reader, DocumentFinder $finder)
8186 *
8287 * @param \ReflectionClass $class
8388 *
84- * @return array
89+ * @return array|null
8590 * @throws MissingDocumentAnnotationException
8691 */
8792 public function parse (\ReflectionClass $ class )
8893 {
89- /** @var Document $document */
90- $ document = $ this ->reader ->getClassAnnotation ($ class , self ::DOCUMENT_ANNOTATION );
91-
92- if ($ document === null ) {
93- throw new MissingDocumentAnnotationException (
94- sprintf (
95- '"%s" class cannot be parsed as document because @Document annotation is missing. ' ,
96- $ class ->getName ()
97- )
98- );
94+ $ className = $ class ->getName ();
95+
96+ if ($ class ->isTrait ()) {
97+ return false ;
9998 }
10099
101- $ fields = [];
102-
103- return [
104- 'type ' => $ document ->type ?: Caser::snake ($ class ->getShortName ()),
105- 'properties ' => $ this ->getProperties ($ class ),
106- 'fields ' => array_filter (
107- array_merge (
108- $ document ->dump (),
109- $ fields
110- )
111- ),
112- 'aliases ' => $ this ->getAliases ($ class , $ fields ),
113- 'analyzers ' => $ this ->getAnalyzers ($ class ),
114- 'objects ' => $ this ->getObjects (),
115- 'namespace ' => $ class ->getName (),
116- 'class ' => $ class ->getShortName (),
117- ];
100+ if (!isset ($ this ->documents [$ className ])) {
101+ /** @var Document $document */
102+ $ document = $ this ->reader ->getClassAnnotation ($ class , self ::DOCUMENT_ANNOTATION );
103+
104+ if ($ document === null ) {
105+ throw new MissingDocumentAnnotationException (
106+ sprintf (
107+ '"%s" class cannot be parsed as document because @Document annotation is missing. ' ,
108+ $ class ->getName ()
109+ )
110+ );
111+ }
112+
113+ $ fields = [];
114+ $ aliases = $ this ->getAliases ($ class , $ fields );
115+
116+ $ this ->documents [$ className ] = [
117+ 'type ' => $ document ->type ?: Caser::snake ($ class ->getShortName ()),
118+ 'properties ' => $ this ->getProperties ($ class ),
119+ 'fields ' => array_filter (
120+ array_merge (
121+ $ document ->dump (),
122+ $ fields
123+ )
124+ ),
125+ 'aliases ' => $ aliases ,
126+ 'analyzers ' => $ this ->getAnalyzers ($ class ),
127+ 'objects ' => $ this ->getObjects (),
128+ 'namespace ' => $ class ->getName (),
129+ 'class ' => $ class ->getShortName (),
130+ ];
131+ }
132+ return $ this ->documents [$ className ];
118133 }
119134
120135 /**
@@ -236,7 +251,6 @@ private function getObjects()
236251 private function getAliases (\ReflectionClass $ reflectionClass , array &$ metaFields = null )
237252 {
238253 $ reflectionName = $ reflectionClass ->getName ();
239- $ directory = $ this ->guessDirName ($ reflectionClass );
240254
241255 // We skip cache in case $metaFields is given. This should not affect performance
242256 // because for each document this method is called only once. For objects it might
@@ -251,6 +265,8 @@ private function getAliases(\ReflectionClass $reflectionClass, array &$metaField
251265 $ properties = $ this ->getDocumentPropertiesReflection ($ reflectionClass );
252266
253267 foreach ($ properties as $ name => $ property ) {
268+ $ directory = $ this ->guessDirName ($ property ->getDeclaringClass ());
269+
254270 $ type = $ this ->getPropertyAnnotationData ($ property );
255271 $ type = $ type !== null ? $ type : $ this ->getEmbeddedAnnotationData ($ property );
256272 $ type = $ type !== null ? $ type : $ this ->getHashMapAnnotationData ($ property );
@@ -456,9 +472,10 @@ private function getDocumentPropertiesReflection(\ReflectionClass $reflectionCla
456472 private function getAnalyzers (\ReflectionClass $ reflectionClass )
457473 {
458474 $ analyzers = [];
459- $ directory = $ this ->guessDirName ($ reflectionClass );
460475
461476 foreach ($ this ->getDocumentPropertiesReflection ($ reflectionClass ) as $ name => $ property ) {
477+ $ directory = $ this ->guessDirName ($ property ->getDeclaringClass ());
478+
462479 $ type = $ this ->getPropertyAnnotationData ($ property );
463480 $ type = $ type !== null ? $ type : $ this ->getEmbeddedAnnotationData ($ property );
464481
@@ -504,10 +521,11 @@ private function getAnalyzers(\ReflectionClass $reflectionClass)
504521 private function getProperties (\ReflectionClass $ reflectionClass , $ properties = [], $ flag = false )
505522 {
506523 $ mapping = [];
507- $ directory = $ this ->guessDirName ($ reflectionClass );
508524
509525 /** @var \ReflectionProperty $property */
510526 foreach ($ this ->getDocumentPropertiesReflection ($ reflectionClass ) as $ name => $ property ) {
527+ $ directory = $ this ->guessDirName ($ property ->getDeclaringClass ());
528+
511529 $ type = $ this ->getPropertyAnnotationData ($ property );
512530 $ type = $ type !== null ? $ type : $ this ->getEmbeddedAnnotationData ($ property );
513531 $ type = $ type !== null ? $ type : $ this ->getHashMapAnnotationData ($ property );
0 commit comments