diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..21f0facd --- /dev/null +++ b/.travis.yml @@ -0,0 +1,21 @@ +language: php +php: + - '5.4' + - '5.5' + - '5.6' + - '7.0' + - '7.1' +# - hhvm # on Trusty only +# - nightly +before_install: + - nvm install 6.11 +install: + - composer install + - npm install -g mongodb-runner + - npm install +before_script: + - mongodb-runner --start +script: + - nohup npm start 1>&2 & + - sleep 10 + - ./vendor/bin/phpunit diff --git a/src/Parse/ParseClient.php b/src/Parse/ParseClient.php index 7f439d87..6fd38c1c 100755 --- a/src/Parse/ParseClient.php +++ b/src/Parse/ParseClient.php @@ -497,7 +497,7 @@ public static function _request( if(!isset($decoded) && $response !== '') { throw new ParseException( 'Bad Request. Could not decode Response: '. - '('.json_last_error().') '.json_last_error_msg(), + '('.json_last_error().') '.self::getLastJSONErrorMsg(), -1 ); @@ -522,6 +522,35 @@ public static function _request( } + /** + * Returns the last error message from a failed json_decode call + * + * @return string + */ + private static function getLastJSONErrorMsg() + { + // check if json_last_error_msg is defined (>= 5.5.0) + if (!function_exists('json_last_error_msg')) { + // return custom error messages for each code + $error_strings = array( + JSON_ERROR_NONE => 'No error', + JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', + JSON_ERROR_STATE_MISMATCH => 'State mismatch (invalid or malformed JSON)', + JSON_ERROR_CTRL_CHAR => 'Control character error, potentially incorrectly encoded', + JSON_ERROR_SYNTAX => 'Syntax error', + JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, potentially incorrectly encoded' + ); + + $error = json_last_error(); + return isset($error_strings[$error]) ? $error_strings[$error] : 'Unknown error'; + + } + + // use existing function + return json_last_error_msg(); + + } + /** * ParseClient::setStorage, will update the storage object used for * persistence. diff --git a/tests/Parse/AddOperationTest.php b/tests/Parse/AddOperationTest.php index 3c28bcfe..3ff30827 100644 --- a/tests/Parse/AddOperationTest.php +++ b/tests/Parse/AddOperationTest.php @@ -40,7 +40,7 @@ public function testAddOperation() */ public function testBadObjects() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'AddOperation requires an array.'); new AddOperation('not an array'); @@ -84,7 +84,7 @@ public function testMergePrevious() */ public function testInvalidMerge() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'Operation is invalid after previous operation.'); $addOp = new AddOperation([ 'key1' => 'value1' diff --git a/tests/Parse/AddUniqueOperationTest.php b/tests/Parse/AddUniqueOperationTest.php index ab120ec2..629fbbba 100644 --- a/tests/Parse/AddUniqueOperationTest.php +++ b/tests/Parse/AddUniqueOperationTest.php @@ -50,7 +50,7 @@ public function testAddUniqueOp() */ public function testBadObjects() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'AddUniqueOperation requires an array.'); $addUnique = new AddUniqueOperation('not-an-array'); @@ -114,7 +114,7 @@ public function testMergePrevious() */ public function testInvalidMerge() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'Operation is invalid after previous operation.'); $addOp = new AddUniqueOperation([ 'key1' => 'value1' diff --git a/tests/Parse/IncrementOperationTest.php b/tests/Parse/IncrementOperationTest.php index dd0f000d..76601971 100644 --- a/tests/Parse/IncrementOperationTest.php +++ b/tests/Parse/IncrementOperationTest.php @@ -62,7 +62,7 @@ public function testMergePrevious() */ public function testInvalidMerge() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'Operation is invalid after previous operation.'); $addOp = new IncrementOperation(); $addOp->_mergeWithPrevious(new AddOperation(['key' => 'value'])); diff --git a/tests/Parse/ParseClientTest.php b/tests/Parse/ParseClientTest.php index 910171ac..eacfe0ee 100644 --- a/tests/Parse/ParseClientTest.php +++ b/tests/Parse/ParseClientTest.php @@ -71,7 +71,7 @@ public function testParseNotInitialized() { * @group client-not-initialized */ public function testAppNotNotInitialized() { - $this->setExpectedException(\Exception::class, + $this->setExpectedException('\Exception', 'You must call Parse::initialize(..., $accountKey) before making any app requests. '. 'Your account key must not be null or empty.' ); @@ -508,7 +508,7 @@ public function testStreamCAFile() */ public function testBadApiResponse() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'Bad Request. Could not decode Response: (4) Syntax error'); $httpClient = ParseClient::getHttpClient(); diff --git a/tests/Parse/ParseCurlTest.php b/tests/Parse/ParseCurlTest.php index 45b2e7bf..f92b6396 100644 --- a/tests/Parse/ParseCurlTest.php +++ b/tests/Parse/ParseCurlTest.php @@ -16,7 +16,7 @@ class ParseCurlTest extends \PHPUnit_Framework_TestCase { public function testBadExec() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'You must call ParseCurl::init first'); $parseCurl = new ParseCurl(); @@ -26,7 +26,7 @@ public function testBadExec() public function testBadSetOption() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'You must call ParseCurl::init first'); $parseCurl = new ParseCurl(); @@ -36,7 +36,7 @@ public function testBadSetOption() public function testBadSetOptionsArray() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'You must call ParseCurl::init first'); $parseCurl = new ParseCurl(); @@ -46,7 +46,7 @@ public function testBadSetOptionsArray() public function testBadGetInfo() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'You must call ParseCurl::init first'); $parseCurl = new ParseCurl(); @@ -56,7 +56,7 @@ public function testBadGetInfo() public function testBadGetError() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'You must call ParseCurl::init first'); $parseCurl = new ParseCurl(); @@ -66,7 +66,7 @@ public function testBadGetError() public function testBadErrorCode() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'You must call ParseCurl::init first'); $parseCurl = new ParseCurl(); @@ -76,7 +76,7 @@ public function testBadErrorCode() public function testBadClose() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'You must call ParseCurl::init first'); $parseCurl = new ParseCurl(); diff --git a/tests/Parse/ParseInstallationTest.php b/tests/Parse/ParseInstallationTest.php index 3c732de4..bfef41c9 100644 --- a/tests/Parse/ParseInstallationTest.php +++ b/tests/Parse/ParseInstallationTest.php @@ -23,7 +23,7 @@ public function tearDown() */ public function testMissingIdentifyingField() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'at least one ID field (deviceToken, installationId) must be specified in this operation'); (new ParseInstallation())->save(); @@ -34,7 +34,7 @@ public function testMissingIdentifyingField() */ public function testMissingDeviceType() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'deviceType must be specified in this operation'); $installation = new ParseInstallation(); @@ -48,7 +48,7 @@ public function testMissingDeviceType() */ public function testClientsCannotFindWithoutMasterKey() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'Clients aren\'t allowed to perform the find operation on the installation collection.'); $query = ParseInstallation::query(); @@ -66,7 +66,7 @@ public function testClientsCannotDestroyWithoutMasterKey() $installation->set('deviceType', 'android'); $installation->save(); - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', "Clients aren't allowed to perform the delete operation on the installation collection."); // try destroying, without using the master key diff --git a/tests/Parse/ParsePushTest.php b/tests/Parse/ParsePushTest.php index 68f1679f..0675cbe8 100644 --- a/tests/Parse/ParsePushTest.php +++ b/tests/Parse/ParsePushTest.php @@ -21,7 +21,7 @@ public function tearDown() } public function testNoMasterKey() { - $this->setExpectedException(ParseException::class); + $this->setExpectedException('\Parse\ParseException'); ParsePush::send( [ @@ -46,7 +46,7 @@ public function testBasicPush() */ public function testMissingWhereAndChannels() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', "Sending a push requires either \"channels\" or a \"where\" query."); ParsePush::send([ @@ -62,7 +62,7 @@ public function testMissingWhereAndChannels() */ public function testWhereAndChannels() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', "Channels and query can not be set at the same time."); $query = ParseInstallation::query(); @@ -108,7 +108,7 @@ public function testPushToQueryWithoutWhere() public function testNonQueryWhere() { - $this->setExpectedException(\Exception::class, + $this->setExpectedException('\Exception', 'Where parameter for Parse Push must be of type ParseQuery'); ParsePush::send( [ @@ -133,7 +133,7 @@ public function testPushDates() public function testExpirationTimeAndIntervalSet() { - $this->setExpectedException(\Exception::class, + $this->setExpectedException('\Exception', 'Both expiration_time and expiration_interval can\'t be set.'); ParsePush::send( [ diff --git a/tests/Parse/ParseQueryTest.php b/tests/Parse/ParseQueryTest.php index bea05d25..73a680c0 100644 --- a/tests/Parse/ParseQueryTest.php +++ b/tests/Parse/ParseQueryTest.php @@ -2243,7 +2243,7 @@ public function testAscendingByArray() { public function testOrQueriesVaryingClasses() { - $this->setExpectedException(\Exception::class, + $this->setExpectedException('\Exception', 'All queries must be for the same class'); ParseQuery::orQueries([ new ParseQuery('Class1'), @@ -2275,7 +2275,7 @@ public function testSetConditions() public function testBadConditions() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', "Conditions must be in an array"); $query = new ParseQuery('TestObject'); diff --git a/tests/Parse/ParseRelationOperationTest.php b/tests/Parse/ParseRelationOperationTest.php index 2f52605b..fe4b5a9f 100644 --- a/tests/Parse/ParseRelationOperationTest.php +++ b/tests/Parse/ParseRelationOperationTest.php @@ -30,7 +30,7 @@ public function tearDown() */ public function testMissingObjects() { - $this->setExpectedException(\Exception::class, + $this->setExpectedException('\Exception', 'Cannot create a ParseRelationOperation with no objects.'); new ParseRelationOperation(null, null); @@ -41,7 +41,7 @@ public function testMissingObjects() */ public function testMixedClasses() { - $this->setExpectedException(\Exception::class, + $this->setExpectedException('\Exception', 'All objects in a relation must be of the same class.'); $objects = []; @@ -78,7 +78,7 @@ public function testSingleObjects() */ public function testApplyDifferentClassRelation() { - $this->setExpectedException(\Exception::class, + $this->setExpectedException('\Exception', 'Related object object must be of class ' .'Class1, but DifferentClass' .' was passed in.'); @@ -96,7 +96,7 @@ public function testApplyDifferentClassRelation() */ public function testInvalidApply() { - $this->setExpectedException(\Exception::class, + $this->setExpectedException('\Exception', 'Operation is invalid after previous operation.'); $addObj = new ParseObject('Class1'); $op = new ParseRelationOperation($addObj, null); @@ -120,7 +120,7 @@ public function testMergeNone() */ public function testMergeDifferentClass() { - $this->setExpectedException(\Exception::class, + $this->setExpectedException('\Exception', 'Related object object must be of class ' .'Class1, but AnotherClass' .' was passed in.'); @@ -140,7 +140,7 @@ public function testMergeDifferentClass() */ public function testInvalidMerge() { - $this->setExpectedException(\Exception::class, + $this->setExpectedException('\Exception', 'Operation is invalid after previous operation.'); $obj = new ParseObject('Class1'); $op = new ParseRelationOperation($obj, null); diff --git a/tests/Parse/ParseRoleTest.php b/tests/Parse/ParseRoleTest.php index e2b82ff2..0ee7c347 100644 --- a/tests/Parse/ParseRoleTest.php +++ b/tests/Parse/ParseRoleTest.php @@ -235,7 +235,7 @@ public function createEden() public function testSettingNonStringAsName() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', "A role's name must be a string."); $role = new ParseRole(); $role->setName(12345); @@ -247,7 +247,7 @@ public function testSettingNonStringAsName() */ public function testSavingWithoutName() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'Roles must have a name.'); $role = new ParseRole(); $role->setACL(new ParseACL()); diff --git a/tests/Parse/ParseSchemaTest.php b/tests/Parse/ParseSchemaTest.php index 75c90bf6..3c13c3f8 100644 --- a/tests/Parse/ParseSchemaTest.php +++ b/tests/Parse/ParseSchemaTest.php @@ -334,7 +334,7 @@ public function testInvalidTypeException() */ public function testBadSchemaGet() { - $this->setExpectedException(ParseException::class); + $this->setExpectedException('\Parse\ParseException'); $user = new ParseUser(); $user->setUsername('schema-user'); @@ -351,7 +351,7 @@ public function testBadSchemaGet() */ public function testBadSchemaSave() { - $this->setExpectedException(ParseException::class); + $this->setExpectedException('\Parse\ParseException'); $user = new ParseUser(); $user->setUsername('schema-user'); @@ -368,7 +368,7 @@ public function testBadSchemaSave() */ public function testBadSchemaUpdate() { - $this->setExpectedException(ParseException::class); + $this->setExpectedException('\Parse\ParseException'); $user = new ParseUser(); $user->setUsername('schema-user'); @@ -385,7 +385,7 @@ public function testBadSchemaUpdate() */ public function testBadSchemaDelete() { - $this->setExpectedException(ParseException::class); + $this->setExpectedException('\Parse\ParseException'); $user = new ParseUser(); $user->setUsername('schema-user'); diff --git a/tests/Parse/ParseSessionStorageAltTest.php b/tests/Parse/ParseSessionStorageAltTest.php index 6ebdd013..7d66a1f1 100644 --- a/tests/Parse/ParseSessionStorageAltTest.php +++ b/tests/Parse/ParseSessionStorageAltTest.php @@ -19,7 +19,7 @@ class ParseSessionStorageAltTest extends \PHPUnit_Framework_TestCase */ public function testNoSessionActive() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'PHP session_start() must be called first.'); new ParseSessionStorage(); diff --git a/tests/Parse/ParseStreamHttpClientTest.php b/tests/Parse/ParseStreamHttpClientTest.php index e98a9952..2637afa8 100644 --- a/tests/Parse/ParseStreamHttpClientTest.php +++ b/tests/Parse/ParseStreamHttpClientTest.php @@ -34,7 +34,7 @@ public function testInvalidUrl() { $url = 'http://example.com/lots of spaces here'; - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'Url may not contain spaces for stream client: ' .$url); diff --git a/tests/Parse/RemoveOperationTest.php b/tests/Parse/RemoveOperationTest.php index d0eabce3..577fa6f1 100644 --- a/tests/Parse/RemoveOperationTest.php +++ b/tests/Parse/RemoveOperationTest.php @@ -22,7 +22,7 @@ class RemoveOperationTest extends \PHPUnit_Framework_TestCase */ public function testMissingArray() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'RemoveOperation requires an array.'); new RemoveOperation('not an array'); @@ -65,7 +65,7 @@ public function testMergePrevious() */ public function testInvalidMerge() { - $this->setExpectedException(ParseException::class, + $this->setExpectedException('\Parse\ParseException', 'Operation is invalid after previous operation.'); $removeOp = new RemoveOperation([ 'key1' => 'value1'