update 1.0.8.0

Commits for version update
This commit is contained in:
Manish Verma
2016-10-17 12:02:27 +05:30
parent dec927987b
commit 76e85db070
9674 changed files with 495757 additions and 58922 deletions

3
vendor/mremi/url-shortener/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
composer.lock
phpunit.xml
vendor

View File

@@ -0,0 +1,8 @@
language: php
php:
- 5.3
- 5.4
- 5.5
before_script: composer install --dev --prefer-source

21
vendor/mremi/url-shortener/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-2014 Rémi Marseille <marseille.remi@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

148
vendor/mremi/url-shortener/README.md vendored Normal file
View File

@@ -0,0 +1,148 @@
URL shortener library
=====================
This library allows you to shorten a URL, reverse is also possible.
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/c4e06c9d-547c-47bb-8abb-fccc68b7df7a/big.png)](https://insight.sensiolabs.com/projects/c4e06c9d-547c-47bb-8abb-fccc68b7df7a)
[![Build Status](https://api.travis-ci.org/mremi/UrlShortener.png?branch=master)](https://travis-ci.org/mremi/UrlShortener)
[![Total Downloads](https://poser.pugx.org/mremi/url-shortener/downloads.png)](https://packagist.org/packages/mremi/url-shortener)
[![Latest Stable Version](https://poser.pugx.org/mremi/url-shortener/v/stable.png)](https://packagist.org/packages/mremi/url-shortener)
[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/mremi/UrlShortener/badges/quality-score.png?s=34c4ba6b0cd272673fa121c32a63e1ce668b9b2a)](https://scrutinizer-ci.com/g/mremi/UrlShortener/)
[![Code Coverage](https://scrutinizer-ci.com/g/mremi/UrlShortener/badges/coverage.png?s=7a8c3388ae7b50f35fd548b4b7874526c634e8c5)](https://scrutinizer-ci.com/g/mremi/UrlShortener/)
**Basic Docs**
* [Installation](#installation)
* [Bit.ly API](#bitly-api)
* [Google API](#google-api)
* [Chain providers](#chain-providers)
* [Retrieve link](#retrieve-link)
* [Contribution](#contribution)
<a name="installation"></a>
## Installation
Only 1 step:
### Download UrlShortener using composer
Add UrlShortener in your composer.json:
```js
{
"require": {
"mremi/url-shortener": "dev-master"
}
}
```
Now tell composer to download the library by running the command:
``` bash
$ php composer.phar update mremi/url-shortener
```
Composer will install the library to your project's `vendor/mremi` directory.
<a name="bitly-api"></a>
## Bit.ly API
```php
<?php
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Bitly\BitlyProvider;
use Mremi\UrlShortener\Provider\Bitly\OAuthClient;
$link = new Link;
$link->setLongUrl('http://www.google.com');
$bitlyProvider = new BitlyProvider(
new OAuthClient('username', 'password'),
array('connect_timeout' => 1, 'timeout' => 1)
);
$bitlyProvider->shorten($link);
$bitlyProvider->expand($link);
```
<a name="google-api"></a>
## Google API
```php
<?php
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Google\GoogleProvider;
$link = new Link;
$link->setLongUrl('http://www.google.com');
$googleProvider = new GoogleProvider(
'api_key',
array('connect_timeout' => 1, 'timeout' => 1)
);
$googleProvider->shorten($link);
$googleProvider->expand($link);
```
<a name="chain-providers"></a>
## Chain providers
```php
<?php
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\ChainProvider;
$chainProvider = new ChainProvider;
$chainProvider->addProvider($bitlyProvider);
$chainProvider->addProvider($googleProvider);
// add yours...
$link = new Link;
$link->setLongUrl('http://www.google.com');
$chainProvider->getProvider('bitly')->shorten($link);
$chainProvider->getProvider('google')->expand($link);
```
<a name="retrieve-link"></a>
## Retrieve link
You can retrieve some links using these finders:
```php
<?php
use Mremi\UrlShortener\Model\LinkManager;
$linkManager = new LinkManager($chainProvider);
$shortened = $linkManager->findOneByProviderAndShortUrl('bitly', 'http://bit.ly/ze6poY');
$expanded = $linkManager->findOneByProviderAndLongUrl('google', 'http://www.google.com');
```
<a name="contribution"></a>
## Contribution
Any question or feedback? Open an issue and I will try to reply quickly.
A feature is missing here? Feel free to create a pull request to solve it!
I hope this has been useful and has helped you. If so, share it and recommend
it! :)
[@mremitsme](https://twitter.com/mremitsme)

View File

@@ -0,0 +1,21 @@
{
"name": "mremi/url-shortener",
"type": "library",
"description": "A PHP5 library using API to shorten/expand URL",
"keywords": ["url", "shortener", "api"],
"homepage": "https://github.com/mremi/UrlShortener",
"license": "MIT",
"authors": [
{
"name": "Rémi Marseille",
"email": "marseille.remi@gmail.com"
}
],
"require": {
"php": ">=5.3.3",
"guzzle/guzzle": "~3.7"
},
"autoload": {
"psr-0": { "Mremi\\UrlShortener": "src" }
}
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="UrlShortener Test Suite">
<directory>./tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src</directory>
<exclude>
<directory>./tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

View File

@@ -0,0 +1,21 @@
<?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\Exception;
/**
* Invalid API response exception class
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class InvalidApiResponseException extends \RuntimeException
{
}

View File

@@ -0,0 +1,112 @@
<?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\Model;
/**
* Link class
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class Link implements LinkInterface
{
/**
* @var string
*/
protected $providerName;
/**
* @var string
*/
protected $shortUrl;
/**
* @var string
*/
protected $longUrl;
/**
* @var \DateTime
*/
protected $createdAt;
/**
* Constructor
*/
public function __construct()
{
$this->setCreatedAt(new \DateTime);
}
/**
* {@inheritdoc}
*/
public function setCreatedAt(\DateTime $createdAt)
{
$this->createdAt = $createdAt;
}
/**
* {@inheritdoc}
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* {@inheritdoc}
*/
public function setLongUrl($longUrl)
{
$this->longUrl = $longUrl;
}
/**
* {@inheritdoc}
*/
public function getLongUrl()
{
return $this->longUrl;
}
/**
* {@inheritdoc}
*/
public function setProviderName($providerName)
{
$this->providerName = $providerName;
}
/**
* {@inheritdoc}
*/
public function getProviderName()
{
return $this->providerName;
}
/**
* {@inheritdoc}
*/
public function setShortUrl($shortUrl)
{
$this->shortUrl = $shortUrl;
}
/**
* {@inheritdoc}
*/
public function getShortUrl()
{
return $this->shortUrl;
}
}

View File

@@ -0,0 +1,76 @@
<?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\Model;
/**
* Class LinkInterface
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
interface LinkInterface
{
/**
* Sets the created at
*
* @param \DateTime $createdAt
*/
public function setCreatedAt(\DateTime $createdAt);
/**
* Gets the created at
*
* @return \DateTime
*/
public function getCreatedAt();
/**
* Sets the long URL
*
* @param string $longUrl
*/
public function setLongUrl($longUrl);
/**
* Gets the long URL
*
* @return string
*/
public function getLongUrl();
/**
* Sets the provider name
*
* @param string $providerName
*/
public function setProviderName($providerName);
/**
* Gets the provider name
*
* @return string
*/
public function getProviderName();
/**
* Sets the short URL
*
* @param string $shortUrl
*/
public function setShortUrl($shortUrl);
/**
* Gets the short URL
*
* @return string
*/
public function getShortUrl();
}

View File

@@ -0,0 +1,84 @@
<?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\Model;
use Mremi\UrlShortener\Provider\ChainProvider;
/**
* Link manager class
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class LinkManager implements LinkManagerInterface
{
/**
* @var ChainProvider
*/
protected $chainProvider;
/**
* @var string
*/
protected $class;
/**
* Constructor
*
* @param ChainProvider $chainProvider A chain provider instance
* @param string $class The Link class namespace, optional
*/
public function __construct(ChainProvider $chainProvider, $class = 'Mremi\UrlShortener\Model\Link')
{
$this->chainProvider = $chainProvider;
$this->class = $class;
}
/**
* {@inheritdoc}
*/
public function create()
{
return new $this->class;
}
/**
* {@inheritdoc}
*/
public function findOneByProviderAndShortUrl($providerName, $shortUrl)
{
$provider = $this->chainProvider->getProvider($providerName);
$link = $this->create();
$link->setProviderName($provider->getName());
$link->setShortUrl($shortUrl);
$provider->expand($link);
return $link;
}
/**
* {@inheritdoc}
*/
public function findOneByProviderAndLongUrl($providerName, $longUrl)
{
$provider = $this->chainProvider->getProvider($providerName);
$link = $this->create();
$link->setProviderName($provider->getName());
$link->setLongUrl($longUrl);
$provider->shorten($link);
return $link;
}
}

View File

@@ -0,0 +1,51 @@
<?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\Model;
/**
* Link manager interface
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
interface LinkManagerInterface
{
/**
* Creates and returns a new link instance
*
* @return LinkInterface
*/
public function create();
/**
* Finds one link by a provider and a short URL
*
* @param string $providerName A provider name
* @param string $shortUrl A short URL
*
* @return LinkInterface
*
* @throws \Mremi\UrlShortener\Exception\InvalidApiResponseException
*/
public function findOneByProviderAndShortUrl($providerName, $shortUrl);
/**
* Finds one link by a provider and a long URL
*
* @param string $providerName A provider name
* @param string $longUrl A long URL
*
* @return LinkInterface
*
* @throws \Mremi\UrlShortener\Exception\InvalidApiResponseException
*/
public function findOneByProviderAndLongUrl($providerName, $longUrl);
}

View File

@@ -0,0 +1,27 @@
<?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\Bitly;
/**
* Authentication interface
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
interface AuthenticationInterface
{
/**
* Calls Bit.ly API to get an access token
*
* @return string
*/
public function getAccessToken();
}

View File

@@ -0,0 +1,146 @@
<?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\Bitly;
use Guzzle\Http\Client;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\UrlShortenerProviderInterface;
/**
* Bit.ly provider class
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class BitlyProvider implements UrlShortenerProviderInterface
{
/**
* @var AuthenticationInterface
*/
private $auth;
/**
* @var array
*/
private $options;
/**
* Constructor
*
* @param AuthenticationInterface $auth An authentication instance
* @param array $options An array of options used to do the shorten/expand request
*/
public function __construct(AuthenticationInterface $auth, array $options = array())
{
$this->auth = $auth;
$this->options = $options;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'bitly';
}
/**
* {@inheritdoc}
*
* @param LinkInterface $link A link instance
* @param string $domain The domain to use, optional (bit.ly | j.mp | bitly.com)
*
* @throws InvalidApiResponseException
*/
public function shorten(LinkInterface $link, $domain = null)
{
$client = $this->createClient();
$request = $client->get(sprintf('/v3/shorten?access_token=%s&longUrl=%s&domain=%s',
$this->auth->getAccessToken(),
urlencode($link->getLongUrl()),
$domain
), array(), $this->options);
$response = $this->validate($request->send()->getBody(true));
$link->setShortUrl($response->data->url);
}
/**
* {@inheritdoc}
*
* @param LinkInterface $link A link instance
* @param string $hash A Bit.ly hash
*
* @throws InvalidApiResponseException
*/
public function expand(LinkInterface $link, $hash = null)
{
$client = $this->createClient();
$request = $client->get(sprintf('/v3/expand?access_token=%s&shortUrl=%s&hash=%s',
$this->auth->getAccessToken(),
urlencode($link->getShortUrl()),
$hash
), array(), $this->options);
$response = $this->validate($request->send()->getBody(true));
$link->setLongUrl($response->data->expand[0]->long_url);
}
/**
* 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('https://api-ssl.bitly.com');
}
/**
* Validates the Bit.ly's response and returns it whether the status code is 200
*
* @param string $apiRawResponse
*
* @return object
*
* @throws InvalidApiResponseException
*/
private function validate($apiRawResponse)
{
$response = json_decode($apiRawResponse);
if (null === $response) {
throw new InvalidApiResponseException('Bit.ly response is probably mal-formed because cannot be json-decoded.');
}
if (!property_exists($response, 'status_code')) {
throw new InvalidApiResponseException('Property "status_code" does not exist within Bit.ly response.');
}
if (200 !== $response->status_code) {
throw new InvalidApiResponseException(sprintf('Bit.ly returned status code "%s" with message "%s"',
$response->status_code,
property_exists($response, 'status_txt') ? $response->status_txt : ''
));
}
return $response;
}
}

View File

@@ -0,0 +1,61 @@
<?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\Bitly;
use Guzzle\Http\Client;
/**
* OAuth client class
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class OAuthClient implements AuthenticationInterface
{
/**
* @var string
*/
private $username;
/**
* @var string
*/
private $password;
/**
* Constructor
*
* @param string $username A valid Bit.ly username
* @param string $password A valid Bit.ly password
*/
public function __construct($username, $password)
{
$this->username = $username;
$this->password = $password;
}
/**
* {@inheritdoc}
*/
public function getAccessToken()
{
$client = new Client('https://api-ssl.bitly.com/oauth/access_token');
$request = $client->post(null, null, null, array(
'auth' => array(
$this->username,
$this->password,
),
));
return $request->send()->getBody(true);
}
}

View File

@@ -0,0 +1,75 @@
<?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;
/**
* Chain provider class
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class ChainProvider
{
/**
* @var array
*/
private $providers = array();
/**
* Adds the given provider to the chain
*
* @param UrlShortenerProviderInterface $provider A provider instance
*/
public function addProvider(UrlShortenerProviderInterface $provider)
{
$this->providers[$provider->getName()] = $provider;
}
/**
* Gets a provider by name
*
* @param string $name A provider name
*
* @return UrlShortenerProviderInterface
*
* @throws \RuntimeException If the provider does not exist
*/
public function getProvider($name)
{
if (!$this->hasProvider($name)) {
throw new \RuntimeException(sprintf('Unable to retrieve the provider named: "%s"', $name));
}
return $this->providers[$name];
}
/**
* Gets the chain providers
*
* @return UrlShortenerProviderInterface[]
*/
public function getProviders()
{
return $this->providers;
}
/**
* Returns TRUE whether the given name identifies a configured provider
*
* @param string $name A provider name
*
* @return boolean
*/
public function hasProvider($name)
{
return array_key_exists($name, $this->providers);
}
}

View File

@@ -0,0 +1,171 @@
<?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\Google;
use Guzzle\Http\Client;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\UrlShortenerProviderInterface;
/**
* Google provider class
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class GoogleProvider implements UrlShortenerProviderInterface
{
/**
* @var string
*/
private $apiKey;
/**
* @var array
*/
private $options;
/**
* Constructor
*
* @param string $apiKey A Google API key, optional
* @param array $options An array of options used to do the shorten/expand request
*/
public function __construct($apiKey = null, array $options = array())
{
$this->apiKey = $apiKey;
$this->options = $options;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'google';
}
/**
* {@inheritdoc}
*/
public function shorten(LinkInterface $link)
{
$client = $this->createClient();
$request = $client->post($this->getUri(), array(
'Content-Type' => 'application/json'
), json_encode(array(
'longUrl' => $link->getLongUrl(),
)), $this->options);
$response = $this->validate($request->send()->getBody(true));
return $response->id;
$link->setShortUrl($response->id);
}
/**
* {@inheritdoc}
*/
public function expand(LinkInterface $link)
{
$client = $this->createClient();
$request = $client->get($this->getUri(array(
'shortUrl' => $link->getShortUrl(),
)), array(), $this->options);
$response = $this->validate($request->send()->getBody(true), true);
$link->setLongUrl($response->longUrl);
}
/**
* 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('https://www.googleapis.com/urlshortener/v1/url');
}
/**
* Gets the URI
*
* @param array $parameters An array of parameters, optional
*
* @return null|string
*/
private function getUri(array $parameters = array())
{
if ($this->apiKey) {
$parameters = array_merge($parameters, array('key' => $this->apiKey));
}
if (0 === count($parameters)) {
return null;
}
return sprintf('?%s', http_build_query($parameters));
}
/**
* Validates the Google's response and returns it whether the status code is 200
*
* @param string $apiRawResponse An API response, as it returned
* @param boolean $checkStatus TRUE whether the status code has to be checked, default FALSE
*
* @return object
*
* @throws InvalidApiResponseException
*/
private function validate($apiRawResponse, $checkStatus = false)
{
$response = json_decode($apiRawResponse);
if (null === $response) {
throw new InvalidApiResponseException('Google response is probably mal-formed because cannot be json-decoded.');
}
if (property_exists($response, 'error')) {
throw new InvalidApiResponseException(sprintf('Google returned status code "%s" with message "%s".',
property_exists($response->error, 'code') ? $response->error->code : '',
property_exists($response->error, 'message') ? $response->error->message : ''
));
}
if (!property_exists($response, 'id')) {
throw new InvalidApiResponseException('Property "id" does not exist within Google response.');
}
if (!property_exists($response, 'longUrl')) {
throw new InvalidApiResponseException('Property "longUrl" does not exist within Google response.');
}
if (!$checkStatus) {
return $response;
}
if (!property_exists($response, 'status')) {
throw new InvalidApiResponseException('Property "status" does not exist within Google response.');
}
if ('OK' !== $response->status) {
throw new InvalidApiResponseException(sprintf('Google returned status code "%s".', $response->status));
}
return $response;
}
}

View File

@@ -0,0 +1,47 @@
<?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;
use Mremi\UrlShortener\Model\LinkInterface;
/**
* Url shortener provider interface
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
interface UrlShortenerProviderInterface
{
/**
* Gets the provider name
*
* @return string
*/
public function getName();
/**
* Shortens the long given URL
*
* @param LinkInterface $link A link instance
*
* @throws \Mremi\UrlShortener\Exception\InvalidApiResponseException
*/
public function shorten(LinkInterface $link);
/**
* Expands the short given URL
*
* @param LinkInterface $link A link instance
*
* @throws \Mremi\UrlShortener\Exception\InvalidApiResponseException
*/
public function expand(LinkInterface $link);
}

View File

@@ -0,0 +1,100 @@
<?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\Model;
use Mremi\UrlShortener\Model\LinkManager;
/**
* Tests Link manager class
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class LinkManagerTest extends \PHPUnit_Framework_TestCase
{
/**
* @var LinkManager
*/
private $manager;
/**
* @var object
*/
private $chainProvider;
/**
* Tests the findOneByProviderAndShortUrl method
*/
public function testFindOneByProviderAndShortUrl()
{
$provider = $this->getMock('Mremi\UrlShortener\Provider\UrlShortenerProviderInterface');
$provider
->expects($this->once())
->method('getName')
->will($this->returnValue('bitly'));
$provider
->expects($this->once())
->method('expand');
$this->chainProvider
->expects($this->once())
->method('getProvider')
->with($this->equalTo('bitly'))
->will($this->returnValue($provider));
$link = $this->manager->findOneByProviderAndShortUrl('bitly', 'http://bit.ly/ZGUlzK');
$this->assertInstanceOf('Mremi\UrlShortener\Model\Link', $link);
$this->assertEquals('http://bit.ly/ZGUlzK', $link->getShortUrl());
}
/**
* Tests the findOneByProviderAndLongUrl method
*/
public function testFindOneByProviderAndLongUrl()
{
$provider = $this->getMock('Mremi\UrlShortener\Provider\UrlShortenerProviderInterface');
$provider
->expects($this->once())
->method('getName')
->will($this->returnValue('google'));
$provider
->expects($this->once())
->method('shorten');
$this->chainProvider
->expects($this->once())
->method('getProvider')
->with($this->equalTo('google'))
->will($this->returnValue($provider));
$link = $this->manager->findOneByProviderAndLongUrl('google', 'http://www.google.com/');
$this->assertInstanceOf('Mremi\UrlShortener\Model\Link', $link);
$this->assertEquals('http://www.google.com/', $link->getLongUrl());
}
/**
* Initializes chainProvider & manager properties
*/
protected function setUp()
{
$this->chainProvider = $this->getMockBuilder('Mremi\UrlShortener\Provider\ChainProvider')
->disableOriginalConstructor()
->getMock();
$this->manager = new LinkManager($this->chainProvider, 'Mremi\UrlShortener\Model\Link');
}
}

View File

@@ -0,0 +1,32 @@
<?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\Model;
use Mremi\UrlShortener\Model\Link;
/**
* Tests Link class
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class LinkTest extends \PHPUnit_Framework_TestCase
{
/**
* Tests the createdAt property
*/
public function testCreatedAt()
{
$link = new Link;
$this->assertInstanceOf('\DateTime', $link->getCreatedAt());
}
}

View File

@@ -0,0 +1,361 @@
<?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\Bitly;
use Mremi\UrlShortener\Provider\Bitly\BitlyProvider;
/**
* Tests BitlyProvider class
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class BitlyProviderTest extends \PHPUnit_Framework_TestCase
{
/**
* @var object
*/
private $provider;
/**
* Tests the shorten method throws exception if Bit.ly returns a string
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Bit.ly response is probably mal-formed because cannot be json-decoded.
*/
public function testShortenThrowsExceptionIfApiResponseIsString()
{
$this->mockClient($this->getMockResponseAsString());
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method throws exception if Bit.ly returns a response with no status_code
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Property "status_code" does not exist within Bit.ly response.
*/
public function testShortenThrowsExceptionIfApiResponseHasNoStatusCode()
{
$this->mockClient($this->getMockResponseAsInvalidObject());
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method throws exception if Bit.ly returns an invalid status code
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Bit.ly returned status code "500" with message "KO"
*/
public function testShortenThrowsExceptionIfApiResponseHasInvalidStatusCode()
{
$this->mockClient($this->getMockResponseWithInvalidStatusCode());
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method with a valid Bit.ly's response
*/
public function testShortenWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
{
"data": {
"global_hash": "900913",
"hash": "ze6poY",
"long_url": "http://www.google.com/",
"new_hash": 0,
"url": "http://bit.ly/ze6poY"
},
"status_code": 200,
"status_txt": "OK"
}
JSON;
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
$link = $this->getMockLongLink();
$link
->expects($this->once())
->method('setShortUrl')
->with($this->equalTo('http://bit.ly/ze6poY'));
$this->mockClient($response);
$this->provider->shorten($link);
}
/**
* Tests the expand method throws exception if Bit.ly returns a string
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Bit.ly response is probably mal-formed because cannot be json-decoded.
*/
public function testExpandThrowsExceptionIfApiResponseIsString()
{
$this->mockClient($this->getMockResponseAsString());
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Bit.ly returns a response with no status_code
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Property "status_code" does not exist within Bit.ly response.
*/
public function testExpandThrowsExceptionIfApiResponseHasNoStatusCode()
{
$this->mockClient($this->getMockResponseAsInvalidObject());
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Bit.ly returns an invalid status code
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Bit.ly returned status code "500" with message "KO"
*/
public function testExpandThrowsExceptionIfApiResponseHasInvalidStatusCode()
{
$this->mockClient($this->getMockResponseWithInvalidStatusCode());
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method with a valid Bit.ly's response
*/
public function testExpandWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
{
"data": {
"expand": [
{
"global_hash": "900913",
"long_url": "http://www.google.com/",
"short_url": "http://bit.ly/ze6poY",
"user_hash": "ze6poY"
}
]
},
"status_code": 200,
"status_txt": "OK"
}
JSON;
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
$link = $this->getMockShortLink();
$link
->expects($this->once())
->method('setLongUrl')
->with($this->equalTo('http://www.google.com/'));
$this->mockClient($response);
$this->provider->expand($link);
}
/**
* Initializes the provider
*/
protected function setUp()
{
$auth = $this->getMock('Mremi\UrlShortener\Provider\Bitly\AuthenticationInterface');
$this->provider = $this->getMockBuilder('Mremi\UrlShortener\Provider\Bitly\BitlyProvider')
->setConstructorArgs(array($auth))
->setMethods(array('createClient'))
->getMock();
}
/**
* Cleanups the provider
*/
protected function tearDown()
{
unset($this->provider);
}
/**
* Gets mock of response
*
* @return object
*/
private function getBaseMockResponse()
{
return $this->getMockBuilder('Guzzle\Http\Message\Response')
->disableOriginalConstructor()
->getMock();
}
/**
* Returns an invalid response string
*
* @return object
*/
private function getMockResponseAsString()
{
$response = $this->getBaseMockResponse();
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue('foo'));
return $response;
}
/**
* Returns an invalid response object
*
* @return object
*/
private function getMockResponseAsInvalidObject()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
{
"data": {
"global_hash": "900913",
"hash": "ze6poY",
"long_url": "http://www.google.com/",
"new_hash": 0,
"url": "http://bit.ly/ze6poY"
}
}
JSON;
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
return $response;
}
/**
* Returns a response with an invalid status code
*
* @return object
*/
private function getMockResponseWithInvalidStatusCode()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
{
"data": {
"global_hash": "900913",
"hash": "ze6poY",
"long_url": "http://www.google.com/",
"new_hash": 0,
"url": "http://bit.ly/ze6poY"
},
"status_code": 500,
"status_txt": "KO"
}
JSON;
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
return $response;
}
/**
* Mocks the client
*
* @param object $response
*/
private function mockClient($response)
{
$request = $this->getMock('Guzzle\Http\Message\RequestInterface');
$request
->expects($this->once())
->method('send')
->will($this->returnValue($response));
$client = $this->getMock('Guzzle\Http\ClientInterface');
$client
->expects($this->once())
->method('get')
->will($this->returnValue($request));
$this->provider
->expects($this->once())
->method('createClient')
->will($this->returnValue($client));
}
/**
* Gets mock of link
*
* @return object
*/
private function getBaseMockLink()
{
return $this->getMock('Mremi\UrlShortener\Model\LinkInterface');
}
/**
* Gets mock of short link
*
* @return object
*/
private function getMockShortLink()
{
$link = $this->getBaseMockLink();
$link
->expects($this->once())
->method('getShortUrl')
->will($this->returnValue('http://bit.ly/ze6poY'));
return $link;
}
/**
* Gets mock of long link
*
* @return object
*/
private function getMockLongLink()
{
$link = $this->getBaseMockLink();
$link
->expects($this->once())
->method('getLongUrl')
->will($this->returnValue('http://www.google.com/'));
return $link;
}
}

View File

@@ -0,0 +1,74 @@
<?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;
use Mremi\UrlShortener\Provider\ChainProvider;
/**
* Tests ChainProvider class
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class ChainProviderTest extends \PHPUnit_Framework_TestCase
{
/**
* Tests that an unknown provider throws an exception
*
* @expectedException \RuntimeException
* @expectedExceptionMessage Unable to retrieve the provider named: "foo"
*/
public function testUnknownProvider()
{
$chainProvider = new ChainProvider;
$chainProvider->getProvider('foo');
}
/**
* Tests to add and get some providers
*/
public function testAddAndGetProviders()
{
$chainProvider = new ChainProvider;
$bitlyProvider = $this->getMockBuilder('Mremi\UrlShortener\Provider\Bitly\BitlyProvider')
->disableOriginalConstructor()
->getMock();
$bitlyProvider
->expects($this->once())
->method('getName')
->will($this->returnValue('bitly'));
$chainProvider->addProvider($bitlyProvider);
$this->assertEquals($bitlyProvider, $chainProvider->getProvider('bitly'));
$this->assertArrayHasKey('bitly', $chainProvider->getProviders());
$this->assertTrue($chainProvider->hasProvider('bitly'));
$this->assertCount(1, $chainProvider->getProviders());
$googleProvider = $this->getMockBuilder('Mremi\UrlShortener\Provider\Google\GoogleProvider')
->disableOriginalConstructor()
->getMock();
$googleProvider
->expects($this->once())
->method('getName')
->will($this->returnValue('google'));
$chainProvider->addProvider($googleProvider);
$this->assertEquals($googleProvider, $chainProvider->getProvider('google'));
$this->assertArrayHasKey('google', $chainProvider->getProviders());
$this->assertTrue($chainProvider->hasProvider('google'));
$this->assertCount(2, $chainProvider->getProviders());
}
}

View File

@@ -0,0 +1,507 @@
<?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\Google;
use Mremi\UrlShortener\Provider\Google\GoogleProvider;
/**
* Tests GoogleProvider class
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class GoogleProviderTest extends \PHPUnit_Framework_TestCase
{
/**
* @var object
*/
private $provider;
/**
* Tests the getUri method with no API key and no parameters
*/
public function testGetUriWithNoApiKeyAndNoParameters()
{
$method = new \ReflectionMethod($this->provider, 'getUri');
$method->setAccessible(true);
$uri = $method->invoke($this->provider);
$this->assertNull($uri);
}
/**
* Tests the getUri method with no API key and some parameters
*/
public function testGetUriWithNoApiKeyAndSomeParameters()
{
$method = new \ReflectionMethod($this->provider, 'getUri');
$method->setAccessible(true);
$uri = $method->invoke($this->provider, array('foo' => 'bar'));
$this->assertEquals('?foo=bar', $uri);
}
/**
* Tests the getUri method with API key and no parameters
*/
public function testGetUriWithApiKeyAndNoParameters()
{
$provider = new GoogleProvider('secret');
$method = new \ReflectionMethod($provider, 'getUri');
$method->setAccessible(true);
$uri = $method->invoke($provider);
$this->assertEquals('?key=secret', $uri);
}
/**
* Tests the getUri method with API key and some parameters
*/
public function testGetUriWithApiKeyAndSomeParameters()
{
$provider = new GoogleProvider('secret');
$method = new \ReflectionMethod($provider, 'getUri');
$method->setAccessible(true);
$uri = $method->invoke($provider, array('foo' => 'bar'));
$this->assertEquals('?foo=bar&key=secret', $uri);
}
/**
* Tests the shorten method throws exception if Google returns a string
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Google response is probably mal-formed because cannot be json-decoded.
*/
public function testShortenThrowsExceptionIfResponseApiIsString()
{
$this->mockClient($this->getMockResponseAsString(), 'post');
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method throws exception if Google returns an error response
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Google returned status code "400" with message "Required"
*/
public function testShortenThrowsExceptionIfApiResponseIsError()
{
$this->mockClient($this->getMockResponseWithError(), 'post');
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method throws exception if Google returns a response with no id
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Property "id" does not exist within Google response.
*/
public function testShortenThrowsExceptionIfApiResponseHasNoId()
{
$this->mockClient($this->getMockResponseWithNoId(), 'post');
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method throws exception if Google returns a response with no longUrl
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Property "longUrl" does not exist within Google response.
*/
public function testShortenThrowsExceptionIfApiResponseHasNoLongUrl()
{
$this->mockClient($this->getMockResponseWithNoLongUrl(), 'post');
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method with a valid Google's response
*/
public function testShortenWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS",
"longUrl": "http://www.google.com/"
}
JSON;
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
$link = $this->getMockLongLink();
$link
->expects($this->once())
->method('setShortUrl')
->with($this->equalTo('http://goo.gl/fbsS'));
$this->mockClient($response, 'post');
$this->provider->shorten($link);
}
/**
* Tests the expand method throws exception if Google returns a string
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Google response is probably mal-formed because cannot be json-decoded.
*/
public function testExpandThrowsExceptionIfResponseApiIsString()
{
$this->mockClient($this->getMockResponseAsString(), 'get');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Google returns an error response
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Google returned status code "400" with message "Required"
*/
public function testExpandThrowsExceptionIfApiResponseIsError()
{
$this->mockClient($this->getMockResponseWithError(), 'get');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Google returns a response with no id
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Property "id" does not exist within Google response.
*/
public function testExpandThrowsExceptionIfApiResponseHasNoId()
{
$this->mockClient($this->getMockResponseWithNoId(), 'get');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Google returns a response with no longUrl
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Property "longUrl" does not exist within Google response.
*/
public function testExpandThrowsExceptionIfApiResponseHasNoLongUrl()
{
$this->mockClient($this->getMockResponseWithNoLongUrl(), 'get');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Google returns a response with no status
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Property "status" does not exist within Google response.
*/
public function testExpandThrowsExceptionIfApiResponseHasNoStatus()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS",
"longUrl": "http://www.google.com/"
}
JSON;
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
$this->mockClient($response, 'get');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Google returns an invalid status code
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Google returned status code "KO".
*/
public function testExpandThrowsExceptionIfApiResponseHasInvalidStatusCode()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS",
"longUrl": "http://www.google.com/",
"status": "KO"
}
JSON;
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
$this->mockClient($response, 'get');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method with a valid Google's response
*/
public function testExpandWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS",
"longUrl": "http://www.google.com/",
"status": "OK"
}
JSON;
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
$link = $this->getMockShortLink();
$link
->expects($this->once())
->method('setLongUrl')
->with($this->equalTo('http://www.google.com/'));
$this->mockClient($response, 'get');
$this->provider->expand($link);
}
/**
* Initializes the provider
*/
protected function setUp()
{
$this->provider = $this->getMockBuilder('Mremi\UrlShortener\Provider\Google\GoogleProvider')
->setMethods(array('createClient'))
->getMock();
}
/**
* Cleanups the provider
*/
protected function tearDown()
{
unset($this->provider);
}
/**
* Gets a mocked response
*
* @return object
*/
private function getBaseMockResponse()
{
return $this->getMockBuilder('Guzzle\Http\Message\Response')
->disableOriginalConstructor()
->getMock();
}
/**
* Returns an invalid response string
*
* @return object
*/
private function getMockResponseAsString()
{
$response = $this->getBaseMockResponse();
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue('foo'));
return $response;
}
/**
* Returns a response object with "error" node
*
* @return object
*/
private function getMockResponseWithError()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Required",
"locationType": "parameter",
"location": "resource.longUrl"
}
],
"code": 400,
"message": "Required"
}
}
JSON;
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
return $response;
}
/**
* Returns a response object with no "id" node
*
* @return object
*/
private function getMockResponseWithNoId()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
{
"kind": "urlshortener#url",
"longUrl": "http://www.google.com/"
}
JSON;
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
return $response;
}
/**
* Returns a response object with no "longUrl" node
*
* @return object
*/
private function getMockResponseWithNoLongUrl()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS"
}
JSON;
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
return $response;
}
/**
* Mocks the client
*
* @param object $response A mocked response
* @param string $requestMethod A request method (get|post)
*/
private function mockClient($response, $requestMethod)
{
$request = $this->getMock('Guzzle\Http\Message\RequestInterface');
$request
->expects($this->once())
->method('send')
->will($this->returnValue($response));
$client = $this->getMock('Guzzle\Http\ClientInterface');
$client
->expects($this->once())
->method($requestMethod)
->will($this->returnValue($request));
$this->provider
->expects($this->once())
->method('createClient')
->will($this->returnValue($client));
}
/**
* Gets mock of link
*
* @return object
*/
private function getBaseMockLink()
{
return $this->getMock('Mremi\UrlShortener\Model\LinkInterface');
}
/**
* Gets mock of short link
*
* @return object
*/
private function getMockShortLink()
{
$link = $this->getBaseMockLink();
$link
->expects($this->once())
->method('getShortUrl')
->will($this->returnValue('http://goo.gl/fbsS'));
return $link;
}
/**
* Gets mock of long link
*
* @return object
*/
private function getMockLongLink()
{
$link = $this->getBaseMockLink();
$link
->expects($this->once())
->method('getLongUrl')
->will($this->returnValue('http://www.google.com/'));
return $link;
}
}