All-in-one Daniweb API Class

diafol 2 Tallied Votes 530 Views Share

OK, as promised, here's an updated 'quick(!) and dirty' class for retrieving and setting data via the Daniweb API. It allows the extraction of data based around:

DATA RETRIEVAL & SETTING

non-OAuth

  • forums
  • articles
  • posts
  • members
  • activity points
  • endorsements
  • reputation

OAuth (requires client_id and secret key)

  • who am i? (me - more data than from non-OAuth members)
  • articles (expansion of non-OAuth articles)
  • watched articles (watch and unwatch)
  • voting on posts (upvote and downvote)
  • PMs (currently inactive)

Direct URL retrieval

  • getLink

RSS

  • get data for RSS

This is in no way 'production'-standard code. It is intended for picking apart in order to build your own solutions, e.g. if you intend on using the API or entering the API contest. NB - there is very poor error checking / no exception handling.

Also check out pritaeas' class(es).

USAGE

non-OAuth

require 'dwapi.class.php';
$dw = new dwAPI;

echo $dw->getForums(); //echo json output of all forums
echo $dw->getForums(false,17) //echo data about the PHP (#17) forum
echo $dw->getList('http://www.daniweb.com/api/members/1/posts?filter=solved'); // get direct url data. NO CHECKS!

OAuth

//set $client_id and $client_secret
require 'dwapi.class.php';
$dw = new dwAPI($client_id, $client_secret);
echo $dw->getMe(); //get my data

RSS

require 'dwapi.class.php';
$dw = new dwAPI;

echo $dw->formatFeed($dw->getRSS(17),5); //echo first 5 links from PHP (#17) 

Hope it helps. Oh, and as always, please feel free to point out errors, improvements and any daft implementations. diafol :)

pritaeas commented: Nice. +14
LastMitch commented: This is Nice! +11
<?php
/**
  * This is the all-purpose dwAPI Class for accessing Daniweb API data.
  *
  * The dwAPI class is presented as an example of how to interact with
  * the Daniweb API Data as can be found at 
  * http://www.daniweb.com/api/documentation
  * 
  * It should allow access to non-OAuth data without need for
  * modification. 
  *
  * Operations for OAuth data may require a client id and 
  * a client secret key. These can be sought at 
  * http://www.daniweb.com/api/applications
  * 
  * @author  Alan Davies <ardavies@tiscali.co.uk>
  * @version 1.0.1 
  */

class dwAPI{

	private $conn = false;
	private $url;
	private $connFGC = false;
	private $connCURL = false;
	private $connType;
	
	//OAuth
	public $access_token;
	private $client_id = false;
	private $client_secret = false;


/**
  * Simple constructor to test for retrieval method (curl and file_get_contents)
  * It can also optionally set client id / secret key for OAuth calls
  * 
  * @param int	$client_id		Optional. YOUR Daniweb Client ID
  * @param str	$client_secret	Optional. YOUR Daniweb Secret Key
  */
	public function __construct($client_id=false, $client_secret=false)
	{
		if($client_id) $this->client_id = $client_id;
		if($client_secret) $this->client_secret = $client_secret;
		$this->connFGC = ini_get('allow_url_fopen');
		$this->connCURL = extension_loaded('curl');
		if(!$this->connFGC && !$this->connCURL){
			echo 	"<h3>dwAPI: NO RETRIEVAL METHOD AVAILABLE:</h3>
					<p>file_get_contents() is disabled and cURL is not loaded.</p>";
			exit;	
		}else{
			$this->connType = ($this->connCURL) ? 'curl' : 'file'; 	
		}
		if($client_id && $client_secret)$this->connect();
	}



/**
  * Route all requests through this to get JSON data
  *
  * @return str Returns the JSON string.
  */
	private function returnData()
	{
		if(!$this->conn) $this->setConn();
		//echo $this->url;
		return $this->conn->getJSON($this->url);	
	}



/**
  * Method to manually set the data retrieval method
  *
  * @param str 	$connectionType 	Set to file|curl 
  */
	public function setConnectionType($connectionType){
		if(strtolower($connectionType) == 'file' && $this->connFGC) $this->connType = 'file';
		if(strtolower($connectionType) == 'curl' && $this->connCURL) $this->connType = 'curl';
		$this->setConn();
	}
	
	
	
/**
  * Method to instatiate the retrieval method
  * Just sets the $conn
  */
	private function setConn(){
		$this->conn = ($this->connType == 'curl') ? new dwCurlGet : new dwFileGet;	
	}



/**
  * Method for validating/converting data to /{:IDS} format
  * This data should be in '/1;2;5' or '/5' format
  * N.B. This is pretty poor and could/should be improved
  *
  * @param mixed[] 	array|int|str 	$val 		
  *
  * @return str Returns the correct format for the /{:IDS}.
  */
	private function idsConvert($val)
	{
		if(is_array($val)){
			foreach($val as $item){
				if(!is_int($item)){
					echo "<h3>dwAPI: BAD IDS ARRAY</h3><p>Non integer value detected in array: $item.</p>";
					exit;	
				}
			}
			$out = implode(";", $val);	
		}elseif(is_int($val)){
			$out = $val;
		}else{
			if(preg_match('/[^\d;]/',$val)){
				echo "<h3>dwAPI: BAD IDS STRING</h3><p>Separate <strong>integers</strong> with <strong>semi-colons</strong>. No spaces or any other characters.</p>";
				exit;
			}else{
				$out = $val;	
			}
		}
		return '/' . $out;		
	}


	
/**
  * Method to query the API for forums data,
  * e.g. 
  * http://www.daniweb.com/api/forums
  * http://www.daniweb.com/api/forums/children?include_self=
  * http://www.daniweb.com/api/forums/descendants?include_self=
  * http://www.daniweb.com/api/forums/{:IDS}
  * http://www.daniweb.com/api/forums/{:IDS}/ancestors?include_self=
  * http://www.daniweb.com/api/forums/{:IDS}/children?include_self=
  * http://www.daniweb.com/api/forums/{:IDS}/descendants?include_self=
  *
  * Querystring parameters: include_self
  
  * @param bool 					$self 		Optional. Can be true|false 
  * @param mixed[] 	array|int|str 	$ids 		Optional.
  * @param str 						$related 	Optional. Can be one of ancestors|children|descendants
  *
  * @return str Returns the JSON string via returnData method.
  */
	public function getForums($self=false, $ids=false, $related=false)
	{
		$incSelf = ($self) ? '?include_self=' : '';
		$url1 = '';
		$incRelated = ($related && in_array($related, array("ancestors","children","descendants"))) ? '/' . $related : ''; 
		if($ids)
		{
			if($ids){
				if($cleanIDS = $this->idsConvert($ids)){
					$url1 .= $cleanIDS;
				}
			}
		}
		$this->url = 'http://www.daniweb.com/api/forums' . $url1 . $incRelated . $incSelf;
		return $this->returnData();
	}

	
	
/**
  * Method to query the API for article data,
  * e.g. 
  * http://www.daniweb.com/api/articles
  * http://www.daniweb.com/api/articles/{:IDS}
  * http://www.daniweb.com/api/forums/{:IDS}/articles
  * http://www.daniweb.com/api/members/{:IDS}/articles?forum_id=
  * Querystring parameters: filter, orderby, page, forum_id
  * recommeded|viewed|watching filter param values are OAuth-only
  *
  * @param str $type Optional. Can be articles|forums|members 
  * @param mixed[] array|int|str $ids Optional. Can be multiple or single ID - see above
  * @param str $filter Optional. Can be one of unanswered|solved|threads|news|reviews|interviews|tutorials|code|whitepapers|recommeded|viewed|watching
  * @param str $order Optional. Can be one of firstpost|lastpost
  * @param int $page Optional. This is the page#
  * @param int $forum Optional. This is the forum id#
  *
  * @return str Returns the JSON string via returnData method.
  */
    public function getArticles($type=false,$ids=false,$filter=false,$order=false,$page=false,$forum=false)
	{
		$url1 = '/articles';
		$endType = '';
		switch($type)
		{
			case false:
			case 'articles':
				if($ids){
					if($cleanIDS = $this->idsConvert($ids)){
						$url1 .= $cleanIDS;
					}
				}
				break;
			case 'forums':
			case 'members':
				$url1 = '/'. $type;
				$endType = '/articles';
				if($ids && is_int($ids)){
					 $url1 .= '/' . $ids;
				}else{
					echo "<h3>dwAPI: INVALID ID</h3><p>The id has to be an integer. ID given: $ids</p>";
					exit;	
				}
				break;			
		}
		$qs = array();
		if($filter && in_array($filter, array('unanswered','solved','threads','news','reviews','interviews','tutorials','code','whitepapers','recommended'
,'viewed','watching'))) $qs[] = 'filter=' . $filter;
		if($order && in_array($order, array('firstpost','lastpost'))) $qs[] = 'orderby=' . $order;
		if($page && is_int($page)) $qs[] = 'page=' . $page;
		if($forum && is_int($forum)) $qs[] = 'forum_id=' . $forum;
		$qString = (!empty($qs)) ? '?' . implode('&',$qs) : '';
		$this->url = 'http://www.daniweb.com/api' . $url1 . $endType . $qString;
		//OAuth Request
		if(in_array($filter, array('recommended','viewed','watching'))){
			if (isset($this->access_token)) 
			{ 
				$this->url .= "&access_token={$this->access_token}";
				return $this->returnData();
			}else{
				return $this->returnOAuthRequired();	
			}
		//Normal non-OAuth request	
		}else{
			return $this->returnData();
		}
	}	



/**
  * Method to query the API for posts data,
  * e.g. 
  * http://www.daniweb.com/api/posts
  * http://www.daniweb.com/api/posts/{:IDS}
  * http://www.daniweb.com/api/articles/{:ID}/posts
  * http://www.daniweb.com/api/forums/{:ID}/posts
  * http://www.daniweb.com/api/members/{:ID}/posts?filter=
  *
  * @param str $type Optional. Can be posts|articles|forums|members 
  * @param mixed[] array|int|str $ids Optional. Can be multiple or single ID - see above
  * @param str $filter Optional. Can be one of solved|upvoted|downvoted
  * @param int $page Optional. This is the page#
  *
  * @return str Returns the JSON string via returnData method.
  */
	public function getPosts($type=false,$ids=false,$filter=false,$page=false)
	{
		$url1 = '/posts';
		$endType = '';
		
		switch($type)
		{
			case false:
			case 'posts':
				if($ids){
					if($cleanIDS = $this->idsConvert($ids)){
						$url1 .= $cleanIDS;
					}
				}
				break;
			case 'articles':
			case 'forums':
			case 'members':
				$url1 = '/'. $type;
				$endType = '/posts';
				if($ids && is_int($ids)){
					 $url1 .= '/' . $ids;
				}else{
					echo "<h3>dwAPI: INVALID ID</h3><p>The id has to be an integer. ID given: $ids</p>";
					exit;	
				}
				break;			
		}
		$qs = array();
		if($filter && in_array($filter, array('solved','upvoted','downvoted'))) $qs[] = 'filter=' . $filter;
		if($page && is_int($page)) $qs[] = 'page=' . $page;
		$qString = (!empty($qs)) ? '?' . implode('&',$qs) : '';
		$this->url = 'http://www.daniweb.com/api' . $url1 . $endType . $qString;
		return $this->returnData();
	}



/**
  * Method to query the API for member data,
  * e.g. 
  * http://www.daniweb.com/api/members?username=
  * http://www.daniweb.com/api/members?page=
  * http://www.daniweb.com/api/members/{:IDS}?page=
  *
  * @param mixed[] array|int|str $member_ids Optional. Member#s 
  * @param str $username Optional. This is a valid username
  * @param int $page Optional. This is the page#
  *
  * @return str Returns the JSON string via returnData method.
  */
	public function getMembers($member_ids=false,$username=false,$page=false)
	{
		$url1 = '/members';
		if($member_ids){
			if($cleanIDS = $this->idsConvert($member_ids)){
				$url1 .= $cleanIDS;
			}
		}
		
		$qs ='';
		if($page && is_int($page)) $qs = '?page=' . $page;
		if($username) $qs = '?username=' . $username;
		$this->url = 'http://www.daniweb.com/api' . $url1 . $qs;
		return $this->returnData();
	}



/**
  * Method to query the API for endorsement data,
  * e.g. 
  * http://www.daniweb.com/api/members/{:ID}/endorsements
  *
  * @param int $member_id 	This is the member#
  *
  * @return str Returns the JSON string via returnData method.
  */
	public function getEndorsements($member_id)
	{
		if($member_id && is_int($member_id)){
			 $url1 = '/' . $member_id . '/endorsements';
		}else{
			echo "<h3>dwAPI: INVALID ID</h3><p>The id has to be an integer. ID given: $specify</p>";
			exit;	
		}
		$this->url = 'http://www.daniweb.com/api/members' . $url1;
		return $this->returnData();
	}



/**
  * Method to query the API for activity points data,
  * e.g. 
  * http://www.daniweb.com/api/members/{:ID}/activities
  *
  * @param int $member_id 	This is the member#
  *
  * @return str Returns the JSON string via returnData method.
  */
	public function getActivities($member_id)
	{
		if($member_id && is_int($member_id)){
			 $url1 = '/' . $member_id . '/activities';
		}else{
			echo "<h3>dwAPI: INVALID ID</h3><p>The id has to be an integer. ID given: $specify</p>";
			exit;	
		}
		$this->url = 'http://www.daniweb.com/api/members' . $url1;
		return $this->returnData();
	}



/**
  * Method to query the API for reputation data,
  * e.g. 
  * http://www.daniweb.com/api/posts/{:ID}/comments
  * http://www.daniweb.com/api/members/{:ID}/comments?page=
  *
  * @param str $type 	This can be 'members' or 'posts'
  *	@param int $id 		This refers to the id of the member# or the post#
  * @param int $page	Optional. Refers to page#
  *
  * @return str Returns the JSON string via returnData method.
  */
	public function getReputation($type, $id, $page=false)
	{
		if(in_array($type, array("members","posts")) && is_int($id)){
			 $url1 = '/' . $type . '/' . $id . '/comments';
			 if($page && is_int($page)) $url .= '?page=' . $page;
		}else{
			echo "<h3>dwAPI: INVALID PARAMETERS</h3><p>The type has to be either 'members' or 'posts' and the id has to be an integer. TYPE given: $type and ID given: $id</p>";
			exit;	
		}
		$this->url = 'http://www.daniweb.com/api' . $url1;
		return $this->returnData();
	}



/**
  * Shortcut method to query the API with a direct url,
  * e.g. http://www.daniweb.com/api/members/1/posts?filter=solved
  *
  * @param str $url URL string.
  *
  * @return str Returns the JSON string via returnData method.
  */
	public function getList($url)
	{
		$this->url = $url;
		return $this->returnData();
	}



/**
  * Method to manually apply connection details for OAuth calls,
  *	
  * @param int $client_id 		YOUR client id number.
  * @param str $client_secret 	YOUR secret key.
  */
	public function addConnectionDetails($client_id, $client_secret)
	{
		$this->client_id = $client_id;
		$this->client_secret = $client_secret;
		$this->connect();
	}



/**
  * Method to connect to Daniweb for OAuth calls. This is primarily the
  * code found on the Daniweb API page (not mine!)
  */
	private function connect()
	{
		if(!$this->client_id || !$this->client_secret){
			echo 	"<h3>dwAPI: CLIENT ID and CLIENT SECRET REQUIRED:</h3>
					<p>You tried to connect without full client credentials.</p>";
			exit;
		}
		
		$current_url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
		if (isset($_REQUEST['access_token']) AND $access_token = $_REQUEST['access_token']) 
		{ 
			$this->access_token = $access_token;		
			//echo file_get_contents("http://www.daniweb.com/api/me/outbox?access_token={$access_token}",true);
		}
		else
		{
			// Send your website visitor to our authorization page along with a way to get back
			if (!isset($_REQUEST['code']))
			{
				header("Location: http://www.daniweb.com/api/oauth?client_id={$this->client_id}&redirect_uri=".urlencode($current_url));
			}
			
			// Upon authorizing your access, they will be redirected to your redirect_uri
			//	and Code will be passed along as a query string parameter
			
			// Initialize cURL to send a POST request
			$ch = curl_init('http://www.daniweb.com/api/access_token');
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
			curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
			curl_setopt($ch, CURLOPT_POST, true);
			
			// Use the Code to acquire a temporary Access Token
			//	to use for the current session
			//	You can save the Code to retrieve a new Access Token
			//	when it expires (and invalidate the existing Access Token
			//	if it hasn't expired yet)
			curl_setopt($ch, CURLOPT_POSTFIELDS, array(
				'code' => $_REQUEST['code'],
				'redirect_uri' => $current_url,
				'client_id' => $this->client_id,
				'client_secret' => $this->client_secret
			));
			curl_exec($ch);
			curl_close($ch);
		}
	}

	
/**
  * Method get 'Who am I' details via OAuth,
  *	
  * @return str Returns the JSON string via returnData method.
  */
	public function returnOAuthRequired()
	{
		return "<h3>dwAPI: OAuth CREDENTIALS REQUIRED</h3><p>You need to pass your client_id and client secret key in order to get this data.</p>";
	}


	
/**
  * Method get 'Who am I' details via OAuth,
  *	
  * @return str Returns the JSON string via returnData method.
  */
	public function getMe()
	{
		if (isset($this->access_token)) 
		{ 
			$this->url = "http://www.daniweb.com/api/me?access_token={$this->access_token}";
			return $this->returnData();
		}else{
			return $this->returnOAuthRequired();	
		}
	}


	
/**
  * Method get PMs via OAuth,
  *	
  * @param str $folder PM folder name can be inbox|outbox
  *
  * @return str Returns the JSON string via returnData method.
  */
  
/*
For some reason the inbox/outbox doesn't seem to work
	public function getPMs($folder)
	{
		if (isset($this->access_token)) 
		{ 
			if(in_array($folder, array('inbox', 'outbox'))){ 		
				$this->url = "http://www.daniweb.com/api/$folder?access_token={$this->access_token}";
				return $this->returnData();
			}else{
				echo "<h3>dwAPI: PROVIDE A VALID PM FOLDER</h3><p>Use 'inbox' or 'outbox' as parameters</p>";
				exit;
			}
		}else{
			return $this->returnOAuthRequired();	
		}
	}
*/



/**
  * Method watch an article via OAuth,
  *	
  * @param int $article Article#
  *
  * @return str Returns the JSON string via returnData method.
  */
	public function watchArticle($article)
	{
		if (isset($this->access_token)) 
		{ 
			$this->url = "http://www.daniweb.com/api/articles/$article/watch?access_token={$this->access_token}";
			return $this->returnData();
		}else{
			return $this->returnOAuthRequired();	
		}
	}



/**
  * Method unwatch an article via OAuth,
  *	
  * @param int $article Article#
  *
  * @return str Returns the JSON string via returnData method.
  */
	public function unwatchArticle($article)
	{
		if (isset($this->access_token)) 
		{ 
			$this->url = "http://www.daniweb.com/api/articles/$article/watch?remove=true&access_token={$this->access_token}";
			return $this->returnData();
		}else{
			return $this->returnOAuthRequired();	
		}
	}



/**
  * Method upvote or downvote a post via OAuth,
  *	
  * @param int $post Post#
  * @param int $vote Default = 1 Optional, Upvote = 1, Downvote = -1
  *
  * @return str Returns the JSON string via returnData method.
  */
	public function votePost($post, $vote=1)
	{
		if (isset($this->access_token)) 
		{ 
			if(($vote == 1 || $vote == -1) && is_int($post)){
				$this->url = "http://www.daniweb.com/api/posts/$post/vote?vote=$vote&access_token={$this->access_token}";
				return $this->returnData();
			}
		}else{
			return $this->returnOAuthRequired();	
		}
	}



/**
  * Method get RSS data,
  * e.g.
  * http://www.daniweb.com/rss/pull/{FORUM ID #}
  * http://www.daniweb.com/rss/pull/{ARTICLE TYPE}
  * http://www.daniweb.com/rss/pull/{FORUM ID #}/{ARTICLE TYPE}	
  *
  * @param int $forum_id Optional, Provide forum_id# 
  * @param str article_type Optional, Can be one of unanswered|solved|news|reviews|interviews|tutorials|code|whitepapers
  *
  * @return str Returns the JSON string via returnData method.
  */
	public function getRSS($forum_id=false, $article_type=false)
	{
		$f_id = ($forum_id && is_int($forum_id)) ? '/' . $forum_id : '';
		$a_type = ($article_type && in_array($article_type, array('unanswered','solved','news','reviews','interviews','tutorials','code','whitepapers'))) ? '/' . $article_type : '';
		$this->url = "http://www.daniweb.com/rss/pull" . $f_id . $a_type;
		return $this->returnData();
	}



/**
  * Method getting formatted RSS data,
  *
  * @param str $feed Provide feed data
  * @param int $limit Optional, Limit number of links to return 
  *
  * @return str Returns a link list from the original feed data.
  */
	public function formatFeed($feed, $limit=false)
	{
		$output = '';
		$articles = new SimpleXMLElement($feed);
		$n = count($articles->channel->item);
		if($limit && is_int($limit) && $limit < $n) $n = $limit;
		for($i=0;$i<$n;$i++) {
			$article = $articles->channel->item[$i]; 
			$output .= '<a href="' . $article->link . '">' . $article->title . '</a><br />';
		}
		return $output;
	}


	
/**
  * Returns data as a PHP associative array.
  *
  * @param str $str JSON string.
  *
  * @return mixed[] Returns the associative array.
  */
  	public function json2Array($str)
	{
		return json_decode($str,true);	
	}

}



/**
  * iConn is a simple interface for data retrieval.
  *
  * iConn is for providing a consistent interface to data
  * retrieval via different methods, namely cURL and 
  * file_get_contents()
  *
  * @author  Alan Davies <ardavies@tiscali.co.uk>
  * @version 1.0.0 
  */
interface iConn{
	function getJSON($url);
}



/**
  * dwFileGet allows simple data retrieval via file_get_contents.
  *
  * dwFileGet provides a method of retrieving data. It
  * implements the iConn interface and currently has one method,
  * just to get json data from the api url  
  
  * @author  Alan Davies <ardavies@tiscali.co.uk>
  * @version 1.0.0 
  */
class dwFileGet implements iConn{
	public function getJSON($url){
		$result = false;
		if($content = file_get_contents($url))
		{
			$result = $content;	
		}
		return $result;	
	}
}



/**
  * dwCurlGet allows simple data retrieval via cURL.
  *
  * dwCurlGet provides a method of retrieving data. It
  * implements the iConn interface and currently has one method,
  * just to get json data from the api url  
  * Thanks to pritaeas for most of the code below from 
  * http://www.daniweb.com/web-development/php/code/451390/daniweb-api-rss-class
  *
  * @version 1.0.0 
  */
class dwCurlGet implements iConn{
	public function getJSON($url){
		$result = false;
		$ch = curl_init();
		if ($ch)
		{
			curl_setopt($ch, CURLOPT_URL, $url);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
			$curl = curl_exec($ch);
			if ($curl)
			{
				$result = $curl;
			}
			curl_close($ch);
		}
		return $result;
	}
}
Member Avatar for diafol
diafol

This is not a bump!
Following a conversation with pritaeas, his changes to the original cURL code make the clumsy authentication above a lot simpler. I'll be making changes and posting back here with an ammended class asap. In the meantime, pritaeas has posted nice classes of his own here: http://www.daniweb.com/web-development/php/code/451816/php-class-for-daniweb-apis-unauthenticated-calls

Member Avatar for LastMitch
LastMitch

I'll be making changes and posting back here with an ammended class asap.

This is nice! Thanks for sharing and updating the codes.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.