@@ -164,13 +164,11 @@ public function getMetadataFor($className)
164164 }
165165
166166 if ($ this ->cacheDriver ) {
167- if (($ cached = $ this ->cacheDriver -> fetch ( " $ realClassName\$ CLASSMETADATA " )) !== false ) {
167+ if (($ cached = $ this ->fetchMetadataFromCache ( $ realClassName )) !== false ) {
168168 $ this ->loadedMetadata [$ realClassName ] = $ cached ;
169169 } else {
170170 foreach ($ this ->loadMetadata ($ realClassName ) as $ loadedClassName ) {
171- $ this ->cacheDriver ->save (
172- "$ loadedClassName \$CLASSMETADATA " , $ this ->loadedMetadata [$ loadedClassName ], null
173- );
171+ $ this ->cacheMetadata ($ loadedClassName , $ this ->loadedMetadata [$ loadedClassName ]);
174172 }
175173 }
176174 } else {
@@ -319,6 +317,11 @@ protected function loadMetadata($name)
319317
320318 $ class ->setParentClasses ($ visited );
321319
320+ // Calculate Discriminator Map if needed and if no discriminator map is set
321+ if ($ class ->isInheritanceTypeJoined () && empty ($ class ->discriminatorMap )) {
322+ $ this ->addDefaultDiscriminatorMap ($ class );
323+ }
324+
322325 if ($ this ->evm ->hasListeners (Events::loadClassMetadata)) {
323326 $ eventArgs = new \Doctrine \ORM \Event \LoadClassMetadataEventArgs ($ class , $ this ->em );
324327 $ this ->evm ->dispatchEvent (Events::loadClassMetadata, $ eventArgs );
@@ -388,6 +391,89 @@ protected function newClassMetadataInstance($className)
388391 return new ClassMetadata ($ className );
389392 }
390393
394+ /**
395+ * Adds a default discriminator map if no one is given
396+ *
397+ * @param \Doctrine\ORM\Mapping\ClassMetadata $class
398+ */
399+ private function addDefaultDiscriminatorMap (ClassMetadata $ class )
400+ {
401+ $ allClasses = $ this ->driver ->getAllClassNames ();
402+ $ subClassesMetadata = array ();
403+ $ fqcn = $ class ->getName ();
404+ $ map = array (str_replace ('\\' , '. ' , $ fqcn ) => $ fqcn );
405+
406+ foreach ($ allClasses as $ c ) {
407+ if (is_subclass_of ($ c , $ fqcn )) {
408+ if (isset ($ this ->loadedMetadata [$ c ])) {
409+ $ subClassMetadata = $ this ->loadedMetadata [$ c ];
410+ } else {
411+ $ subClassMetadata = $ this ->newClassMetadataInstance ($ c );
412+ $ this ->driver ->loadMetadataForClass ($ c , $ subClassMetadata );
413+ }
414+
415+ if (!$ subClassMetadata ->isMappedSuperclass ) {
416+ $ map [str_replace ('\\' , '. ' , $ c )] = $ c ;
417+ $ subClassesMetadata [$ c ] = $ subClassMetadata ;
418+ }
419+ }
420+ }
421+
422+ $ class ->setDiscriminatorMap ($ map );
423+
424+ // Now we set the discriminator map for the subclasses already loaded
425+ foreach ($ subClassesMetadata as $ subClassFqcn => $ subClassMetadata ) {
426+ $ subClassMetadata ->setDiscriminatorMap ($ map );
427+
428+ // We need to overwrite the cached version of the metadata, because
429+ // it was cached without the discriminator map
430+ if ($ this ->cacheDriver && $ this ->cacheContainsMetadata ($ subClassFqcn )) {
431+ // If subclass metadata is not already loaded, it's incomplete so
432+ // we reload it again from cache
433+ if (!isset ($ this ->loadedMetadata [$ subClassFqcn ])) {
434+ $ subClassMetadata = $ this ->fetchMetadataFromCache ($ subClassFqcn );
435+ $ subClassMetadata ->setDiscriminatorMap ($ map );
436+ }
437+
438+ $ this ->cacheMetadata ($ subClassFqcn , $ subClassMetadata );
439+ }
440+ }
441+ }
442+
443+ /**
444+ * Cache the metadata
445+ *
446+ * @param $className
447+ * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata
448+ */
449+ private function cacheMetadata ($ className , ClassMetadata $ metadata )
450+ {
451+ $ this ->cacheDriver ->save (
452+ "$ className \$CLASSMETADATA " , $ metadata , null
453+ );
454+ }
455+
456+ /**
457+ * Verify if metadata is cached
458+ *
459+ * @param $className
460+ * @return bool
461+ */
462+ private function cacheContainsMetadata ($ className )
463+ {
464+ return $ this ->cacheDriver ->contains ("$ className \$CLASSMETADATA " );
465+ }
466+
467+ /**
468+ * Fetch metadata from cache
469+ *
470+ * @param $className
471+ */
472+ private function fetchMetadataFromCache ($ className )
473+ {
474+ return $ this ->cacheDriver ->fetch ("$ className \$CLASSMETADATA " );
475+ }
476+
391477 /**
392478 * Adds inherited fields to the subclass mapping.
393479 *
0 commit comments