Skip to content

Commit 77947b3

Browse files
committed
Client: init
0 parents  commit 77947b3

18 files changed

+812
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.php_cs.cache
2+
vendor
3+
composer.lock

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Private Packagist Api Client
2+
3+
## Requirements
4+
5+
* PHP >= 5.6
6+
* [Guzzle](https://github.com/guzzle/guzzle) library,
7+
8+
## Install
9+
10+
Via Composer:
11+
12+
```bash
13+
$ composer require priavate-packagist/api-client php-http/guzzle6-adapter
14+
```
15+
16+
Why `php-http/guzzle6-adapter`? We are decoupled from any HTTP messaging client with help by [HTTPlug](http://httplug.io/).
17+
18+
## Basic usage of `priavate-packagist/api-client` client
19+
20+
```php
21+
<?php
22+
23+
// This file is generated by Composer
24+
require_once __DIR__ . '/vendor/autoload.php';
25+
26+
$client = new \PrivatePackagist\ApiClient\Client();
27+
$client->authenticate('api-token', 'api-secret');
28+
$packages = $client->packages()->all();
29+
```
30+
31+
From `$client` object, you can access the full Private Packagist Api.
32+
33+
## Documentation
34+
35+
TODO
36+
37+
## License
38+
39+
`priavate-packagist/api-client` is licensed under the MIT License

composer.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "priavate-packagist/api-client",
3+
"description": "Private Packagist Api Client",
4+
"keywords": ["private packagist", "composer", "api"],
5+
"type": "library",
6+
"license": "MIT",
7+
"authors": [
8+
{
9+
"name": "Stephan Vock",
10+
"email": "stephan.vock@gmail.com"
11+
}
12+
],
13+
"minimum-stability": "stable",
14+
"require": {
15+
"php": "^5.6 || ^7.0",
16+
"psr/http-message": "^1.0",
17+
"php-http/httplug": "^1.0",
18+
"php-http/discovery": "^1.0",
19+
"php-http/client-implementation": "^1.0",
20+
"php-http/client-common": "^1.3"
21+
},
22+
"require-dev": {
23+
"phpunit/phpunit": "^5.5 || ^6.0",
24+
"php-http/guzzle6-adapter": "^1.0",
25+
"php-http/mock-client": "^1.0",
26+
"guzzlehttp/psr7": "^1.2",
27+
"cache/array-adapter": "^0.4",
28+
"phpstan/phpstan": "^0.9.1",
29+
"friendsofphp/php-cs-fixer": "^2.10"
30+
},
31+
"autoload": {
32+
"psr-4": { "PrivatePackagist\\ApiClient\\": "src/" }
33+
},
34+
"autoload-dev": {
35+
"psr-4": { "PrivatePackagist\\ApiClient\\": "tests/"}
36+
}
37+
}

src/Api/AbstractApi.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
namespace PrivatePackagist\ApiClient\Api;
4+
5+
use PrivatePackagist\ApiClient\Client;
6+
use PrivatePackagist\ApiClient\HttpClient\Message\ResponseMediator;
7+
8+
abstract class AbstractApi
9+
{
10+
/** @var Client */
11+
protected $client;
12+
/** @var ResponseMediator */
13+
private $responseMediator;
14+
15+
public function __construct(Client $client, ResponseMediator $responseMediator = null)
16+
{
17+
$this->client = $client;
18+
$this->responseMediator = $responseMediator ? $responseMediator : new ResponseMediator();
19+
}
20+
21+
/**
22+
* @param string $path
23+
* @param array $parameters
24+
* @param array $headers
25+
* @return array|string
26+
*/
27+
protected function get($path, array $parameters = [], array $headers = [])
28+
{
29+
if (count($parameters) > 0) {
30+
$path .= '?'.http_build_query($parameters);
31+
}
32+
$response = $this->client->getHttpClient()->get($path, $headers);
33+
34+
return $this->responseMediator->getContent($response);
35+
}
36+
37+
/**
38+
* @param string $path
39+
* @param array $parameters
40+
* @param array $headers
41+
* @return array|string
42+
*/
43+
protected function post($path, array $parameters = [], array $headers = [])
44+
{
45+
$response = $this->client->getHttpClient()->post(
46+
$path,
47+
$headers,
48+
$this->createJsonBody($parameters)
49+
);
50+
51+
return $this->responseMediator->getContent($response);
52+
}
53+
54+
/**
55+
* @param string $path
56+
* @param array $parameters
57+
* @param array $headers
58+
* @return array|string
59+
*/
60+
protected function delete($path, array $parameters = [], array $headers = [])
61+
{
62+
$response = $this->client->getHttpClient()->delete(
63+
$path,
64+
$headers,
65+
$this->createJsonBody($parameters)
66+
);
67+
68+
return $this->responseMediator->getContent($response);
69+
}
70+
/**
71+
* @param array $parameters
72+
* @return null|string
73+
*/
74+
protected function createJsonBody(array $parameters)
75+
{
76+
return (count($parameters) === 0) ? null : json_encode($parameters, empty($parameters) ? JSON_FORCE_OBJECT : 0);
77+
}
78+
}

src/Api/Customers.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace PrivatePackagist\ApiClient\Api;
4+
5+
class Customers extends AbstractApi
6+
{
7+
public function all()
8+
{
9+
return $this->get('/customers/');
10+
}
11+
12+
public function create($name)
13+
{
14+
return $this->postRaw('/customers/', $this->createJsonBody(['name' => $name]));
15+
}
16+
17+
public function remove($customerId)
18+
{
19+
return $this->delete(sprintf('/customers/%s/', $customerId));
20+
}
21+
22+
public function listPackages($customerId)
23+
{
24+
return $this->get(sprintf('/customers/%s/packages/', $customerId));
25+
}
26+
27+
public function addPackages($customerId, array $packages)
28+
{
29+
return $this->postRaw(sprintf('/customers/%s/packages/', $customerId), $this->createJsonBody($packages));
30+
}
31+
32+
public function removePackage($customerId, $packageId)
33+
{
34+
return $this->delete(sprintf('/customers/%s/packages/%s/', $customerId, $packageId));
35+
}
36+
}

src/Api/Packages.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace PrivatePackagist\ApiClient\Api;
4+
5+
class Packages extends AbstractApi
6+
{
7+
public function all()
8+
{
9+
return $this->get('/packages/');
10+
}
11+
}

src/Client.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace PrivatePackagist\ApiClient;
4+
5+
use Http\Client\Common\Plugin;
6+
use Http\Discovery\UriFactoryDiscovery;
7+
use PrivatePackagist\ApiClient\HttpClient\HttpPluginClientBuilder;
8+
use PrivatePackagist\ApiClient\HttpClient\Plugin\PathPrepend;
9+
use PrivatePackagist\ApiClient\HttpClient\Plugin\RequestSignature;
10+
11+
class Client
12+
{
13+
/** @var HttpPluginClientBuilder */
14+
private $httpClientBuilder;
15+
16+
/** @param string $privatePackagistUrl */
17+
public function __construct(HttpPluginClientBuilder $httpClientBuilder = null, $privatePackagistUrl = null)
18+
{
19+
$this->httpClientBuilder = $builder = $httpClientBuilder ?: new HttpPluginClientBuilder();
20+
$privatePackagistUrl = $privatePackagistUrl ? : 'https://packagist.com';
21+
22+
$builder->addPlugin(new Plugin\AddHostPlugin(UriFactoryDiscovery::find()->createUri($privatePackagistUrl)));
23+
$builder->addPlugin(new PathPrepend('/api'));
24+
$builder->addPlugin(new Plugin\HeaderDefaultsPlugin([
25+
'User-Agent' => 'php-private-packagist-api (http://github.com/packagist/private-packagist-api)', // @todo
26+
]));
27+
}
28+
29+
/**
30+
* @param string $token
31+
* @param string $secret
32+
*/
33+
public function authenticate($token, $secret)
34+
{
35+
$this->httpClientBuilder->removePlugin(RequestSignature::class);
36+
$this->httpClientBuilder->addPlugin(new RequestSignature($token, $secret));
37+
}
38+
39+
public function customers()
40+
{
41+
return new Api\Customers($this);
42+
}
43+
44+
public function packages()
45+
{
46+
return new Api\Packages($this);
47+
}
48+
49+
public function getHttpClient()
50+
{
51+
return $this->getHttpClientBuilder()->getHttpClient();
52+
}
53+
54+
protected function getHttpClientBuilder()
55+
{
56+
return $this->httpClientBuilder;
57+
}
58+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
namespace PrivatePackagist\ApiClient\HttpClient;
4+
5+
use Http\Client\Common\HttpMethodsClient;
6+
use Http\Client\Common\Plugin;
7+
use Http\Client\Common\PluginClient;
8+
use Http\Client\HttpClient;
9+
use Http\Discovery\HttpClientDiscovery;
10+
use Http\Discovery\MessageFactoryDiscovery;
11+
use Http\Message\MessageFactory;
12+
use Http\Message\RequestFactory;
13+
14+
class HttpPluginClientBuilder
15+
{
16+
/** @var HttpClient */
17+
private $httpClient;
18+
/** @var HttpMethodsClient */
19+
private $pluginClient;
20+
/** @var MessageFactory */
21+
private $requestFactory;
22+
/** @var Plugin[] */
23+
private $plugins = [];
24+
25+
public function __construct(HttpClient $httpClient = null, RequestFactory $requestFactory = null)
26+
{
27+
$this->httpClient = $httpClient ?: HttpClientDiscovery::find();
28+
$this->requestFactory = $requestFactory ?: MessageFactoryDiscovery::find();
29+
}
30+
31+
public function addPlugin(Plugin $plugin)
32+
{
33+
$this->plugins[] = $plugin;
34+
$this->pluginClient = null;
35+
}
36+
37+
/**
38+
* @param string $pluginClass
39+
*/
40+
public function removePlugin($pluginClass)
41+
{
42+
foreach ($this->plugins as $idx => $plugin) {
43+
if ($plugin instanceof $pluginClass) {
44+
unset($this->plugins[$idx]);
45+
$this->pluginClient = null;
46+
}
47+
}
48+
}
49+
50+
public function getHttpClient()
51+
{
52+
if (!$this->pluginClient) {
53+
$this->pluginClient = new HttpMethodsClient(
54+
new PluginClient($this->httpClient, $this->plugins),
55+
$this->requestFactory
56+
);
57+
}
58+
59+
return $this->pluginClient;
60+
}
61+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace PrivatePackagist\ApiClient\HttpClient\Message;
4+
5+
use Psr\Http\Message\ResponseInterface;
6+
7+
class ResponseMediator
8+
{
9+
/**
10+
* @return mixed|string
11+
*/
12+
public function getContent(ResponseInterface $response)
13+
{
14+
$body = $response->getBody()->__toString();
15+
if (strpos($response->getHeaderLine('Content-Type'), 'application/json') === 0) {
16+
$content = json_decode($body, true);
17+
if (JSON_ERROR_NONE === json_last_error()) {
18+
return $content;
19+
}
20+
}
21+
22+
return $body;
23+
}
24+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace PrivatePackagist\ApiClient\HttpClient\Plugin;
4+
5+
use Http\Client\Common\Plugin;
6+
use Psr\Http\Message\RequestInterface;
7+
8+
class PathPrepend implements Plugin
9+
{
10+
/** @var string */
11+
private $path;
12+
13+
/**
14+
* @param string $path
15+
*/
16+
public function __construct($path)
17+
{
18+
$this->path = $path;
19+
}
20+
21+
/**
22+
* {@inheritdoc}
23+
*/
24+
public function handleRequest(RequestInterface $request, callable $next, callable $first)
25+
{
26+
$uri = $request->getUri();
27+
28+
if (strpos($uri->getPath(), $this->path) !== 0) {
29+
$request = $request->withUri($uri->withPath($this->path . $uri->getPath()));
30+
}
31+
32+
return $next($request);
33+
}
34+
}

0 commit comments

Comments
 (0)