1<?php 2 3namespace Doctrine\Persistence; 4 5use InvalidArgumentException; 6use ReflectionClass; 7use function class_exists; 8use function explode; 9use function interface_exists; 10use function sprintf; 11use function strpos; 12 13/** 14 * Abstract implementation of the ManagerRegistry contract. 15 */ 16abstract class AbstractManagerRegistry implements ManagerRegistry 17{ 18 /** @var string */ 19 private $name; 20 21 /** @var string[] */ 22 private $connections; 23 24 /** @var string[] */ 25 private $managers; 26 27 /** @var string */ 28 private $defaultConnection; 29 30 /** @var string */ 31 private $defaultManager; 32 33 /** @var string */ 34 private $proxyInterfaceName; 35 36 /** 37 * @param string $name 38 * @param string[] $connections 39 * @param string[] $managers 40 * @param string $defaultConnection 41 * @param string $defaultManager 42 * @param string $proxyInterfaceName 43 */ 44 public function __construct($name, array $connections, array $managers, $defaultConnection, $defaultManager, $proxyInterfaceName) 45 { 46 $this->name = $name; 47 $this->connections = $connections; 48 $this->managers = $managers; 49 $this->defaultConnection = $defaultConnection; 50 $this->defaultManager = $defaultManager; 51 $this->proxyInterfaceName = $proxyInterfaceName; 52 } 53 54 /** 55 * Fetches/creates the given services. 56 * 57 * A service in this context is connection or a manager instance. 58 * 59 * @param string $name The name of the service. 60 * 61 * @return ObjectManager The instance of the given service. 62 */ 63 abstract protected function getService($name); 64 65 /** 66 * Resets the given services. 67 * 68 * A service in this context is connection or a manager instance. 69 * 70 * @param string $name The name of the service. 71 * 72 * @return void 73 */ 74 abstract protected function resetService($name); 75 76 /** 77 * Gets the name of the registry. 78 * 79 * @return string 80 */ 81 public function getName() 82 { 83 return $this->name; 84 } 85 86 /** 87 * {@inheritdoc} 88 */ 89 public function getConnection($name = null) 90 { 91 if ($name === null) { 92 $name = $this->defaultConnection; 93 } 94 95 if (! isset($this->connections[$name])) { 96 throw new InvalidArgumentException(sprintf('Doctrine %s Connection named "%s" does not exist.', $this->name, $name)); 97 } 98 99 return $this->getService($this->connections[$name]); 100 } 101 102 /** 103 * {@inheritdoc} 104 */ 105 public function getConnectionNames() 106 { 107 return $this->connections; 108 } 109 110 /** 111 * {@inheritdoc} 112 */ 113 public function getConnections() 114 { 115 $connections = []; 116 foreach ($this->connections as $name => $id) { 117 $connections[$name] = $this->getService($id); 118 } 119 120 return $connections; 121 } 122 123 /** 124 * {@inheritdoc} 125 */ 126 public function getDefaultConnectionName() 127 { 128 return $this->defaultConnection; 129 } 130 131 /** 132 * {@inheritdoc} 133 */ 134 public function getDefaultManagerName() 135 { 136 return $this->defaultManager; 137 } 138 139 /** 140 * {@inheritdoc} 141 * 142 * @throws InvalidArgumentException 143 */ 144 public function getManager($name = null) 145 { 146 if ($name === null) { 147 $name = $this->defaultManager; 148 } 149 150 if (! isset($this->managers[$name])) { 151 throw new InvalidArgumentException(sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name)); 152 } 153 154 return $this->getService($this->managers[$name]); 155 } 156 157 /** 158 * {@inheritdoc} 159 */ 160 public function getManagerForClass($class) 161 { 162 // Check for namespace alias 163 if (strpos($class, ':') !== false) { 164 [$namespaceAlias, $simpleClassName] = explode(':', $class, 2); 165 $class = $this->getAliasNamespace($namespaceAlias) . '\\' . $simpleClassName; 166 } 167 168 $proxyClass = new ReflectionClass($class); 169 170 if ($proxyClass->implementsInterface($this->proxyInterfaceName)) { 171 $parentClass = $proxyClass->getParentClass(); 172 173 if (! $parentClass) { 174 return null; 175 } 176 177 $class = $parentClass->getName(); 178 } 179 180 foreach ($this->managers as $id) { 181 $manager = $this->getService($id); 182 183 if (! $manager->getMetadataFactory()->isTransient($class)) { 184 return $manager; 185 } 186 } 187 } 188 189 /** 190 * {@inheritdoc} 191 */ 192 public function getManagerNames() 193 { 194 return $this->managers; 195 } 196 197 /** 198 * {@inheritdoc} 199 */ 200 public function getManagers() 201 { 202 $dms = []; 203 foreach ($this->managers as $name => $id) { 204 $dms[$name] = $this->getService($id); 205 } 206 207 return $dms; 208 } 209 210 /** 211 * {@inheritdoc} 212 */ 213 public function getRepository($persistentObjectName, $persistentManagerName = null) 214 { 215 return $this 216 ->selectManager($persistentObjectName, $persistentManagerName) 217 ->getRepository($persistentObjectName); 218 } 219 220 /** 221 * {@inheritdoc} 222 */ 223 public function resetManager($name = null) 224 { 225 if ($name === null) { 226 $name = $this->defaultManager; 227 } 228 229 if (! isset($this->managers[$name])) { 230 throw new InvalidArgumentException(sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name)); 231 } 232 233 // force the creation of a new document manager 234 // if the current one is closed 235 $this->resetService($this->managers[$name]); 236 237 return $this->getManager($name); 238 } 239 240 private function selectManager(string $persistentObjectName, ?string $persistentManagerName = null) : ObjectManager 241 { 242 if ($persistentManagerName !== null) { 243 return $this->getManager($persistentManagerName); 244 } 245 246 return $this->getManagerForClass($persistentObjectName) ?? $this->getManager(); 247 } 248} 249 250class_exists(\Doctrine\Common\Persistence\AbstractManagerRegistry::class); 251interface_exists(ObjectManager::class); 252