diff --git a/README.md b/README.md index 29013864..aadb0869 100644 --- a/README.md +++ b/README.md @@ -328,6 +328,40 @@ if(ParsePush::hasStatus($response)) { } ``` +Server Info: + +Get information regarding the configuration of the server you are connecting to. +```php +// get the current version of the server you are connected to (2.6.5, 2.5.4, etc.) +$version = ParseServerInfo::getVersion(); + +// get various features +$globalConfigFeatures = ParseServerInfo::getGlobalConfigFeatures(); +/** + * Returns json of the related features + * { + * "create" : true, + * "read" : true, + * "update" : true, + * "delete" : true + * } + */ +``` + + You can get details on the following features as well: + + ```php + ParseServerInfo::getHooksFeatures(); + ParseServerInfo::getCloudCodeFeatures(); + ParseServerInfo::getLogsFeatures(); + ParseServerInfo::getPushFeatures(); + ParseServerInfo::getSchemasFeatures(); + + // additional features can be obtained manually using 'get' + $feature = ParseServerInfo::get('new-feature'); + + ``` + Contributing / Testing ---------------------- diff --git a/src/Parse/ParseServerInfo.php b/src/Parse/ParseServerInfo.php new file mode 100644 index 00000000..13da5830 --- /dev/null +++ b/src/Parse/ParseServerInfo.php @@ -0,0 +1,173 @@ + + * @package Parse + */ +class ParseServerInfo +{ + /** + * Reported server features and configs + * + * @var array + */ + private static $serverFeatures; + + /** + * Reported server version + * + * @var string + */ + private static $serverVersion; + + /** + * Requests, sets and returns server features and version + * + * @return array + * @throws ParseException + */ + private static function getServerInfo() + { + if (!isset(self::$serverFeatures) || !isset(self::$serverVersion)) { + $info = ParseClient::_request( + 'GET', + 'serverInfo/', + null, + null, + true + ); + + // validate we have features & version + + if (!isset($info['features'])) { + throw new ParseException('Missing features in server info.'); + } + + if (!isset($info['parseServerVersion'])) { + throw new ParseException('Missing version in server info.'); + } + + self::$serverFeatures = $info['features']; + self::_setServerVersion($info['parseServerVersion']); + } + + return [ + 'features' => self::$serverFeatures, + 'version' => self::$serverVersion + ]; + } + + /** + * Sets the current server version. + * Allows setting the server version to avoid making an additional request + * if the version is obtained elsewhere. + * + * @param string $version Version to set + */ + public static function _setServerVersion($version) + { + self::$serverVersion = $version; + } + + /** + * Get a specific feature set from the server + * + * @param string $key Feature set to get + * @return mixed + */ + public static function get($key) + { + return self::getServerInfo()['features'][$key]; + } + + /** + * Gets features for the current server + * + * @return array + */ + public static function getFeatures() + { + return self::getServerInfo()['features']; + } + + /** + * Gets the reported version of the current server + * + * @return string + */ + public static function getVersion() + { + if (!isset(self::$serverVersion)) { + return self::getServerInfo()['version']; + } else { + return self::$serverVersion; + } + } + + /** + * Gets features available for globalConfig + * + * @return array + */ + public static function getGlobalConfigFeatures() + { + return self::get('globalConfig'); + } + + /** + * Gets features available for hooks + * + * @return array + */ + public static function getHooksFeatures() + { + return self::get('hooks'); + } + + /** + * Gets features available for cloudCode + * + * @return array + */ + public static function getCloudCodeFeatures() + { + return self::get('cloudCode'); + } + + /** + * Gets features available for logs + * + * @return array + */ + public static function getLogsFeatures() + { + return self::get('logs'); + } + + /** + * Gets features available for push + * + * @return array + */ + public static function getPushFeatures() + { + return self::get('push'); + } + + /** + * Gets features available for schemas + * + * @return array + */ + public static function getSchemasFeatures() + { + return self::get('schemas'); + } +} diff --git a/tests/Parse/ParseServerInfoTest.php b/tests/Parse/ParseServerInfoTest.php new file mode 100644 index 00000000..affd6018 --- /dev/null +++ b/tests/Parse/ParseServerInfoTest.php @@ -0,0 +1,186 @@ +assertNotNull($logs); + } + + public function testGetFeatures() + { + $features = ParseServerInfo::getFeatures(); + $this->assertNotEmpty($features); + } + + /** + * @group test-get-version + */ + public function testGetVersion() + { + ParseServerInfo::_setServerVersion(null); + $version = ParseServerInfo::getVersion(); + $this->assertNotNull($version); + } + + public function testSetVersion() + { + /** + * Tests setting the version. + * /health may return the version in the future as well. + * Rather than fetch that information again we can always have the option + * to set it from wherever we happen to get it. + */ + $version = '1.2.3'; + ParseServerInfo::_setServerVersion($version); + $this->assertEquals($version, ParseServerInfo::getVersion()); + } + + /** + * @group server-info-missing-features + */ + public function testMissingFeatures() + { + $this->setExpectedException( + 'Parse\ParseException', + 'Missing features in server info.' + ); + + $httpClient = ParseClient::getHttpClient(); + + // create a mock of the current http client + $stubClient = $this->getMockBuilder(get_class($httpClient)) + ->getMock(); + + // stub the response type to return + // something we will try to work with + $stubClient + ->method('getResponseContentType') + ->willReturn('application/octet-stream'); + + $stubClient + ->method('send') + ->willReturn(json_encode([ + 'empty' => true + ])); + + // replace the client with our stub + ParseClient::setHttpClient($stubClient); + + ParseServerInfo::_setServerVersion(null); + ParseServerInfo::getFeatures(); + } + + /** + * @group server-info-missing-version + */ + public function testMissingVersion() + { + $this->setExpectedException( + 'Parse\ParseException', + 'Missing version in server info.' + ); + + $httpClient = ParseClient::getHttpClient(); + + // create a mock of the current http client + $stubClient = $this->getMockBuilder(get_class($httpClient)) + ->getMock(); + + // stub the response type to return + // something we will try to work with + $stubClient + ->method('getResponseContentType') + ->willReturn('application/octet-stream'); + + $stubClient + ->method('send') + ->willReturn(json_encode([ + 'features' => [] + ])); + + // replace the client with our stub + ParseClient::setHttpClient($stubClient); + + ParseServerInfo::_setServerVersion(null); + ParseServerInfo::getFeatures(); + } + + public function testGlobalConfigFeatures() + { + $globalConfigFeatures = ParseServerInfo::getGlobalConfigFeatures(); + $this->assertTrue($globalConfigFeatures['create']); + $this->assertTrue($globalConfigFeatures['read']); + $this->assertTrue($globalConfigFeatures['update']); + $this->assertTrue($globalConfigFeatures['delete']); + } + + public function testHooksFeatures() + { + $hooksFeatures = ParseServerInfo::getHooksFeatures(); + $this->assertTrue($hooksFeatures['create']); + $this->assertTrue($hooksFeatures['read']); + $this->assertTrue($hooksFeatures['update']); + $this->assertTrue($hooksFeatures['delete']); + } + + public function testCloudCodeFeatures() + { + $cloudCodeFeatures = ParseServerInfo::getCloudCodeFeatures(); + $this->assertTrue($cloudCodeFeatures['jobs']); + } + + public function testLogsFeatures() + { + $logsFeatures = ParseServerInfo::getLogsFeatures(); + $this->assertTrue($logsFeatures['level']); + $this->assertTrue($logsFeatures['size']); + $this->assertTrue($logsFeatures['order']); + $this->assertTrue($logsFeatures['until']); + $this->assertTrue($logsFeatures['from']); + } + + public function testPushFeatures() + { + $pushFeatures = ParseServerInfo::getPushFeatures(); + + // these may change depending on the server being tested against + $this->assertTrue(isset($pushFeatures['immediatePush'])); + $this->assertTrue(isset($pushFeatures['scheduledPush'])); + $this->assertTrue(isset($pushFeatures['storedPushData'])); + + $this->assertTrue($pushFeatures['pushAudiences']); + $this->assertTrue($pushFeatures['localization']); + } + + public function testSchemasFeatures() + { + $schemasFeatures = ParseServerInfo::getSchemasFeatures(); + $this->assertTrue($schemasFeatures['addField']); + $this->assertTrue($schemasFeatures['removeField']); + $this->assertTrue($schemasFeatures['addClass']); + $this->assertTrue($schemasFeatures['removeClass']); + $this->assertTrue($schemasFeatures['clearAllDataFromClass']); + $this->assertFalse($schemasFeatures['exportClass']); + $this->assertTrue($schemasFeatures['editClassLevelPermissions']); + $this->assertTrue($schemasFeatures['editPointerPermissions']); + } +} diff --git a/tests/bootstrap-stream.php b/tests/bootstrap-stream.php index 0beb835a..29c33548 100644 --- a/tests/bootstrap-stream.php +++ b/tests/bootstrap-stream.php @@ -9,6 +9,8 @@ namespace Parse; +use Parse\Test\Helper; + require_once dirname(__DIR__).'/vendor/autoload.php'; define('APPLICATION_PATH', dirname(__DIR__)); @@ -16,4 +18,8 @@ // use the steam client $USE_CLIENT_STREAM = true; -echo "[ testing with stream client ]\n"; \ No newline at end of file +// indicate which server version & client we're testing against +Helper::setUp(); +$version = ParseServerInfo::getVersion(); + +echo "[ testing against {$version} with stream client ]\n"; \ No newline at end of file diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 06b8f9eb..32e21fd1 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -7,8 +7,14 @@ namespace Parse; +use Parse\Test\Helper; + require_once dirname(__DIR__).'/vendor/autoload.php'; define('APPLICATION_PATH', dirname(__DIR__)); -echo "[ testing with curl client ]\n"; \ No newline at end of file +// indicate which server version & client we're testing against +Helper::setUp(); +$version = ParseServerInfo::getVersion(); + +echo "[ testing against {$version} with curl client ]\n"; \ No newline at end of file