Skip to content

Commit be0fa49

Browse files
committed
Everything: Unit tests. Rename Api class to Client since that makes more sense.
1 parent e8d2377 commit be0fa49

File tree

7 files changed

+469
-128
lines changed

7 files changed

+469
-128
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
21
.DS_Store
2+
vendor
3+
composer.lock
4+
coverage

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Usage
2929
``` php
3030
require_once( './vendor/autoload.php' );
3131

32-
$client = new Behance\Api( $client_id );
32+
$client = new Behance\Client( $client_id );
3333

3434
// User data
3535
$client->getUser( 'bryan' );

composer.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,12 @@
2323
}
2424
],
2525
"require": {
26-
"php": ">=5.2.0",
26+
"php": ">=5.3.3",
2727
"ext-curl": "*"
2828
},
29+
"require-dev": {
30+
"phpunit/phpunit": "4.3.*"
31+
},
2932
"autoload": {
3033
"psr-4": {"Behance\\": "src/"}
3134
}

phpunit.xml.dist

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit backupGlobals="false"
3+
backupStaticAttributes="false"
4+
bootstrap="./tests/bootstrap.php"
5+
colors="true"
6+
convertErrorsToExceptions="true"
7+
convertNoticesToExceptions="true"
8+
convertWarningsToExceptions="true"
9+
forceCoversAnnotation="false"
10+
mapTestClassNameToCoveredClassName="false"
11+
printerClass="PHPUnit_TextUI_ResultPrinter"
12+
processIsolation="false"
13+
stopOnError="false"
14+
stopOnFailure="false"
15+
stopOnIncomplete="false"
16+
stopOnSkipped="false"
17+
strict="false"
18+
verbose="true">
19+
20+
<testsuites>
21+
<testsuite name="Unit Tests">
22+
<directory suffix=".php">./tests</directory>
23+
</testsuite>
24+
</testsuites>
25+
26+
<php>
27+
<ini name="memory_limit" value="-1"/>
28+
</php>
29+
30+
<filter>
31+
<blacklist>
32+
<directory>./vendor</directory>
33+
<directory>./tests</directory>
34+
</blacklist>
35+
</filter>
36+
37+
</phpunit>

src/Api.php renamed to src/Client.php

Lines changed: 39 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* @link http://be.net/dev
1616
*
1717
*/
18-
class Api {
18+
class Client {
1919

2020
const API_ROOT = 'https://www.behance.net/v2';
2121
const ENDPOINT_PROJECTS = '/projects';
@@ -48,10 +48,6 @@ class Api {
4848
*/
4949
public function __construct( $client_id, $debug = false ) {
5050

51-
if ( !extension_loaded( 'curl' ) ) {
52-
throw new ApiException( 'cURL module is required' );
53-
}
54-
5551
$this->_client_id = $client_id;
5652
$this->_debug = $debug;
5753

@@ -197,28 +193,6 @@ public function getUserFollowers( $id_or_username, $options = array(), $assoc =
197193

198194
} // getUserFollowers
199195

200-
/**
201-
* Retrieves a list of users in the given user's feedback circle
202-
*
203-
* @param int|string $id_or_username : user
204-
* @param bool $assoc : return objects will be converted to associative arrays
205-
* @param array $options : search options
206-
*
207-
* @return array stdClass objects or associative arrays, based on $assoc
208-
*/
209-
public function getUserFeedbackCircle( $id_or_username, $options = array(), $assoc = false ) {
210-
211-
$endpoint = self::ENDPOINT_USERS . '/' . $id_or_username . '/feedback';
212-
213-
$results = $this->_getDecodedJson( $endpoint, $options, 'feedback_circlezz', $assoc );
214-
215-
// IMPORTANT: Ensure this will always return an array
216-
return ( empty( $results ) )
217-
? array()
218-
: $results;
219-
220-
} // getUserFeedbackCircle
221-
222196
/**
223197
* Retrieves a list of $id_or_username's works in progress
224198
*
@@ -549,129 +523,69 @@ protected function _makeFullURL( $endpoint, array $query_params = array() ) {
549523
*/
550524
protected function _executeRequest( $method, $url, $request_body = false, $curl_params = array() ) {
551525

526+
if ( !$this->_isCurlLoaded() ) {
527+
throw new ApiException( 'cURL module is required' );
528+
}
529+
552530
$user_agent = "Behance API/PHP (App {$this->_client_id})";
553531
$default_curl_params = array(
554532
CURLOPT_HTTPHEADER => array(
555533
'Accept: application/json',
556534
'Content-Type: multipart/form-data',
557535
'Expect:'
558536
),
559-
CURLOPT_TIMEOUT => self::TIMEOUT_DEFAULT_SEC,
560-
CURLOPT_USERAGENT => $user_agent,
561-
CURLOPT_RETURNTRANSFER => true,
562-
CURLOPT_BINARYTRANSFER => true,
563-
CURLOPT_HEADER => true,
564-
CURLOPT_SSL_VERIFYPEER => false
537+
CURLOPT_TIMEOUT => self::TIMEOUT_DEFAULT_SEC,
538+
CURLOPT_USERAGENT => $user_agent,
539+
CURLOPT_RETURNTRANSFER => true,
540+
CURLOPT_BINARYTRANSFER => true,
541+
CURLOPT_SSL_VERIFYPEER => false,
542+
CURLOPT_POST => false,
543+
CURLOPT_HTTPGET => true
565544
);
566545

567-
// Replace recursive will knock this *into* an array afterwards
568-
if ( !empty( $curl_params[ CURLOPT_HTTPHEADER ] ) ) {
569-
unset( $default_curl_params[ CURLOPT_HTTPHEADER ] );
570-
}
571-
572546
$curl_params = array_replace_recursive( $default_curl_params, $curl_params );
573-
$method = strtoupper( $method );
574-
575-
switch ( $method ) {
576-
577-
case 'GET':
578-
579-
$curl_params[ CURLOPT_HTTPGET ] = true;
580-
$curl_params[ CURLOPT_POST ] = false;
581-
break;
582-
583-
case 'POST':
584-
585-
$curl_params[ CURLOPT_HTTPGET ] = false;
586-
$curl_params[ CURLOPT_POST ] = true;
587-
588-
// IMPORTANT: Since @ is used to signify files in arrays passed to this option,
589-
// pre-encode this array to prevent this from attempting to read a file
590-
// if ( is_array( $request_body ) )
591-
// $request_body = http_build_query( $request_body );
592-
593-
// $curl_params[ CURLOPT_HTTPHEADER ][] = 'Content-Length: ' . strlen( $request_body );
594-
$curl_params[ CURLOPT_POSTFIELDS ] = $request_body;
595-
break;
596-
597-
case 'PUT':
598-
599-
$curl_params[ CURLOPT_HTTPGET ] = false;
600-
$curl_params[ CURLOPT_POST ] = false;
601-
$curl_params[ CURLOPT_CUSTOMREQUEST ] = 'PUT';
602-
603-
// IMPORTANT: Since @ is used to signify files in arrays passed to this option,
604-
// pre-encode this array to prevent this from attempting to read a file
605-
if ( is_array( $request_body ) ) {
606-
$request_body = http_build_query( $request_body );
607-
}
608-
609-
$curl_params[ CURLOPT_HTTPHEADER ][] = 'Content-Length: ' . strlen( $request_body );
610-
$curl_params[ CURLOPT_POSTFIELDS ] = $request_body;
611-
break;
612-
613-
case 'DELETE':
614-
615-
$curl_params[ CURLOPT_HTTPGET ] = false;
616-
$curl_params[ CURLOPT_CUSTOMREQUEST ] = 'DELETE';
617-
618-
// IMPORTANT: Since @ is used to signify files in arrays passed to this option,
619-
// pre-encode this array to prevent this from attempting to read a file
620-
if ( is_array( $request_body ) ) {
621-
$request_body = http_build_query( $request_body );
622-
}
623-
624-
$curl_params[ CURLOPT_POSTFIELDS ] = $request_body;
625-
break;
626-
627-
default:
628-
throw new ApiException( "Unhandled method: [{$method}]" );
629-
630-
} // switch method
631547

632548
$ch = curl_init( $url );
633549

634550
curl_setopt_array( $ch, $curl_params );
635551

636-
$request_response = curl_exec( $ch );
637-
638-
$request_info = curl_getinfo( $ch );
639-
$response_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
552+
list( $response_body, $request_info, $response_code ) = $this->_executeCurl( $ch );
640553

641554
curl_close( $ch );
642555

643-
$response_body = false;
644-
645-
if ( $request_info['download_content_length'] <= 0 ) {
556+
// @throws ApiException on response non-2xx (success) responses from service
557+
if ( (int)round( $response_code, -2 ) !== 200 ) {
558+
throw new ApiException( "Unsuccessful Request, response ({$response_code}): " . ( empty( $response_body ) ? '' : ": {$response_body} " ) );
559+
}
646560

647-
$exploded = explode( "\r\n\r\n", $request_response );
561+
return $response_body;
648562

649-
while ( $exploded[0] == 'HTTP/1.1 100 Continue' ) {
650-
array_shift( $exploded );
651-
}
563+
} // _executeRequest
652564

653-
$response_body = ( isset( $exploded[1] ) )
654-
? $exploded[1]
655-
: '';
565+
/**
566+
* @codeCoverageIgnore
567+
*
568+
* @return boolean
569+
*/
570+
protected function _isCurlLoaded() {
656571

657-
} // if download_content_length = 0
572+
return extension_loaded( 'curl' );
658573

659-
else {
660-
$response_body = substr( $request_response, -$request_info['download_content_length'] );
661-
} // else
574+
} // _isCurlLoaded
662575

663-
// Unless array_shift completely solves headers in body problem, leave this line in
664-
if ( substr( $response_body, 0, 4 ) == 'HTTP' ) {
665-
throw new ApiException( "Malformed response_body: " . var_export( $response_body, 1 ) );
666-
}
576+
/**
577+
* @codeCoverageIgnore
578+
*
579+
* @return array
580+
*/
581+
protected function _executeCurl( $ch ) {
667582

668-
// @throws ApiException on response non-2xx (success) responses from service
669-
if ( (int)round( $response_code, -2 ) !== 200 ) {
670-
throw new ApiException( "Unsuccessful Request, response ({$response_code}): " . ( empty( $response_body ) ? '' : ": {$response_body} " ) );
671-
}
583+
$request_response = curl_exec( $ch );
584+
$request_info = curl_getinfo( $ch );
585+
$response_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
672586

673-
return $response_body;
587+
return array( $request_response, $request_info, $response_code );
674588

675-
} // _executeRequest
589+
} // _executeCurl
676590

677-
} // Api
591+
} // Client

0 commit comments

Comments
 (0)