Skip to content

Commit

Permalink
Client: init
Browse files Browse the repository at this point in the history
  • Loading branch information
glaubinix committed Feb 15, 2018
0 parents commit 77947b3
Show file tree
Hide file tree
Showing 18 changed files with 812 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.php_cs.cache
vendor
composer.lock
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Private Packagist Api Client

## Requirements

* PHP >= 5.6
* [Guzzle](https://github.com/guzzle/guzzle) library,

## Install

Via Composer:

```bash
$ composer require priavate-packagist/api-client php-http/guzzle6-adapter
```

Why `php-http/guzzle6-adapter`? We are decoupled from any HTTP messaging client with help by [HTTPlug](http://httplug.io/).

## Basic usage of `priavate-packagist/api-client` client

```php
<?php

// This file is generated by Composer
require_once __DIR__ . '/vendor/autoload.php';

$client = new \PrivatePackagist\ApiClient\Client();
$client->authenticate('api-token', 'api-secret');
$packages = $client->packages()->all();
```

From `$client` object, you can access the full Private Packagist Api.

## Documentation

TODO

## License

`priavate-packagist/api-client` is licensed under the MIT License
37 changes: 37 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "priavate-packagist/api-client",
"description": "Private Packagist Api Client",
"keywords": ["private packagist", "composer", "api"],
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Stephan Vock",
"email": "[email protected]"
}
],
"minimum-stability": "stable",
"require": {
"php": "^5.6 || ^7.0",
"psr/http-message": "^1.0",
"php-http/httplug": "^1.0",
"php-http/discovery": "^1.0",
"php-http/client-implementation": "^1.0",
"php-http/client-common": "^1.3"
},
"require-dev": {
"phpunit/phpunit": "^5.5 || ^6.0",
"php-http/guzzle6-adapter": "^1.0",
"php-http/mock-client": "^1.0",
"guzzlehttp/psr7": "^1.2",
"cache/array-adapter": "^0.4",
"phpstan/phpstan": "^0.9.1",
"friendsofphp/php-cs-fixer": "^2.10"
},
"autoload": {
"psr-4": { "PrivatePackagist\\ApiClient\\": "src/" }
},
"autoload-dev": {
"psr-4": { "PrivatePackagist\\ApiClient\\": "tests/"}
}
}
78 changes: 78 additions & 0 deletions src/Api/AbstractApi.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace PrivatePackagist\ApiClient\Api;

use PrivatePackagist\ApiClient\Client;
use PrivatePackagist\ApiClient\HttpClient\Message\ResponseMediator;

abstract class AbstractApi
{
/** @var Client */
protected $client;
/** @var ResponseMediator */
private $responseMediator;

public function __construct(Client $client, ResponseMediator $responseMediator = null)
{
$this->client = $client;
$this->responseMediator = $responseMediator ? $responseMediator : new ResponseMediator();
}

/**
* @param string $path
* @param array $parameters
* @param array $headers
* @return array|string
*/
protected function get($path, array $parameters = [], array $headers = [])
{
if (count($parameters) > 0) {
$path .= '?'.http_build_query($parameters);
}
$response = $this->client->getHttpClient()->get($path, $headers);

return $this->responseMediator->getContent($response);
}

/**
* @param string $path
* @param array $parameters
* @param array $headers
* @return array|string
*/
protected function post($path, array $parameters = [], array $headers = [])
{
$response = $this->client->getHttpClient()->post(
$path,
$headers,
$this->createJsonBody($parameters)
);

return $this->responseMediator->getContent($response);
}

/**
* @param string $path
* @param array $parameters
* @param array $headers
* @return array|string
*/
protected function delete($path, array $parameters = [], array $headers = [])
{
$response = $this->client->getHttpClient()->delete(
$path,
$headers,
$this->createJsonBody($parameters)
);

return $this->responseMediator->getContent($response);
}
/**
* @param array $parameters
* @return null|string
*/
protected function createJsonBody(array $parameters)
{
return (count($parameters) === 0) ? null : json_encode($parameters, empty($parameters) ? JSON_FORCE_OBJECT : 0);
}
}
36 changes: 36 additions & 0 deletions src/Api/Customers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace PrivatePackagist\ApiClient\Api;

class Customers extends AbstractApi
{
public function all()
{
return $this->get('/customers/');
}

public function create($name)
{
return $this->postRaw('/customers/', $this->createJsonBody(['name' => $name]));
}

public function remove($customerId)
{
return $this->delete(sprintf('/customers/%s/', $customerId));
}

public function listPackages($customerId)
{
return $this->get(sprintf('/customers/%s/packages/', $customerId));
}

public function addPackages($customerId, array $packages)
{
return $this->postRaw(sprintf('/customers/%s/packages/', $customerId), $this->createJsonBody($packages));
}

public function removePackage($customerId, $packageId)
{
return $this->delete(sprintf('/customers/%s/packages/%s/', $customerId, $packageId));
}
}
11 changes: 11 additions & 0 deletions src/Api/Packages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace PrivatePackagist\ApiClient\Api;

class Packages extends AbstractApi
{
public function all()
{
return $this->get('/packages/');
}
}
58 changes: 58 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace PrivatePackagist\ApiClient;

use Http\Client\Common\Plugin;
use Http\Discovery\UriFactoryDiscovery;
use PrivatePackagist\ApiClient\HttpClient\HttpPluginClientBuilder;
use PrivatePackagist\ApiClient\HttpClient\Plugin\PathPrepend;
use PrivatePackagist\ApiClient\HttpClient\Plugin\RequestSignature;

class Client
{
/** @var HttpPluginClientBuilder */
private $httpClientBuilder;

/** @param string $privatePackagistUrl */
public function __construct(HttpPluginClientBuilder $httpClientBuilder = null, $privatePackagistUrl = null)
{
$this->httpClientBuilder = $builder = $httpClientBuilder ?: new HttpPluginClientBuilder();
$privatePackagistUrl = $privatePackagistUrl ? : 'https://packagist.com';

$builder->addPlugin(new Plugin\AddHostPlugin(UriFactoryDiscovery::find()->createUri($privatePackagistUrl)));
$builder->addPlugin(new PathPrepend('/api'));
$builder->addPlugin(new Plugin\HeaderDefaultsPlugin([
'User-Agent' => 'php-private-packagist-api (http://github.com/packagist/private-packagist-api)', // @todo
]));
}

/**
* @param string $token
* @param string $secret
*/
public function authenticate($token, $secret)
{
$this->httpClientBuilder->removePlugin(RequestSignature::class);
$this->httpClientBuilder->addPlugin(new RequestSignature($token, $secret));
}

public function customers()
{
return new Api\Customers($this);
}

public function packages()
{
return new Api\Packages($this);
}

public function getHttpClient()
{
return $this->getHttpClientBuilder()->getHttpClient();
}

protected function getHttpClientBuilder()
{
return $this->httpClientBuilder;
}
}
61 changes: 61 additions & 0 deletions src/HttpClient/HttpPluginClientBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace PrivatePackagist\ApiClient\HttpClient;

use Http\Client\Common\HttpMethodsClient;
use Http\Client\Common\Plugin;
use Http\Client\Common\PluginClient;
use Http\Client\HttpClient;
use Http\Discovery\HttpClientDiscovery;
use Http\Discovery\MessageFactoryDiscovery;
use Http\Message\MessageFactory;
use Http\Message\RequestFactory;

class HttpPluginClientBuilder
{
/** @var HttpClient */
private $httpClient;
/** @var HttpMethodsClient */
private $pluginClient;
/** @var MessageFactory */
private $requestFactory;
/** @var Plugin[] */
private $plugins = [];

public function __construct(HttpClient $httpClient = null, RequestFactory $requestFactory = null)
{
$this->httpClient = $httpClient ?: HttpClientDiscovery::find();
$this->requestFactory = $requestFactory ?: MessageFactoryDiscovery::find();
}

public function addPlugin(Plugin $plugin)
{
$this->plugins[] = $plugin;
$this->pluginClient = null;
}

/**
* @param string $pluginClass
*/
public function removePlugin($pluginClass)
{
foreach ($this->plugins as $idx => $plugin) {
if ($plugin instanceof $pluginClass) {
unset($this->plugins[$idx]);
$this->pluginClient = null;
}
}
}

public function getHttpClient()
{
if (!$this->pluginClient) {
$this->pluginClient = new HttpMethodsClient(
new PluginClient($this->httpClient, $this->plugins),
$this->requestFactory
);
}

return $this->pluginClient;
}
}
24 changes: 24 additions & 0 deletions src/HttpClient/Message/ResponseMediator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace PrivatePackagist\ApiClient\HttpClient\Message;

use Psr\Http\Message\ResponseInterface;

class ResponseMediator
{
/**
* @return mixed|string
*/
public function getContent(ResponseInterface $response)
{
$body = $response->getBody()->__toString();
if (strpos($response->getHeaderLine('Content-Type'), 'application/json') === 0) {
$content = json_decode($body, true);
if (JSON_ERROR_NONE === json_last_error()) {
return $content;
}
}

return $body;
}
}
34 changes: 34 additions & 0 deletions src/HttpClient/Plugin/PathPrepend.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace PrivatePackagist\ApiClient\HttpClient\Plugin;

use Http\Client\Common\Plugin;
use Psr\Http\Message\RequestInterface;

class PathPrepend implements Plugin
{
/** @var string */
private $path;

/**
* @param string $path
*/
public function __construct($path)
{
$this->path = $path;
}

/**
* {@inheritdoc}
*/
public function handleRequest(RequestInterface $request, callable $next, callable $first)
{
$uri = $request->getUri();

if (strpos($uri->getPath(), $this->path) !== 0) {
$request = $request->withUri($uri->withPath($this->path . $uri->getPath()));
}

return $next($request);
}
}
Loading

0 comments on commit 77947b3

Please sign in to comment.