Skip to content
139 changes: 139 additions & 0 deletions src/Mremi/UrlShortener/Provider/ShortCm/ShortCmProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php

/*
* This file is part of the Mremi\UrlShortener library.
*
* (c) Rémi Marseille <marseille.remi@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Mremi\UrlShortener\Provider\ShortCm;

use GuzzleHttp\Client;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\UrlShortenerProviderInterface;

/**
* Short.cm provider class.
*/
class ShortCmProvider implements UrlShortenerProviderInterface
{
/**
* @var string
*/
private $apiKey;

/**
* @var string
*/
private $domain;

/**
* Constructor.
*
* @param string $apiKey An API key
* @param string $domain Domain name you added to short.cm
*/
public function __construct($apiKey, $domain)
{
$this->apiKey = $apiKey;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove extra whitespace

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still relevant

$this->domain = $domain;
}

/**
* {@inheritdoc}
*/
public function getName()
{
return 'shortcm';
}

/**
* {@inheritdoc}
*/
public function shorten(LinkInterface $link)
{
$client = $this->createClient();

$data = array(
'domain' => $this->domain,
'originalURL' => $link->getLongUrl(),
);

$response = $client->post('/links', array(
'json' => $data,
));

$this->validate($response);

$body = json_decode($response->getBody()->__toString(), true);

$url = !empty($body['secureShortURL'])
? $body['secureShortURL']
: !empty($body['shortURL'])
? $body['shortURL']
: null;

$link->setShortUrl($url);
}

/**
* @todo Implement method expand()
* {@inheritdoc}
*/
public function expand(LinkInterface $link)
{
throw new \Exception('Not implemented');
Comment thread
felixmaier1989 marked this conversation as resolved.
Outdated
}

/**
* Creates a client.
*
* This method is mocked in unit tests in order to not make a real request,
* so visibility must be protected or public.
*
* @return Client
*/
protected function createClient()
{
return new Client(array(
'base_uri' => 'https://api.short.cm',
'headers' => array(
'Authorization' => $this->apiKey,
),
));
}

/**
* Validates the API response.
*
* @param \GuzzleHttp\Psr7\Response $response API response
Comment thread
felixmaier1989 marked this conversation as resolved.
Outdated
*
* @throws InvalidApiResponseException
*/
private function validate($response)
Comment thread
felixmaier1989 marked this conversation as resolved.
Outdated
{
if ($response->getStatusCode() !== 200) {
throw new InvalidApiResponseException('Short.cm API returned unexpected status code '.$response->getStatusCode());
}

$body = $response->getBody()->__toString();

if (empty($body)) {
throw new InvalidApiResponseException('Short.cm API returned an empty body');
}

$body = json_decode($body, true);

if (empty($body)) {
throw new InvalidApiResponseException('Short.cm API response body isnt valid JSON');
}

if (empty($body['secureShortURL']) && empty($body['shortURL'])) {
throw new InvalidApiResponseException('Short.cm API could not generate a short URL');
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php

/*
* This file is part of the Mremi\UrlShortener library.
*
* (c) Rémi Marseille <marseille.remi@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Mremi\UrlShortener\Tests\Provider\ShortCm;

use Mremi\UrlShortener\Provider\ShortCm\ShortCmProvider;

/**
* Tests ShortCmProvider class.
*/
class ShortCmProviderTest extends \PHPUnit_Framework_TestCase
{
public function testShorten()
{
$provider = $this->getMock('\Mremi\UrlShortener\Provider\ShortCm\ShortCmProvider', array('createClient'), array(
Comment thread
felixmaier1989 marked this conversation as resolved.
Outdated
'ABCD1234',
'abc.de',
));
$client = $this->getMock('\GuzzleHttp\Client', array('post'));

$response = new \GuzzleHttp\Psr7\Response(
Comment thread
felixmaier1989 marked this conversation as resolved.
Outdated
200,
array(),
'{"id":12345678,"originalURL":"http://perdu.com?k=12345678901234567890","DomainId":98765,"archived":false,"path":"pgsYuBjuGtzn","redirectType":null,"OwnerId":12345,"updatedAt":"2019-05-10T05:18:24.928Z","createdAt":"2019-05-10T05:18:24.928Z","secureShortURL":"https://abc.de/pgsYuBjuGtzn","shortURL":"https://abc.de/pgsYuBjuGtzn","duplicate":false}'
);

$client
->expects($this->once())
->method('post')
->with(
'/links',
array(
'json' => array(
'domain' => 'abc.de',
'originalURL' => 'http://perdu.com?k=12345678901234567890',
),
)
)
->will($this->returnValue($response));

$provider
->expects($this->once())
->method('createClient')
->will($this->returnValue($client));

$link = new \Mremi\UrlShortener\Model\Link();
Comment thread
felixmaier1989 marked this conversation as resolved.
Outdated
$link->setLongUrl('http://perdu.com?k=12345678901234567890');
$provider->shorten($link);

$this->assertSame('https://abc.de/pgsYuBjuGtzn', $link->getShortUrl());
}

public function testValidate()
{
$response = new \GuzzleHttp\Psr7\Response(
Comment thread
felixmaier1989 marked this conversation as resolved.
Outdated
200,
array(),
'{"id":12345678,"originalURL":"http://perdu.com?k=12345678901234567890","DomainId":98765,"archived":false,"path":"pgsYuBjuGtzn","redirectType":null,"OwnerId":12345,"updatedAt":"2019-05-10T05:18:24.928Z","createdAt":"2019-05-10T05:18:24.928Z","secureShortURL":"https://abc.de/pgsYuBjuGtzn","shortURL":"https://abc.de/pgsYuBjuGtzn","duplicate":false}'
);

$provider = new ShortCmProvider(
'ABCD1234',
'abc.de'
);

$method = new \ReflectionMethod($provider, 'validate');
$method->setAccessible(true);
$method->invoke($provider, $response);
}

public function testValidateIncomplete()
{
$response = new \GuzzleHttp\Psr7\Response(
Comment thread
felixmaier1989 marked this conversation as resolved.
Outdated
200,
array(),
'{"id":12345678,"originalURL":"http://perdu.com?k=12345678901234567890","DomainId":98765,"archived":false,"path":"pgsYuBjuGtzn","redirectType":null,"OwnerId":12345,"updatedAt":"2019-05-10T05:18:24.928Z","createdAt":"2019-05-10T05:18:24.928Z","secureShortURL":"","shortURL":"","duplicate":false}'
);

$provider = new ShortCmProvider(
'ABCD1234',
'abc.de'
);

$this->setExpectedException('\Mremi\UrlShortener\Exception\InvalidApiResponseException');
Comment thread
felixmaier1989 marked this conversation as resolved.
Outdated

$method = new \ReflectionMethod($provider, 'validate');
$method->setAccessible(true);
$method->invoke($provider, $response);
}

public function testValidateError()
{
$response = new \GuzzleHttp\Psr7\Response(

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a use statement

409
);

$provider = new ShortCmProvider(
'ABCD1234',
'abc.de'
);

$this->setExpectedException('\Mremi\UrlShortener\Exception\InvalidApiResponseException');
Comment thread
felixmaier1989 marked this conversation as resolved.
Outdated

$method = new \ReflectionMethod($provider, 'validate');
$method->setAccessible(true);
$method->invoke($provider, $response);
}
}