3 * 01.07.2008 22:32:28est
10 * 'author' => 'viagra-test-123',
11 * 'email' => 'test@example.com',
12 * 'website' => 'http://www.example.com/',
13 * 'body' => 'This is a test comment',
14 * 'permalink' => 'http://yourdomain.com/yourblogpost.url',
17 * $akismet = new Akismet('http://www.yourdomain.com/', 'YOUR_WORDPRESS_API_KEY', $comment);
19 * if($akismet->errorsExist()) {
20 * echo"Couldn't connected to Akismet server!";
22 * if($akismet->isSpam()) {
23 * echo"Spam detected";
25 * echo"yay, no spam!";
30 * @author Bret Kuhns {@link www.miphp.net}
31 * @link http://www.miphp.net/blog/view/new_akismet_class/
33 * @license http://www.opensource.org/licenses/mit-license.php MIT License
39 define("AKISMET_SERVER_NOT_FOUND", 0);
40 define("AKISMET_RESPONSE_FAILED", 1);
41 define("AKISMET_INVALID_KEY", 2);
45 // Base class to assist in error handling between Akismet classes
47 var $errors = array();
51 * Add a new error to the errors array in the object
53 * @param String $name A name (array key) for the error
54 * @param String $string The error message
57 // Set an error in the object
58 function setError($name, $message) {
59 $this->errors[$name] = $message;
64 * Return a specific error message from the errors array
66 * @param String $name The name of the error you want
67 * @return mixed Returns a String if the error exists, a false boolean if it does not exist
69 function getError($name) {
70 if($this->isError($name)) {
71 return $this->errors[$name];
79 * Return all errors in the object
83 function getErrors() {
84 return (array)$this->errors;
89 * Check if a certain error exists
91 * @param String $name The name of the error you want
94 function isError($name) {
95 return isset($this->errors[$name]);
100 * Check if any errors exist
104 function errorsExist() {
105 return (count($this->errors) > 0);
115 // Used by the Akismet class to communicate with the Akismet service
116 class AkismetHttpClient extends AkismetObject {
117 var $akismetVersion = '1.1';
123 var $errors = array();
127 function AkismetHttpClient($host, $blogUrl, $apiKey, $port = 80) {
130 $this->blogUrl = $blogUrl;
131 $this->apiKey = $apiKey;
135 // Use the connection active in $con to get a response from the server and return that response
136 function getResponse($request, $path, $type = "post", $responseLength = 1160) {
139 if($this->con && !$this->isError(AKISMET_SERVER_NOT_FOUND)) {
141 strToUpper($type)." /{$this->akismetVersion}/$path HTTP/1.1\r\n" .
142 "Host: ".((!empty($this->apiKey)) ? $this->apiKey."." : null)."{$this->host}\r\n" .
143 "Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n" .
144 "Content-Length: ".strlen($request)."\r\n" .
145 "User-Agent: Akismet PHP4 Class\r\n" .
151 @fwrite($this->con, $request);
153 while(!feof($this->con)) {
154 $response .= @fgets($this->con, $responseLength);
157 $response = explode("\r\n\r\n", $response, 2);
160 $this->setError(AKISMET_RESPONSE_FAILED, "The response could not be retrieved.");
163 $this->_disconnect();
167 // Connect to the Akismet server and store that connection in the instance variable $con
168 function _connect() {
169 if(!($this->con = @fsockopen($this->host, $this->port))) {
170 $this->setError(AKISMET_SERVER_NOT_FOUND, "Could not connect to akismet server.");
175 // Close the connection to the Akismet server
176 function _disconnect() {
187 // The controlling class. This is the ONLY class the user should instantiate in
188 // order to use the Akismet service!
189 class Akismet extends AkismetObject {
191 var $akismetServer = 'rest.akismet.com';
192 var $akismetVersion = '1.1';
197 'HTTP_X_FORWARDED_FOR',
198 'HTTP_X_FORWARDED_HOST',
200 'HTTP_X_FORWARDED_SERVER',
213 var $comment = array();
219 * Set instance variables, connect to Akismet, and check API key
221 * @param String $blogUrl The URL to your own blog
222 * @param String $apiKey Your wordpress API key
223 * @param String[] $comment A formatted comment array to be examined by the Akismet service
226 function Akismet($blogUrl, $apiKey, $comment = array()) {
227 $this->blogUrl = $blogUrl;
228 $this->apiKey = $apiKey;
229 $this->setComment($comment);
231 // Connect to the Akismet server and populate errors if they exist
232 $this->http = new AkismetHttpClient($this->akismetServer, $blogUrl, $apiKey);
233 if($this->http->errorsExist()) {
234 $this->errors = array_merge($this->errors, $this->http->getErrors());
237 // Check if the API key is valid
238 if(!$this->_isValidApiKey($apiKey)) {
239 $this->setError(AKISMET_INVALID_KEY, "Your Akismet API key is not valid.");
245 * Query the Akismet and determine if the comment is spam or not
250 $response = $this->http->getResponse($this->_getQueryString(), 'comment-check');
252 return ($response == "true");
257 * Submit this comment as an unchecked spam to the Akismet server
261 function submitSpam() {
262 $this->http->getResponse($this->_getQueryString(), 'submit-spam');
267 * Submit a false-positive comment as "ham" to the Akismet server
271 function submitHam() {
272 $this->http->getResponse($this->_getQueryString(), 'submit-ham');
277 * Manually set the comment value of the instantiated object.
279 * @param Array $comment
282 function setComment($comment) {
283 $this->comment = $comment;
284 if(!empty($comment)) {
285 $this->_formatCommentArray();
286 $this->_fillCommentValues();
292 * Returns the current value of the object's comment array.
296 function getComment() {
297 return $this->comment;
302 * Check with the Akismet server to determine if the API key is valid
305 * @param String $key The Wordpress API key passed from the constructor argument
308 function _isValidApiKey($key) {
309 $keyCheck = $this->http->getResponse("key=".$this->apiKey."&blog=".$this->blogUrl, 'verify-key');
311 return ($keyCheck == "valid");
316 * Format the comment array in accordance to the Akismet API
321 function _formatCommentArray() {
323 'type' => 'comment_type',
324 'author' => 'comment_author',
325 'email' => 'comment_author_email',
326 'website' => 'comment_author_url',
327 'body' => 'comment_content'
330 foreach($format as $short => $long) {
331 if(isset($this->comment[$short])) {
332 $this->comment[$long] = $this->comment[$short];
333 unset($this->comment[$short]);
340 * Fill any values not provided by the developer with available values.
344 function _fillCommentValues() {
345 if(!isset($this->comment['user_ip'])) {
346 $this->comment['user_ip'] = ($_SERVER['REMOTE_ADDR'] != getenv('SERVER_ADDR')) ? $_SERVER['REMOTE_ADDR'] : getenv('HTTP_X_FORWARDED_FOR');
348 if(!isset($this->comment['user_agent'])) {
349 $this->comment['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
351 if(!isset($this->comment['referrer'])) {
352 $this->comment['referrer'] = $_SERVER['HTTP_REFERER'];
354 if(!isset($this->comment['blog'])) {
355 $this->comment['blog'] = $this->blogUrl;
361 * Build a query string for use with HTTP requests
366 function _getQueryString() {
367 foreach($_SERVER as $key => $value) {
368 if(!in_array($key, $this->ignore)) {
369 if($key == 'REMOTE_ADDR') {
370 $this->comment[$key] = $this->comment['user_ip'];
372 $this->comment[$key] = $value;
379 foreach($this->comment as $key => $data) {
380 $query_string .= $key . '=' . urlencode(stripslashes($data)) . '&';
383 return $query_string;