built a base to work from
parent
4613cb69ea
commit
8d1b25e8ce
@ -1,3 +1,13 @@
|
|||||||
# php-gitlab-api-async
|
# php-gitlab-api-async
|
||||||
|
|
||||||
An asynchronous implementation of the Gitlab API in PHP, using asynchronous requests/promises to do all of it's I/O.
|
An asynchronous implementation of the Gitlab API in PHP, using asynchronous requests/promises to do all of it's I/O.
|
||||||
|
|
||||||
|
- Make pagination not matter
|
||||||
|
- Fix a way to do token auth that doesn't suck
|
||||||
|
|
||||||
|
Use cases:
|
||||||
|
- Check if group exists
|
||||||
|
- Create group
|
||||||
|
- Check if project exists
|
||||||
|
- Create project
|
||||||
|
- Find all projects in group and subgroups
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Gitlab\Api;
|
||||||
|
|
||||||
|
|
||||||
|
use Gitlab\Http\QueryString;
|
||||||
|
use Http\Client\HttpAsyncClient;
|
||||||
|
use Http\Message\MessageFactory;
|
||||||
|
use Http\Promise\Promise;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
abstract class Base
|
||||||
|
{
|
||||||
|
private $client;
|
||||||
|
private $messageFactory;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
HttpAsyncClient $client,
|
||||||
|
MessageFactory $messageFactory
|
||||||
|
)
|
||||||
|
{
|
||||||
|
$this->client = $client;
|
||||||
|
$this->messageFactory = $messageFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getClient() : HttpAsyncClient
|
||||||
|
{
|
||||||
|
return $this->client;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createOptionsResolver() : OptionsResolver
|
||||||
|
{
|
||||||
|
$resolver = new OptionsResolver();
|
||||||
|
|
||||||
|
// Every query can have page and per_page
|
||||||
|
$resolver->setDefined('page')
|
||||||
|
->setAllowedTypes('page', 'int')
|
||||||
|
->setAllowedValues('page', function ($value) {
|
||||||
|
return $value > 0;
|
||||||
|
})
|
||||||
|
->setDefined('per_page')
|
||||||
|
->setAllowedTypes('per_page', 'int')
|
||||||
|
->setAllowedValues('per_page', function ($value) {
|
||||||
|
return $value > 0 && $value <= 100;
|
||||||
|
});
|
||||||
|
|
||||||
|
return $resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getBooleanNormaliser() : callable
|
||||||
|
{
|
||||||
|
return function ($value) {
|
||||||
|
return $value === true ? 'true' : 'false';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function encodeObjectPath(string $path) : string
|
||||||
|
{
|
||||||
|
return str_replace('.', '%2E', rawurlencode($path));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $path
|
||||||
|
* @param array $parameters
|
||||||
|
* @return Promise
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
protected function post(string $path, array $parameters) : Promise
|
||||||
|
{
|
||||||
|
$uri = $path;
|
||||||
|
|
||||||
|
$request = $this->messageFactory->createRequest(
|
||||||
|
'POST',
|
||||||
|
$uri,
|
||||||
|
[],
|
||||||
|
QueryString::build($parameters));
|
||||||
|
|
||||||
|
return $this->getClient()->sendAsyncRequest($request);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Gitlab\Api;
|
||||||
|
|
||||||
|
|
||||||
|
use Gitlab\Api\Plugin\Authentication;
|
||||||
|
use Http\Client\Common\Plugin\AddHostPlugin;
|
||||||
|
use Http\Client\Common\Plugin\AddPathPlugin;
|
||||||
|
use Http\Client\Common\PluginClient;
|
||||||
|
use Http\Client\HttpAsyncClient;
|
||||||
|
use Http\Discovery\UriFactoryDiscovery;
|
||||||
|
use Http\Message\UriFactory;
|
||||||
|
|
||||||
|
class ClientFactory
|
||||||
|
{
|
||||||
|
public static function create(
|
||||||
|
HttpAsyncClient $client,
|
||||||
|
Authentication $authentication,
|
||||||
|
string $host
|
||||||
|
) : PluginClient
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var UriFactory
|
||||||
|
*/
|
||||||
|
$uriFactory = UriFactoryDiscovery::find();
|
||||||
|
|
||||||
|
$plugins = [
|
||||||
|
$authentication,
|
||||||
|
// Prepend api version to path
|
||||||
|
new AddPathPlugin($uriFactory->createUri('/api/v4/')),
|
||||||
|
// Make sure host is set to the right uri
|
||||||
|
new AddHostPlugin($uriFactory->createUri($host), ['replace' => true]),
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
return new PluginClient($client, $plugins);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Gitlab\Api;
|
||||||
|
|
||||||
|
|
||||||
|
use Http\Promise\Promise;
|
||||||
|
|
||||||
|
class Group extends Base
|
||||||
|
{
|
||||||
|
public function projects(string $path, array $parameters) : Promise
|
||||||
|
{
|
||||||
|
$resolver = $this->createOptionsResolver();
|
||||||
|
|
||||||
|
$resolver->setDefined('include_subgroups')
|
||||||
|
->setAllowedTypes('include_subgroups', 'bool')
|
||||||
|
->setNormalizer('include_subgroups', $this->getBooleanNormaliser());
|
||||||
|
|
||||||
|
$queryPath = 'groups/' . $this->encodeObjectPath($path) . '/projects';
|
||||||
|
|
||||||
|
$resolvedParameters = $resolver->resolve($parameters);
|
||||||
|
|
||||||
|
return $this->post($queryPath, $resolvedParameters);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Gitlab\Api\Parameters;
|
||||||
|
|
||||||
|
|
||||||
|
class ListGroupProjects
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $archived;// boolean no Limit by archived status
|
||||||
|
private $visibility;// string no Limit by visibility public, internal, or private
|
||||||
|
private $order_by;// string no Return projects ordered by id, name, path, created_at, updated_at, or last_activity_at fields. Default is created_at
|
||||||
|
private $sort;// string no Return projects sorted in asc or desc order. Default is desc
|
||||||
|
private $search;// string no Return list of authorized projects matching the search criteria
|
||||||
|
private $simple;// boolean no Return only the ID, URL, name, and path of each project
|
||||||
|
private $owned;// boolean no Limit by projects owned by the current user
|
||||||
|
private $starred;// boolean no Limit by projects starred by the current user
|
||||||
|
private $with_issues_enabled;// boolean no Limit by projects with issues feature enabled. Default is false
|
||||||
|
private $with_merge_requests_enabled;// boolean no Limit by projects with merge requests feature enabled. Default is false
|
||||||
|
private $with_shared;// boolean no Include projects shared to this group. Default is true
|
||||||
|
private $include_subgroups;// boolean no Include projects in subgroups of this group. Default is false
|
||||||
|
private $with_custom_attributes;// boolean no Include custom attributes in response (admins only)
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Gitlab\Api\Plugin;
|
||||||
|
|
||||||
|
|
||||||
|
use Http\Client\Common\Plugin;
|
||||||
|
use Http\Promise\Promise;
|
||||||
|
use Psr\Http\Message\RequestInterface;
|
||||||
|
|
||||||
|
class Authentication implements Plugin
|
||||||
|
{
|
||||||
|
public const TOKEN = 'token';
|
||||||
|
public const OAUTH = 'oauth';
|
||||||
|
|
||||||
|
private $method;
|
||||||
|
private $token;
|
||||||
|
private $sudo;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
string $method,
|
||||||
|
string $token,
|
||||||
|
bool $sudo = false
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if ($method !== self::TOKEN && $method !== self::OAUTH) {
|
||||||
|
throw new \InvalidArgumentException('Method must be either TOKEN or OAUTH');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->method = $method;
|
||||||
|
$this->token = $token;
|
||||||
|
$this->sudo = $sudo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the request and return the response coming from the next callable.
|
||||||
|
*
|
||||||
|
* @see http://docs.php-http.org/en/latest/plugins/build-your-own.html
|
||||||
|
*
|
||||||
|
* @param RequestInterface $request
|
||||||
|
* @param callable $next Next middleware in the chain, the request is passed as the first argument
|
||||||
|
* @param callable $first First middleware in the chain, used to to restart a request
|
||||||
|
*
|
||||||
|
* @return Promise Resolves a PSR-7 Response or fails with an Http\Client\Exception (The same as HttpAsyncClient).
|
||||||
|
*/
|
||||||
|
public function handleRequest(RequestInterface $request, callable $next, callable $first)
|
||||||
|
{
|
||||||
|
if ($this->sudo === true) {
|
||||||
|
$request = $request->withAddedHeader('Sudo', 'yes');
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($this->method) {
|
||||||
|
case self::TOKEN:
|
||||||
|
$request = $request->withAddedHeader('Private-Token', $this->token);
|
||||||
|
break;
|
||||||
|
case self::OAUTH:
|
||||||
|
$request = $request->withAddedHeader('Authorization', 'Bearer ' . $this->token);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Gitlab\Api;
|
||||||
|
|
||||||
|
|
||||||
|
class Project extends Base
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Gitlab\Api\Response;
|
||||||
|
|
||||||
|
|
||||||
|
class PaginationPromiseResolve
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Gitlab\Http;
|
||||||
|
|
||||||
|
|
||||||
|
final class QueryString
|
||||||
|
{
|
||||||
|
public static function build($values) : string
|
||||||
|
{
|
||||||
|
return json_encode($values);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue