From e35b8607e3150be50f3021952c988ed3e4741665 Mon Sep 17 00:00:00 2001 From: user3581488 Date: Wed, 12 Nov 2014 15:07:19 -0600 Subject: [PATCH 01/27] Updated + cleaned up Added post support internally and OATH 2 usage so you can now make authorized requests and not be limited to information passed back from the Api. Also added a new GET function getGroups(). Cleaned up usage to match example and instead of returning $response->results only $response is returned so you can iterate over $response->results properly, otherwise you'd be missing all of the other information included in the json object which is useful. --- meetup.php | 326 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 208 insertions(+), 118 deletions(-) diff --git a/meetup.php b/meetup.php index 317f45e..04a975c 100644 --- a/meetup.php +++ b/meetup.php @@ -1,128 +1,218 @@ _parameters = array_merge($this->_parameters, $parameters); + } -class Meetup { - const BASE = 'https://api.meetup.com'; - - protected $_parameters = array( - 'sign' => 'true', - ); - - public function __construct(array $parameters = array()) { - $this->_parameters = array_merge($this->_parameters, $parameters); - } - - public function getEvents(array $parameters = array()) { - return $this->get('/2/events', $parameters)->results; - } - - public function getPhotos(array $parameters = array()) { - return $this->get('/2/photos', $parameters)->results; - } - - public function getDiscussionBoards(array $parameters = array()) { - return $this->get('/:urlname/boards', $parameters); - } - - public function getDiscussions(array $parameters = array()) { - return $this->get('/:urlname/boards/:bid/discussions', $parameters); - } - - public function getMembers(array $parameters = array()) { - return $this->get('/2/members', $parameters); - } + public function getEvents(array $parameters = array()) + { + return $this->get('/2/events', $parameters); + } - public function getNext($response) { - if (!isset($response) || !isset($response->meta->next)) - { - throw new Exception("Invalid response object."); - } - return $this->get_url($response->meta->next); - } - - public function get($path, array $parameters = array()) { - $parameters = array_merge($this->_parameters, $parameters); - - if (preg_match_all('/:([a-z]+)/', $path, $matches)) { - - foreach ($matches[0] as $i => $match) { - - if (isset($parameters[$matches[1][$i]])) { - $path = str_replace($match, $parameters[$matches[1][$i]], $path); - unset($parameters[$matches[1][$i]]); - } else { - throw new Exception("Missing parameter '" . $matches[1][$i] . "' for path '" . $path . "'."); - } - } - } + public function getGroups(array $parameters = array()) + { + return $this->get('/2/groups', $parameters); + } + + public function getPhotos(array $parameters = array()) + { + return $this->get('/2/photos', $parameters); + } - $url = self::BASE . $path . '?' . http_build_query($parameters); + public function getDiscussionBoards(array $parameters = array()) + { + return $this->get('/:urlname/boards', $parameters); + } - return $this->get_url($url); - } + public function getDiscussions(array $parameters = array()) + { + return $this->get('/:urlname/boards/:bid/discussions', $parameters); + } + public function getMembers(array $parameters = array()) + { + return $this->get('/2/members', $parameters); + } + public function getNext($response) + { + if (!isset($response) || !isset($response->meta->next)) + { + throw new Exception("Invalid response object."); + } + return $this->api($response->meta->next); + } - protected function get_url($url) { - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_HTTPHEADER, array("Accept-Charset: utf-8")); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); - $content = curl_exec($ch); - - if (curl_errno($ch)) { - $error = curl_error($ch); - curl_close($ch); - - throw new Exception("Failed retrieving '" . $url . "' because of ' " . $error . "'."); - } - - $response = json_decode($content); - $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); - - curl_close($ch); - - if ($status != 200) { - - if (isset($response->errors[0]->message)) { - $error = $response->errors[0]->message; - } else { - $error = 'Status ' . $status; - } - - throw new Exception("Failed retrieving '" . $url . "' because of ' " . $error . "'."); - } + public function get($path, array $parameters = array()) + { + if (preg_match_all('/:([a-z]+)/', $path, $matches)) + { + foreach ($matches[0] as $i => $match) + { + if (isset($parameters[$matches[1][$i]])) + { + $path = str_replace($match, $parameters[$matches[1][$i]], $path); + unset($parameters[$matches[1][$i]]); + } + else + { + throw new Exception("Missing parameter '" . $matches[1][$i] . "' for path '" . $path . "'."); + } + } + } - if (isset($response) == false) { - - switch (json_last_error()) { - case JSON_ERROR_NONE: - $error = 'No errors'; - break; - case JSON_ERROR_DEPTH: - $error = 'Maximum stack depth exceeded'; - break; - case JSON_ERROR_STATE_MISMATCH: - $error = ' Underflow or the modes mismatch'; - break; - case JSON_ERROR_CTRL_CHAR: - $error = 'Unexpected control character found'; - break; - case JSON_ERROR_SYNTAX: - $error = 'Syntax error, malformed JSON'; - break; - case JSON_ERROR_UTF8: - $error = 'Malformed UTF-8 characters, possibly incorrectly encoded'; - break; - default: - $error = 'Unknown error'; - break; - } + return $this->api(self::BASE . $path, $parameters, false); + } + + public function authorize(array $parameters = array()) + { + $location = self::AUTHORIZE . '?' . http_build_query(array_merge($this->_parameters,$parameters)); + header("Location: " . $location); + } + + public function access(array $parameters = array()) + { + return $this->api(self::ACCESS, array_merge($parameters, array('grant_type'=>'authorization_code')), true); + } - throw new Exception("Cannot read response by '" . $url . "' because of: '" . $error . "'."); - } - - return $response; - } + public function refresh(array $parameters = array()) + { + $this->api(self::ACCESS, array_merge($parameters, array('grant_type'=>'refresh_token')), true); + } + + protected function api($url, $parameters, $post=false) + { + //merge parameters + $this->_parameters = array_merge($parameters, $this->_parameters); + + + //make sure 'sign' is included when using api key only + if(in_array('key', $this->_parameters) && $url!=self::ACCESS && $url!=self::AUTHORIZE) + { + //api request (any) - include sign parameters + $this->_parameters = array_merge( array('sign', 'true'), $this->_parameters ); + } + + //init curl + $ch = curl_init(); + + $headers = array("Accept-Charset: utf-8"); + + //set options for connection + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 120); + curl_setopt($ch, CURLOPT_TIMEOUT, 120); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); + + //either GET or POST against api + if($post===false) + { + //include headers as specified by manual + if( $url == self::ACCESS ) + { + array_push($headers, 'Content-Type: application/x-www-form-urlencoded'); + } + else if( strpos($url, self::BASE) === 0 && in_array('access_token', $this->_parameters) ) + { + array_merge($this->_parameters, array('token_type'=>'bearer')); + } + + curl_setopt($ch, CURLOPT_URL, $url . '?' . http_build_query($this->_parameters)); + } + else + { + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POST, count($parameters)); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($this->_parameters)); + } + + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + + //fetch content + $content = curl_exec($ch); + + //was there an error on the connection? + if (curl_errno($ch)) + { + $error = curl_error($ch); + curl_close($ch); + + throw new Exception("Failed retrieving '" . $url . "' because of connection issue: ' " . $error . "'."); + } + + //retrieve json + $response = json_decode($content); + $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); + + curl_close($ch); + + if (!is_null($response) && $status != 200) + { + //tell them what went wrong or just relay the status + if( isset($response->error) && isset($response->error_description) ) + { + //what we see against Oath + $error = $response->error . ' - ' . $response->error_description; + } + else if( isset($response->details) && isset($response->problem) && isset($response->code) ) + { + //what we see against regular access + $error = $response->code . ' - ' . $response->problem . ' - ' . $response->details; + } + else + { + $error = 'Status ' . $status; + } + + throw new Exception("Failed retrieving '" . $url . "' because of ' " . $error . "'."); + } + else if (is_null($response)) + { + //did we have any parsing issues for the response? + switch (json_last_error()) + { + case JSON_ERROR_NONE: + $error = 'No errors'; + break; + case JSON_ERROR_DEPTH: + $error = 'Maximum stack depth exceeded'; + break; + case JSON_ERROR_STATE_MISMATCH: + $error = ' Underflow or the modes mismatch'; + break; + case JSON_ERROR_CTRL_CHAR: + $error = 'Unexpected control character found'; + break; + case JSON_ERROR_SYNTAX: + $error = 'Syntax error, malformed JSON'; + break; + case JSON_ERROR_UTF8: + $error = 'Malformed UTF-8 characters, possibly incorrectly encoded'; + break; + default: + $error = 'Unknown error'; + break; + } + + throw new Exception("Cannot read response by '" . $url . "' because of: '" . $error . "'."); + } + + return $response; + } } +?> From bed7b965b05a51f16150b2d527731174d08016a3 Mon Sep 17 00:00:00 2001 From: user3581488 Date: Wed, 12 Nov 2014 15:25:44 -0600 Subject: [PATCH 02/27] Update README.md Added more usage information b/c of OATH inclusion. Also cleaned up reference to $response->meta_total_count to $response->meta->total_count --- README.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d8d5a2a..96be719 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,72 @@ require 'meetup.php'; $meetup = new Meetup(array( 'key' => 'YOUR_API_KEY' )); + +$response = $meetup->getEvents(); //somewhat restricted +``` + +* Get your [Consumer details](https://secure.meetup.com/meetup_api/oauth_consumers/). +* Require the library, create a Meetup object and set your consumer details and gain access: + +```php +if( !isset($_GET['code']) ) +{ + try + { + //authorize and go to URI w/ code + $meetup = new Meetup(); + $meetup->authorize( + 'client_id' => ', + 'redirect_uri' => '' + ); + } + catch(Exception $e) + { + //tell us what happened + echo $e->getMessage(); + return; + } +} +else +{ + //assuming we came back here... + try + { + $meetup = new Meetup( + array( + "client_id" => ', + "client_secret" => '', + "redirect_uri" => '', + "code" => $_GET['code'] + ) + ); + + $response = $meetup->access(); + + $accessToken = $response->access_token; + $refreshToken = $response->refresh_token; + $expires = time() + (intval($response->expires_in)-10); //10 second buffer + } + catch(Exception $e) + { + //tell us what happened + echo $e->getMessage(); + return; + } + + //now we can re-use this object for several requests + $meetup = new Meetup( + array( + "access_token" => $accessToken, + ) + ); + + //get all groups for this member + $response = $meetup->getGroups('member_id' => '); + + //get all events for this member + $response = $meetup->getEvents('member_id' => '); +} ``` * Retrieve some events: @@ -21,7 +87,7 @@ $response = $meetup->getEvents(array( )); // total number of items matching the get request -$total_count = $response->meta_total_count; +$total_count = $response->meta->total_count; $events = $response->results; @@ -40,7 +106,12 @@ $events = $response->results; ## Constructing the client The class constructors takes one optional argument. This `(array)` will be stored in the object and used as default parameters for any request you make. -I would suggest passing the `key` when you construct the client, but you could do just `$meetup = new Meetup;` and then pass the `key` parameter in every request you make. +I would suggest passing the `key` when you construct the client, but you could do just `$meetup = new Meetup;` and then pass the `key` parameter in every request you make. These requests are somewhat restricted on the information passed back, you have to use OATH 2 for full access. + +Using OATH 2 there's additional steps required to get an access token and pass it on subsequent requests. Your access token is only good for 1 hour and you'll have to refresh it if you plan on making subsequent calls to the service. + +## Constructing the client using OATH + ## Doing GET requests You can call any [Meetup API GET-method](http://www.meetup.com/meetup_api/docs/) using `get()`. @@ -67,6 +138,7 @@ Feel free to fork the code and add more! |Client method |API method | |---------------------|-----------------------------------| | getEvents | /2/events | +| getGroups | /2/groups | | getMembers | /2/members | | getPhotos | /2/photos | | getDiscussionBoards | /:urlname/boards | @@ -77,6 +149,7 @@ Feel free to fork the code and add more! * Implement `POST` and `DELETE` methods. * Add more short-hands. * Have some meetups... +* Modify/post using OATH 2 ## Alternatives Before starting this client, I checked out the following [existing clients](http://www.meetup.com/meetup_api/clients/): @@ -84,6 +157,7 @@ Before starting this client, I checked out the following [existing clients](http * [wizonesolutions/meetup_api](https://github.com/wizonesolutions/meetup_api): Huge library, hasn't been updated for 3 years. * [blobaugh](https://github.com/blobaugh/Meetup-API-client-for-PHP): Huge library, documentation quick start doesn't get you started. +This is a more simplified library for access and interactions! ## License

From 440f01693e3b2251fc89ea0ee46fb483f88b0174 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Wed, 12 Nov 2014 15:26:38 -0600
Subject: [PATCH 03/27] Added response_type to authorize behind the scenes

Added parameter behind the scenes so we don't have to for authorize routine.
---
 meetup.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/meetup.php b/meetup.php
index 04a975c..703cd8b 100644
--- a/meetup.php
+++ b/meetup.php
@@ -77,7 +77,7 @@ public function get($path, array $parameters = array())
     
     public function authorize(array $parameters = array())
     {
-    	$location = self::AUTHORIZE . '?' . http_build_query(array_merge($this->_parameters,$parameters));
+    	$location = self::AUTHORIZE . '?' . http_build_query(array_merge($this->_parameters,$parameters, array('response_type' => 'code')));
     	header("Location: " . $location);
     }
     

From 724040bf3085f5b13d5a1d4e01fc7dea74d1b7f2 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Wed, 12 Nov 2014 15:27:47 -0600
Subject: [PATCH 04/27] background information

Added some more background information about including parameters behind the scenes
---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 96be719..6a5569a 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
 # Meetup API
-This a very simple, one-file, PHP client for accessing most of the [Meetup API](http://www.meetup.com/meetup_api/).
+This a very simple, one-file, PHP client for accessing most of the [Meetup API](http://www.meetup.com/meetup_api/).  Some parameters are included behind the scenes so you don't have to using array_merge when the parameters have fixed values like signed or response_type depending on the nature of the request.
 
 ## Quick Start
 

From 75a477b1f53df3389da2a5a3ad5881e5ba461c92 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Wed, 12 Nov 2014 17:41:17 -0600
Subject: [PATCH 05/27] Some cleanup to Readme.md

Some cleanup and straight forward usage without try catch blocks.
---
 README.md | 69 ++++++++++++++++++++-----------------------------------
 1 file changed, 25 insertions(+), 44 deletions(-)

diff --git a/README.md b/README.md
index 6a5569a..49ac9ad 100644
--- a/README.md
+++ b/README.md
@@ -21,56 +21,40 @@ $response = $meetup->getEvents(); //somewhat restricted
 ```php
 if( !isset($_GET['code']) )
 {
-    try
-    {
-	    //authorize and go to URI w/ code
-	    $meetup = new Meetup();
-	    $meetup->authorize(
-		'client_id'     => ',
-		'redirect_uri'  => ''    	
-	    );
-    }
-    catch(Exception $e)
-    {
-        //tell us what happened
-    	echo $e->getMessage();
-    	return;
-    }
+    //authorize and go to URI w/ code
+    $meetup = new Meetup();
+    $meetup->authorize(
+	'client_id'     => ',
+	'redirect_uri'  => ''    	
+    );
 }
 else
 {
     //assuming we came back here...
-    try
-    {    
-        $meetup = new Meetup(
-    	    	array(
-    				"client_id"     => ',
-    				"client_secret" => '',
-    				"redirect_uri"  => '',
-    				"code"          => $_GET['code']
-    		)
-        );
-
-        $response = $meetup->access();
-                	                
-        $accessToken  = $response->access_token;
-        $refreshToken = $response->refresh_token;
-        $expires      = time() + (intval($response->expires_in)-10);	//10 second buffer	        
-    }
-    catch(Exception $e)
-    {
-        //tell us what happened
-        echo $e->getMessage();
-        return;
-    } 
-    
+    $meetup = new Meetup(
+	        	array(
+	    			"client_id"     => ',
+	    			"client_secret" => '',
+	    			"redirect_uri"  => '',
+	    			"code"          => $_GET['code']
+	    	)
+    );
+	
+    $response = $meetup->access();
+	        	                
     //now we can re-use this object for several requests
     $meetup = new Meetup(
     		array(
-    			"access_token"  => $accessToken,
+    			"access_token"  => $response->access_token,
     		)
      );
 
+     //store details for later in case we need to do requests elsewhere
+     //or refresh token
+     $_SESSION['access_token'] = $response->access_token;
+     $_SESSION['refresh_token'] = $response->refresh_token;
+     $_SESSION['expires'] = time() + intval($response->expires_in);
+     
      //get all groups for this member
      $response = $meetup->getGroups('member_id' => ');
      
@@ -106,13 +90,10 @@ $events = $response->results;
 ## Constructing the client
 The class constructors takes one optional argument. This `(array)` will be stored in the object and used as default parameters for any request you make.
 
-I would suggest passing the `key` when you construct the client, but you could do just `$meetup = new Meetup;` and then pass the `key` parameter in every request you make.  These requests are somewhat restricted on the information passed back, you have to use OATH 2 for full access.
+I would suggest passing the `key` or `consumer details` when you construct the client, but you could do just `$meetup = new Meetup;` and then pass parameters in every request you make.  These requests are somewhat restricted on the information passed back, you have to use OATH 2 for full access otherwise you may not get back some information.
 
 Using OATH 2 there's additional steps required to get an access token and pass it on subsequent requests.  Your access token is only good for 1 hour and you'll have to refresh it if you plan on making subsequent calls to the service.
 
-## Constructing the client using OATH 
-
-
 ## Doing GET requests
 You can call any [Meetup API GET-method](http://www.meetup.com/meetup_api/docs/) using `get()`.
 

From 9bb1120943ea157d4c8e9d9532188b3fd62dcf17 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Wed, 12 Nov 2014 17:43:16 -0600
Subject: [PATCH 06/27] Updated Readme.md

Added information about using try/catch blocks.
---
 README.md | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/README.md b/README.md
index 49ac9ad..e832ee1 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,18 @@
 # Meetup API
 This a very simple, one-file, PHP client for accessing most of the [Meetup API](http://www.meetup.com/meetup_api/).  Some parameters are included behind the scenes so you don't have to using array_merge when the parameters have fixed values like signed or response_type depending on the nature of the request.
 
+Exceptions are thrown and can be caught when there's any errors interacting with the API, they are standard exceptions.
+
+```php
+try{
+   $meetup = new Meetup('');
+   $meetup->getEvents();
+}catch(Exception $e)
+{
+    echo $e->getMessage();
+}
+```
+
 ## Quick Start
 
 * Get your [API key](http://www.meetup.com/meetup_api/key/).

From a1efcc9ba63162b1e68c2d9b3dd3e4d13937a5cb Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Wed, 12 Nov 2014 17:44:01 -0600
Subject: [PATCH 07/27] Update README.md

---
 README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index e832ee1..efc4482 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ try{
 ```php
 require 'meetup.php';
 $meetup = new Meetup(array(
-	'key' => 'YOUR_API_KEY'
+	'key' => ''
 ));
 
 $response = $meetup->getEvents(); //somewhat restricted
@@ -36,7 +36,7 @@ if( !isset($_GET['code']) )
     //authorize and go to URI w/ code
     $meetup = new Meetup();
     $meetup->authorize(
-	'client_id'     => ',
+	'client_id'     => '',
 	'redirect_uri'  => ''    	
     );
 }

From 4859961e9b3b96179649ced5fc021f51a1435f85 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Wed, 12 Nov 2014 17:51:48 -0600
Subject: [PATCH 08/27] Update README.md

---
 README.md | 47 +++++++++++++++++++++++------------------------
 1 file changed, 23 insertions(+), 24 deletions(-)

diff --git a/README.md b/README.md
index efc4482..5174832 100644
--- a/README.md
+++ b/README.md
@@ -33,10 +33,10 @@ $response = $meetup->getEvents(); //somewhat restricted
 ```php
 if( !isset($_GET['code']) )
 {
-    //authorize and go to URI w/ code
+    //authorize and go back to URI w/ code
     $meetup = new Meetup();
     $meetup->authorize(
-	'client_id'     => '',
+	'client_id'     => '',
 	'redirect_uri'  => ''    	
     );
 }
@@ -44,34 +44,36 @@ else
 {
     //assuming we came back here...
     $meetup = new Meetup(
-	        	array(
-	    			"client_id"     => ',
-	    			"client_secret" => '',
-	    			"redirect_uri"  => '',
-	    			"code"          => $_GET['code']
-	    	)
+        array(
+    		"client_id"     => '',
+    		"client_secret" => '',
+    		"redirect_uri"  => '',
+    		"code"          => $_GET['code'] //passed back to us from meetup
+    	)
     );
 	
+    //get an access token
     $response = $meetup->access();
 	        	                
-    //now we can re-use this object for several requests
+    //now we can re-use this object for several requests using our access
+    //token
     $meetup = new Meetup(
-    		array(
-    			"access_token"  => $response->access_token,
-    		)
+    	array(
+    		"access_token"  => $response->access_token,
+    	)
      );
 
      //store details for later in case we need to do requests elsewhere
      //or refresh token
      $_SESSION['access_token'] = $response->access_token;
      $_SESSION['refresh_token'] = $response->refresh_token;
-     $_SESSION['expires'] = time() + intval($response->expires_in);
+     $_SESSION['expires'] = time() + intval($response->expires_in); //use if >= intval($_SESSION['expires']) to check
      
      //get all groups for this member
-     $response = $meetup->getGroups('member_id' => ');
+     $response = $meetup->getGroups('member_id' => '');
      
      //get all events for this member
-     $response = $meetup->getEvents('member_id' => ');
+     $response = $meetup->getEvents('member_id' => '');
 }
 ```
 
@@ -85,14 +87,11 @@ $response = $meetup->getEvents(array(
 // total number of items matching the get request
 $total_count = $response->meta->total_count;
 
-$events = $response->results;
-
-foreach ($events as $event) {
+foreach ($response->results as $event) {
 	echo $event->name . ' at ' . date('Y-m-d H:i', $event->time / 1000) . PHP_EOL;
 }
 ```
-Many of the get requests will match more entries than the API will return in one request. A convenience method has been provided to return the next
-page of entries after you have performed a successful get request:
+Many of the get requests will match more entries than the API will return in one request. A convenience method has been provided to return the next page of entries after you have performed a successful get request:
 
 $response = $meetup->getNext($response);
 
@@ -104,13 +103,13 @@ The class constructors takes one optional argument. This `(array)` will be store
 
 I would suggest passing the `key` or `consumer details` when you construct the client, but you could do just `$meetup = new Meetup;` and then pass parameters in every request you make.  These requests are somewhat restricted on the information passed back, you have to use OATH 2 for full access otherwise you may not get back some information.
 
-Using OATH 2 there's additional steps required to get an access token and pass it on subsequent requests.  Your access token is only good for 1 hour and you'll have to refresh it if you plan on making subsequent calls to the service.
+Using OATH 2 there's additional steps required to get an access token and pass it on subsequent requests.  Your access token is only good for 1 hour and you'll have to refresh it if you plan on making subsequent calls to the service after that.
 
 ## Doing GET requests
-You can call any [Meetup API GET-method](http://www.meetup.com/meetup_api/docs/) using `get()`.
+You can call any [Meetup API GET-method](http://www.meetup.com/meetup_api/docs/) using `get()`.  There's several stub functions already for the more common ones and new ones will be added.
 
 ### Arguments
-The method takes two arguments, of which the second one is optional:
+The method get() takes two arguments, of which the second one is optional:
 
 1. `(string)` Meetup API method (e.g. `/2/events`)
 2. `(array)` Meetup API method paramaters (e.g. `array('group_urlname' => 'your-meetup-group')`)
@@ -142,7 +141,7 @@ Feel free to fork the code and add more!
 * Implement `POST` and `DELETE` methods.
 * Add more short-hands.
 * Have some meetups...
-* Modify/post using OATH 2
+* Modify/post using OATH 2 and write not just read
 
 ## Alternatives
 Before starting this client, I checked out the following [existing clients](http://www.meetup.com/meetup_api/clients/): 

From 5d6f15806605888b5da5c07b4f416b3829b23ede Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Wed, 12 Nov 2014 17:54:25 -0600
Subject: [PATCH 09/27] Update README.md

---
 README.md | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 5174832..893d434 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,24 @@
 # Meetup API
 This a very simple, one-file, PHP client for accessing most of the [Meetup API](http://www.meetup.com/meetup_api/).  Some parameters are included behind the scenes so you don't have to using array_merge when the parameters have fixed values like signed or response_type depending on the nature of the request.
 
+#Exceptions
 Exceptions are thrown and can be caught when there's any errors interacting with the API, they are standard exceptions.
 
 ```php
-try{
+try
+{
    $meetup = new Meetup('');
    $meetup->getEvents();
-}catch(Exception $e)
+}
+catch(Exception $e)
 {
     echo $e->getMessage();
 }
 ```
 
+#Hardcoded parameters
+Underneath there's parameters (depending on the request being made) that get injected using array_merge because these values aren't variable they're fixed.  This way you don't have to know about them or worry about implementing them and if they're duplicated by you it won't matter.  You can just focus on including the core information and using the stub methods to handle the heavy lifting.
+
 ## Quick Start
 
 * Get your [API key](http://www.meetup.com/meetup_api/key/).
@@ -36,8 +42,8 @@ if( !isset($_GET['code']) )
     //authorize and go back to URI w/ code
     $meetup = new Meetup();
     $meetup->authorize(
-	'client_id'     => '',
-	'redirect_uri'  => ''    	
+		'client_id'     => '',
+		'redirect_uri'  => ''    	
     );
 }
 else

From 846df8b2151c63664960e6f6b4f749c0d88a886a Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Wed, 12 Nov 2014 18:00:39 -0600
Subject: [PATCH 10/27] Update README.md

---
 README.md | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/README.md b/README.md
index 893d434..7bd7f05 100644
--- a/README.md
+++ b/README.md
@@ -99,9 +99,11 @@ foreach ($response->results as $event) {
 ```
 Many of the get requests will match more entries than the API will return in one request. A convenience method has been provided to return the next page of entries after you have performed a successful get request:
 
+```php
 $response = $meetup->getNext($response);
 
 $events = $response->results;
+```
 ...
 
 ## Constructing the client
@@ -111,6 +113,16 @@ I would suggest passing the `key` or `consumer details` when you construct the c
 
 Using OATH 2 there's additional steps required to get an access token and pass it on subsequent requests.  Your access token is only good for 1 hour and you'll have to refresh it if you plan on making subsequent calls to the service after that.
 
+## What's OATH
+To keep it short and sweet it's a way to authenticate against the system and gain full privileged access, without it you don't have full access using only an API key.  You get consumer details from meetup, authorize yourself, meetup sends a code to your redirect uri, you read in the code and get an access token with it, using that access token you gain authenticated access to meetup.  You only have an hour but you can use your refresh token to get a new access token and repeat the process always using the newest access/refresh token you get back.
+
+```php
+$response = $meetup->refresh();
+
+//new details passed back
+//$response->access_token, $response->refresh_token, $response->expires_in
+```
+
 ## Doing GET requests
 You can call any [Meetup API GET-method](http://www.meetup.com/meetup_api/docs/) using `get()`.  There's several stub functions already for the more common ones and new ones will be added.
 
@@ -148,6 +160,8 @@ Feel free to fork the code and add more!
 * Add more short-hands.
 * Have some meetups...
 * Modify/post using OATH 2 and write not just read
+* Update Meetup object to be have member variables and store data internally for important information
+  like access tokens and etc.
 
 ## Alternatives
 Before starting this client, I checked out the following [existing clients](http://www.meetup.com/meetup_api/clients/): 

From c68726d661054a3543ac2b8d555e7860a0a286e1 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Thu, 13 Nov 2014 08:32:39 -0600
Subject: [PATCH 11/27] Missing return statement in refresh()

Added the missing return statement in refresh() call, otherwise you won't get back the details you need for access.
---
 meetup.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/meetup.php b/meetup.php
index 703cd8b..ec14c76 100644
--- a/meetup.php
+++ b/meetup.php
@@ -88,7 +88,7 @@ public function access(array $parameters = array())
     
     public function refresh(array $parameters = array())
     {
-    	$this->api(self::ACCESS, array_merge($parameters, array('grant_type'=>'refresh_token')), true);
+    	return $this->api(self::ACCESS, array_merge($parameters, array('grant_type'=>'refresh_token')), true);
     }
     
     protected function api($url, $parameters, $post=false)

From de33b8c07c6e736c12b42a4b0fb57eac189f56a2 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Thu, 13 Nov 2014 12:33:33 -0600
Subject: [PATCH 12/27] More updates and fixes

Fixed bug where overwrote member variable parameters, shouldn't do that per request in case we want to re-use object multiple times based off constructor parameters.

Added javadoc documentation to document the code and give small code examples.

Added put/delete support on top of get/post.  However post/put/delete require authorized access.

Added a post and delete stub method.
---
 meetup.php | 323 +++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 277 insertions(+), 46 deletions(-)

diff --git a/meetup.php b/meetup.php
index ec14c76..e7307e6 100644
--- a/meetup.php
+++ b/meetup.php
@@ -1,69 +1,255 @@
 _parameters = array_merge($this->_parameters, $parameters);
     }
-
+   /**
+    * Stub for fetching events
+    *
+    * @param array $parameters The parameters passed for this request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+   */  
     public function getEvents(array $parameters = array()) 
     {
         return $this->get('/2/events', $parameters);
     }
-
+   /**
+    * Stub for fetching groups
+    *
+    * @param array $parameters The parameters passed for this request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+   */  
     public function getGroups(array $parameters = array()) 
     {
         return $this->get('/2/groups', $parameters);
     }
-    
+    /**
+    * Stub for fetching photos
+    *
+    * @param array $parameters The parameters passed for this request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+   */     
     public function getPhotos(array $parameters = array())
     {
         return $this->get('/2/photos', $parameters);
     }
-
+   /**
+    * Stub for fetching discussion boards
+    *
+    * @param array $parameters The parameters passed for this request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+   */  
     public function getDiscussionBoards(array $parameters = array()) 
     {
         return $this->get('/:urlname/boards', $parameters);
     }
-
+   /**
+    * Stub for fetching discussions
+    *
+    * @param array $parameters The parameters passed for this request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+   */  
     public function getDiscussions(array $parameters = array()) 
     {
         return $this->get('/:urlname/boards/:bid/discussions', $parameters);
     }
+    /**
+    * Stub for fetching member
+    *
+    * @param array $parameters The parameters passed for this request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+   */     
     public function getMembers(array $parameters = array()) 
     {
         return $this->get('/2/members', $parameters);
     }
+   /**
+    * Stub for grabbing the next response data if it's available in the meta information
+    * of a response.  Normally if there's too many results it won't return them all.
+    *
+    * @param mixed $response The response object given back from a previous request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+   */      
     public function getNext($response)
     {
         if (!isset($response) || !isset($response->meta->next))
         {
             throw new Exception("Invalid response object.");
         }
-        return $this->api($response->meta->next);
+        return $this->api($response->meta->next, array(), self::GET);
     }
-
+   /**
+    * Stub for updating an event
+    *
+    * @param array $parameters The parameters passed for this request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+   */   
+    public function postEvent(array $parameters = array())
+    {
+    	return $this->post('/2/event/:id', $parameters);
+    }
+   /**
+    * Stub for deleting an event
+    *
+    * @param array $parameters The parameters passed for this request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+   */       
+    public function deleteEvent(array $parameters = array())
+    {
+    	return $this->delete('/2/event/:id', $parameters);
+    }   
+   /**
+    * Perform a get on any url supported by meetup, use : to specify parameters that use
+    * placeholders and pass that exact parameter name as a parameter.
+    *
+    * @param array $parameters The parameters passed for this request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+    *
+    * @code 
+    * $meetup->get('/2/event/:id', array('id'=>10));
+    * $meetup->get('/2/members', array('group_urlname'=>'foobar'));
+    * @endcode
+   */            
     public function get($path, array $parameters = array())
     {    
-        if (preg_match_all('/:([a-z]+)/', $path, $matches))
+    	list($url, $params) = $this->params($path, $parameters);
+    	
+        return $this->api(self::BASE . $url, $params, self::GET);
+    }
+   /**
+    * Perform a post on any url supported by meetup, use : to specify parameters that use
+    * placeholders and pass that exact parameter name as a parameter.
+    *
+    * @param array $parameters The parameters passed for this request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+    *
+    * @code 
+    * $meetup->post('/2/member/:id', array('id'=>10));
+    * @endcode
+   */                
+    public function post($path, array $parameters = array())
+    {
+     	list($url, $params) = $this->params($path, $parameters);
+    	
+        return $this->api(self::BASE . $url, $params, self::POST);   
+    }
+    /**
+    * Perform a put on any url supported by meetup, use : to specify parameters that use
+    * placeholders and pass that exact parameter name as a parameter.
+    *
+    * @param array $parameters The parameters passed for this request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+    *
+    * @note There isn't any PUT supported events at the moment
+   */      
+    public function put($path, array $parameters = array())
+    {
+     	list($url, $params) = $this->params($path, $parameters);
+    	
+        return $this->api(self::BASE . $url, $params, self::PUT);       
+    }
+   /**
+    * Perform a delete on any url supported by meetup, use : to specify parameters that use
+    * placeholders and pass that exact parameter name as a parameter.
+    *
+    * @param array $parameters The parameters passed for this request
+    * @return mixed A json object containing response data
+    * @throws Exception if anything goes wrong
+    *
+    * @code 
+    * $meetup->delete('/2/member/:id', array('id'=>10));
+    * @endcode
+   */  
+    public function delete($path, array $parameters = array())
+    {
+     	list($url, $params) = $this->params($path, $parameters);
+    	
+        return $this->api(self::BASE . $url, $params, self::DELETE);       
+    }
+   /**
+    * Utility function for swapping place holders with parameters if any are found in 
+    * the request url.  The place holder parameter gets swapped out and the array gets
+    * the parameter removed, otherwise the request is left un-altered.
+    *
+    * @param string $path The relative path of the request from meetup (not including base path)
+    * @param array $parameters The parameters passed for this request
+    * @return array An array of the path and parameters modified or un-altered
+    * @throws Exception if anything goes wrong
+   */          
+    protected function params($path, array $parameters = array())
+    {
+    	$url    = $path;
+    	$params = $parameters;
+        if (preg_match_all('/:([a-z]+)/', $url, $matches))
         {           	
             foreach ($matches[0] as $i => $match)
             {                	
-                if (isset($parameters[$matches[1][$i]]))
+                if (isset($params[$matches[1][$i]]))
                 {
-                    $path = str_replace($match, $parameters[$matches[1][$i]], $path);
-                    unset($parameters[$matches[1][$i]]);
+                    $url = str_replace($match, $params[$matches[1][$i]], $url);
+                    unset($params[$matches[1][$i]]);
                 } 
                 else 
                 {
@@ -71,39 +257,70 @@ public function get($path, array $parameters = array())
                 }
             }
         }
-
-        return $this->api(self::BASE . $path, $parameters, false);
-    }
-    
+        
+        return array($url, $params);    
+    }  
+   /**
+    * Utility function for authorizing ourselves with meetup.  Visit this url
+    * https://secure.meetup.com/meetup_api/oauth_consumers/ to learn about OATH and the 
+    * consumer details required for authorized access.
+    *
+    * @param array $parameters The parameters passed for this request
+    * @note You're sent to meetup and they will either have an error or a page requiring you to authorize, they'll send
+    *       you back to the redirect uri specified in your consumer details
+    * @note The parameter 'response_type' is automatically included with value 'code'
+   */       
     public function authorize(array $parameters = array())
-    {
-    	$location = self::AUTHORIZE . '?' . http_build_query(array_merge($this->_parameters,$parameters, array('response_type' => 'code')));
+    {   	
+    	$location = self::AUTHORIZE . '?' . http_build_query(array_merge($this->_parameters,$parameters, array('response_type'=>'code')));
     	header("Location: " . $location);
     }
-    
+   /**
+    * Utility function for getting an access token from meetup with the code they passed back in
+    * the authorization step.  Visit this url https://secure.meetup.com/meetup_api/oauth_consumers/ 
+    * to learn about OATH and the consumer details required for authorized access.
+    *
+    * @param array $parameters The parameters passed for this request
+    * @throws Exception if anything goes wrong
+    * @note The parameter 'grant_type' is automatically included with value 'authorization_code'
+   */      
     public function access(array $parameters = array())
     {
-    	return $this->api(self::ACCESS, array_merge($parameters, array('grant_type'=>'authorization_code')), true);
+    	return $this->api(self::ACCESS, array_merge($parameters, array('grant_type'=>'authorization_code')), self::POST);
     }
-    
+    /**
+    * Utility function for getting an refresh token from meetup to avoid authorization from expiring.  
+    * Visit this url https://secure.meetup.com/meetup_api/oauth_consumers/ to learn about OATH and the 
+    * consumer details required for authorized access.
+    *
+    * @param array $parameters The parameters passed for this request
+    * @throws Exception if anything goes wrong
+    * @note The parameter 'grant_type' is automatically included with value 'refresh_token'
+   */    
     public function refresh(array $parameters = array())
-    {
-    	return $this->api(self::ACCESS, array_merge($parameters, array('grant_type'=>'refresh_token')), true);
+    {    	
+    	return $this->api(self::ACCESS, array_merge($parameters, array('grant_type'=>'refresh_token')), self::POST);
     }
-    
-    protected function api($url, $parameters, $post=false)
+    /**
+    * Main routine that all requests go through which handles the CURL call to the server and
+    * prepares the request accordingly.
+    *
+    * @param array $parameters The parameters passed for this request
+    * @throws Exception if anything goes wrong
+    * @note The parameter 'sign' is automatically included with value 'true' if using an api key
+   */        
+    protected function api($url, $parameters, $action=self::GET)
     {
     	//merge parameters
-    	$this->_parameters = array_merge($parameters, $this->_parameters);
-    	
-    	
+    	$params = array_merge($parameters, $this->_parameters);
+    	   	
     	//make sure 'sign' is included when using api key only	
-	if(in_array('key', $this->_parameters) && $url!=self::ACCESS && $url!=self::AUTHORIZE)
+	if(in_array('key', $params) && $url!=self::ACCESS && $url!=self::AUTHORIZE)
     	{
     		//api request (any) - include sign parameters
-    		$this->_parameters = array_merge( array('sign', 'true'), $this->_parameters );
+    		$params = array_merge( array('sign', 'true'), $params );
     	}
-
+  	
     	//init curl
     	$ch = curl_init();
     	
@@ -118,33 +335,48 @@ protected function api($url, $parameters, $post=false)
     	curl_setopt($ch, CURLOPT_HEADER, false);
     	curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
     	
-    	//either GET or POST against api
-    	if($post===false)
+    	//either GET/POST/PUT/DELETE against api
+    	if($action==self::GET || $action==self::DELETE)
     	{   		
+    		//GET + DELETE
+    		
     		//include headers as specified by manual
     		if( $url == self::ACCESS )
     		{
     			array_push($headers, 'Content-Type: application/x-www-form-urlencoded');
     		}
-    		else if( strpos($url, self::BASE) === 0 && in_array('access_token', $this->_parameters) )
+    		else if( strpos($url, self::BASE) === 0 && in_array('access_token', $params) )
     		{
-    			array_merge($this->_parameters, array('token_type'=>'bearer'));
+    			array_merge($params, array('token_type'=>'bearer'));
     		}
     		
-    		curl_setopt($ch, CURLOPT_URL, $url . '?' . http_build_query($this->_parameters));
+    		curl_setopt($ch, CURLOPT_URL, $url . '?' . http_build_query($params));
     	}	
     	else
     	{
+    		//POST + PUT
+    		
     		curl_setopt($ch, CURLOPT_URL, $url);    		
-    		curl_setopt($ch, CURLOPT_POST, count($parameters));
-    		curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($this->_parameters));   		
+    		curl_setopt($ch, CURLOPT_POST, count($params));
+    		curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
     	}    	
-    	     	  	
+    	 
+    	//need custom types for PUT/DELETE
+    	switch($action)
+    	{
+    		case self::DELETE:
+    			curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
+    		break;
+    		case self::PUT:
+    			curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
+    		break;
+    	}
+    	    	  	
         curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
          
     	//fetch content
     	$content = curl_exec($ch);
-    	   	
+	    		    	   	
     	//was there an error on the connection?
     	if (curl_errno($ch))
     	{
@@ -159,7 +391,7 @@ protected function api($url, $parameters, $post=false)
     	$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    	
     	curl_close($ch);
-    	
+    	    	
     	if (!is_null($response) && $status != 200)
     	{    	        
     		//tell them what went wrong or just relay the status
@@ -215,4 +447,3 @@ protected function api($url, $parameters, $post=false)
     }
 }
 ?>
-

From b5e3141bf075f464fc5eca055930d710dc6c02d0 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Thu, 13 Nov 2014 12:39:26 -0600
Subject: [PATCH 13/27] Updated Readme.md to match code

Reflect current state with new post/delete functionality and stub methods
---
 README.md | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 7bd7f05..a50063a 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,7 @@ Underneath there's parameters (depending on the request being made) that get inj
 ## Quick Start
 
 * Get your [API key](http://www.meetup.com/meetup_api/key/).
+* Limited information returned on GET requests (ie may not get private event or member details unless authorized)
 * Require the library, create a Meetup object and set your key:
 
 ```php
@@ -34,6 +35,7 @@ $response = $meetup->getEvents(); //somewhat restricted
 ```
 
 * Get your [Consumer details](https://secure.meetup.com/meetup_api/oauth_consumers/).
+* Use authorized access to get ALL information on GET requests and perform POST/DELETE requests also
 * Require the library, create a Meetup object and set your consumer details and gain access:
 
 ```php
@@ -123,7 +125,7 @@ $response = $meetup->refresh();
 //$response->access_token, $response->refresh_token, $response->expires_in
 ```
 
-## Doing GET requests
+## Doing GET/POST/DELETE requests
 You can call any [Meetup API GET-method](http://www.meetup.com/meetup_api/docs/) using `get()`.  There's several stub functions already for the more common ones and new ones will be added.
 
 ### Arguments
@@ -153,23 +155,24 @@ Feel free to fork the code and add more!
 | getPhotos           | /2/photos                         |
 | getDiscussionBoards | /:urlname/boards                  |
 | getDiscussions      | /:urlname/boards/:bid/discussions |
-
+| postEvent           | /event/:id                        |
+| deleteEvent         | /event/:id                        |
 
 ## Roadmap
-* Implement `POST` and `DELETE` methods.
 * Add more short-hands.
 * Have some meetups...
-* Modify/post using OATH 2 and write not just read
 * Update Meetup object to be have member variables and store data internally for important information
-  like access tokens and etc.
+  like access tokens and etc. and don't just use arrays for everything
 
 ## Alternatives
 Before starting this client, I checked out the following [existing clients](http://www.meetup.com/meetup_api/clients/): 
 
 * [wizonesolutions/meetup_api](https://github.com/wizonesolutions/meetup_api): Huge library, hasn't been updated for 3 years.
 * [blobaugh](https://github.com/blobaugh/Meetup-API-client-for-PHP): Huge library, documentation quick start doesn't get you started.
+* [FokkeZB](https://github.com/FokkeZB/Meetup): Great simple library, missing OATH and post/delete.
+* 
+This is a more simplified library for access and interactions covering OATH and post/delete using the Meetup API!
 
-This is a more simplified library for access and interactions!
 ## License
 
 

From f6d6c01cdaf0ebb85c663cec6cca31f35f4635ad Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Thu, 13 Nov 2014 12:40:06 -0600
Subject: [PATCH 14/27] Update README.md

---
 README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/README.md b/README.md
index a50063a..bfb79a0 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
 # Meetup API
 This a very simple, one-file, PHP client for accessing most of the [Meetup API](http://www.meetup.com/meetup_api/).  Some parameters are included behind the scenes so you don't have to using array_merge when the parameters have fixed values like signed or response_type depending on the nature of the request.
 
+The code is documented to include more information along with small code snippets in the documentation where applicable.
+
 #Exceptions
 Exceptions are thrown and can be caught when there's any errors interacting with the API, they are standard exceptions.
 

From ce695568059740e54b10f94c698aad0838b02927 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Thu, 13 Nov 2014 12:44:10 -0600
Subject: [PATCH 15/27] Updated Readme.md to match code

Updated readme to reflect new functionality for get/post/put/delete
---
 README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index bfb79a0..7a95b69 100644
--- a/README.md
+++ b/README.md
@@ -128,10 +128,10 @@ $response = $meetup->refresh();
 ```
 
 ## Doing GET/POST/DELETE requests
-You can call any [Meetup API GET-method](http://www.meetup.com/meetup_api/docs/) using `get()`.  There's several stub functions already for the more common ones and new ones will be added.
+You can call any [Meetup API method](http://www.meetup.com/meetup_api/docs/) using `get()` or `post()` or `delete()` or `put()`.  There's several stub functions already for the more common ones and new ones will be added down the road.  You just have to supply the path relative from meetup (don't include the base path) and the parameters you want.  Use place holders in your path : and make sure to include the parameter in your parameters exactly as it appears in the placeholder.
 
 ### Arguments
-The method get() takes two arguments, of which the second one is optional:
+The method `get()`,`put()`,`post()`,`delete()` takes two arguments, of which the second one is optional:
 
 1. `(string)` Meetup API method (e.g. `/2/events`)
 2. `(array)` Meetup API method paramaters (e.g. `array('group_urlname' => 'your-meetup-group')`)

From 399cfea3bbbab517f6c818a92cd83736352a0776 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Thu, 13 Nov 2014 13:01:46 -0600
Subject: [PATCH 16/27] Bug fix for GET requests

Fixed bug when building GET request, if parameters are empty don't append '?' to the url just leave it as is, issue when building requests but also using getNext() since the data was already in the url.
---
 meetup.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/meetup.php b/meetup.php
index e7307e6..c0e1b4f 100644
--- a/meetup.php
+++ b/meetup.php
@@ -350,7 +350,7 @@ protected function api($url, $parameters, $action=self::GET)
     			array_merge($params, array('token_type'=>'bearer'));
     		}
     		
-    		curl_setopt($ch, CURLOPT_URL, $url . '?' . http_build_query($params));
+    		curl_setopt($ch, CURLOPT_URL, $url . (!empty($params) ? ('?' . http_build_query($params)) : ''));
     	}	
     	else
     	{

From 8e0d46a5eecbd46338c14dc6813b9cfcbcd53074 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Thu, 13 Nov 2014 13:36:48 -0600
Subject: [PATCH 17/27] Update meetup.php

Return null in getNext() for easier processing instead of throwing if there's no next responses to get.
---
 meetup.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/meetup.php b/meetup.php
index c0e1b4f..67bdda9 100644
--- a/meetup.php
+++ b/meetup.php
@@ -125,13 +125,13 @@ public function getMembers(array $parameters = array())
     *
     * @param mixed $response The response object given back from a previous request
     * @return mixed A json object containing response data
-    * @throws Exception if anything goes wrong
    */      
     public function getNext($response)
     {
         if (!isset($response) || !isset($response->meta->next))
         {
-            throw new Exception("Invalid response object.");
+            //return null for easier processing
+            return null;
         }
         return $this->api($response->meta->next, array(), self::GET);
     }

From 1d91662e3ad03ea7dcbd3b28b177338440d1e281 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Thu, 13 Nov 2014 14:07:13 -0600
Subject: [PATCH 18/27] Added hasNext() and updated getNext().

Added new function hasNext for checking meta data in case it has the next request to make to get remaining data.  Store response internally so we don't have to pass anything to hasNext() or getNext() and it updates internal as it's called.  Also make it easier for getting the next result set if available for requests.
---
 meetup.php | 47 ++++++++++++++++++++++++++++-------------------
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/meetup.php b/meetup.php
index 67bdda9..2352caa 100644
--- a/meetup.php
+++ b/meetup.php
@@ -45,6 +45,11 @@ class Meetup
     * @var array
    */       
     protected $_parameters = array();
+  /**
+    * The response object from the request
+    * @var mixed
+   */           
+    protected $_response = null;
    /**
     * Constructor
     * @param array $parameters The parameters passed during construction
@@ -52,6 +57,7 @@ class Meetup
     public function __construct(array $parameters = array())
     {
         $this->_parameters = array_merge($this->_parameters, $parameters);
+        $this->_next = $this->_response = null;
     }
    /**
     * Stub for fetching events
@@ -123,17 +129,20 @@ public function getMembers(array $parameters = array())
     * Stub for grabbing the next response data if it's available in the meta information
     * of a response.  Normally if there's too many results it won't return them all.
     *
-    * @param mixed $response The response object given back from a previous request
     * @return mixed A json object containing response data
    */      
-    public function getNext($response)
+    public function getNext($all=false)
+    {   	
+    	return $this->hasNext() ? $this->api($this->_response->meta->next, array(), self::GET) : null;
+    }
+   /**
+    * Is there more data to retrieve?
+    *
+    * @return boolean True if there's more results to process
+   */     
+    public function hasNext()
     {
-        if (!isset($response) || !isset($response->meta->next))
-        {
-            //return null for easier processing
-            return null;
-        }
-        return $this->api($response->meta->next, array(), self::GET);
+    	return isset($this->_response->meta) && isset($this->_response->meta->next);
     }
    /**
     * Stub for updating an event
@@ -386,24 +395,24 @@ protected function api($url, $parameters, $action=self::GET)
     		throw new Exception("Failed retrieving  '" . $url . "' because of connection issue: ' " . $error . "'.");
     	}
     	
-    	//retrieve json
-    	$response = json_decode($content);
-    	$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+    	//retrieve json and store it internally
+    	$this->_response = json_decode($content);
+    	$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    	
     	curl_close($ch);
     	    	
-    	if (!is_null($response) && $status != 200)
+    	if (!is_null($this->_response) && $status != 200)
     	{    	        
     		//tell them what went wrong or just relay the status
-    		if( isset($response->error) && isset($response->error_description) )
+    		if( isset($this->_response->error) && isset($this->_response->error_description) )
     		{
     			//what we see against Oath 
-    			$error = $response->error . ' - ' . $response->error_description;
+    			$error = $this->_response->error . ' - ' . $this->_response->error_description;
     		}
-    		else if( isset($response->details) && isset($response->problem) && isset($response->code) )
+    		else if( isset($this->_response->details) && isset($this->_response->problem) && isset($this->_response->code) )
     		{
     			//what we see against regular access
-    			$error = $response->code . ' - ' . $response->problem . ' - ' . $response->details;
+    			$error = $this->_response->code . ' - ' . $this->_response->problem . ' - ' . $this->_response->details;
     		}
     		else
     		{
@@ -412,7 +421,7 @@ protected function api($url, $parameters, $action=self::GET)
     		 
     		throw new Exception("Failed retrieving  '" . $url . "' because of ' " . $error . "'.");
     	}	
-    	else if (is_null($response)) 
+    	else if (is_null($this->_response)) 
     	{
     		//did we have any parsing issues for the response?
     		switch (json_last_error()) 
@@ -442,8 +451,8 @@ protected function api($url, $parameters, $action=self::GET)
     	
     		throw new Exception("Cannot read response by  '" . $url . "' because of: '" . $error . "'.");
     	}
-    	
-    	return $response;
+   	
+    	return $this->_response;
     }
 }
 ?>

From 8010231706dc5eb34ade0bb5860f70f81df908fa Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Thu, 13 Nov 2014 14:09:48 -0600
Subject: [PATCH 19/27] Update Readme.md

Reflect new state of hasNext() and getNext()
---
 README.md | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 7a95b69..6277370 100644
--- a/README.md
+++ b/README.md
@@ -97,16 +97,23 @@ $response = $meetup->getEvents(array(
 // total number of items matching the get request
 $total_count = $response->meta->total_count;
 
-foreach ($response->results as $event) {
+foreach ($response->results as $event) 
+{
 	echo $event->name . ' at ' . date('Y-m-d H:i', $event->time / 1000) . PHP_EOL;
 }
 ```
 Many of the get requests will match more entries than the API will return in one request. A convenience method has been provided to return the next page of entries after you have performed a successful get request:
 
 ```php
-$response = $meetup->getNext($response);
-
-$events = $response->results;
+//can check if there's more by using $response->hasNext(). Keep processing
+//events if they're available and make subsequent calls to the API
+while( ($response = $meetup->getNext()) !== null)	       	        
+{
+    foreach($response->results as $event)
+    {
+        //process event	            
+    }	
+}
 ```
 ...
 

From 8dc26326ad71c698bd47199a34f2faba5bcab6c3 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Mon, 17 Nov 2014 12:19:19 -0600
Subject: [PATCH 20/27] Updated hasNext() and getNext() meetup.php

Improved check for hasNext() in meta link for additional results and how it's used in getNext().  Now checking if the meta data is set and if it is if the link isn't empty before accepting that we have additional results to process.
---
 meetup.php | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/meetup.php b/meetup.php
index 2352caa..84ab6c4 100644
--- a/meetup.php
+++ b/meetup.php
@@ -131,7 +131,7 @@ public function getMembers(array $parameters = array())
     *
     * @return mixed A json object containing response data
    */      
-    public function getNext($all=false)
+    public function getNext()
     {   	
     	return $this->hasNext() ? $this->api($this->_response->meta->next, array(), self::GET) : null;
     }
@@ -142,7 +142,17 @@ public function getNext($all=false)
    */     
     public function hasNext()
     {
-    	return isset($this->_response->meta) && isset($this->_response->meta->next);
+    	$next = null;
+    	if( isset($this->_response->meta) && isset($this->_response->meta->next) )
+    	{
+    		$next = $this->_response->meta->next;
+    		if( strlen($next) )
+    		{
+    			return true;
+    		}
+    	}
+    	
+    	return false;
     }
    /**
     * Stub for updating an event

From 32f162b19ffb7e3944c55b61bf0a48d96ecea810 Mon Sep 17 00:00:00 2001
From: user3581488 
Date: Mon, 17 Nov 2014 12:22:17 -0600
Subject: [PATCH 21/27] Update README.md

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 6277370..cad2439 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # Meetup API
 This a very simple, one-file, PHP client for accessing most of the [Meetup API](http://www.meetup.com/meetup_api/).  Some parameters are included behind the scenes so you don't have to using array_merge when the parameters have fixed values like signed or response_type depending on the nature of the request.
 
-The code is documented to include more information along with small code snippets in the documentation where applicable.
+The code is documented to include more information along with small code snippets in the documentation where applicable.  This library supports OATH, api key, get/put/delete calls, and has several useful stub methods for accessing API functionality from meetup.  There's documentation and comments in the code and a detailed README to help you get started easily using the library.
 
 #Exceptions
 Exceptions are thrown and can be caught when there's any errors interacting with the API, they are standard exceptions.

From 8bee92a3c9ebeba868bc001c3ca8d738d5e93b5f Mon Sep 17 00:00:00 2001
From: Jonathan Devine 
Date: Sun, 11 Jan 2015 02:46:44 +0000
Subject: [PATCH 22/27] Create composer.json

---
 composer.json | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 composer.json

diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..e2b97b8
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,16 @@
+{
+    "name": "user3581488/Meetup",
+    "type": "library",
+    "description": "PHP client for accessing most of the Meetup API",
+    "keywords": ["meetup"],
+    "homepage": "https://github.com/user3581488/Meetup",
+    "license": "Apache-2.0",
+    "require": {
+        "php": ">=5.2.1"
+    },
+    "autoload": {
+        "classmap": [
+            "/"
+        ]
+    }
+}

From 026775aad24ff2c60528cd77fa2f1988acbcd159 Mon Sep 17 00:00:00 2001
From: Jonathan Devine 
Date: Sun, 11 Jan 2015 04:02:38 +0000
Subject: [PATCH 23/27] Update composer.json

---
 composer.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/composer.json b/composer.json
index e2b97b8..edfcd49 100644
--- a/composer.json
+++ b/composer.json
@@ -6,7 +6,7 @@
     "homepage": "https://github.com/user3581488/Meetup",
     "license": "Apache-2.0",
     "require": {
-        "php": ">=5.2.1"
+        "php": ">=5.3.3",
     },
     "autoload": {
         "classmap": [

From d8ff84dacce990f5ba7b74e9e7a8f8930b67a96c Mon Sep 17 00:00:00 2001
From: Jonathan Devine 
Date: Sun, 11 Jan 2015 05:22:24 +0000
Subject: [PATCH 24/27] Update composer.json

---
 composer.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/composer.json b/composer.json
index edfcd49..38cce89 100644
--- a/composer.json
+++ b/composer.json
@@ -6,7 +6,7 @@
     "homepage": "https://github.com/user3581488/Meetup",
     "license": "Apache-2.0",
     "require": {
-        "php": ">=5.3.3",
+        "php": ">=5.3.3"
     },
     "autoload": {
         "classmap": [

From 44282f1e9b3943d06df09e156d1ba383e60145d3 Mon Sep 17 00:00:00 2001
From: Jonathan Devine 
Date: Sun, 11 Jan 2015 05:31:00 +0000
Subject: [PATCH 25/27] Update composer.json

---
 composer.json | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/composer.json b/composer.json
index 38cce89..1725664 100644
--- a/composer.json
+++ b/composer.json
@@ -12,5 +12,10 @@
         "classmap": [
             "/"
         ]
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.0"
+        }
     }
 }

From 6e4a44908889b578470103d91904fdebd08ac6b4 Mon Sep 17 00:00:00 2001
From: Jonathan Devine 
Date: Sun, 11 Jan 2015 20:07:07 +0000
Subject: [PATCH 26/27] Update README.md

---
 README.md | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index cad2439..21f3aeb 100644
--- a/README.md
+++ b/README.md
@@ -79,11 +79,11 @@ else
      $_SESSION['refresh_token'] = $response->refresh_token;
      $_SESSION['expires'] = time() + intval($response->expires_in); //use if >= intval($_SESSION['expires']) to check
      
-     //get all groups for this member
-     $response = $meetup->getGroups('member_id' => '');
+     //get all groups for this member, to get your own use array('member_id' => 'self')
+     $response = $meetup->getGroups(array('member_id' => ''));
      
-     //get all events for this member
-     $response = $meetup->getEvents('member_id' => '');
+     //get all events for this member, to get your own use array('member_id' => 'self')
+     $response = $meetup->getEvents(array('member_id' => ''));
 }
 ```
 

From 4982cea0eaffe0ebece24fb31b7ac6145fb3ae7a Mon Sep 17 00:00:00 2001
From: Ricardo 
Date: Thu, 6 Apr 2017 22:31:02 +0200
Subject: [PATCH 27/27] Fixed postEvent and updateEvent

Posting events works now.

Also changed the HTML response code detection. postEvent will return 201 if successful:  https://www.meetup.com/meetup_api/docs/2/event/
---
 meetup.php | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/meetup.php b/meetup.php
index 84ab6c4..e716492 100644
--- a/meetup.php
+++ b/meetup.php
@@ -154,6 +154,17 @@ public function hasNext()
     	
     	return false;
     }
+    /**
+     * Stub for adding an event
+     *
+     * @param array $parameters The parameters passed for this request
+     * @return mixed A json object containing response data
+     * @throws Exception if anything goes wrong
+    */   
+     public function postEvent(array $parameters = array())
+     {
+     	return $this->post('/2/event', $parameters);
+     }
    /**
     * Stub for updating an event
     *
@@ -161,7 +172,7 @@ public function hasNext()
     * @return mixed A json object containing response data
     * @throws Exception if anything goes wrong
    */   
-    public function postEvent(array $parameters = array())
+    public function updateEvent(array $parameters = array())
     {
     	return $this->post('/2/event/:id', $parameters);
     }
@@ -411,7 +422,7 @@ protected function api($url, $parameters, $action=self::GET)
    	
     	curl_close($ch);
     	    	
-    	if (!is_null($this->_response) && $status != 200)
+    	if (!is_null($this->_response) && ($status < 200 || $status >= 300))
     	{    	        
     		//tell them what went wrong or just relay the status
     		if( isset($this->_response->error) && isset($this->_response->error_description) )