From c132f3ea15992db70e2b70b114f757e6b0212ba6 Mon Sep 17 00:00:00 2001 From: Michael Moussa Date: Sat, 30 Nov 2013 16:04:08 -0500 Subject: [PATCH 1/9] Initial UI --- asset/zf-apigility-admin/css/main.css | 2 +- asset/zf-apigility-admin/partials/api.html | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 asset/zf-apigility-admin/partials/api.html diff --git a/asset/zf-apigility-admin/css/main.css b/asset/zf-apigility-admin/css/main.css index e5e59d6c..cd67791a 100644 --- a/asset/zf-apigility-admin/css/main.css +++ b/asset/zf-apigility-admin/css/main.css @@ -59,7 +59,7 @@ border-right: 1px solid #563d7c; } #api-version { - margin-top: -100px; + margin-top: -125px; } div.alert { position: fixed; diff --git a/asset/zf-apigility-admin/partials/api.html b/asset/zf-apigility-admin/partials/api.html new file mode 100644 index 00000000..49329a83 --- /dev/null +++ b/asset/zf-apigility-admin/partials/api.html @@ -0,0 +1,19 @@ +
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+
+
From 4a125cce6a8ae7b508401be6da8b5727a1d4f739 Mon Sep 17 00:00:00 2001 From: Michael Moussa Date: Sat, 30 Nov 2013 16:43:05 -0500 Subject: [PATCH 2/9] Model logic to update the default API version --- .../Apigility/Admin/Model/VersioningModel.php | 23 +++++++++++++++++++ .../Version/config/module.config.php.dist | 3 +++ .../Admin/Model/VersioningModelTest.php | 11 +++++++++ 3 files changed, 37 insertions(+) diff --git a/src/ZF/Apigility/Admin/Model/VersioningModel.php b/src/ZF/Apigility/Admin/Model/VersioningModel.php index de737e20..ee11ff18 100644 --- a/src/ZF/Apigility/Admin/Model/VersioningModel.php +++ b/src/ZF/Apigility/Admin/Model/VersioningModel.php @@ -95,6 +95,29 @@ public function getModuleVersions($module, $path = false) return $versions; } + /** + * Updates the default version of a module that will be used if no version is + * specified by the API consumer. + * + * @param integer $defaultVersion + * @return boolean + */ + public function setDefaultVersion($defaultVersion) + { + $defaultVersion = (int) $defaultVersion; + + $this->configResource->patch(array( + 'zf-versioning' => array( + 'default-version' => $defaultVersion + ) + ), true); + + $config = $this->configResource->fetch(true); + + return isset($config['zf-versioning']['default-version']) && + $config['zf-versioning']['default-version'] === $defaultVersion; + } + /** * Copy file and folder recursively * diff --git a/test/ZFTest/Apigility/Admin/Model/TestAsset/module/Version/config/module.config.php.dist b/test/ZFTest/Apigility/Admin/Model/TestAsset/module/Version/config/module.config.php.dist index 80b3150a..71d09e79 100644 --- a/test/ZFTest/Apigility/Admin/Model/TestAsset/module/Version/config/module.config.php.dist +++ b/test/ZFTest/Apigility/Admin/Model/TestAsset/module/Version/config/module.config.php.dist @@ -138,6 +138,9 @@ return array ( ), ), ), + 'zf-versioning' => array ( + 'default-version' => 1, + ), 'zf-apigility' => array ( 'db-connected' => array ( 'Version\\V1\\Rest\\Message\\MessageResource' => array ( diff --git a/test/ZFTest/Apigility/Admin/Model/VersioningModelTest.php b/test/ZFTest/Apigility/Admin/Model/VersioningModelTest.php index 017b2bdc..f2840e65 100644 --- a/test/ZFTest/Apigility/Admin/Model/VersioningModelTest.php +++ b/test/ZFTest/Apigility/Admin/Model/VersioningModelTest.php @@ -184,4 +184,15 @@ public function testCreateNewVersionClonesAuthorizationConfigurationForNewVersio $this->assertEquals($originalAuthorization[$serviceName], $updatedAuthorization[$newServiceName]); } } + + public function testSettingTheApiDefaultVersion() + { + $config = include $this->moduleConfigFile; + $this->assertSame(1, $config['zf-versioning']['default-version']); + + $this->assertTrue($this->model->setDefaultVersion(1337)); + + $newConfig = include $this->moduleConfigFile; + $this->assertSame(1337, $newConfig['zf-versioning']['default-version']); + } } From e9d9460a7eff8aa2c019da0a44d4124199c5ec73 Mon Sep 17 00:00:00 2001 From: Michael Moussa Date: Sat, 30 Nov 2013 16:45:25 -0500 Subject: [PATCH 3/9] Route + controller action to handle default api version updates --- config/module.config.php | 10 +++++++ .../Admin/Controller/VersioningController.php | 28 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/config/module.config.php b/config/module.config.php index ba5437bd..353569ea 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -100,6 +100,16 @@ ), ), ), + 'default-version' => array( + 'type' => 'literal', + 'options' => array( + 'route' => '/default-version', + 'defaults' => array( + 'controller' => 'ZF\Apigility\Admin\Controller\Versioning', + 'action' => 'defaultVersion', + ), + ), + ), 'module' => array( 'type' => 'segment', 'options' => array( diff --git a/src/ZF/Apigility/Admin/Controller/VersioningController.php b/src/ZF/Apigility/Admin/Controller/VersioningController.php index e97c466f..ee485365 100644 --- a/src/ZF/Apigility/Admin/Controller/VersioningController.php +++ b/src/ZF/Apigility/Admin/Controller/VersioningController.php @@ -21,6 +21,34 @@ public function __construct(VersioningModelFactory $modelFactory) $this->modelFactory = $modelFactory; } + public function defaultVersionAction() + { + $module = $this->bodyParam('module', false); + if (!$module) { + return new ApiProblemModel( + new ApiProblem(422, 'Module parameter not provided', 'https://tools.ietf.org/html/rfc4918', 'Unprocessable Entity') + ); + } + + $version = $this->bodyParam('version', false); + + if (!$version || !is_numeric($version)) { + return new ApiProblemModel( + new ApiProblem(422, 'Missing or invalid version', 'https://tools.ietf.org/html/rfc4918', 'Unprocessable Entity') + ); + } + + $model = $this->modelFactory->factory($module); + + if ($model->setDefaultVersion($version)) { + return array('success' => true, 'version' => $version); + } else { + return new ApiProblemModel( + new ApiProblem(500, 'An unexpected error occurred while attempting to set the default version') + ); + } + } + public function versioningAction() { $request = $this->getRequest(); From d518d98d2139ac94f120fd68cd55ea08ce921afc Mon Sep 17 00:00:00 2001 From: Michael Moussa Date: Sat, 30 Nov 2013 16:47:14 -0500 Subject: [PATCH 4/9] Angular logic to update the default version --- asset/zf-apigility-admin/js/app.js | 27 +++++++++++++++++++ .../Admin/Controller/VersioningController.php | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/asset/zf-apigility-admin/js/app.js b/asset/zf-apigility-admin/js/app.js index f798c08b..d3223aa8 100644 --- a/asset/zf-apigility-admin/js/app.js +++ b/asset/zf-apigility-admin/js/app.js @@ -253,6 +253,19 @@ module.controller( ); }; + ApiRepository.setApiModel($routeParams.apiName, null, true).then(function (api) { + $scope.$apply(function () { + // controller scope + $scope.api = api; + $scope.currentApiVersion = ApisResource.currentApiVersion; + $scope.defaultApiVersion = $scope.currentApiVersion; + $scope.section = $routeParams.section; + + // root scope page elements + $rootScope.pageTitle = api.namespace; + $rootScope.pageDescription = 'tbd'; + }); + var createAuthentication = function (options) { AuthenticationRepository.createAuthentication(options).then(function (authentication) { flash.success = 'Authentication created'; @@ -311,6 +324,12 @@ module.controller( createAuthentication(options); }; + $scope.setDefaultApiVersion = function () { + ApisResource.setDefaultApiVersion($scope.api.name, $scope.defaultApiVersion).then(function (data) { + $scope.defaultApiVersion = data.version; + }); + }; + $scope.createOAuth2Authentication = function () { var options = { dsn : $scope.dsn, @@ -540,6 +559,7 @@ module.controller( ApiRepository.getApi($routeParams.apiName, $routeParams.version).then(function (api) { $scope.api = api; $scope.currentVersion = api.version; + $scope.defaultApiVersion = $scope.currentVersion; }); $scope.createNewApiVersion = function () { @@ -793,6 +813,13 @@ module.factory('DbAdapterResource', ['$http', '$q', '$location', 'apiBasePath', }); }; + resource.setDefaultApiVersion = function (apiName, defaultApiVersion) { + return $http({method: 'patch', url: '/admin/api/default-version', data: {module: apiName, version: defaultApiVersion}}) + .then(function (response) { + return response.data; + }); + }; + return resource; }]); diff --git a/src/ZF/Apigility/Admin/Controller/VersioningController.php b/src/ZF/Apigility/Admin/Controller/VersioningController.php index ee485365..53705fc8 100644 --- a/src/ZF/Apigility/Admin/Controller/VersioningController.php +++ b/src/ZF/Apigility/Admin/Controller/VersioningController.php @@ -48,7 +48,7 @@ public function defaultVersionAction() ); } } - + public function versioningAction() { $request = $this->getRequest(); From 3321c4176088eb565ef3f5a7d557a1b4f7d7b287 Mon Sep 17 00:00:00 2001 From: Michael Moussa Date: Sat, 30 Nov 2013 17:26:02 -0500 Subject: [PATCH 5/9] ModuleModel logic returns default version for /admin/api/module Also added ModuleEntityTest, which was missing. --- src/ZF/Apigility/Admin/Model/ModuleEntity.php | 29 +++++++++++++++---- src/ZF/Apigility/Admin/Model/ModuleModel.php | 16 +++++++++- .../Admin/Model/ModuleEntityTest.php | 22 ++++++++++++++ .../Apigility/Admin/Model/ModuleModelTest.php | 29 +++++++++++++++++++ vendor/Test/Bar/Module.php | 4 +++ vendor/Test/Foo/Module.php | 8 +++++ 6 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 test/ZFTest/Apigility/Admin/Model/ModuleEntityTest.php diff --git a/src/ZF/Apigility/Admin/Model/ModuleEntity.php b/src/ZF/Apigility/Admin/Model/ModuleEntity.php index 6d059bbd..5e787a05 100644 --- a/src/ZF/Apigility/Admin/Model/ModuleEntity.php +++ b/src/ZF/Apigility/Admin/Model/ModuleEntity.php @@ -11,6 +11,11 @@ class ModuleEntity { + /** + * @var int + */ + protected $defaultVersion = 1; + /** * @var string */ @@ -64,6 +69,14 @@ public function __construct($namespace, array $restServices = array(), array $rp $this->isVendor = is_bool($isVendor) ? $isVendor : null; } + /** + * @return int + */ + public function getDefaultVersion() + { + return $this->defaultVersion; + } + /** * @return string */ @@ -173,6 +186,9 @@ public function exchangeArray(array $data) } $this->versions = $value; break; + case 'default_version': + $this->defaultVersion = (int) $value; + break; default: break; } @@ -187,12 +203,13 @@ public function exchangeArray(array $data) public function getArrayCopy() { return array( - 'name' => $this->name, - 'namespace' => $this->namespace, - 'is_vendor' => $this->isVendor(), - 'rest' => $this->getRestServices(), - 'rpc' => $this->getRpcServices(), - 'versions' => $this->versions, + 'name' => $this->name, + 'namespace' => $this->namespace, + 'is_vendor' => $this->isVendor(), + 'rest' => $this->getRestServices(), + 'rpc' => $this->getRpcServices(), + 'versions' => $this->versions, + 'default_version' => $this->defaultVersion, ); } diff --git a/src/ZF/Apigility/Admin/Model/ModuleModel.php b/src/ZF/Apigility/Admin/Model/ModuleModel.php index 5f8157f9..ade34ef4 100644 --- a/src/ZF/Apigility/Admin/Model/ModuleModel.php +++ b/src/ZF/Apigility/Admin/Model/ModuleModel.php @@ -15,6 +15,7 @@ use Zend\View\Resolver; use ZF\Apigility\Admin\Exception; use ZF\Apigility\ApigilityModuleInterface; +use ZF\Configuration\Module; class ModuleModel { @@ -235,7 +236,8 @@ protected function getEnabledModules() $versions = $this->getVersionsByModule($moduleName, $module); $entity = new ModuleEntity($moduleName, $services['rest'], $services['rpc']); $entity->exchangeArray(array( - 'versions' => $versions, + 'versions' => $versions, + 'default_version' => $this->getModuleDefaultVersion($module), )); $this->modules[$entity->getName()] = $entity; @@ -244,6 +246,18 @@ protected function getEnabledModules() return $this->modules; } + /** + * Retrieves the configured default version for the specified module. + * + * @param ApigilityModuleInterface $module + * @return int + */ + protected function getModuleDefaultVersion(ApigilityModuleInterface $module) + { + $config = $module->getConfig(); + return isset($config['zf-versioning']['default-version']) ? $config['zf-versioning']['default-version'] : 1; + } + /** * Retrieve all services for a given module * diff --git a/test/ZFTest/Apigility/Admin/Model/ModuleEntityTest.php b/test/ZFTest/Apigility/Admin/Model/ModuleEntityTest.php new file mode 100644 index 00000000..e85be428 --- /dev/null +++ b/test/ZFTest/Apigility/Admin/Model/ModuleEntityTest.php @@ -0,0 +1,22 @@ +assertSame(1, $moduleEntity->getDefaultVersion()); // initial state + + $moduleEntity->exchangeArray(array('default_version' => 123)); + $this->assertSame(123, $moduleEntity->getDefaultVersion()); + } +} diff --git a/test/ZFTest/Apigility/Admin/Model/ModuleModelTest.php b/test/ZFTest/Apigility/Admin/Model/ModuleModelTest.php index 0a15f68d..458e5d34 100644 --- a/test/ZFTest/Apigility/Admin/Model/ModuleModelTest.php +++ b/test/ZFTest/Apigility/Admin/Model/ModuleModelTest.php @@ -249,4 +249,33 @@ public function testVendorModulesAreMarkedAccordingly() $this->assertTrue($module->isVendor()); } } + + public function testDefaultApiVersionIsSetProperly() + { + $modules = array( + 'Test\Bar' => new Test\Bar\Module(), + 'Test\Foo' => new Test\Foo\Module(), + ); + $moduleManager = $this->getMockBuilder('Zend\ModuleManager\ModuleManager') + ->disableOriginalConstructor() + ->getMock(); + $moduleManager->expects($this->any()) + ->method('getLoadedModules') + ->will($this->returnValue($modules)); + + $model = new ModuleModel($moduleManager, array(), array()); + + $modules = $model->getModules(); + + $this->assertSame( + 1, + $modules[0]->getDefaultVersion(), + 'Did not default to version 1 as the default version for unconfigured default version of Test\Bar!' + ); + $this->assertSame( + 123, + $modules[1]->getDefaultVersion(), + 'Did not read configured default version 123 for Test\Foo!' + ); + } } diff --git a/vendor/Test/Bar/Module.php b/vendor/Test/Bar/Module.php index 26950408..fcaae0f4 100644 --- a/vendor/Test/Bar/Module.php +++ b/vendor/Test/Bar/Module.php @@ -6,4 +6,8 @@ class Module implements ApigilityModuleInterface { + public function getConfig() + { + return array(); + } } diff --git a/vendor/Test/Foo/Module.php b/vendor/Test/Foo/Module.php index dbbdb5a7..941ac07d 100644 --- a/vendor/Test/Foo/Module.php +++ b/vendor/Test/Foo/Module.php @@ -6,4 +6,12 @@ class Module implements ApigilityModuleInterface { + public function getConfig() + { + return array( + 'zf-versioning' => array( + 'default-version' => 123, + ), + ); + } } From d4024c094a702e539c6277d1c88391ca01837102 Mon Sep 17 00:00:00 2001 From: Michael Moussa Date: Sat, 30 Nov 2013 17:32:41 -0500 Subject: [PATCH 6/9] Set the default version based on /admin/api/module response --- asset/zf-apigility-admin/js/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asset/zf-apigility-admin/js/app.js b/asset/zf-apigility-admin/js/app.js index d3223aa8..ff1ada9d 100644 --- a/asset/zf-apigility-admin/js/app.js +++ b/asset/zf-apigility-admin/js/app.js @@ -258,7 +258,7 @@ module.controller( // controller scope $scope.api = api; $scope.currentApiVersion = ApisResource.currentApiVersion; - $scope.defaultApiVersion = $scope.currentApiVersion; + $scope.defaultApiVersion = api.default_version; $scope.section = $routeParams.section; // root scope page elements From e50f1b4654567264842bb3ab8c54ce6d26a0a592 Mon Sep 17 00:00:00 2001 From: Michael Moussa Date: Fri, 6 Dec 2013 11:52:30 -0500 Subject: [PATCH 7/9] Code formatting --- src/ZF/Apigility/Admin/Model/VersioningModel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ZF/Apigility/Admin/Model/VersioningModel.php b/src/ZF/Apigility/Admin/Model/VersioningModel.php index ee11ff18..27c53d51 100644 --- a/src/ZF/Apigility/Admin/Model/VersioningModel.php +++ b/src/ZF/Apigility/Admin/Model/VersioningModel.php @@ -114,8 +114,8 @@ public function setDefaultVersion($defaultVersion) $config = $this->configResource->fetch(true); - return isset($config['zf-versioning']['default-version']) && - $config['zf-versioning']['default-version'] === $defaultVersion; + return isset($config['zf-versioning']['default-version']) + && $config['zf-versioning']['default-version'] === $defaultVersion; } /** From c4a22086cbe53d86e7851ffdfc3a15b619c7f8a1 Mon Sep 17 00:00:00 2001 From: Michael Moussa Date: Fri, 6 Dec 2013 12:44:31 -0500 Subject: [PATCH 8/9] Fixes to default versioning UI after rebasing --- asset/zf-apigility-admin/js/app.js | 44 +++++++------------ asset/zf-apigility-admin/partials/api.html | 19 -------- .../partials/api/version.html | 18 ++++++-- 3 files changed, 31 insertions(+), 50 deletions(-) delete mode 100644 asset/zf-apigility-admin/partials/api.html diff --git a/asset/zf-apigility-admin/js/app.js b/asset/zf-apigility-admin/js/app.js index ff1ada9d..a02167f2 100644 --- a/asset/zf-apigility-admin/js/app.js +++ b/asset/zf-apigility-admin/js/app.js @@ -253,19 +253,6 @@ module.controller( ); }; - ApiRepository.setApiModel($routeParams.apiName, null, true).then(function (api) { - $scope.$apply(function () { - // controller scope - $scope.api = api; - $scope.currentApiVersion = ApisResource.currentApiVersion; - $scope.defaultApiVersion = api.default_version; - $scope.section = $routeParams.section; - - // root scope page elements - $rootScope.pageTitle = api.namespace; - $rootScope.pageDescription = 'tbd'; - }); - var createAuthentication = function (options) { AuthenticationRepository.createAuthentication(options).then(function (authentication) { flash.success = 'Authentication created'; @@ -324,12 +311,6 @@ module.controller( createAuthentication(options); }; - $scope.setDefaultApiVersion = function () { - ApisResource.setDefaultApiVersion($scope.api.name, $scope.defaultApiVersion).then(function (data) { - $scope.defaultApiVersion = data.version; - }); - }; - $scope.createOAuth2Authentication = function () { var options = { dsn : $scope.dsn, @@ -452,6 +433,7 @@ module.controller('ApiRestServicesController', ['$http', '$rootScope', '$scope', $timeout(function () { ApiRepository.getApi($scope.api.name, $scope.api.version, true).then(function (api) { $scope.api = api; + $scope.currentVersion = api.currentVersion; }); }, 500); $scope.showNewRestServiceForm = false; @@ -559,7 +541,7 @@ module.controller( ApiRepository.getApi($routeParams.apiName, $routeParams.version).then(function (api) { $scope.api = api; $scope.currentVersion = api.version; - $scope.defaultApiVersion = $scope.currentVersion; + $scope.defaultApiVersion = api.default_version; }); $scope.createNewApiVersion = function () { @@ -572,6 +554,12 @@ module.controller( }); }; + $scope.setDefaultApiVersion = function () { + ApiRepository.setDefaultApiVersion($scope.api.name, $scope.defaultApiVersion).then(function (data) { + $scope.defaultApiVersion = data.version; + }); + }; + $scope.changeVersion = function () { var curPath = $location.path(); var lastSegment = curPath.substr(curPath.lastIndexOf('/') + 1); @@ -740,6 +728,13 @@ module.factory('ApiRepository', ['$rootScope', '$q', '$http', 'apiBasePath', fun .then(function (response) { return response.data; }); + }, + + setDefaultApiVersion: function (apiName, defaultApiVersion) { + return $http({method: 'patch', url: '/admin/api/default-version', data: {module: apiName, version: defaultApiVersion}}) + .then(function (response) { + return response.data; + }); } }; @@ -813,14 +808,7 @@ module.factory('DbAdapterResource', ['$http', '$q', '$location', 'apiBasePath', }); }; - resource.setDefaultApiVersion = function (apiName, defaultApiVersion) { - return $http({method: 'patch', url: '/admin/api/default-version', data: {module: apiName, version: defaultApiVersion}}) - .then(function (response) { - return response.data; - }); - }; - - return resource; + return resource; }]); module.factory( diff --git a/asset/zf-apigility-admin/partials/api.html b/asset/zf-apigility-admin/partials/api.html deleted file mode 100644 index 49329a83..00000000 --- a/asset/zf-apigility-admin/partials/api.html +++ /dev/null @@ -1,19 +0,0 @@ -
-
- - -
-
- - -
-
- -
-
-
-
-
-
-
diff --git a/asset/zf-apigility-admin/partials/api/version.html b/asset/zf-apigility-admin/partials/api/version.html index 01a12b11..01e46994 100644 --- a/asset/zf-apigility-admin/partials/api/version.html +++ b/asset/zf-apigility-admin/partials/api/version.html @@ -1,8 +1,20 @@
-
Current Version: {{ api.version }}
- + + +
+
+ + +
+
- +
+
+
+
+
From 5d8bab047e3781ef5172e35ee0e11a1024225a8f Mon Sep 17 00:00:00 2001 From: Michael Moussa Date: Fri, 6 Dec 2013 12:48:51 -0500 Subject: [PATCH 9/9] Whitespace fix --- asset/zf-apigility-admin/js/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asset/zf-apigility-admin/js/app.js b/asset/zf-apigility-admin/js/app.js index a02167f2..8ff95f7d 100644 --- a/asset/zf-apigility-admin/js/app.js +++ b/asset/zf-apigility-admin/js/app.js @@ -808,7 +808,7 @@ module.factory('DbAdapterResource', ['$http', '$q', '$location', 'apiBasePath', }); }; - return resource; + return resource; }]); module.factory(