PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/jms/serializer/src/JMS/Serializer/SerializerBuilder.php

https://gitlab.com/cuza/Clinic_Recods
PHP | 400 lines | 252 code | 65 blank | 83 comment | 16 complexity | 63cbde5863a859c633e4faf85d694835 MD5 | raw file
  1. <?php
  2. /*
  3. * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. namespace JMS\Serializer;
  18. use JMS\Serializer\Builder\DefaultDriverFactory;
  19. use JMS\Serializer\Builder\DriverFactoryInterface;
  20. use JMS\Serializer\Handler\PhpCollectionHandler;
  21. use JMS\Serializer\Handler\PropelCollectionHandler;
  22. use JMS\Serializer\Exception\RuntimeException;
  23. use Metadata\Driver\DriverInterface;
  24. use Metadata\MetadataFactory;
  25. use JMS\Serializer\Metadata\Driver\AnnotationDriver;
  26. use JMS\Serializer\Handler\HandlerRegistry;
  27. use JMS\Serializer\Construction\UnserializeObjectConstructor;
  28. use PhpCollection\Map;
  29. use JMS\Serializer\EventDispatcher\EventDispatcher;
  30. use Metadata\Driver\DriverChain;
  31. use JMS\Serializer\Metadata\Driver\YamlDriver;
  32. use JMS\Serializer\Metadata\Driver\XmlDriver;
  33. use Metadata\Driver\FileLocator;
  34. use JMS\Serializer\Handler\DateHandler;
  35. use JMS\Serializer\Handler\ArrayCollectionHandler;
  36. use JMS\Serializer\Construction\ObjectConstructorInterface;
  37. use JMS\Serializer\EventDispatcher\Subscriber\DoctrineProxySubscriber;
  38. use JMS\Serializer\Naming\CamelCaseNamingStrategy;
  39. use JMS\Serializer\Naming\PropertyNamingStrategyInterface;
  40. use Doctrine\Common\Annotations\Reader;
  41. use Doctrine\Common\Annotations\AnnotationReader;
  42. use Doctrine\Common\Annotations\FileCacheReader;
  43. use Metadata\Cache\FileCache;
  44. use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
  45. use JMS\Serializer\Exception\InvalidArgumentException;
  46. /**
  47. * Builder for serializer instances.
  48. *
  49. * This object makes serializer construction a breeze for projects that do not use
  50. * any special dependency injection container.
  51. *
  52. * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  53. */
  54. class SerializerBuilder
  55. {
  56. private $metadataDirs = array();
  57. private $handlerRegistry;
  58. private $handlersConfigured = false;
  59. private $eventDispatcher;
  60. private $listenersConfigured = false;
  61. private $objectConstructor;
  62. private $serializationVisitors;
  63. private $deserializationVisitors;
  64. private $visitorsAdded = false;
  65. private $propertyNamingStrategy;
  66. private $debug = false;
  67. private $cacheDir;
  68. private $annotationReader;
  69. private $includeInterfaceMetadata = false;
  70. private $driverFactory;
  71. public static function create()
  72. {
  73. return new static();
  74. }
  75. public function __construct()
  76. {
  77. $this->handlerRegistry = new HandlerRegistry();
  78. $this->eventDispatcher = new EventDispatcher();
  79. $this->driverFactory = new DefaultDriverFactory();
  80. $this->serializationVisitors = new Map();
  81. $this->deserializationVisitors = new Map();
  82. }
  83. public function setAnnotationReader(Reader $reader)
  84. {
  85. $this->annotationReader = $reader;
  86. return $this;
  87. }
  88. public function setDebug($bool)
  89. {
  90. $this->debug = (boolean) $bool;
  91. return $this;
  92. }
  93. public function setCacheDir($dir)
  94. {
  95. if ( ! is_dir($dir)) {
  96. $this->createDir($dir);
  97. }
  98. if ( ! is_writable($dir)) {
  99. throw new InvalidArgumentException(sprintf('The cache directory "%s" is not writable.', $dir));
  100. }
  101. $this->cacheDir = $dir;
  102. return $this;
  103. }
  104. public function addDefaultHandlers()
  105. {
  106. $this->handlersConfigured = true;
  107. $this->handlerRegistry->registerSubscribingHandler(new DateHandler());
  108. $this->handlerRegistry->registerSubscribingHandler(new PhpCollectionHandler());
  109. $this->handlerRegistry->registerSubscribingHandler(new ArrayCollectionHandler());
  110. $this->handlerRegistry->registerSubscribingHandler(new PropelCollectionHandler());
  111. return $this;
  112. }
  113. public function configureHandlers(\Closure $closure)
  114. {
  115. $this->handlersConfigured = true;
  116. $closure($this->handlerRegistry);
  117. return $this;
  118. }
  119. public function addDefaultListeners()
  120. {
  121. $this->listenersConfigured = true;
  122. $this->eventDispatcher->addSubscriber(new DoctrineProxySubscriber());
  123. return $this;
  124. }
  125. public function configureListeners(\Closure $closure)
  126. {
  127. $this->listenersConfigured = true;
  128. $closure($this->eventDispatcher);
  129. return $this;
  130. }
  131. public function setObjectConstructor(ObjectConstructorInterface $constructor)
  132. {
  133. $this->objectConstructor = $constructor;
  134. return $this;
  135. }
  136. public function setPropertyNamingStrategy(PropertyNamingStrategyInterface $propertyNamingStrategy)
  137. {
  138. $this->propertyNamingStrategy = $propertyNamingStrategy;
  139. return $this;
  140. }
  141. public function setSerializationVisitor($format, VisitorInterface $visitor)
  142. {
  143. $this->visitorsAdded = true;
  144. $this->serializationVisitors->set($format, $visitor);
  145. return $this;
  146. }
  147. public function setDeserializationVisitor($format, VisitorInterface $visitor)
  148. {
  149. $this->visitorsAdded = true;
  150. $this->deserializationVisitors->set($format, $visitor);
  151. return $this;
  152. }
  153. public function addDefaultSerializationVisitors()
  154. {
  155. $this->initializePropertyNamingStrategy();
  156. $this->visitorsAdded = true;
  157. $this->serializationVisitors->setAll(array(
  158. 'xml' => new XmlSerializationVisitor($this->propertyNamingStrategy),
  159. 'yml' => new YamlSerializationVisitor($this->propertyNamingStrategy),
  160. 'json' => new JsonSerializationVisitor($this->propertyNamingStrategy),
  161. ));
  162. return $this;
  163. }
  164. public function addDefaultDeserializationVisitors()
  165. {
  166. $this->initializePropertyNamingStrategy();
  167. $this->visitorsAdded = true;
  168. $this->deserializationVisitors->setAll(array(
  169. 'xml' => new XmlDeserializationVisitor($this->propertyNamingStrategy),
  170. 'json' => new JsonDeserializationVisitor($this->propertyNamingStrategy),
  171. ));
  172. return $this;
  173. }
  174. /**
  175. * @param Boolean $include Whether to include the metadata from the interfaces
  176. *
  177. * @return SerializerBuilder
  178. */
  179. public function includeInterfaceMetadata($include)
  180. {
  181. $this->includeInterfaceMetadata = (Boolean) $include;
  182. return $this;
  183. }
  184. /**
  185. * Sets a map of namespace prefixes to directories.
  186. *
  187. * This method overrides any previously defined directories.
  188. *
  189. * @param array<string,string> $namespacePrefixToDirMap
  190. *
  191. * @return SerializerBuilder
  192. *
  193. * @throws InvalidArgumentException When a directory does not exist
  194. */
  195. public function setMetadataDirs(array $namespacePrefixToDirMap)
  196. {
  197. foreach ($namespacePrefixToDirMap as $dir) {
  198. if ( ! is_dir($dir)) {
  199. throw new InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
  200. }
  201. }
  202. $this->metadataDirs = $namespacePrefixToDirMap;
  203. return $this;
  204. }
  205. /**
  206. * Adds a directory where the serializer will look for class metadata.
  207. *
  208. * The namespace prefix will make the names of the actual metadata files a bit shorter. For example, let's assume
  209. * that you have a directory where you only store metadata files for the ``MyApplication\Entity`` namespace.
  210. *
  211. * If you use an empty prefix, your metadata files would need to look like:
  212. *
  213. * ``my-dir/MyApplication.Entity.SomeObject.yml``
  214. * ``my-dir/MyApplication.Entity.OtherObject.xml``
  215. *
  216. * If you use ``MyApplication\Entity`` as prefix, your metadata files would need to look like:
  217. *
  218. * ``my-dir/SomeObject.yml``
  219. * ``my-dir/OtherObject.yml``
  220. *
  221. * Please keep in mind that you currently may only have one directory per namespace prefix.
  222. *
  223. * @param string $dir The directory where metadata files are located.
  224. * @param string $namespacePrefix An optional prefix if you only store metadata for specific namespaces in this directory.
  225. *
  226. * @return SerializerBuilder
  227. *
  228. * @throws InvalidArgumentException When a directory does not exist
  229. * @throws InvalidArgumentException When a directory has already been registered
  230. */
  231. public function addMetadataDir($dir, $namespacePrefix = '')
  232. {
  233. if ( ! is_dir($dir)) {
  234. throw new InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
  235. }
  236. if (isset($this->metadataDirs[$namespacePrefix])) {
  237. throw new InvalidArgumentException(sprintf('There is already a directory configured for the namespace prefix "%s". Please use replaceMetadataDir() to override directories.', $namespacePrefix));
  238. }
  239. $this->metadataDirs[$namespacePrefix] = $dir;
  240. return $this;
  241. }
  242. /**
  243. * Adds a map of namespace prefixes to directories.
  244. *
  245. * @param array<string,string> $namespacePrefixToDirMap
  246. *
  247. * @return SerializerBuilder
  248. */
  249. public function addMetadataDirs(array $namespacePrefixToDirMap)
  250. {
  251. foreach ($namespacePrefixToDirMap as $prefix => $dir) {
  252. $this->addMetadataDir($dir, $prefix);
  253. }
  254. return $this;
  255. }
  256. /**
  257. * Similar to addMetadataDir(), but overrides an existing entry.
  258. *
  259. * @param string $dir
  260. * @param string $namespacePrefix
  261. *
  262. * @return SerializerBuilder
  263. *
  264. * @throws InvalidArgumentException When a directory does not exist
  265. * @throws InvalidArgumentException When no directory is configured for the ns prefix
  266. */
  267. public function replaceMetadataDir($dir, $namespacePrefix = '')
  268. {
  269. if ( ! is_dir($dir)) {
  270. throw new InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
  271. }
  272. if ( ! isset($this->metadataDirs[$namespacePrefix])) {
  273. throw new InvalidArgumentException(sprintf('There is no directory configured for namespace prefix "%s". Please use addMetadataDir() for adding new directories.', $namespacePrefix));
  274. }
  275. $this->metadataDirs[$namespacePrefix] = $dir;
  276. return $this;
  277. }
  278. public function setMetadataDriverFactory(DriverFactoryInterface $driverFactory)
  279. {
  280. $this->driverFactory = $driverFactory;
  281. return $this;
  282. }
  283. public function build()
  284. {
  285. $annotationReader = $this->annotationReader;
  286. if (null === $annotationReader) {
  287. $annotationReader = new AnnotationReader();
  288. if (null !== $this->cacheDir) {
  289. $this->createDir($this->cacheDir.'/annotations');
  290. $annotationReader = new FileCacheReader($annotationReader, $this->cacheDir.'/annotations', $this->debug);
  291. }
  292. }
  293. $metadataDriver = $this->driverFactory->createDriver($this->metadataDirs, $annotationReader);
  294. $metadataFactory = new MetadataFactory($metadataDriver, null, $this->debug);
  295. $metadataFactory->setIncludeInterfaces($this->includeInterfaceMetadata);
  296. if (null !== $this->cacheDir) {
  297. $this->createDir($this->cacheDir.'/metadata');
  298. $metadataFactory->setCache(new FileCache($this->cacheDir.'/metadata'));
  299. }
  300. if ( ! $this->handlersConfigured) {
  301. $this->addDefaultHandlers();
  302. }
  303. if ( ! $this->listenersConfigured) {
  304. $this->addDefaultListeners();
  305. }
  306. if ( ! $this->visitorsAdded) {
  307. $this->addDefaultSerializationVisitors();
  308. $this->addDefaultDeserializationVisitors();
  309. }
  310. return new Serializer(
  311. $metadataFactory,
  312. $this->handlerRegistry,
  313. $this->objectConstructor ?: new UnserializeObjectConstructor(),
  314. $this->serializationVisitors,
  315. $this->deserializationVisitors,
  316. $this->eventDispatcher
  317. );
  318. }
  319. private function initializePropertyNamingStrategy()
  320. {
  321. if (null !== $this->propertyNamingStrategy) {
  322. return;
  323. }
  324. $this->propertyNamingStrategy = new SerializedNameAnnotationStrategy(new CamelCaseNamingStrategy());
  325. }
  326. private function createDir($dir)
  327. {
  328. if (is_dir($dir)) {
  329. return;
  330. }
  331. if (false === @mkdir($dir, 0777, true)) {
  332. throw new RuntimeException(sprintf('Could not create directory "%s".', $dir));
  333. }
  334. }
  335. }