diff --git a/README.md b/README.md index 8d240d63..babef245 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ You can also generate a schema.yml with ``` ## Hooks + * Has a hook "registerMigrationService" to add exports with your own data. ```php diff --git a/consolecommands/SchematicCommand.php b/consolecommands/SchematicCommand.php index e9876aa1..1bc94afc 100644 --- a/consolecommands/SchematicCommand.php +++ b/consolecommands/SchematicCommand.php @@ -25,19 +25,20 @@ public function actionImport($file = 'craft/config/schema.yml', $force = false) { if (!IOHelper::fileExists($file)) { $this->usageError(Craft::t('File not found.')); - exit(1); } $result = craft()->schematic->importFromYaml($file, $force); if (!$result->hasErrors()) { - echo Craft::t('Loaded schema from {file}', array('file' => $file))."\n"; - exit(0); + SchematicPlugin::log(Craft::t('Loaded schema from {file}', array('file' => $file))); + + return 0; } - echo Craft::t('There was an error loading schema from {file}', array('file' => $file))."\n"; - print_r($result->errors); - exit(1); + SchematicPlugin::log(Craft::t('There was an error loading schema from {file}', array('file' => $file))); + print_r($result->getErrors()); + + return 1; } /** @@ -49,7 +50,8 @@ public function actionExport($file = 'craft/config/schema.yml') { craft()->schematic->exportToYaml($file); - echo Craft::t('Exported schema to {file}', array('file' => $file))."\n"; - exit(0); + SchematicPlugin::log(Craft::t('Exported schema to {file}', array('file' => $file))); + + return 0; } } diff --git a/services/Schematic_PluginsService.php b/services/Schematic_PluginsService.php index 4af2fe05..98f794b2 100644 --- a/services/Schematic_PluginsService.php +++ b/services/Schematic_PluginsService.php @@ -24,7 +24,24 @@ protected function getPluginService() } /** - * Installs plugin by handle + * @return MigrationsService + */ + protected function getMigrationsService() + { + return craft()->migrations; + } + + /** + * @return UpdatesService + */ + protected function getUpdatesService() + { + return craft()->updates; + } + + /** + * Installs plugin by handle. + * * @param string $handle */ protected function installPluginByHandle($handle) @@ -37,7 +54,8 @@ protected function installPluginByHandle($handle) } /** - * Uninstalls plugin by handle + * Uninstalls plugin by handle. + * * @param $handle */ protected function uninstallPluginByHandle($handle) @@ -46,8 +64,10 @@ protected function uninstallPluginByHandle($handle) } /** - * Returns plugin by handle + * Returns plugin by handle. + * * @param string $handle + * * @return BasePlugin|null */ protected function getPlugin($handle) @@ -61,9 +81,10 @@ protected function getPlugin($handle) } /** - * Toggles plugin based on enabled flag + * Toggles plugin based on enabled flag. + * * @param string $handle - * @param bool $isEnabled + * @param bool $isEnabled */ protected function togglePluginByHandle($handle, $isEnabled) { @@ -75,7 +96,23 @@ protected function togglePluginByHandle($handle, $isEnabled) } /** + * Run plugin migrations automatically. + * * @param BasePlugin $plugin + */ + protected function runMigrations(BasePlugin $plugin) + { + if (!$this->getMigrationsService()->runToTop($plugin)) { + throw new Exception(Craft::t('There was a problem updating your database.')); + } + if (!$this->getUpdatesService()->setNewPluginInfo($plugin)) { + throw new Exception(Craft::t('The update was performed successfully, but there was a problem setting the new info in the plugins table.')); + } + } + + /** + * @param BasePlugin $plugin + * * @return array */ private function getPluginDefinition(BasePlugin $plugin) @@ -83,13 +120,14 @@ private function getPluginDefinition(BasePlugin $plugin) return array( 'isInstalled' => $plugin->isInstalled, 'isEnabled' => $plugin->isEnabled, - 'settings' => $plugin->getSettings()->attributes + 'settings' => $plugin->getSettings()->attributes, ); } /** * @param array $pluginDefinitions - * @param bool $force + * @param bool $force + * * @return Schematic_ResultModel */ public function import(array $pluginDefinitions, $force = false) @@ -97,7 +135,11 @@ public function import(array $pluginDefinitions, $force = false) foreach ($pluginDefinitions as $handle => $pluginDefinition) { if ($plugin = $this->getPlugin($handle)) { if ($pluginDefinition['isInstalled']) { - $this->installPluginByHandle($handle); + if (!$plugin->isInstalled) { + $this->installPluginByHandle($handle); + } else { + $this->runMigrations($plugin); + } $this->togglePluginByHandle($handle, $pluginDefinition['isEnabled']); @@ -115,6 +157,7 @@ public function import(array $pluginDefinitions, $force = false) /** * @param array $data + * * @return array */ public function export(array $data = array()) @@ -126,6 +169,7 @@ public function export(array $data = array()) $pluginDefinitions[$handle] = $this->getPluginDefinition($plugin); } ksort($pluginDefinitions); + return $pluginDefinitions; } } diff --git a/tests/Schematic_PluginsServiceTest.php b/tests/Schematic_PluginsServiceTest.php index b753cd2c..16aebbe5 100644 --- a/tests/Schematic_PluginsServiceTest.php +++ b/tests/Schematic_PluginsServiceTest.php @@ -5,7 +5,7 @@ use PHPUnit_Framework_MockObject_MockObject as Mock; /** - * Class Schematic_PluginsServiceTest + * Class Schematic_PluginsServiceTest. * * @author Itmundi * @copyright Copyright (c) 2015, Itmundi @@ -44,12 +44,31 @@ public static function setUpBeforeClass() require_once __DIR__.'/../services/Schematic_PluginsService.php'; } + /** + * Prevent code duplication by mocking multiple services. + * + * @param bool $returnPlugin + * @param bool $installPluginResponse + */ + public function mockMultipleServices( + $returnPlugin = true, + $installPluginResponse = true + ) { + $mockPluginsService = $this->getMockPluginsService($returnPlugin, $installPluginResponse); + $this->setComponent(craft(), 'plugins', $mockPluginsService); + $mockMigrationsService = $this->getMockMigrationsService(); + $this->setComponent(craft(), 'migrations', $mockMigrationsService); + $mockUpdatesService = $this->getMockUpdatesService(); + $this->setComponent(craft(), 'updates', $mockUpdatesService); + } + /** * @param bool $returnPlugin * @param bool $installPluginResponse * @param bool $enablePluginResponse * @param bool $disablePluginResponse * @param bool $uninstallPluginResponse + * * @return PluginsService|Mock */ public function getMockPluginsService( @@ -63,7 +82,7 @@ public function getMockPluginsService( $mock->expects($this->any())->method('getPlugin')->willReturn(($returnPlugin) ? $this->getMockBasePlugin() : null); - if($installPluginResponse) { + if ($installPluginResponse) { $mock->expects($this->any())->method('installPlugin')->willReturn($installPluginResponse); } else { $mock->expects($this->any())->method('installPlugin')->willThrowException(new Exception()); @@ -76,6 +95,28 @@ public function getMockPluginsService( return $mock; } + /** + * @return MigrationsService|Mock + */ + public function getMockMigrationsService() + { + $mock = $this->getMockBuilder('Craft\MigrationsService')->getMock(); + $mock->expects($this->any())->method('runToTop')->willReturn(true); + + return $mock; + } + + /** + * @return UpdatesService|Mock + */ + public function getMockUpdatesService() + { + $mock = $this->getMockBuilder('Craft\UpdatesService')->getMock(); + $mock->expects($this->any())->method('setNewPluginInfo')->willReturn(true); + + return $mock; + } + /** * @return Mock|BasePlugin */ @@ -87,14 +128,15 @@ public function getMockBasePlugin() } /** - * Test default import functionality + * Test default import functionality. + * * @covers ::import */ public function testImportWithInstalledPlugins() { $data = $this->getPluginsData(); - $mockPluginsService = $this->getMockPluginsService(); - $this->setComponent(craft(), 'plugins', $mockPluginsService); + + $this->mockMultipleServices(); $import = $this->schematicPluginsService->import($data); @@ -103,15 +145,16 @@ public function testImportWithInstalledPlugins() } /** - * Test default import functionality + * Test default import functionality. + * * @covers ::import */ public function testImportWithInstalledDisabledPlugins() { $data = $this->getPluginsData(); $data['itmundiplugin']['isEnabled'] = false; - $mockPluginsService = $this->getMockPluginsService(); - $this->setComponent(craft(), 'plugins', $mockPluginsService); + + $this->mockMultipleServices(); $import = $this->schematicPluginsService->import($data); @@ -120,7 +163,8 @@ public function testImportWithInstalledDisabledPlugins() } /** - * Test default import functionality + * Test default import functionality. + * * @covers ::import */ public function testImportWithMissingPlugin() @@ -137,15 +181,15 @@ public function testImportWithMissingPlugin() } /** - * Test default import functionality + * Test default import functionality. + * * @covers ::import */ public function testImportWithInstallException() { $data = $this->getPluginsData(); - $mockPluginsService = $this->getMockPluginsService(true, false); - $this->setComponent(craft(), 'plugins', $mockPluginsService); + $this->mockMultipleServices(true, false); $import = $this->schematicPluginsService->import($data); @@ -154,7 +198,8 @@ public function testImportWithInstallException() } /** - * Test default import functionality + * Test default import functionality. + * * @covers ::import */ public function testImportWithNotInstalledPlugin() @@ -172,7 +217,8 @@ public function testImportWithNotInstalledPlugin() } /** - * Test export functionality + * Test export functionality. + * * @covers ::export */ public function testExport() @@ -199,7 +245,8 @@ public function testExport() } /** - * Returns plugins data + * Returns plugins data. + * * @return array */ public function getPluginsData() @@ -211,9 +258,9 @@ public function getPluginsData() 'settings' => array( 'pluginName' => 'Menu', 'canDoActions' => '', - 'quietErrors' => '' - ) - ) + 'quietErrors' => '', + ), + ), ); } }