From ea480664f25a89b3dc16c4022a8b3b325d20ab28 Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Sat, 2 Sep 2017 09:59:47 -0400 Subject: [PATCH 01/13] - Fixing issue with nested objects in the create call - Replacing deprecated getMock() with createMock() - Fixing PHPDocs - Updating the version --- README.md | 3 ++ aweber_api/oauth_application.php | 22 ++++++++----- tests/AWeberCollectionTest.php | 54 ++++++++++++++++++++++++++++++++ tests/AWeberCreateEntryTest.php | 4 +-- tests/AWeberEntryTest.php | 22 ++++++++++++- tests/OAuthApplicationTest.php | 16 +++++----- tests/mock_adapter.php | 6 ++++ 7 files changed, 108 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 402b27b..2ebcfd5 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,9 @@ subscriber information. Changelog: ---------- +2017-09-02: v1.1.18 + * Fixing issues on the formatting of nested objects on 'application/json' requests + 2017-08-21: v1.1.17 * Fixing UTF-8 issues on creates diff --git a/aweber_api/oauth_application.php b/aweber_api/oauth_application.php index 4276a02..bd8d449 100644 --- a/aweber_api/oauth_application.php +++ b/aweber_api/oauth_application.php @@ -65,7 +65,7 @@ class OAuthApplication implements AWeberOAuthAdapter { public $signatureMethod = 'HMAC-SHA1'; - public $clientVersion = '1.1.17'; + public $clientVersion = '1.1.18'; public $oAuthVersion = '1.0'; @@ -86,7 +86,8 @@ class OAuthApplication implements AWeberOAuthAdapter { * * Create a new OAuthApplication, based on an OAuthServiceProvider * @access public - * @return void + * @param bool $parentApp + * @throws Exception */ public function __construct($parentApp = false) { if ($parentApp) { @@ -116,8 +117,8 @@ public function request($method, $uri, $data = array(), $options = array(), $hea $uri = $this->app->removeBaseUri($uri); $url = $this->app->getBaseUri() . $uri; - # WARNING: non-primative items in data must be json serialized in GET and POST. - if ($method == 'POST' or $method == 'GET') { + # WARNING: If not being sent as json, non-primative items in data must be json serialized in GET and POST. + if ( (!in_array("Content-Type: application/json", $headers) and $method == 'POST') or $method == 'GET' ) { foreach ($data as $key => $value) { if (is_array($value)) { $data[$key] = json_encode($value); @@ -171,6 +172,7 @@ public function getRequestToken($callbackUrl=false) { * * @access public * @return void + * @throws AWeberOAuthDataMissing */ public function getAccessToken() { $resp = $this->makeRequest('POST', $this->app->getAccessTokenUrl(), @@ -212,10 +214,11 @@ public function parseAsError($response) { * Enforce that all the fields in requiredFields are present and not * empty in data. If a required field is empty, throw an exception. * - * @param mixed $data Array of data - * @param mixed $requiredFields Array of required field names. - * @access protected + * @param mixed $data Array of data + * @param mixed $requiredFields Array of required field names. * @return void + * @throws AWeberOAuthDataMissing + * @access protected */ protected function requiredFromResponse($data, $requiredFields) { foreach ($requiredFields as $field) { @@ -441,8 +444,11 @@ public function signRequest($method, $url, $data) { * @param mixed $method * @param mixed $url - Reserved characters in query params MUST be escaped * @param mixed $data - Reserved characters in values MUST NOT be escaped + * @param mixed $headers - Reserved characters in values MUST NOT be escaped * @access public * @return void + * + * @throws AWeberAPIException */ public function makeRequest($method, $url, $data=array(), $headers=array()) { @@ -450,7 +456,7 @@ public function makeRequest($method, $url, $data=array(), $headers=array()) { switch (strtoupper($method)) { case 'POST': - $oauth = $this->prepareRequest($method, $url, $data); + $oauth = $this->prepareRequest($method, $url, in_array("Content-Type: application/json", $headers) ? array() : $data); $resp = $this->post($url, $oauth, $data, $headers); break; diff --git a/tests/AWeberCollectionTest.php b/tests/AWeberCollectionTest.php index 44ca90c..40bb01b 100644 --- a/tests/AWeberCollectionTest.php +++ b/tests/AWeberCollectionTest.php @@ -17,6 +17,60 @@ public function setUp() { $this->found = $this->subscribers->find($this->params); } + /** + * Test to ensure that the nested objects, such as "custom_fields", are formatted correctly for GET request. The + * nested objects should be a JSON encoded string. + */ + public function testFormatOfGetData() { + $findParams = array('custom_fields' => array('test' => 'test')); + $expectedFindData = array('ws.op' => 'find', 'custom_fields' => '{"test":"test"}'); + + $this->adapter->clearRequests(); + + $resp = $this->subscribers->find($findParams); + + $req = $this->adapter->requestsMade[0]; + $this->assertEquals($req['method'], 'GET'); + $this->assertEquals($req['data'], $expectedFindData); + $this->assertEmpty($req['headers'], "Find request shouldn't have a Content-Type header"); + } + + /** + * Checks that the nested objects, such as "custom_fields", are formatted correctly. The "create" method + * is a POST with Content-Type of 'application/json'. The data should be formatted as JSON. + */ + public function testFormatOfPostData() { + + $createParams = array( + 'email' => 'test@example.com', + 'ip_address' => '127.0.0.1', + 'name' => 'John Doe', + 'custom_fields' => array( + 'custom' => 'test' + ) + ); + + $expectedCreateParams = array( + 'ws.op' => 'create', + 'email' => 'test@example.com', + 'ip_address' => '127.0.0.1', + 'name' => 'John Doe', + 'custom_fields' => array( + 'custom' => 'test' + ) + ); + + $this->adapter->clearRequests(); + + $resp = $this->subscribers->create($createParams); + + $req = $this->adapter->requestsMade[0]; + $this->assertEquals($req['method'], 'POST'); + $this->assertEquals($req['data'], $expectedCreateParams); + $this->assertEquals(array('Content-Type: application/json'), $req['headers'], "Create request should have a Content-Type header"); + + } + /** * The find method makes two requests, one for the collection, and the other to get total_size. */ diff --git a/tests/AWeberCreateEntryTest.php b/tests/AWeberCreateEntryTest.php index aa10909..9f51510 100644 --- a/tests/AWeberCreateEntryTest.php +++ b/tests/AWeberCreateEntryTest.php @@ -88,7 +88,7 @@ public function testCreateSuccessWithAdapter() { $aweber = new AWeberAPI($consumerKey, $consumerSecret); // Set up the cURL Stub - $stub = $this->getMock('CurlObject'); + $stub = $this->createMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->onConsecutiveCalls($postCustomFieldRsp, @@ -137,7 +137,7 @@ public function testCreateFailureWithAdapter() { $aweber = new AWeberAPI($consumerKey, $consumerSecret); // Set up the cURL Stub - $stub = $this->getMock('CurlObject'); + $stub = $this->createMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($postCustomFieldRsp)); diff --git a/tests/AWeberEntryTest.php b/tests/AWeberEntryTest.php index 29fdb48..473dabe 100644 --- a/tests/AWeberEntryTest.php +++ b/tests/AWeberEntryTest.php @@ -269,6 +269,26 @@ public function testShouldSupportFindSubscribersMethod() { $this->assertEquals($subscribers->data['entries'][0]['self_link'], 'https://api.aweber.com/1.0/accounts/1/lists/303449/subscribers/1'); } + + /** + * Test to ensure that the nested objects, such as "custom_fields", are formatted correctly for GET request. The + * nested objects should be a JSON encoded string. + */ + public function testShouldFormatFindSubscribersParameters() { + + $findSubscribersParameters = array('email' => 'joe@example.com', 'custom_fields' => array('test' => 'test')); + $expectedFindSubscribersParameters = array('email' => 'joe@example.com', 'custom_fields' => '{"test":"test"}', 'ws.op' => 'findSubscribers'); + + $subscribers = $this->entry->findSubscribers($findSubscribersParameters); + + $req = $this->adapter->requestsMade[1]; + $this->assertEquals($req['method'], 'GET'); + $this->assertEquals($req['data'], $expectedFindSubscribersParameters, "Request data should be formatted properly."); + + print_r($req['data']); + + } + } class TestAWeberSubscriberEntry extends PHPUnit_Framework_TestCase { @@ -363,7 +383,7 @@ public function testMove_Success() { $this->assertEquals($req['data'], array( 'ws.op' => 'move', 'list_link' => $this->different_list->self_link)); - $this->assertEmpty($req['headers'], "Move request shouldn't have a Content-Type header"); + $this->assertEmpty($req['headers'], "Move request shouldn't have a Content-Type header"); $req = $this->adapter->requestsMade[1]; $this->assertEquals($req['method'], 'GET'); diff --git a/tests/OAuthApplicationTest.php b/tests/OAuthApplicationTest.php index b62bef0..3e972af 100644 --- a/tests/OAuthApplicationTest.php +++ b/tests/OAuthApplicationTest.php @@ -341,7 +341,7 @@ public function testRequestReturnValueIsZeroNotInJSONFormat(){ } public function testMakeRequestGet() { - $stub = $this->getMock('CurlObject'); + $stub = $this->createMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -352,7 +352,7 @@ public function testMakeRequestGet() { } public function testMakeRequestPost() { - $stub = $this->getMock('CurlObject'); + $stub = $this->createMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -363,7 +363,7 @@ public function testMakeRequestPost() { } public function testMakeRequestPut() { - $stub = $this->getMock('CurlObject'); + $stub = $this->createMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -374,7 +374,7 @@ public function testMakeRequestPut() { } public function testMakeRequestDelete() { - $stub = $this->getMock('CurlObject'); + $stub = $this->createMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -404,7 +404,7 @@ public function testMakeRequestContainsReservedCharInUrl() { $patchedoauth->consumerSecret = 'CONSUMERSECRET'; $patchedoauth->consumerKey = 'consumer_key'; - $stub = $this->getMock('CurlObject'); + $stub = $this->createMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -434,7 +434,7 @@ public function testMakeRequestContainsSeparatorInUrl() { $patchedoauth->consumerSecret = 'CONSUMERSECRET'; $patchedoauth->consumerKey = 'consumer_key'; - $stub = $this->getMock('CurlObject'); + $stub = $this->createMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -463,7 +463,7 @@ public function testMakeRequestContainsReservedCharInData() { $patchedoauth->consumerSecret = 'CONSUMERSECRET'; $patchedoauth->consumerKey = 'consumer_key'; - $stub = $this->getMock('CurlObject'); + $stub = $this->createMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -492,7 +492,7 @@ public function testMakeRequestContainsSeparatorInData() { $patchedoauth->consumerSecret = 'CONSUMERSECRET'; $patchedoauth->consumerKey = 'consumer_key'; - $stub = $this->getMock('CurlObject'); + $stub = $this->createMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); diff --git a/tests/mock_adapter.php b/tests/mock_adapter.php index ebb7639..2304ac9 100644 --- a/tests/mock_adapter.php +++ b/tests/mock_adapter.php @@ -51,6 +51,12 @@ function get_mock_adapter() { $map['POST' ]['/accounts/1/lists/303449/subscribers/1' ] = array(201, '/accounts/1/lists/505454/subscribers/3'); $map['POST' ]['/accounts/1/lists/303449/subscribers/2' ] = array(400, 'error'); +# Entity Body formatting +$map['POST' ]['/accounts/1/lists/303449/subscribers' ] = array(201, '/accounts/1/lists/505454/subscribers/3'); +$map['GET' ]['/accounts/1?email=joe%40example.com&custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=findSubscribers&ws.show=total_size' ] = array(200, 'accounts/findSubscribers_ts'); +$map['GET' ]['/accounts/1?email=joe%40example.com&custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=findSubscribers' ] = array(200, 'accounts/findSubscribers'); +$map['GET' ]['/accounts/1/lists/303449/subscribers?custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=find' ] = array(200, 'subscribers/find_1of2'); +$map['GET' ]['/accounts/1/lists/303449/subscribers?custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=find&ws.show=total_size' ] = array(200, 'subscribers/find_1of2_tsl'); class MockOAuthAdapter extends OAuthApplication { From 9b2804397aa01fa4f3420334122f99b625ae5523 Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Tue, 5 Sep 2017 09:45:06 -0400 Subject: [PATCH 02/13] - Fixing improper headers being sent with GET requests --- aweber_api/oauth_application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aweber_api/oauth_application.php b/aweber_api/oauth_application.php index bd8d449..694e926 100644 --- a/aweber_api/oauth_application.php +++ b/aweber_api/oauth_application.php @@ -462,7 +462,7 @@ public function makeRequest($method, $url, $data=array(), $headers=array()) { case 'GET': $oauth = $this->prepareRequest($method, $url, $data); - $resp = $this->get($url, $oauth, $data, $headers); + $resp = $this->get($url, $oauth, $headers); break; case 'DELETE': From 25ad1e8053a712c26b0b95500241482d4c899d28 Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Tue, 5 Sep 2017 13:19:14 -0400 Subject: [PATCH 03/13] - Adding check for custom fields to not encode as JSON, as request fails not form encoded --- aweber_api/aweber_collection.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aweber_api/aweber_collection.php b/aweber_api/aweber_collection.php index 26c0bc5..fbbd244 100644 --- a/aweber_api/aweber_collection.php +++ b/aweber_api/aweber_collection.php @@ -116,7 +116,8 @@ protected function _type() { public function create($kv_pairs) { # Create Resource $params = array_merge(array('ws.op' => 'create'), $kv_pairs); - $data = $this->adapter->request('POST', $this->url, $params, array('return' => 'headers'), array('Content-Type: application/json')); + $headers = strstr($this->url,'custom_fields') ? array() : array('Content-Type: application/json'); + $data = $this->adapter->request('POST', $this->url, $params, array('return' => 'headers'), $headers); # Return new Resource $url = $data['Location']; From 46d9b8772c50e92dc6f939c155364ca9a0ce4c33 Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Tue, 5 Sep 2017 13:22:51 -0400 Subject: [PATCH 04/13] Updating README.md file --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 2ebcfd5..014f58b 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,9 @@ Changelog: ---------- 2017-09-02: v1.1.18 * Fixing issues on the formatting of nested objects on 'application/json' requests + * Fixing issue with extra data being sent in header. + * Fixing issue to allow the creation of custom fields to be sent as form encoded. + * Updating the deprecated getMock method to createMock. 2017-08-21: v1.1.17 * Fixing UTF-8 issues on creates From 96156e2f4bc0a1eaee57640a7c63dbf1bf082895 Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Tue, 5 Sep 2017 14:00:05 -0400 Subject: [PATCH 05/13] Adding test to check the encoding of the request to create subscriber and custom fields, since they use the same method, but different encodings. --- tests/AWeberCreateEntryTest.php | 42 +++++++++++++++++++++++++++++---- tests/AWeberEntryTest.php | 2 -- tests/mock_adapter.php | 3 ++- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/tests/AWeberCreateEntryTest.php b/tests/AWeberCreateEntryTest.php index 9f51510..367d886 100644 --- a/tests/AWeberCreateEntryTest.php +++ b/tests/AWeberCreateEntryTest.php @@ -18,17 +18,22 @@ public function setUp() { $data = $this->adapter->request('GET', $url); $this->custom_fields = new AWeberCollection($data, $url, $this->adapter); + $subscribers_url = '/accounts/1/lists/303449/subscribers'; + $this->subscribers = new AWeberCollection( + $this->adapter->request('GET', $subscribers_url), + $subscribers_url, + $this->adapter); } /** - * Create Success + * Create Custom Field Success * * A unit test of a successful call to the Collection create method. * Testing is limited to the Collection module; the OAuthAdapater * module that handles the communications with the AWeber Public * API Web Service is stubbed out. */ - public function testCreateSuccess() { + public function testCreateCustomFieldSuccess() { $this->adapter->clearRequests(); $resp = $this->custom_fields->create(array('name' => 'AwesomeField')); @@ -42,14 +47,43 @@ public function testCreateSuccess() { $this->assertEquals($req['data'], array( 'ws.op' => 'create', 'name' => 'AwesomeField')); - $this->assertEquals(array('Content-Type: application/json'), $req['headers'], "Create request should have a Content-Type header"); + $this->assertEmpty($req['headers'], "Custom Field create request should have a Content-Type header"); $req = $this->adapter->requestsMade[1]; $this->assertEquals($req['method'], 'GET'); $this->assertEquals($req['uri'], '/accounts/1/lists/303449/custom_fields/2'); $this->assertEmpty($req['headers'], "Get Custom fields request shouldn't have a Content-Type header"); } - + + /** + * Create Success + * + * A unit test of a successful call to the Collection create method. + * Testing is limited to the Collection module; the OAuthAdapater + * module that handles the communications with the AWeber Public + * API Web Service is stubbed out. + */ + public function testCreateSubscriberSuccess() { + + $this->adapter->clearRequests(); + $resp = $this->subscribers->create(array('email' => 'test@test.com')); + + + $this->assertEquals(sizeOf($this->adapter->requestsMade), 2); + + $req = $this->adapter->requestsMade[0]; + $this->assertEquals($req['method'], 'POST'); + $this->assertEquals($req['data'], array( + 'ws.op' => 'create', + 'email' => 'test@test.com')); + $this->assertEquals(array('Content-Type: application/json'), $req['headers'], "Create request should have a Content-Type header"); + + $req = $this->adapter->requestsMade[1]; + $this->assertEquals($req['method'], 'GET'); + $this->assertEquals($req['uri'], '/accounts/1/lists/303449/subscribers/3'); + $this->assertEmpty($req['headers'], "Get subscriber request shouldn't have a Content-Type header"); + } + /** * Create Success With Adapter * diff --git a/tests/AWeberEntryTest.php b/tests/AWeberEntryTest.php index 473dabe..20dcbe2 100644 --- a/tests/AWeberEntryTest.php +++ b/tests/AWeberEntryTest.php @@ -285,8 +285,6 @@ public function testShouldFormatFindSubscribersParameters() { $this->assertEquals($req['method'], 'GET'); $this->assertEquals($req['data'], $expectedFindSubscribersParameters, "Request data should be formatted properly."); - print_r($req['data']); - } } diff --git a/tests/mock_adapter.php b/tests/mock_adapter.php index 2304ac9..4ea94e5 100644 --- a/tests/mock_adapter.php +++ b/tests/mock_adapter.php @@ -30,6 +30,7 @@ function get_mock_adapter() { $map['GET' ]['/accounts/1/lists/303449/subscribers?email=someone%40example.com&ws.op=find' ] = array(200, 'subscribers/find'); $map['GET' ]['/accounts/1/lists/505454' ] = array(200, 'lists/505454'); $map['GET' ]['/accounts/1/lists/505454/subscribers/3' ] = array(200, 'subscribers/3'); +$map['GET' ]['/accounts/1/lists/303449/subscribers/3' ] = array(200, 'subscribers/3'); $map['GET' ]['/accounts/1/lists?ws.start=20&ws.size=20' ] = array(200, 'lists/page2'); $map['GET' ]['/accounts/1?email=joe%40example.com&ws.op=findSubscribers&ws.show=total_size' ] = array(200, 'accounts/findSubscribers_ts'); $map['GET' ]['/accounts/1?email=joe%40example.com&ws.op=findSubscribers' ] = array(200, 'accounts/findSubscribers'); @@ -52,7 +53,7 @@ function get_mock_adapter() { $map['POST' ]['/accounts/1/lists/303449/subscribers/2' ] = array(400, 'error'); # Entity Body formatting -$map['POST' ]['/accounts/1/lists/303449/subscribers' ] = array(201, '/accounts/1/lists/505454/subscribers/3'); +$map['POST' ]['/accounts/1/lists/303449/subscribers' ] = array(201, '/accounts/1/lists/303449/subscribers/3'); $map['GET' ]['/accounts/1?email=joe%40example.com&custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=findSubscribers&ws.show=total_size' ] = array(200, 'accounts/findSubscribers_ts'); $map['GET' ]['/accounts/1?email=joe%40example.com&custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=findSubscribers' ] = array(200, 'accounts/findSubscribers'); $map['GET' ]['/accounts/1/lists/303449/subscribers?custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=find' ] = array(200, 'subscribers/find_1of2'); From 88c442353c832a307ca480a97f92dbc21e4491dc Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Tue, 5 Sep 2017 14:37:56 -0400 Subject: [PATCH 06/13] Updating travis.yml file to update the composer dependencies --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index f04ab82..2cbb18c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ php: - 5.3 - 5.4 +install: composer install --dev script: phpunit --configuration build/phpunit.xml notifications: From 872f776a624906b6f8d16d580eef9f2866dfc261 Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Tue, 5 Sep 2017 15:40:00 -0400 Subject: [PATCH 07/13] Reverting the upgrade to createMock method as it creates issue with the build. The build fails because it can't find the method. Tried to update the libraries, but certain libraries have issues with the version of PHP. --- .travis.yml | 1 - tests/AWeberCreateEntryTest.php | 4 ++-- tests/OAuthApplicationTest.php | 16 ++++++++-------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2cbb18c..f04ab82 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ php: - 5.3 - 5.4 -install: composer install --dev script: phpunit --configuration build/phpunit.xml notifications: diff --git a/tests/AWeberCreateEntryTest.php b/tests/AWeberCreateEntryTest.php index 367d886..77165ff 100644 --- a/tests/AWeberCreateEntryTest.php +++ b/tests/AWeberCreateEntryTest.php @@ -122,7 +122,7 @@ public function testCreateSuccessWithAdapter() { $aweber = new AWeberAPI($consumerKey, $consumerSecret); // Set up the cURL Stub - $stub = $this->createMock('CurlObject'); + $stub = $this->getMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->onConsecutiveCalls($postCustomFieldRsp, @@ -171,7 +171,7 @@ public function testCreateFailureWithAdapter() { $aweber = new AWeberAPI($consumerKey, $consumerSecret); // Set up the cURL Stub - $stub = $this->createMock('CurlObject'); + $stub = $this->getMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($postCustomFieldRsp)); diff --git a/tests/OAuthApplicationTest.php b/tests/OAuthApplicationTest.php index 3e972af..b62bef0 100644 --- a/tests/OAuthApplicationTest.php +++ b/tests/OAuthApplicationTest.php @@ -341,7 +341,7 @@ public function testRequestReturnValueIsZeroNotInJSONFormat(){ } public function testMakeRequestGet() { - $stub = $this->createMock('CurlObject'); + $stub = $this->getMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -352,7 +352,7 @@ public function testMakeRequestGet() { } public function testMakeRequestPost() { - $stub = $this->createMock('CurlObject'); + $stub = $this->getMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -363,7 +363,7 @@ public function testMakeRequestPost() { } public function testMakeRequestPut() { - $stub = $this->createMock('CurlObject'); + $stub = $this->getMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -374,7 +374,7 @@ public function testMakeRequestPut() { } public function testMakeRequestDelete() { - $stub = $this->createMock('CurlObject'); + $stub = $this->getMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -404,7 +404,7 @@ public function testMakeRequestContainsReservedCharInUrl() { $patchedoauth->consumerSecret = 'CONSUMERSECRET'; $patchedoauth->consumerKey = 'consumer_key'; - $stub = $this->createMock('CurlObject'); + $stub = $this->getMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -434,7 +434,7 @@ public function testMakeRequestContainsSeparatorInUrl() { $patchedoauth->consumerSecret = 'CONSUMERSECRET'; $patchedoauth->consumerKey = 'consumer_key'; - $stub = $this->createMock('CurlObject'); + $stub = $this->getMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -463,7 +463,7 @@ public function testMakeRequestContainsReservedCharInData() { $patchedoauth->consumerSecret = 'CONSUMERSECRET'; $patchedoauth->consumerKey = 'consumer_key'; - $stub = $this->createMock('CurlObject'); + $stub = $this->getMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); @@ -492,7 +492,7 @@ public function testMakeRequestContainsSeparatorInData() { $patchedoauth->consumerSecret = 'CONSUMERSECRET'; $patchedoauth->consumerKey = 'consumer_key'; - $stub = $this->createMock('CurlObject'); + $stub = $this->getMock('CurlObject'); $stub->expects($this->any()) ->method('execute') ->will($this->returnValue($this->stubrsp)); From 105d9b7386e5530c53db39871c8af5c68a79be28 Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Tue, 5 Sep 2017 15:59:14 -0400 Subject: [PATCH 08/13] Updating travis configuration to get the PHP 5.3 build --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index f04ab82..623139a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: php +sudo: required php: - 5.3 - 5.4 From 91623911f678a8b51e8938f82dd4893d2d3f1482 Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Fri, 8 Sep 2017 15:33:00 -0400 Subject: [PATCH 09/13] Refactoring the code to perform the ContentType check once and make it more readable Using the _type to check the 'custom_fields' endpoint Fixing test to handle the reordering of how the request URL and Bosy are built Removing the PHP 5.3 build from Travis as it has been sunset from Travis CI (will do the 5.3 builds internally) --- .travis.yml | 1 - aweber_api/aweber_collection.php | 2 +- aweber_api/oauth_application.php | 111 +++++++++++++++++++------------ tests/AWeberCollectionTest.php | 10 +-- tests/AWeberCreateEntryTest.php | 2 +- tests/AWeberEntryTest.php | 8 +-- tests/mock_adapter.php | 38 +++++++---- 7 files changed, 104 insertions(+), 68 deletions(-) diff --git a/.travis.yml b/.travis.yml index 623139a..f3b6214 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: php sudo: required php: - - 5.3 - 5.4 script: phpunit --configuration build/phpunit.xml diff --git a/aweber_api/aweber_collection.php b/aweber_api/aweber_collection.php index fbbd244..0ce6fed 100644 --- a/aweber_api/aweber_collection.php +++ b/aweber_api/aweber_collection.php @@ -116,7 +116,7 @@ protected function _type() { public function create($kv_pairs) { # Create Resource $params = array_merge(array('ws.op' => 'create'), $kv_pairs); - $headers = strstr($this->url,'custom_fields') ? array() : array('Content-Type: application/json'); + $headers = $this->_type() == 'custom_fields' ? array() : array('Content-Type: application/json'); $data = $this->adapter->request('POST', $this->url, $params, array('return' => 'headers'), $headers); # Return new Resource diff --git a/aweber_api/oauth_application.php b/aweber_api/oauth_application.php index 694e926..49544f0 100644 --- a/aweber_api/oauth_application.php +++ b/aweber_api/oauth_application.php @@ -117,14 +117,6 @@ public function request($method, $uri, $data = array(), $options = array(), $hea $uri = $this->app->removeBaseUri($uri); $url = $this->app->getBaseUri() . $uri; - # WARNING: If not being sent as json, non-primative items in data must be json serialized in GET and POST. - if ( (!in_array("Content-Type: application/json", $headers) and $method == 'POST') or $method == 'GET' ) { - foreach ($data as $key => $value) { - if (is_array($value)) { - $data[$key] = json_encode($value); - } - } - } $response = $this->makeRequest($method, $url, $data, $headers); if (!empty($options['return'])) { @@ -232,14 +224,14 @@ protected function requiredFromResponse($data, $requiredFields) { * get * * Make a get request. Used to exchange user tokens with serice provider. - * @param mixed $url URL to make a get request from. - * @param array $data Data for the request. - * @param mixed $headers Headers for the request + * @param mixed $url URL to make a get request from. + * @param String $url_params URL parameter string + * @param mixed $headers Headers for the request * @access protected * @return void */ - protected function get($url, $data, $headers) { - $url = $this->_addParametersToUrl($url, $data); + protected function get($url, $url_params, $headers = array()) { + $url = $this->_addParametersToUrl($url, $url_params); $handle = $this->curl->init($url); $resp = $this->_sendRequest($handle, $headers); return $resp; @@ -251,7 +243,7 @@ protected function get($url, $data, $headers) { * Adds the parameters in associative array $data to the * given URL * @param String $url URL - * @param array $data Parameters to be added as a query string to + * @param String $data Parameters to be added as a query string to * the URL provided * @access protected * @return void @@ -259,9 +251,9 @@ protected function get($url, $data, $headers) { protected function _addParametersToUrl($url, $data) { if (!empty($data)) { if (strpos($url, '?') === false) { - $url .= '?'.$this->buildData($data); + $url .= '?' . $data; } else { - $url .= '&'.$this->buildData($data); + $url .= '&' . $data; } } return $url; @@ -454,25 +446,23 @@ public function makeRequest($method, $url, $data=array(), $headers=array()) { if ($this->debug) echo "\n** {$method}: $url\n"; + list($url_params, $request_body) = $this->formatRequestData($method, $url, $data, $headers); + switch (strtoupper($method)) { case 'POST': - $oauth = $this->prepareRequest($method, $url, in_array("Content-Type: application/json", $headers) ? array() : $data); - $resp = $this->post($url, $oauth, $data, $headers); + $resp = $this->post($url, $url_params, $request_body, $headers); break; case 'GET': - $oauth = $this->prepareRequest($method, $url, $data); - $resp = $this->get($url, $oauth, $headers); + $resp = $this->get($url, $url_params, $headers); break; case 'DELETE': - $oauth = $this->prepareRequest($method, $url, $data); - $resp = $this->delete($url, $oauth, $headers); + $resp = $this->delete($url, $url_params, $headers); break; case 'PATCH': - $oauth = $this->prepareRequest($method, $url, array()); - $resp = $this->patch($url, $oauth, $data, $headers); + $resp = $this->patch($url, $url_params, $request_body, $headers); break; } @@ -501,21 +491,22 @@ public function makeRequest($method, $url, $data=array(), $headers=array()) { } /** - * put + * patch * - * Prepare an OAuth put method. + * Prepare an OAuth patch method. * - * @param mixed $url URL where we are making the request to - * @param mixed $data Data that is used to make the request - * @param mixed $headers Headers for the request + * @param mixed $url URL where we are making the request to + * @param mixed $url_params URL parameter string + * @param mixed $post_field Data that is used to make the request + * @param mixed $headers Headers for the request * @access protected * @return void */ - protected function patch($url, $oauth, $data, $headers) { - $url = $this->_addParametersToUrl($url, $oauth); + protected function patch($url, $url_params, $post_field, $headers = array()) { + $url = $this->_addParametersToUrl($url, $url_params); $handle = $this->curl->init($url); $this->curl->setopt($handle, CURLOPT_CUSTOMREQUEST, 'PATCH'); - $this->curl->setopt($handle, CURLOPT_POSTFIELDS, json_encode($data)); + $this->curl->setopt($handle, CURLOPT_POSTFIELDS, $post_field); $resp = $this->_sendRequest($handle, $headers); return $resp; } @@ -525,18 +516,18 @@ protected function patch($url, $oauth, $data, $headers) { * * Prepare an OAuth post method. * - * @param mixed $url URL where we are making the request to - * @param mixed $data Data that is used to make the request - * @param mixed $headers Headers for the request + * @param mixed $url URL where we are making the request to + * @param mixed $url_params URL parameter string + * @param mixed $post_field Data that is used to make the request + * @param mixed $headers Headers for the request * @access protected * @return void */ - protected function post($url, $oauth, $data, $headers = array()) { - $url = $this->_addParametersToUrl($url, $oauth); + protected function post($url, $url_params, $post_field, $headers = array()) { + $url = $this->_addParametersToUrl($url, $url_params); $handle = $this->curl->init($url); $this->curl->setopt($handle, CURLOPT_POST, true); - $postData = in_array("Content-Type: application/json", $headers) ? json_encode($data) : $this->buildData($data); - $this->curl->setopt($handle, CURLOPT_POSTFIELDS, $postData); + $this->curl->setopt($handle, CURLOPT_POSTFIELDS, $post_field); $resp = $this->_sendRequest($handle, $headers); return $resp; } @@ -546,13 +537,13 @@ protected function post($url, $oauth, $data, $headers = array()) { * * Makes a DELETE request * @param mixed $url URL where we are making the request to - * @param mixed $data Data that is used in the request + * @param mixed $url_params URL parameter string * @param mixed $headers Headers for the request * @access protected * @return void */ - protected function delete($url, $data, $headers = array()) { - $url = $this->_addParametersToUrl($url, $data); + protected function delete($url, $url_params, $headers = array()) { + $url = $this->_addParametersToUrl($url, $url_params); $handle = $this->curl->init($url); $this->curl->setopt($handle, CURLOPT_CUSTOMREQUEST, 'DELETE'); $resp = $this->_sendRequest($handle, $headers); @@ -655,6 +646,42 @@ protected function userAgent() { return $this->userAgentTitle . $this->clientVersion . ' PHP/' . PHP_VERSION . ' ' . php_uname('m') . '-' . strtolower(php_uname('s')) . '-'. php_uname('r'); } + /** + * @param $method + * @param $headers + * @return bool + * + * Return True if headers array does not contain 'Content-Type: application/json' and is a POST, GET, or DELETE request + */ + protected function needsUrlFormatting($method, $headers) { + return !in_array("Content-Type: application/json", $headers) and ($method == 'POST' or $method == 'GET' or 'DELETE'); + } + + /** + * @param $method + * @param $url + * @param $data + * @param $headers + * @return array + */ + protected function formatRequestData($method, $url, $data, $headers) + { + # WARNING: If not being sent as json, non-primitive items in data must be json serialized in GET and POST. + if ($this->needsUrlFormatting($method, $headers)) { + foreach ($data as $key => $value) { + if (is_array($value)) { + $data[$key] = json_encode($value); + } + } + $url_params = $this->buildData($this->prepareRequest($method, $url, $data)); + $request_body = $this->buildData($data); + } else { + $url_params = $this->buildData($this->prepareRequest($method, $url, array())); + $request_body = json_encode($data); + } + return array($url_params, $request_body); + } + } /** diff --git a/tests/AWeberCollectionTest.php b/tests/AWeberCollectionTest.php index 40bb01b..7263e7d 100644 --- a/tests/AWeberCollectionTest.php +++ b/tests/AWeberCollectionTest.php @@ -23,7 +23,7 @@ public function setUp() { */ public function testFormatOfGetData() { $findParams = array('custom_fields' => array('test' => 'test')); - $expectedFindData = array('ws.op' => 'find', 'custom_fields' => '{"test":"test"}'); + $expectedUri = '/accounts/1/lists/303449/subscribers?custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=find'; $this->adapter->clearRequests(); @@ -31,7 +31,7 @@ public function testFormatOfGetData() { $req = $this->adapter->requestsMade[0]; $this->assertEquals($req['method'], 'GET'); - $this->assertEquals($req['data'], $expectedFindData); + $this->assertEquals($expectedUri, $req['uri']); $this->assertEmpty($req['headers'], "Find request shouldn't have a Content-Type header"); } @@ -84,7 +84,7 @@ public function testShouldInitiallyMake2APIRequests() { public function testShouldRequestCollectionPageFirst() { #$this->subscribers->find($this->params); $uri = $this->adapter->requestsMade[0]['uri']; - $this->assertEquals($uri, '/accounts/1/lists/303449/subscribers?status=unsubscribed&ws.size=1&ws.start=0&ws.op=find'); + $this->assertEquals($uri, '/accounts/1/lists/303449/subscribers?status=unsubscribed&ws.op=find&ws.size=1&ws.start=0'); } /** @@ -92,7 +92,7 @@ public function testShouldRequestCollectionPageFirst() { */ public function testShouldRequestTotalSizePageSecond() { $uri = $this->adapter->requestsMade[1]['uri']; - $this->assertEquals($uri, '/accounts/1/lists/303449/subscribers?status=unsubscribed&ws.size=1&ws.start=0&ws.op=find&ws.show=total_size'); + $this->assertEquals($uri, '/accounts/1/lists/303449/subscribers?status=unsubscribed&ws.op=find&ws.show=total_size&ws.size=1&ws.start=0'); } /** @@ -111,7 +111,7 @@ public function testShouldRequestCorrectCollectionPage() { $this->adapter->clearRequests(); $subscriber = $this->found[1]; $uri = $this->adapter->requestsMade[0]['uri']; - $this->assertEquals($uri, '/accounts/1/lists/303449/subscribers?status=unsubscribed&ws.size=1&ws.start=1&ws.op=find'); + $this->assertEquals($uri, '/accounts/1/lists/303449/subscribers?status=unsubscribed&ws.op=find&ws.size=1&ws.start=1'); } /** diff --git a/tests/AWeberCreateEntryTest.php b/tests/AWeberCreateEntryTest.php index 77165ff..ede35ea 100644 --- a/tests/AWeberCreateEntryTest.php +++ b/tests/AWeberCreateEntryTest.php @@ -43,7 +43,7 @@ public function testCreateCustomFieldSuccess() { $req = $this->adapter->requestsMade[0]; $this->assertEquals($req['method'], 'POST'); - $this->assertEquals($req['uri'], $this->custom_fields->url); + $this->assertEquals($req['uri'], '/accounts/1/lists/303449/custom_fields?name=AwesomeField&ws.op=create'); $this->assertEquals($req['data'], array( 'ws.op' => 'create', 'name' => 'AwesomeField')); diff --git a/tests/AWeberEntryTest.php b/tests/AWeberEntryTest.php index 20dcbe2..82842ce 100644 --- a/tests/AWeberEntryTest.php +++ b/tests/AWeberEntryTest.php @@ -277,13 +277,13 @@ public function testShouldSupportFindSubscribersMethod() { public function testShouldFormatFindSubscribersParameters() { $findSubscribersParameters = array('email' => 'joe@example.com', 'custom_fields' => array('test' => 'test')); - $expectedFindSubscribersParameters = array('email' => 'joe@example.com', 'custom_fields' => '{"test":"test"}', 'ws.op' => 'findSubscribers'); + $expectedFindSubscribersUri = '/accounts/1?custom_fields=%7B%22test%22%3A%22test%22%7D&email=joe%40example.com&ws.op=findSubscribers'; $subscribers = $this->entry->findSubscribers($findSubscribersParameters); $req = $this->adapter->requestsMade[1]; $this->assertEquals($req['method'], 'GET'); - $this->assertEquals($req['data'], $expectedFindSubscribersParameters, "Request data should be formatted properly."); + $this->assertEquals($expectedFindSubscribersUri, $req['uri'],"Request data should be formatted properly."); } @@ -377,7 +377,7 @@ public function testMove_Success() { $req = $this->adapter->requestsMade[0]; $this->assertEquals($req['method'], 'POST'); - $this->assertEquals($req['uri'], $this->subscriber->url); + $this->assertEquals($req['uri'], '/accounts/1/lists/303449/subscribers/1?list_link=https%3A%2F%2Fapi.aweber.com%2F1.0%2Faccounts%2F1%2Flists%2F505454&ws.op=move'); $this->assertEquals($req['data'], array( 'ws.op' => 'move', 'list_link' => $this->different_list->self_link)); @@ -420,7 +420,7 @@ public function testMoveWLastMessageNumberSent_Success() { $req = $this->adapter->requestsMade[0]; $this->assertEquals($req['method'], 'POST'); - $this->assertEquals($req['uri'], $this->subscriber->url); + $this->assertEquals($req['uri'], '/accounts/1/lists/303449/subscribers/1?last_followup_message_number_sent=1&list_link=https%3A%2F%2Fapi.aweber.com%2F1.0%2Faccounts%2F1%2Flists%2F505454&ws.op=move'); $this->assertEquals($req['data'], array( 'ws.op' => 'move', 'list_link' => $this->different_list->self_link, diff --git a/tests/mock_adapter.php b/tests/mock_adapter.php index 4ea94e5..f23da9d 100644 --- a/tests/mock_adapter.php +++ b/tests/mock_adapter.php @@ -31,7 +31,7 @@ function get_mock_adapter() { $map['GET' ]['/accounts/1/lists/505454' ] = array(200, 'lists/505454'); $map['GET' ]['/accounts/1/lists/505454/subscribers/3' ] = array(200, 'subscribers/3'); $map['GET' ]['/accounts/1/lists/303449/subscribers/3' ] = array(200, 'subscribers/3'); -$map['GET' ]['/accounts/1/lists?ws.start=20&ws.size=20' ] = array(200, 'lists/page2'); +$map['GET' ]['/accounts/1/lists?ws.size=20&ws.start=20' ] = array(200, 'lists/page2'); $map['GET' ]['/accounts/1?email=joe%40example.com&ws.op=findSubscribers&ws.show=total_size' ] = array(200, 'accounts/findSubscribers_ts'); $map['GET' ]['/accounts/1?email=joe%40example.com&ws.op=findSubscribers' ] = array(200, 'accounts/findSubscribers'); $map['GET' ]['/accounts/1?ws.op=getWebFormSplitTests' ] = array(200, 'accounts/webFormSplitTests'); @@ -40,23 +40,24 @@ function get_mock_adapter() { $map['GET' ]['/accounts/1/lists/303449/broadcasts/1337' ] = array(200, 'broadcasts/1337'); # collection pagination tests -$map['GET' ]['/accounts/1/lists/303449/subscribers?status=unsubscribed&ws.size=1&ws.start=0&ws.op=find' ] = array(200, 'subscribers/find_1of2'); -$map['GET' ]['/accounts/1/lists/303449/subscribers?status=unsubscribed&ws.size=1&ws.start=1&ws.op=find' ] = array(200, 'subscribers/find_2of2'); -$map['GET' ]['/accounts/1/lists/303449/subscribers?status=unsubscribed&ws.size=1&ws.start=0&ws.op=find&ws.show=total_size'] = array(200, 'subscribers/find_1of2_tsl'); +$map['GET' ]['/accounts/1/lists/303449/subscribers?status=unsubscribed&ws.op=find&ws.size=1&ws.start=0' ] = array(200, 'subscribers/find_1of2'); +$map['GET' ]['/accounts/1/lists/303449/subscribers?status=unsubscribed&ws.op=find&ws.size=1&ws.start=1' ] = array(200, 'subscribers/find_2of2'); +$map['GET' ]['/accounts/1/lists/303449/subscribers?status=unsubscribed&ws.op=find&ws.show=total_size&ws.size=1&ws.start=0'] = array(200, 'subscribers/find_1of2_tsl'); $map['PATCH' ]['/accounts/1/lists/303449' ] = array(209, 'lists/303449'); $map['PATCH' ]['/accounts/1/lists/303449/subscribers/1' ] = array(209, 'subscribers/1'); $map['PATCH' ]['/accounts/1/lists/505454' ] = array(404, 'error'); -$map['POST' ]['/accounts/1/lists/303449/custom_fields' ] = array(201, '/accounts/1/lists/303449/custom_fields/2'); -$map['POST' ]['/accounts/1/lists/303449/subscribers/1' ] = array(201, '/accounts/1/lists/505454/subscribers/3'); -$map['POST' ]['/accounts/1/lists/303449/subscribers/2' ] = array(400, 'error'); +$map['POST' ]['/accounts/1/lists/303449/custom_fields?name=AwesomeField&ws.op=create' ] = array(201, '/accounts/1/lists/303449/custom_fields/2'); +$map['POST' ]['/accounts/1/lists/303449/subscribers/1?list_link=https%3A%2F%2Fapi.aweber.com%2F1.0%2Faccounts%2F1%2Flists%2F505454&ws.op=move' ] = array(201, '/accounts/1/lists/505454/subscribers/3'); +$map['POST' ]['/accounts/1/lists/303449/subscribers/1?last_followup_message_number_sent=1&list_link=https%3A%2F%2Fapi.aweber.com%2F1.0%2Faccounts%2F1%2Flists%2F505454&ws.op=move' ] = array(201, '/accounts/1/lists/505454/subscribers/3'); +$map['POST' ]['/accounts/1/lists/303449/subscribers/2?list_link=https%3A%2F%2Fapi.aweber.com%2F1.0%2Faccounts%2F1%2Flists%2F505454&ws.op=move' ] = array(400, 'error'); # Entity Body formatting -$map['POST' ]['/accounts/1/lists/303449/subscribers' ] = array(201, '/accounts/1/lists/303449/subscribers/3'); -$map['GET' ]['/accounts/1?email=joe%40example.com&custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=findSubscribers&ws.show=total_size' ] = array(200, 'accounts/findSubscribers_ts'); -$map['GET' ]['/accounts/1?email=joe%40example.com&custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=findSubscribers' ] = array(200, 'accounts/findSubscribers'); -$map['GET' ]['/accounts/1/lists/303449/subscribers?custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=find' ] = array(200, 'subscribers/find_1of2'); +$map['POST' ]['/accounts/1/lists/303449/subscribers' ] = array(201, '/accounts/1/lists/303449/subscribers/3'); +$map['GET' ]['/accounts/1?custom_fields=%7B%22test%22%3A%22test%22%7D&email=joe%40example.com&ws.op=findSubscribers&ws.show=total_size' ] = array(200, 'accounts/findSubscribers_ts'); +$map['GET' ]['/accounts/1?custom_fields=%7B%22test%22%3A%22test%22%7D&email=joe%40example.com&ws.op=findSubscribers' ] = array(200, 'accounts/findSubscribers'); +$map['GET' ]['/accounts/1/lists/303449/subscribers?custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=find' ] = array(200, 'subscribers/find_1of2'); $map['GET' ]['/accounts/1/lists/303449/subscribers?custom_fields=%7B%22test%22%3A%22test%22%7D&ws.op=find&ws.show=total_size' ] = array(200, 'subscribers/find_1of2_tsl'); class MockOAuthAdapter extends OAuthApplication { @@ -75,14 +76,23 @@ public function clearRequests() { $this->requestsMade = array(); } + /* + * Overriding parent to prevent the addition of the OAuth parameters + */ + public function prepareRequest($method, $url, $data) + { + return $data; + } + public function makeRequest($method, $url, $data=array(), $headers=array()) { global $map; # append params to url (for fixtures) $uri = str_replace($this->app->baseUri, '', $url); - if ($method == 'GET' && !empty($data)) { - $uri = $uri.'?'. http_build_query($data); - } + + list($url_params, $request_body) = $this->formatRequestData($method, $uri, $data, $headers); + + $uri = $this->_addParametersToUrl($uri, $url_params); # extract response map parameters # From 614ddb7cb5eb5753a4dc5de69eabcd73c864e0ef Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Tue, 12 Sep 2017 09:44:43 -0400 Subject: [PATCH 10/13] Renaming the _type method to _getResourceType to be more descriptive. Renaming snake case variable to camel case to match PHP standards Improving the readability of the needsUrlFormatting method and fixing missing conditional --- aweber_api/aweber_collection.php | 6 +++--- aweber_api/aweber_response.php | 2 +- aweber_api/oauth_application.php | 22 +++++++++++----------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/aweber_api/aweber_collection.php b/aweber_api/aweber_collection.php index 0ce6fed..b9821fd 100644 --- a/aweber_api/aweber_collection.php +++ b/aweber_api/aweber_collection.php @@ -84,7 +84,7 @@ public function getParentEntry(){ } /** - * _type + * _getResourceType * * Interpret what type of resources are held in this collection by * analyzing the URL @@ -92,7 +92,7 @@ public function getParentEntry(){ * @access protected * @return void */ - protected function _type() { + protected function _getResourceType() { $urlParts = explode('/', $this->url); $type = array_pop($urlParts); return $type; @@ -116,7 +116,7 @@ protected function _type() { public function create($kv_pairs) { # Create Resource $params = array_merge(array('ws.op' => 'create'), $kv_pairs); - $headers = $this->_type() == 'custom_fields' ? array() : array('Content-Type: application/json'); + $headers = $this->_getResourceType() == 'custom_fields' ? array() : array('Content-Type: application/json'); $data = $this->adapter->request('POST', $this->url, $params, array('return' => 'headers'), $headers); # Return new Resource diff --git a/aweber_api/aweber_response.php b/aweber_api/aweber_response.php index 5d021a2..11971fd 100644 --- a/aweber_api/aweber_response.php +++ b/aweber_api/aweber_response.php @@ -65,7 +65,7 @@ public function __get($value) { if (array_key_exists($value, $this->data)) { return $this->data[$value]; } - if ($value == 'type') return $this->_type(); + if ($value == 'type') return $this->_getResourceType(); } } diff --git a/aweber_api/oauth_application.php b/aweber_api/oauth_application.php index 49544f0..0dc2b9d 100644 --- a/aweber_api/oauth_application.php +++ b/aweber_api/oauth_application.php @@ -446,23 +446,23 @@ public function makeRequest($method, $url, $data=array(), $headers=array()) { if ($this->debug) echo "\n** {$method}: $url\n"; - list($url_params, $request_body) = $this->formatRequestData($method, $url, $data, $headers); + list($urlParams, $requestBody) = $this->formatRequestData($method, $url, $data, $headers); switch (strtoupper($method)) { case 'POST': - $resp = $this->post($url, $url_params, $request_body, $headers); + $resp = $this->post($url, $urlParams, $requestBody, $headers); break; case 'GET': - $resp = $this->get($url, $url_params, $headers); + $resp = $this->get($url, $urlParams, $headers); break; case 'DELETE': - $resp = $this->delete($url, $url_params, $headers); + $resp = $this->delete($url, $urlParams, $headers); break; case 'PATCH': - $resp = $this->patch($url, $url_params, $request_body, $headers); + $resp = $this->patch($url, $urlParams, $requestBody, $headers); break; } @@ -654,7 +654,7 @@ protected function userAgent() { * Return True if headers array does not contain 'Content-Type: application/json' and is a POST, GET, or DELETE request */ protected function needsUrlFormatting($method, $headers) { - return !in_array("Content-Type: application/json", $headers) and ($method == 'POST' or $method == 'GET' or 'DELETE'); + return !in_array("Content-Type: application/json", $headers) && in_array($method, array('POST', 'GET', 'DELETE')); } /** @@ -673,13 +673,13 @@ protected function formatRequestData($method, $url, $data, $headers) $data[$key] = json_encode($value); } } - $url_params = $this->buildData($this->prepareRequest($method, $url, $data)); - $request_body = $this->buildData($data); + $urlParams = $this->buildData($this->prepareRequest($method, $url, $data)); + $requestBody = $this->buildData($data); } else { - $url_params = $this->buildData($this->prepareRequest($method, $url, array())); - $request_body = json_encode($data); + $urlParams = $this->buildData($this->prepareRequest($method, $url, array())); + $requestBody = json_encode($data); } - return array($url_params, $request_body); + return array($urlParams, $requestBody); } } From 7793efc1e96445ae90e7ffd443389242d1a2afb6 Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Wed, 13 Sep 2017 08:51:46 -0400 Subject: [PATCH 11/13] Putting the _getResourceType method back to the original name of _type Making sure the application/json conttent-type is set on PATCH --- aweber_api/aweber_collection.php | 6 +++--- aweber_api/aweber_response.php | 2 +- aweber_api/oauth_application.php | 34 ++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/aweber_api/aweber_collection.php b/aweber_api/aweber_collection.php index b9821fd..0ce6fed 100644 --- a/aweber_api/aweber_collection.php +++ b/aweber_api/aweber_collection.php @@ -84,7 +84,7 @@ public function getParentEntry(){ } /** - * _getResourceType + * _type * * Interpret what type of resources are held in this collection by * analyzing the URL @@ -92,7 +92,7 @@ public function getParentEntry(){ * @access protected * @return void */ - protected function _getResourceType() { + protected function _type() { $urlParts = explode('/', $this->url); $type = array_pop($urlParts); return $type; @@ -116,7 +116,7 @@ protected function _getResourceType() { public function create($kv_pairs) { # Create Resource $params = array_merge(array('ws.op' => 'create'), $kv_pairs); - $headers = $this->_getResourceType() == 'custom_fields' ? array() : array('Content-Type: application/json'); + $headers = $this->_type() == 'custom_fields' ? array() : array('Content-Type: application/json'); $data = $this->adapter->request('POST', $this->url, $params, array('return' => 'headers'), $headers); # Return new Resource diff --git a/aweber_api/aweber_response.php b/aweber_api/aweber_response.php index 11971fd..5d021a2 100644 --- a/aweber_api/aweber_response.php +++ b/aweber_api/aweber_response.php @@ -65,7 +65,7 @@ public function __get($value) { if (array_key_exists($value, $this->data)) { return $this->data[$value]; } - if ($value == 'type') return $this->_getResourceType(); + if ($value == 'type') return $this->_type(); } } diff --git a/aweber_api/oauth_application.php b/aweber_api/oauth_application.php index 0dc2b9d..d02f8b2 100644 --- a/aweber_api/oauth_application.php +++ b/aweber_api/oauth_application.php @@ -462,6 +462,7 @@ public function makeRequest($method, $url, $data=array(), $headers=array()) { break; case 'PATCH': + $headers = $this->ensureContentType($headers, 'application/json'); $resp = $this->patch($url, $urlParams, $requestBody, $headers); break; } @@ -682,6 +683,39 @@ protected function formatRequestData($method, $url, $data, $headers) return array($urlParams, $requestBody); } + /** + * Checks the $headers array for content-type and adds the header if it doesn't exist and replaces it if isn't + * what is passed. + * + * @param $headers + * @param $expectedContentType + * @return array + */ + private function ensureContentType($headers, $expectedContentType) { + $found = false; + $stringStart = 0; + $stringLength = 13; + $explodeLimit = 1; + + foreach ($headers as $key => $value) { + if (substr(strtolower($value), $stringStart, $stringLength) == "content-type:") { + list($contentType) = explode(";", trim(substr($value, 14)), $explodeLimit); + if ($expectedContentType == $contentType){ + $found = true; + } else { + $found = true; + unset($headers[$key]); + array_push($headers, 'Content-Type: ' .$expectedContentType); + } + } + } + + if (!$found) { + array_push($headers, 'Content-Type: ' .$expectedContentType); + } + return $headers; + } + } /** From 1c3f07624afb85250a6515bbb98dc70f5f1b5731 Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Wed, 13 Sep 2017 12:04:19 -0400 Subject: [PATCH 12/13] Simplifying the login in ensureContentType and adding the underscore to adhere with conventions --- aweber_api/oauth_application.php | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/aweber_api/oauth_application.php b/aweber_api/oauth_application.php index d02f8b2..35891b6 100644 --- a/aweber_api/oauth_application.php +++ b/aweber_api/oauth_application.php @@ -462,7 +462,7 @@ public function makeRequest($method, $url, $data=array(), $headers=array()) { break; case 'PATCH': - $headers = $this->ensureContentType($headers, 'application/json'); + $headers = $this->_ensureContentType($headers, 'application/json'); $resp = $this->patch($url, $urlParams, $requestBody, $headers); break; } @@ -691,28 +691,16 @@ protected function formatRequestData($method, $url, $data, $headers) * @param $expectedContentType * @return array */ - private function ensureContentType($headers, $expectedContentType) { - $found = false; - $stringStart = 0; - $stringLength = 13; - $explodeLimit = 1; + private function _ensureContentType($headers, $expectedContentType) { foreach ($headers as $key => $value) { - if (substr(strtolower($value), $stringStart, $stringLength) == "content-type:") { - list($contentType) = explode(";", trim(substr($value, 14)), $explodeLimit); - if ($expectedContentType == $contentType){ - $found = true; - } else { - $found = true; + if ( stripos($value, 'content-type:') !== false ) { unset($headers[$key]); - array_push($headers, 'Content-Type: ' .$expectedContentType); - } } - } - if (!$found) { - array_push($headers, 'Content-Type: ' .$expectedContentType); } + + $headers[] = 'Content-Type: ' . $expectedContentType; return $headers; } From 069687952511264e9dbfadced5a65db66aeab013 Mon Sep 17 00:00:00 2001 From: Geoff Paffett Date: Wed, 13 Sep 2017 13:03:44 -0400 Subject: [PATCH 13/13] Removing comment in change log --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 014f58b..3901a43 100644 --- a/README.md +++ b/README.md @@ -64,8 +64,7 @@ Changelog: 2017-09-02: v1.1.18 * Fixing issues on the formatting of nested objects on 'application/json' requests * Fixing issue with extra data being sent in header. - * Fixing issue to allow the creation of custom fields to be sent as form encoded. - * Updating the deprecated getMock method to createMock. + * Fixing issue to allow the creation of custom fields to be sent as form encoded. 2017-08-21: v1.1.17 * Fixing UTF-8 issues on creates