PageRenderTime 48ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/MwbExporter/Bootstrap.php

http://github.com/johmue/mysql-workbench-schema-exporter
PHP | 300 lines | 170 code | 22 blank | 108 comment | 36 complexity | d4c1115ac156d04801a84b88c4f8be44 MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. /*
  3. * The MIT License
  4. *
  5. * Copyright (c) 2010 Johannes Mueller <circus2(at)web.de>
  6. * Copyright (c) 2012-2014 Toha <tohenk@yahoo.com>
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. namespace MwbExporter;
  27. use MwbExporter\Formatter\FormatterInterface;
  28. use MwbExporter\Model\Document;
  29. use MwbExporter\Storage\LoggedStorage;
  30. use MwbExporter\Logger\Logger;
  31. use MwbExporter\Logger\LoggerFile;
  32. use MwbExporter\Logger\LoggerConsole;
  33. class Bootstrap
  34. {
  35. /**
  36. * @var array
  37. */
  38. protected static $formatters = null;
  39. /**
  40. * Get available formatters.
  41. *
  42. * @return array
  43. */
  44. public function getFormatters()
  45. {
  46. if (null === static::$formatters) {
  47. static::$formatters = array();
  48. $dirs = array();
  49. // if we'are using Composer, include these formatters
  50. if ($composer = $this->getComposer()) {
  51. $vendorDir = realpath(__DIR__.'/../../../..');
  52. if (is_readable($installed = $vendorDir.'/composer/installed.json')) {
  53. $packages = json_decode(file_get_contents($installed), true);
  54. foreach ($packages as $package) {
  55. if (isset($package['name']) && is_dir($dir = $vendorDir.DIRECTORY_SEPARATOR.$package['name'])) {
  56. /**
  57. * Check for extended package extra attribute to customize
  58. * formatter inclusion.
  59. *
  60. * An example to include formatter using class:
  61. * {
  62. * "extra" : {
  63. * "mysql-workbench-schema-exporter" : {
  64. * "formatters" : {
  65. * "my-simple" : "\\My\\Simple\\Formatter",
  66. * "my-simple2" : "\\My\\Simple2\\Formatter"
  67. * }
  68. * }
  69. * }
  70. * }
  71. *
  72. * An example include formatter using namespace:
  73. * {
  74. * "extra" : {
  75. * "mysql-workbench-schema-exporter" : {
  76. * "namespaces" : {
  77. * "lib/My/Exporter" : "\\Acme\\My\\Exporter",
  78. * }
  79. * }
  80. * }
  81. * }
  82. */
  83. if (isset($package['extra']) && isset($package['extra']['mysql-workbench-schema-exporter'])) {
  84. if (is_array($options = $package['extra']['mysql-workbench-schema-exporter'])) {
  85. if (isset($options['formatters']) && is_array($options['formatters'])) {
  86. foreach ($options['formatters'] as $name => $class) {
  87. $this->registerFormatter($name, $class);
  88. }
  89. }
  90. if (isset($options['namespaces']) && is_array($options['namespaces'])) {
  91. foreach ($options['namespaces'] as $lib => $namespace) {
  92. $dirs[$dir.DIRECTORY_SEPARATOR.$lib] = $namespace;
  93. }
  94. }
  95. continue;
  96. }
  97. }
  98. $dirs[] = $dir;
  99. }
  100. }
  101. }
  102. } else {
  103. $dirs[] = realpath(__DIR__.'/../..');
  104. }
  105. $this->scanFormatters($dirs);
  106. }
  107. return static::$formatters;
  108. }
  109. /**
  110. * Get formatter.
  111. *
  112. * @param string $name The formatter name
  113. * @return \MwbExporter\Formatter\FormatterInterface
  114. */
  115. public function getFormatter($name)
  116. {
  117. $formatters = $this->getFormatters();
  118. if (!array_key_exists($name, $formatters)) {
  119. list($module, $exporter) = explode('-', $name, 2);
  120. $class = sprintf('\\MwbExporter\\Formatter\\%s\\%s\\Formatter', ucfirst(strtolower($module)), ucfirst(strtolower($exporter)));
  121. if (!class_exists($class)) {
  122. throw new \InvalidArgumentException(sprintf('Unknown formatter "%s".', $name));
  123. }
  124. } else {
  125. $class = $formatters[$name];
  126. }
  127. return new $class($name);
  128. }
  129. /**
  130. * Get writer.
  131. *
  132. * @param string $name The writer name
  133. * @return \MwbExporter\Writer\WriterInterface
  134. */
  135. public function getWriter($name)
  136. {
  137. $class = sprintf('\\MwbExporter\\Writer\\%sWriter', ucfirst($name));
  138. if (class_exists($class)) {
  139. $writter = new $class();
  140. return $writter;
  141. }
  142. throw new \InvalidArgumentException(sprintf('Writer %s not found.', $class));
  143. }
  144. /**
  145. * Get storage.
  146. *
  147. * @param string $name The storage name
  148. * @return \MwbExporter\Storage\StorageInterface
  149. */
  150. public function getStorage($name)
  151. {
  152. $class = sprintf('\\MwbExporter\\Storage\\%sStorage', ucfirst($name));
  153. if (class_exists($class)) {
  154. $storage = new $class();
  155. return $storage;
  156. }
  157. throw new \InvalidArgumentException(sprintf('Storage %s not found.', $class));
  158. }
  159. /**
  160. * Load workbench schema and generate the code.
  161. *
  162. * @param \MwbExporter\Formatter\FormatterInterface $formatter
  163. * @param string $filename
  164. * @param string $outDir
  165. * @param string $storage
  166. * @return \MwbExporter\Model\Document
  167. */
  168. public function export(FormatterInterface $formatter, $filename, $outDir, $storage = 'file')
  169. {
  170. if (!is_readable($filename)) {
  171. throw new \InvalidArgumentException(sprintf('Document not found "%s".', $filename));
  172. }
  173. if ($formatter && $storage = $this->getStorage($storage)) {
  174. if ($formatter->getRegistry()->config->get(FormatterInterface::CFG_USE_LOGGED_STORAGE)) {
  175. $storage = new LoggedStorage($storage);
  176. }
  177. $storage->setName(basename($filename, '.mwb'));
  178. $storage->setOutdir(realpath($outDir) ? realpath($outDir) : $outDir);
  179. $storage->setBackup($formatter->getRegistry()->config->get(FormatterInterface::CFG_BACKUP_FILE));
  180. $writer = $this->getWriter($formatter->getPreferredWriter());
  181. $writer->setStorage($storage);
  182. if ($eol = strtolower(trim($formatter->getRegistry()->config->get(FormatterInterface::CFG_EOL)))) {
  183. switch ($eol) {
  184. case FormatterInterface::EOL_WIN:
  185. $writer->getBuffer()->setEol("\r\n");
  186. break;
  187. case FormatterInterface::EOL_UNIX:
  188. $writer->getBuffer()->setEol("\n");
  189. break;
  190. }
  191. }
  192. $document = new Document($formatter);
  193. if (strlen($logFile = $formatter->getRegistry()->config->get(FormatterInterface::CFG_LOG_FILE))) {
  194. $logger = new LoggerFile(array('filename' => $logFile));
  195. } elseif ($formatter->getRegistry()->config->get(FormatterInterface::CFG_LOG_TO_CONSOLE)) {
  196. $logger = new LoggerConsole();
  197. } else {
  198. $logger = new Logger();
  199. }
  200. $document->setLogger($logger);
  201. $document->load($filename);
  202. $document->write($writer);
  203. if ($e = $document->getError()) {
  204. throw $e;
  205. }
  206. return $document;
  207. }
  208. }
  209. /**
  210. * Register schema exporter class.
  211. *
  212. * @param string $name
  213. * @param string $class
  214. * @return \MwbExporter\Bootstrap
  215. */
  216. public function registerFormatter($name, $class)
  217. {
  218. $name = strtolower(is_array($name) ? implode('-', $name) : $name);
  219. if (array_key_exists($name, static::$formatters)) {
  220. throw new \RuntimeException(sprintf('Formatter %s already registered.', $class));
  221. }
  222. static::$formatters[$name] = $class;
  223. return $this;
  224. }
  225. /**
  226. * Scan directories for available formatters.
  227. *
  228. * Try to guess if schema formatter (or exporter) is present in the specified directory
  229. * which is named according to convention: MwbExporter\Formatter\*\*\Formatter.php.
  230. *
  231. * @param array $dirs
  232. * @return \MwbExporter\Bootstrap
  233. */
  234. protected function scanFormatters($dirs)
  235. {
  236. $dirs = is_array($dirs) ? $dirs : array($dirs);
  237. foreach ($dirs as $key => $dir) {
  238. $namespace = null;
  239. if (is_string($key)) {
  240. $namespace = $dir;
  241. $dir = $key;
  242. }
  243. if (is_dir($dir)) {
  244. $parts = array('*', '*', 'Formatter.php');
  245. if (null == $namespace) {
  246. $parts = array_merge(array('*', 'MwbExporter', 'Formatter'), $parts);
  247. }
  248. $pattern = implode(DIRECTORY_SEPARATOR, array_merge(array($dir), $parts));
  249. foreach (glob($pattern) as $filename) {
  250. $parts = explode(DIRECTORY_SEPARATOR, dirname(realpath($filename)));
  251. $exporter = array_pop($parts);
  252. $module = array_pop($parts);
  253. $class = sprintf('%s\\%s\\%s\\Formatter', $namespace ?: '\\MwbExporter\\Formatter', $module, $exporter);
  254. $this->registerFormatter(array($module, $exporter), $class);
  255. }
  256. }
  257. }
  258. return $this;
  259. }
  260. /**
  261. * Get Composer autoloader instance.
  262. *
  263. * @return \Composer\Autoload\ClassLoader
  264. */
  265. protected function getComposer()
  266. {
  267. if ($autoloaders = spl_autoload_functions()) {
  268. foreach ($autoloaders as $autoload) {
  269. if (is_array($autoload)) {
  270. $class = $autoload[0];
  271. if ('Composer\Autoload\ClassLoader' == get_class($class)) {
  272. return $class;
  273. }
  274. }
  275. }
  276. }
  277. }
  278. }