/vendor/venne/doctrine-module/DoctrineModule/Module/Installers/DoctrineInstaller.php

https://bitbucket.org/iiic/iszp · PHP · 208 lines · 131 code · 37 blank · 40 comment · 9 complexity · a8545a1f199350ccc946e4e88c81c83f MD5 · raw file

  1. <?php
  2. /**
  3. * This file is part of the Venne:CMS (https://github.com/Venne)
  4. *
  5. * Copyright (c) 2011, 2012 Josef Kříž (http://www.josef-kriz.cz)
  6. *
  7. * For the full copyright and license information, please view
  8. * the file license.txt that was distributed with this source code.
  9. */
  10. namespace DoctrineModule\Module\Installers;
  11. use Venne;
  12. use Nette\Reflection\ClassType;
  13. use Venne\Utils\File;
  14. use Nette\DI\Container;
  15. use Venne\Module\IModule;
  16. use Doctrine\ORM\EntityManager;
  17. use Nette\Config\Adapters\NeonAdapter;
  18. use Venne\Module\Installers\BaseInstaller;
  19. use Venne\Module\ModuleManager;
  20. /**
  21. * @author Josef Kříž <pepakriz@gmail.com>
  22. */
  23. class DoctrineInstaller extends BaseInstaller
  24. {
  25. /** @var Container */
  26. protected $context;
  27. /** @var string */
  28. protected $resourcesDir;
  29. /** @var string */
  30. protected $configDir;
  31. /** @var EntityManager */
  32. protected $entityManager;
  33. /**
  34. * @param \Nette\DI\Container $context
  35. * @param \Doctrine\ORM\EntityManager $entityManager
  36. */
  37. public function __construct(Container $context, EntityManager $entityManager)
  38. {
  39. $this->context = $context;
  40. $this->resourcesDir = $context->parameters['resourcesDir'];
  41. $this->configDir = $context->parameters['configDir'];
  42. $this->entityManager = $entityManager;
  43. }
  44. /**
  45. * @param \Venne\Module\IModule $module
  46. */
  47. public function install(IModule $module)
  48. {
  49. if (!$this->context->hasService('doctrine') || !$this->context->doctrine->createCheckConnection()) {
  50. throw new \Exception('Database connection not found!');
  51. }
  52. $classes = $this->getClasses($module);
  53. $metadata = array();
  54. foreach ($classes as $class) {
  55. $metadata[] = $this->entityManager->getClassMetadata($class);
  56. }
  57. $tool = new \Doctrine\ORM\Tools\SchemaTool($this->entityManager);
  58. $this->entityManager->getConnection()->beginTransaction();
  59. try {
  60. $tool->createSchema($metadata);
  61. foreach ($this->getAllClasses() as $class) {
  62. $metadata[] = $this->entityManager->getClassMetadata($class);
  63. }
  64. $tool->updateSchema($metadata);
  65. $this->entityManager->getConnection()->commit();
  66. } catch (Exception $e) {
  67. $this->entityManager->getConnection()->rollback();
  68. $this->entityManager->close();
  69. throw $e;
  70. }
  71. $this->cleanCache();
  72. }
  73. /**
  74. * @param \Venne\Module\IModule $module
  75. */
  76. public function uninstall(IModule $module)
  77. {
  78. if (!$this->context->hasService('doctrine') || !$this->context->doctrine->createCheckConnection()) {
  79. throw new \Exception('Database connection not found!');
  80. }
  81. $classes = $this->getClasses($module);
  82. $metadata = array();
  83. foreach ($classes as $class) {
  84. $metadata[] = $this->entityManager->getClassMetadata($class);
  85. }
  86. $tool = new \Doctrine\ORM\Tools\SchemaTool($this->entityManager);
  87. $this->entityManager->getConnection()->beginTransaction();
  88. try {
  89. foreach ($classes as $class) {
  90. $repository = $this->entityManager->getRepository($class);
  91. foreach ($repository->findAll() as $entity) {
  92. $repository->delete($entity);
  93. }
  94. }
  95. $tool->dropSchema($metadata);
  96. $this->entityManager->getConnection()->commit();
  97. } catch (Exception $e) {
  98. $this->entityManager->getConnection()->rollback();
  99. $this->entityManager->close();
  100. throw $e;
  101. }
  102. $this->cleanCache();
  103. }
  104. /**
  105. * @param \Venne\Module\IModule $module
  106. * @return array
  107. * @throws \Exception
  108. */
  109. protected function getClasses(IModule $module)
  110. {
  111. // find files
  112. $robotLoader = new \Nette\Loaders\RobotLoader;
  113. $robotLoader->setCacheStorage(new \Nette\Caching\Storages\MemoryStorage());
  114. $robotLoader->addDirectory($module->getPath());
  115. $robotLoader->register();
  116. $entities = $robotLoader->getIndexedClasses();
  117. // paths
  118. $paths = array();
  119. foreach (\Nette\Utils\Finder::findDirectories('Entities')->from($module->getPath()) as $file) {
  120. $paths[] = $file->getPath() . '/Entities';
  121. }
  122. $this->entityManager->getConfiguration()->getMetadataDriverImpl()->addPaths($paths);
  123. // classes
  124. $classes = array();
  125. foreach ($entities as $class => $item) {
  126. if (\Nette\Reflection\ClassType::from($class)->hasAnnotation('ORM\Entity')) {
  127. $classes[] = $class;
  128. }
  129. }
  130. $robotLoader->unregister();
  131. return $classes;
  132. }
  133. /**
  134. * @param \Venne\Module\IModule $module
  135. * @return array
  136. * @throws \Exception
  137. */
  138. protected function getAllClasses()
  139. {
  140. // find files
  141. $robotLoader = new \Nette\Loaders\RobotLoader;
  142. $robotLoader->setCacheStorage(new \Nette\Caching\Storages\MemoryStorage());
  143. foreach ($this->context->parameters['modules'] as $name => $item) {
  144. if ($item[ModuleManager::MODULE_STATUS] === ModuleManager::STATUS_INSTALLED) {
  145. $path = $this->context->expand($item[ModuleManager::MODULE_PATH]) . '/' . ucfirst($name) . 'Module';
  146. if (file_exists($path)) {
  147. $robotLoader->addDirectory($path);
  148. }
  149. }
  150. }
  151. $robotLoader->register();
  152. $entities = $robotLoader->getIndexedClasses();
  153. // classes
  154. $classes = array();
  155. foreach ($entities as $class => $item) {
  156. if (\Nette\Reflection\ClassType::from('\\' . $class)->hasAnnotation('ORM\Entity')) {
  157. $classes[] = $class;
  158. }
  159. }
  160. $robotLoader->unregister();
  161. return $classes;
  162. }
  163. protected function cleanCache()
  164. {
  165. if (function_exists("apc_fetch")) {
  166. \apc_clear_cache();
  167. \apc_clear_cache('user');
  168. \apc_clear_cache('opcode');
  169. }
  170. }
  171. }