dependencies-upgrade

This commit is contained in:
RafficMohammed
2023-01-08 02:20:59 +05:30
parent 7870479b18
commit 49021a4497
1711 changed files with 74994 additions and 70803 deletions

View File

@@ -1,3 +1,6 @@
.php_cs
.php_cs.cache
.phpunit.result.cache
composer.lock
phpunit.xml
vendor

View File

@@ -0,0 +1,36 @@
<?php
$header = <<<EOF
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.
EOF;
$finder = PhpCsFixer\Finder::create()
->in(__DIR__);
$config = (new PhpCsFixer\Config())
->setRiskyAllowed(true)
->setRules([
'@Symfony' => true,
'binary_operator_spaces' => [
'operators' => [
'=>' => 'align_single_space_minimal',
'=' => 'align_single_space',
],
],
'header_comment' => [
'header' => $header,
],
'linebreak_after_opening_tag' => true,
'php_unit_construct' => true,
'php_unit_strict' => true,
'single_line_throw' => false,
])
->setUsingCache(true)
->setFinder($finder);
return $config;

View File

@@ -1,8 +1,30 @@
os: linux
dist: bionic
language: php
php:
- 5.3
- 5.4
- 5.5
jobs:
include:
- php: 5.6
dist: xenial
- php: 7.0
dist: xenial
- php: 7.1
- php: 7.2
- php: 7.3
- php: 7.4
- php: 8.0
- php: nightly
allow_failures:
- php: nightly
before_script: composer install --dev --prefer-source
cache:
directories:
- $HOME/.composer/cache/files
before_install:
- composer self-update
install: composer install --dev --prefer-dist --no-interaction
script:
- make ci

39
vendor/mremi/url-shortener/CHANGELOG.md vendored Normal file
View File

@@ -0,0 +1,39 @@
# Changelog
## master
* todo...
## 2.4.0 (2021-09-06)
* Add support for PHP 8+
* Add support for Guzzle 7+
* Add support for Symfony 6+
* Modernize tests
## 2.3.0 (2020-03-23)
* Bump minimum required PHP version to 5.6
* Add support for PHP 7.2+
* Drop support for HHVM (composer/composer#8127)
* Update [Bitly API](https://bitly.is/v4ing) version to 4
* Update [phpunit/phpunit](https://packagist.org/packages/phpunit/phpunit) version to ^5.7
* Update [symfony/phpunit-bridge](https://packagist.org/packages/symfony/phpunit-bridge) version to ^5.0
* Replace [fabpot/php-cs-fixer](https://packagist.org/packages/fabpot/php-cs-fixer) with [friendsofphp/php-cs-fixer v2.16](https://packagist.org/packages/friendsofphp/php-cs-fixer) version ^2.16
## 2.2.1 (2018-10-09)
* Update [symfony/console](https://github.com/symfony/console) version to ^4.1 (See [#14](https://github.com/mremi/UrlShortener/issues/14))
## 2.2.0 (2018-09-24)
* Added providers for baidu, sina and wechat
## 2.1.0 (2017-03-29)
* Bumped minimum required Symfony Console version to ^2.7 and allowed Symfony ^3.1
## 2.0.0 (2017-01-27)
* Bumped minimum required PHP version to 5.5
* Replaced deprecated `guzzle/guzzle` with `guzzlehttp/guzzle`

35
vendor/mremi/url-shortener/Makefile vendored Normal file
View File

@@ -0,0 +1,35 @@
.PHONY: ci cs-dry-run cs-fix help install test update
default: help
help:
@echo "usage: make COMMAND"
@echo ""
@echo "Available commands:"
@echo " ci to run both tests suite and check style"
@echo " cs-dry-run to show files that need to be fixed"
@echo " cs-fix to fix files that need to be fixed"
@echo " help to display this help"
@echo " install to install the project dependencies"
@echo " test to run the tests suite"
@echo " update to update the project dependencies"
ci: test cs-dry-run
cs-dry-run:
@if [ ! -f vendor/bin/php-cs-fixer ]; then make install; fi
vendor/bin/php-cs-fixer fix --dry-run --diff --verbose
cs-fix:
@if [ ! -f vendor/bin/php-cs-fixer ]; then make install; fi
vendor/bin/php-cs-fixer fix --verbose
install:
composer install
test:
@if [ ! -f vendor/bin/simple-phpunit ]; then make install; fi
SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 vendor/bin/simple-phpunit
update:
composer update

View File

@@ -5,7 +5,7 @@ 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)
[![Build Status](https://api.travis-ci.com/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/)
@@ -14,8 +14,11 @@ This library allows you to shorten a URL, reverse is also possible.
**Basic Docs**
* [Installation](#installation)
* [Baidu API](#baidu-api)
* [Bit.ly API](#bitly-api)
* [Google API](#google-api)
* [Sina API](#sina-api)
* [Wechat API](#wechat-api)
* [Chain providers](#chain-providers)
* [Retrieve link](#retrieve-link)
* [Contribution](#contribution)
@@ -24,31 +27,89 @@ This library allows you to shorten a URL, reverse is also possible.
## Installation
Only 1 step:
The preferred method of installation is via [Composer](https://getcomposer.org/). Run the following
command to install the package and add it as a requirement to your project's
`composer.json`:
### Download UrlShortener using composer
Add UrlShortener in your composer.json:
```js
{
"require": {
"mremi/url-shortener": "dev-master"
}
}
```bash
composer require mremi/url-shortener
```
Now tell composer to download the library by running the command:
<a name="baidu-api"></a>
``` bash
$ php composer.phar update mremi/url-shortener
## Baidu API
### Shorten
```php
<?php
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Baidu\BaiduProvider;
$link = new Link;
$link->setLongUrl('http://www.google.com');
$baiduProvider = new BaiduProvider(
['connect_timeout' => 1, 'timeout' => 1]
);
$baiduProvider->shorten($link);
```
Composer will install the library to your project's `vendor/mremi` directory.
You can also use the commands provided by this library, look at the help message:
```bash
$ bin/shortener baidu:shorten --help
```
```bash
$ bin/shortener baidu:shorten http://www.google.com
```
Some options are available:
```bash
$ bin/shortener baidu:shorten http://www.google.com --options='{"connect_timeout":1,"timeout":1}'
```
### Expand
```php
<?php
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Baidu\BaiduProvider;
$link = new Link;
$link->setShortUrl('http://dwz.cn/dDlVEAt5');
$googleProvider = new BaiduProvider(
['connect_timeout' => 1, 'timeout' => 1]
);
$googleProvider->expand($link);
```
```bash
$ bin/shortener baidu:expand --help
```
```bash
$ bin/shortener baidu:expand http://dwz.cn/dDlVEAt5
```
Some options are available:
```bash
$ bin/shortener baidu:expand http://dwz.cn/dDlVEAt5 --options='{"connect_timeout":1,"timeout":1}'
```
<a name="bitly-api"></a>
## Bit.ly API
## Bit.ly API V4
### Shorten
```php
<?php
@@ -61,19 +122,73 @@ $link = new Link;
$link->setLongUrl('http://www.google.com');
$bitlyProvider = new BitlyProvider(
new OAuthClient('username', 'password'),
array('connect_timeout' => 1, 'timeout' => 1)
new GenericAccessTokenAuthenticator('generic_access_token'), // or old OAuthClient('username', 'password')
['connect_timeout' => 1, 'timeout' => 1]
);
$bitlyProvider->shorten($link);
```
You can also use the commands provided by this library, look at the help message:
```bash
$ bin/shortener bitly:shorten --help
```
Some arguments are mandatory:
```bash
$ bin/shortener bitly:shorten username password http://www.google.com
```
Some options are available:
```bash
$ bin/shortener bitly:shorten username password http://www.google.com --options='{"connect_timeout":1,"timeout":1}'
```
### Expand
```php
<?php
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Bitly\BitlyProvider;
use Mremi\UrlShortener\Provider\Bitly\OAuthClient;
$link = new Link;
$link->setShortUrl('http://goo.gl/fbsS');
$bitlyProvider = new BitlyProvider(
new GenericAccessTokenAuthenticator('generic_access_token'), // or old OAuthClient('username', 'password')
['connect_timeout' => 1, 'timeout' => 1]
);
$bitlyProvider->expand($link);
```
```bash
$ bin/shortener bitly:expand --help
```
Some arguments are mandatory:
```bash
$ bin/shortener bitly:expand username password http://bit.ly/ze6poY
```
Some options are available:
```bash
$ bin/shortener bitly:expand username password http://bit.ly/ze6poY --options='{"connect_timeout":1,"timeout":1}'
```
<a name="google-api"></a>
## Google API
### Shorten
```php
<?php
@@ -85,14 +200,193 @@ $link->setLongUrl('http://www.google.com');
$googleProvider = new GoogleProvider(
'api_key',
array('connect_timeout' => 1, 'timeout' => 1)
['connect_timeout' => 1, 'timeout' => 1]
);
$googleProvider->shorten($link);
```
You can also use the commands provided by this library, look at the help message:
```bash
$ bin/shortener google:shorten --help
```
Only one argument is mandatory (the long URL) but you can also provide a Google
API key:
```bash
$ bin/shortener google:shorten http://www.google.com
```
```bash
$ bin/shortener google:shorten http://www.google.com api_key
```
Some options are available:
```bash
$ bin/shortener google:shorten http://www.google.com --options='{"connect_timeout":1,"timeout":1}'
```
### Expand
```php
<?php
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Google\GoogleProvider;
$link = new Link;
$link->setShortUrl('http://goo.gl/fbsS');
$googleProvider = new GoogleProvider(
'api_key',
['connect_timeout' => 1, 'timeout' => 1]
);
$googleProvider->expand($link);
```
```bash
$ bin/shortener google:expand --help
```
Only one argument is mandatory (the short URL) but you can also provide a
Google API key:
```bash
$ bin/shortener google:expand http://goo.gl/fbsS
```
```bash
$ bin/shortener google:expand http://goo.gl/fbsS api_key
```
Some options are available:
```bash
$ bin/shortener google:expand http://goo.gl/fbsS --options='{"connect_timeout":1,"timeout":1}'
```
<a name="sina-api"></a>
## Sina API
### Shorten
```php
<?php
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Sina\SinaProvider;
$link = new Link;
$link->setLongUrl('http://www.google.com');
$sinaProvider = new SinaProvider(
'api_key',
['connect_timeout' => 1, 'timeout' => 1]
);
$sinaProvider->shorten($link);
```
You can also use the commands provided by this library, look at the help message:
```bash
$ bin/shortener sina:shorten --help
```
```bash
$ bin/shortener sina:shorten http://www.google.com api_key
```
Some options are available:
```bash
$ bin/shortener sina:shorten http://www.google.com api_key --options='{"connect_timeout":1,"timeout":1}'
```
### Expand
```php
<?php
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Sina\SinaProvider;
$link = new Link;
$link->setShortUrl('http://t.cn/h51yw');
$sinaProvider = new SinaProvider(
'api_key',
['connect_timeout' => 1, 'timeout' => 1]
);
$googleProvider->expand($link);
```
```bash
$ bin/shortener sina:expand --help
```
```bash
$ bin/shortener sina:expand http://t.cn/h51yw api_key
```
Some options are available:
```bash
$ bin/shortener sina:expand http://t.cn/h51yw api_key --options='{"connect_timeout":1,"timeout":1}'
```
<a name="wechat-api"></a>
## Wechat API
### Shorten
```php
<?php
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Wechat\WechatProvider;
use Mremi\UrlShortener\Provider\Wechat\OAuthClient;
$link = new Link;
$link->setLongUrl('http://www.google.com');
$wechatProvider = new WechatProvider(
new OAuthClient('username', 'password'),
['connect_timeout' => 1, 'timeout' => 1]
);
$wechatProvider->shorten($link);
```
You can also use the commands provided by this library, look at the help message:
```bash
$ bin/shortener wechat:shorten --help
```
Some arguments are mandatory:
```bash
$ bin/shortener wechat:shorten appid secret http://www.google.com
```
Some options are available:
```bash
$ bin/shortener wechat:shorten appid secret http://www.google.com --options='{"connect_timeout":1,"timeout":1}'
```
### Expand
Wechat does not support expand url yet.
<a name="chain-providers"></a>
## Chain providers

20
vendor/mremi/url-shortener/bin/shortener vendored Executable file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env php
<?php
if (file_exists(__DIR__.'/../vendor/autoload.php')) {
require __DIR__.'/../vendor/autoload.php';
} elseif (file_exists(__DIR__.'/../../../autoload.php')) {
require __DIR__.'/../../../autoload.php';
}
use Symfony\Component\Console\Application;
$application = new Application;
foreach (glob(__DIR__.'/../src/Mremi/UrlShortener/Command/*Command.php') as $command) {
$class = sprintf('Mremi\UrlShortener\Command\%s', rtrim(basename($command), '.php'));
$application->add(new $class);
}
$application->run();

View File

@@ -1,8 +1,8 @@
{
"name": "mremi/url-shortener",
"type": "library",
"description": "A PHP5 library using API to shorten/expand URL",
"keywords": ["url", "shortener", "api"],
"description": "A PHP5/PHP7/PHP8 library using API to shorten/expand URL",
"keywords": [ "url", "shortener", "api" ],
"homepage": "https://github.com/mremi/UrlShortener",
"license": "MIT",
"authors": [
@@ -12,10 +12,27 @@
}
],
"require": {
"php": ">=5.3.3",
"guzzle/guzzle": "~3.7"
"php": "^5.6 || ^7.0 || ^8.0",
"guzzlehttp/guzzle": "^6.0 || ^7.0",
"symfony/console": "^3.1 || ^4.1 || ^5.0 || ^6.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.19",
"symfony/phpunit-bridge": "^5.0 || ^6.0"
},
"autoload": {
"psr-0": { "Mremi\\UrlShortener": "src" }
"psr-4": {
"Mremi\\UrlShortener\\": "src/Mremi/UrlShortener"
}
},
"autoload-dev": {
"psr-4": {
"Mremi\\UrlShortener\\Tests\\": "tests/Mremi/UrlShortener/Tests"
}
},
"extra": {
"branch-alias": {
"dev-master": "2.4-dev"
}
}
}

View File

@@ -8,7 +8,6 @@
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="vendor/autoload.php"
>
<testsuites>
@@ -26,5 +25,4 @@
</exclude>
</whitelist>
</filter>
</phpunit>

View File

@@ -0,0 +1,62 @@
<?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\Command;
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Baidu\BaiduProvider;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Expands the short given URL using the Google API.
*
* @author zacksleo <zacksleo@gmail.com>
*/
class BaiduExpandCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
parent::configure();
$this
->setName('baidu:expand')
->setDescription('Expands the short given URL using the dwz.cn API')
->addArgument('short-url', InputArgument::REQUIRED, 'The short URL to expand')
->addOption('options', null, InputOption::VALUE_REQUIRED, 'An array of options used by request');
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$link = new Link();
$link->setShortUrl($input->getArgument('short-url'));
$options = $input->getOption('options') ? json_decode($input->getOption('options'), true) : [];
$provider = new BaiduProvider($options);
try {
$provider->expand($link);
$output->writeln(sprintf('<info>Success:</info> %s', $link->getLongUrl()));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Failure:</error> %s', $e->getMessage()));
}
}
}

View File

@@ -0,0 +1,62 @@
<?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\Command;
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Baidu\BaiduProvider;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Shortens the long given URL using the Google API.
*
* @author zacksleo <zacksleo@gmail.com>
*/
class BaiduShortenCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
parent::configure();
$this
->setName('baidu:shorten')
->setDescription('Shortens the long given URL using the dwz.cn API')
->addArgument('long-url', InputArgument::REQUIRED, 'The long URL to shorten')
->addOption('options', null, InputOption::VALUE_REQUIRED, 'An array of options used by request');
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$link = new Link();
$link->setLongUrl($input->getArgument('long-url'));
$options = $input->getOption('options') ? json_decode($input->getOption('options'), true) : [];
$provider = new BaiduProvider($options);
try {
$provider->shorten($link);
$output->writeln(sprintf('<info>Success:</info> %s', $link->getShortUrl()));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Failure:</error> %s', $e->getMessage()));
}
}
}

View File

@@ -0,0 +1,71 @@
<?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\Command;
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Bitly\BitlyProvider;
use Mremi\UrlShortener\Provider\Bitly\OAuthClient;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Expands the short given URL using the Bitly API.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class BitlyExpandCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
parent::configure();
$this
->setName('bitly:expand')
->setDescription('Expands the short given URL using the Bitly API')
->addArgument('username', InputArgument::REQUIRED, 'A valid Bitly username')
->addArgument('password', InputArgument::REQUIRED, 'A valid Bitly password')
->addArgument('short-url', InputArgument::REQUIRED, 'The short URL to expand')
->addOption('options', null, InputOption::VALUE_REQUIRED, 'An array of options used by request');
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$link = new Link();
$link->setShortUrl($input->getArgument('short-url'));
$options = $input->getOption('options') ? json_decode($input->getOption('options'), true) : [];
$provider = new BitlyProvider(
new OAuthClient($input->getArgument('username'), $input->getArgument('password')),
$options
);
try {
$provider->expand($link);
$output->writeln(sprintf('<info>Success:</info> %s', $link->getLongUrl()));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Failure:</error> %s', $e->getMessage()));
}
}
}

View File

@@ -0,0 +1,71 @@
<?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\Command;
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Bitly\BitlyProvider;
use Mremi\UrlShortener\Provider\Bitly\OAuthClient;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Shortens the long given URL using the Bitly API.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class BitlyShortenCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
parent::configure();
$this
->setName('bitly:shorten')
->setDescription('Shortens the long given URL using the Bitly API')
->addArgument('username', InputArgument::REQUIRED, 'A valid Bitly username')
->addArgument('password', InputArgument::REQUIRED, 'A valid Bitly password')
->addArgument('long-url', InputArgument::REQUIRED, 'The long URL to shorten')
->addOption('options', null, InputOption::VALUE_REQUIRED, 'An array of options used by request');
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$link = new Link();
$link->setLongUrl($input->getArgument('long-url'));
$options = $input->getOption('options') ? json_decode($input->getOption('options'), true) : [];
$provider = new BitlyProvider(
new OAuthClient($input->getArgument('username'), $input->getArgument('password')),
$options
);
try {
$provider->shorten($link);
$output->writeln(sprintf('<info>Success:</info> %s', $link->getShortUrl()));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Failure:</error> %s', $e->getMessage()));
}
}
}

View File

@@ -0,0 +1,66 @@
<?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\Command;
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Google\GoogleProvider;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Expands the short given URL using the Google API.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class GoogleExpandCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
parent::configure();
$this
->setName('google:expand')
->setDescription('Expands the short given URL using the Google API')
->addArgument('short-url', InputArgument::REQUIRED, 'The short URL to expand')
->addArgument('api-key', InputArgument::OPTIONAL, 'A Google API key, optional')
->addOption('options', null, InputOption::VALUE_REQUIRED, 'An array of options used by request');
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$link = new Link();
$link->setShortUrl($input->getArgument('short-url'));
$options = $input->getOption('options') ? json_decode($input->getOption('options'), true) : [];
$provider = new GoogleProvider($input->getArgument('api-key'), $options);
try {
$provider->expand($link);
$output->writeln(sprintf('<info>Success:</info> %s', $link->getLongUrl()));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Failure:</error> %s', $e->getMessage()));
}
}
}

View File

@@ -0,0 +1,66 @@
<?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\Command;
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Google\GoogleProvider;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Shortens the long given URL using the Google API.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class GoogleShortenCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
parent::configure();
$this
->setName('google:shorten')
->setDescription('Shortens the long given URL using the Google API')
->addArgument('long-url', InputArgument::REQUIRED, 'The long URL to shorten')
->addArgument('api-key', InputArgument::OPTIONAL, 'A Google API key, optional')
->addOption('options', null, InputOption::VALUE_REQUIRED, 'An array of options used by request');
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$link = new Link();
$link->setLongUrl($input->getArgument('long-url'));
$options = $input->getOption('options') ? json_decode($input->getOption('options'), true) : [];
$provider = new GoogleProvider($input->getArgument('api-key'), $options);
try {
$provider->shorten($link);
$output->writeln(sprintf('<info>Success:</info> %s', $link->getShortUrl()));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Failure:</error> %s', $e->getMessage()));
}
}
}

View File

@@ -0,0 +1,63 @@
<?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\Command;
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Sina\SinaProvider;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Expands the short given URL using the Google API.
*
* @author zacksleo <zacksleo@gmail.com>
*/
class SinaExpandCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
parent::configure();
$this
->setName('sina:expand')
->setDescription('Expands the short given URL using the Sina API')
->addArgument('short-url', InputArgument::REQUIRED, 'The short URL to expand')
->addArgument('api-key', InputArgument::REQUIRED, 'A Sina API key, optional')
->addOption('options', null, InputOption::VALUE_REQUIRED, 'An array of options used by request');
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$link = new Link();
$link->setShortUrl($input->getArgument('short-url'));
$options = $input->getOption('options') ? json_decode($input->getOption('options'), true) : [];
$provider = new SinaProvider($input->getArgument('api-key'), $options);
try {
$provider->expand($link);
$output->writeln(sprintf('<info>Success:</info> %s', $link->getLongUrl()));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Failure:</error> %s', $e->getMessage()));
}
}
}

View File

@@ -0,0 +1,63 @@
<?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\Command;
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Sina\SinaProvider;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Shortens the long given URL using the Google API.
*
* @author zacksleo <zacksleo@gmail.com>
*/
class SinaShortenCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
parent::configure();
$this
->setName('sina:shorten')
->setDescription('Shortens the long given URL using the Sina API')
->addArgument('long-url', InputArgument::REQUIRED, 'The long URL to shorten')
->addArgument('api-key', InputArgument::REQUIRED, 'A Sina API key, optional')
->addOption('options', null, InputOption::VALUE_REQUIRED, 'An array of options used by request');
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$link = new Link();
$link->setLongUrl($input->getArgument('long-url'));
$options = $input->getOption('options') ? json_decode($input->getOption('options'), true) : [];
$provider = new SinaProvider($input->getArgument('api-key'), $options);
try {
$provider->shorten($link);
$output->writeln(sprintf('<info>Success:</info> %s', $link->getShortUrl()));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Failure:</error> %s', $e->getMessage()));
}
}
}

View File

@@ -0,0 +1,68 @@
<?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\Command;
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Wechat\OAuthClient;
use Mremi\UrlShortener\Provider\Wechat\WechatProvider;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Expands the short given URL using the Wechat API.
*
* @author zacksleo <zacksleo@gmail.com>
*/
class WechatExpandCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
parent::configure();
$this
->setName('wechat:expand')
->setDescription('Expands the short given URL using the Wechat API')
->addArgument('appid', InputArgument::REQUIRED, 'A valid Wechat appid')
->addArgument('appsecret', InputArgument::REQUIRED, 'A valid Wechat appid')
->addArgument('short-url', InputArgument::REQUIRED, 'The short URL to expand')
->addOption('options', null, InputOption::VALUE_REQUIRED, 'An array of options used by request');
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$link = new Link();
$link->setShortUrl($input->getArgument('short-url'));
$options = $input->getOption('options') ? json_decode($input->getOption('options'), true) : [];
$provider = new WechatProvider(
new OAuthClient($input->getArgument('appid'), $input->getArgument('appsecret'), $options)
);
try {
$provider->expand($link);
$output->writeln(sprintf('<info>Success:</info> %s', $link->getLongUrl()));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Failure:</error> %s', $e->getMessage()));
}
}
}

View File

@@ -0,0 +1,69 @@
<?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\Command;
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Provider\Wechat\OAuthClient;
use Mremi\UrlShortener\Provider\Wechat\WechatProvider;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Shortens the long given URL using the Wechat API.
*
* @author zacksleo <zacksleo@gmail.com>
*/
class WechatShortenCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
parent::configure();
$this
->setName('wechat:shorten')
->setDescription('Shortens the long given URL using the Wechat API')
->addArgument('appid', InputArgument::REQUIRED, 'A valid Wechat appid')
->addArgument('appsecret', InputArgument::REQUIRED, 'A valid Wechat appsecret')
->addArgument('long-url', InputArgument::REQUIRED, 'The long URL to shorten')
->addOption('options', null, InputOption::VALUE_REQUIRED, 'An array of options used by request');
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$link = new Link();
$link->setLongUrl($input->getArgument('long-url'));
$options = $input->getOption('options') ? json_decode($input->getOption('options'), true) : [];
$provider = new WechatProvider(
new OAuthClient($input->getArgument('appid'), $input->getArgument('appsecret'), $options)
);
try {
$provider->shorten($link);
$output->writeln(sprintf('<info>Success:</info> %s', $link->getShortUrl()));
} catch (\Exception $e) {
$output->writeln(sprintf('<error>Failure:</error> %s', $e->getMessage()));
}
}
}

View File

@@ -12,7 +12,7 @@
namespace Mremi\UrlShortener\Exception;
/**
* Invalid API response exception class
* Invalid API response exception class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/

View File

@@ -12,7 +12,7 @@
namespace Mremi\UrlShortener\Model;
/**
* Link class
* Link class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
@@ -39,11 +39,11 @@ class Link implements LinkInterface
protected $createdAt;
/**
* Constructor
* Constructor.
*/
public function __construct()
{
$this->setCreatedAt(new \DateTime);
$this->setCreatedAt(new \DateTime());
}
/**

View File

@@ -12,63 +12,61 @@
namespace Mremi\UrlShortener\Model;
/**
* Class LinkInterface
* Class LinkInterface.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
interface LinkInterface
{
/**
* Sets the created at
*
* @param \DateTime $createdAt
* Sets the created at.
*/
public function setCreatedAt(\DateTime $createdAt);
/**
* Gets the created at
* Gets the created at.
*
* @return \DateTime
*/
public function getCreatedAt();
/**
* Sets the long URL
* Sets the long URL.
*
* @param string $longUrl
*/
public function setLongUrl($longUrl);
/**
* Gets the long URL
* Gets the long URL.
*
* @return string
*/
public function getLongUrl();
/**
* Sets the provider name
* Sets the provider name.
*
* @param string $providerName
*/
public function setProviderName($providerName);
/**
* Gets the provider name
* Gets the provider name.
*
* @return string
*/
public function getProviderName();
/**
* Sets the short URL
* Sets the short URL.
*
* @param string $shortUrl
*/
public function setShortUrl($shortUrl);
/**
* Gets the short URL
* Gets the short URL.
*
* @return string
*/

View File

@@ -14,7 +14,7 @@ namespace Mremi\UrlShortener\Model;
use Mremi\UrlShortener\Provider\ChainProvider;
/**
* Link manager class
* Link manager class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
@@ -31,7 +31,7 @@ class LinkManager implements LinkManagerInterface
protected $class;
/**
* Constructor
* Constructor.
*
* @param ChainProvider $chainProvider A chain provider instance
* @param string $class The Link class namespace, optional
@@ -47,7 +47,7 @@ class LinkManager implements LinkManagerInterface
*/
public function create()
{
return new $this->class;
return new $this->class();
}
/**

View File

@@ -12,21 +12,21 @@
namespace Mremi\UrlShortener\Model;
/**
* Link manager interface
* Link manager interface.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
interface LinkManagerInterface
{
/**
* Creates and returns a new link instance
* Creates and returns a new link instance.
*
* @return LinkInterface
*/
public function create();
/**
* Finds one link by a provider and a short URL
* Finds one link by a provider and a short URL.
*
* @param string $providerName A provider name
* @param string $shortUrl A short URL
@@ -38,7 +38,7 @@ interface LinkManagerInterface
public function findOneByProviderAndShortUrl($providerName, $shortUrl);
/**
* Finds one link by a provider and a long URL
* Finds one link by a provider and a long URL.
*
* @param string $providerName A provider name
* @param string $longUrl A long URL

View File

@@ -0,0 +1,138 @@
<?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\Baidu;
use GuzzleHttp\Client;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\UrlShortenerProviderInterface;
/**
* Baidu provider class.
*
* @author zacksleo <zacksleo@gmail.com>
*/
class BaiduProvider implements UrlShortenerProviderInterface
{
/**
* @var array
*/
private $options;
/**
* Constructor.
*
* @param array $options An array of options used to do the shorten/expand request
*/
public function __construct(array $options = [])
{
$this->options = $options;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'baidu';
}
/**
* {@inheritdoc}
*/
public function shorten(LinkInterface $link)
{
$client = $this->createClient();
$response = $client->post('/admin/create', array_merge(
[
'json' => [
'url' => $link->getLongUrl(),
],
],
$this->options
));
$response = $this->validate($response->getBody()->getContents(), true);
$link->setShortUrl($response->ShortUrl);
}
/**
* {@inheritdoc}
*/
public function expand(LinkInterface $link)
{
$client = $this->createClient();
$response = $client->post('/admin/query', array_merge(
[
'json' => [
'shortUrl' => $link->getShortUrl(),
],
],
$this->options
));
$response = $this->validate($response->getBody()->getContents(), 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([
'base_uri' => 'https://dwz.cn',
]);
}
/**
* Validates the Google's response and returns it whether the status code is 200.
*
* @param string $apiRawResponse An API response, as it returned
* @param bool $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('Baidu response is probably mal-formed because cannot be json-decoded.');
}
if (!$checkStatus) {
return $response;
}
if (!property_exists($response, 'Code')) {
throw new InvalidApiResponseException('Property "Code" does not exist within Baidu response.');
}
if (0 !== $response->Code) {
throw new InvalidApiResponseException(sprintf('Baidu returned code error message "%s: %s".', $response->Code, $response->ErrMsg));
}
return $response;
}
}

View File

@@ -12,14 +12,14 @@
namespace Mremi\UrlShortener\Provider\Bitly;
/**
* Authentication interface
* Authentication interface.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
interface AuthenticationInterface
{
/**
* Calls Bit.ly API to get an access token
* Calls Bit.ly API to get an access token.
*
* @return string
*/

View File

@@ -11,14 +11,14 @@
namespace Mremi\UrlShortener\Provider\Bitly;
use Guzzle\Http\Client;
use GuzzleHttp\Client;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\UrlShortenerProviderInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Bit.ly provider class
* Bit.ly provider class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
@@ -35,12 +35,12 @@ class BitlyProvider implements UrlShortenerProviderInterface
private $options;
/**
* Constructor
* 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())
public function __construct(AuthenticationInterface $auth, array $options = [])
{
$this->auth = $auth;
$this->options = $options;
@@ -66,15 +66,18 @@ class BitlyProvider implements UrlShortenerProviderInterface
{
$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);
$this->options['headers']['Authorization'] = 'Bearer '.$this->auth->getAccessToken();
$response = $this->validate($request->send()->getBody(true));
$response = $client->post('/v4/shorten', array_merge([
'json' => [
'domain' => $domain,
'long_url' => $link->getLongUrl(),
],
], $this->options));
$link->setShortUrl($response->data->url);
$response = $this->validate($response);
$link->setShortUrl($response->link);
}
/**
@@ -89,15 +92,17 @@ class BitlyProvider implements UrlShortenerProviderInterface
{
$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);
$this->options['headers']['Authorization'] = 'Bearer '.$this->auth->getAccessToken();
$response = $this->validate($request->send()->getBody(true));
$response = $client->post('/v4/expand', array_merge([
'json' => [
'bitlink_id' => $hash ?: $link->getShortUrl(),
],
], $this->options));
$link->setLongUrl($response->data->expand[0]->long_url);
$response = $this->validate($response);
$link->setLongUrl($response->long_url);
}
/**
@@ -110,37 +115,35 @@ class BitlyProvider implements UrlShortenerProviderInterface
*/
protected function createClient()
{
return new Client('https://api-ssl.bitly.com');
return new Client([
'base_uri' => 'https://api-ssl.bitly.com',
]);
}
/**
* Validates the Bit.ly's response and returns it whether the status code is 200
*
* @param string $apiRawResponse
* Validates the Bit.ly's response and returns it whether the status code is 200.
*
* @return object
*
* @throws InvalidApiResponseException
*/
private function validate($apiRawResponse)
private function validate(ResponseInterface $response)
{
$response = json_decode($apiRawResponse);
$data = json_decode($response->getBody()->getContents());
if (null === $response) {
if (null === $data) {
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.');
}
$statusCode = $response->getStatusCode();
if (200 !== $response->status_code) {
if ($statusCode < 200 || $statusCode >= 300) {
throw new InvalidApiResponseException(sprintf('Bit.ly returned status code "%s" with message "%s"',
$response->status_code,
property_exists($response, 'status_txt') ? $response->status_txt : ''
$statusCode,
property_exists($data, 'message') ? $data->message : ''
));
}
return $response;
return $data;
}
}

View File

@@ -0,0 +1,45 @@
<?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;
/**
* GenericAccessTokenAuthenticator class.
*
* @author Marcus Sá <marcusesa@gmail.com>
*/
class GenericAccessTokenAuthenticator implements AuthenticationInterface
{
/**
* @var string
*/
private $genericAccessToken;
/**
* Constructor.
*
* @param string $genericAccessToken generic access token is a immutable token provided by Bitly
*/
public function __construct($genericAccessToken)
{
$this->genericAccessToken = $genericAccessToken;
}
/**
* Return the Generic Access Token.
*
* @return string
*/
public function getAccessToken()
{
return $this->genericAccessToken;
}
}

View File

@@ -11,10 +11,10 @@
namespace Mremi\UrlShortener\Provider\Bitly;
use Guzzle\Http\Client;
use GuzzleHttp\Client;
/**
* OAuth client class
* OAuth client class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
@@ -31,7 +31,7 @@ class OAuthClient implements AuthenticationInterface
private $password;
/**
* Constructor
* Constructor.
*
* @param string $username A valid Bit.ly username
* @param string $password A valid Bit.ly password
@@ -47,15 +47,17 @@ class OAuthClient implements AuthenticationInterface
*/
public function getAccessToken()
{
$client = new Client('https://api-ssl.bitly.com/oauth/access_token');
$client = new Client([
'base_uri' => 'https://api-ssl.bitly.com/oauth/access_token',
]);
$request = $client->post(null, null, null, array(
'auth' => array(
$response = $client->post(null, [
'auth' => [
$this->username,
$this->password,
),
));
],
]);
return $request->send()->getBody(true);
return $response->getBody()->getContents();
}
}

View File

@@ -12,7 +12,7 @@
namespace Mremi\UrlShortener\Provider;
/**
* Chain provider class
* Chain provider class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
@@ -21,10 +21,10 @@ class ChainProvider
/**
* @var array
*/
private $providers = array();
private $providers = [];
/**
* Adds the given provider to the chain
* Adds the given provider to the chain.
*
* @param UrlShortenerProviderInterface $provider A provider instance
*/
@@ -34,7 +34,7 @@ class ChainProvider
}
/**
* Gets a provider by name
* Gets a provider by name.
*
* @param string $name A provider name
*
@@ -52,7 +52,7 @@ class ChainProvider
}
/**
* Gets the chain providers
* Gets the chain providers.
*
* @return UrlShortenerProviderInterface[]
*/
@@ -62,11 +62,11 @@ class ChainProvider
}
/**
* Returns TRUE whether the given name identifies a configured provider
* Returns TRUE whether the given name identifies a configured provider.
*
* @param string $name A provider name
*
* @return boolean
* @return bool
*/
public function hasProvider($name)
{

View File

@@ -11,14 +11,13 @@
namespace Mremi\UrlShortener\Provider\Google;
use Guzzle\Http\Client;
use GuzzleHttp\Client;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\UrlShortenerProviderInterface;
/**
* Google provider class
* Google provider class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
@@ -35,12 +34,12 @@ class GoogleProvider implements UrlShortenerProviderInterface
private $options;
/**
* Constructor
* 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())
public function __construct($apiKey = null, array $options = [])
{
$this->apiKey = $apiKey;
$this->options = $options;
@@ -61,13 +60,16 @@ class GoogleProvider implements UrlShortenerProviderInterface
{
$client = $this->createClient();
$request = $client->post($this->getUri(), array(
'Content-Type' => 'application/json'
), json_encode(array(
'longUrl' => $link->getLongUrl(),
)), $this->options);
$response = $client->post($this->getUri(), array_merge(
[
'json' => [
'longUrl' => $link->getLongUrl(),
],
],
$this->options
));
$response = $this->validate($request->send()->getBody(true));
$response = $this->validate($response->getBody()->getContents());
$link->setShortUrl($response->id);
}
@@ -79,11 +81,11 @@ class GoogleProvider implements UrlShortenerProviderInterface
{
$client = $this->createClient();
$request = $client->get($this->getUri(array(
$response = $client->get($this->getUri([
'shortUrl' => $link->getShortUrl(),
)), array(), $this->options);
]), $this->options);
$response = $this->validate($request->send()->getBody(true), true);
$response = $this->validate($response->getBody()->getContents(), true);
$link->setLongUrl($response->longUrl);
}
@@ -98,34 +100,36 @@ class GoogleProvider implements UrlShortenerProviderInterface
*/
protected function createClient()
{
return new Client('https://www.googleapis.com/urlshortener/v1/url');
return new Client([
'base_uri' => 'https://www.googleapis.com/urlshortener/v1/url',
]);
}
/**
* Gets the URI
* Gets the URI.
*
* @param array $parameters An array of parameters, optional
*
* @return null|string
* @return string|null
*/
private function getUri(array $parameters = array())
private function getUri(array $parameters = [])
{
if ($this->apiKey) {
$parameters = array_merge($parameters, array('key' => $this->apiKey));
$parameters = array_merge($parameters, ['key' => $this->apiKey]);
}
if (0 === count($parameters)) {
return null;
return;
}
return sprintf('?%s', http_build_query($parameters));
}
/**
* Validates the Google's response and returns it whether the status code is 200
* 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
* @param string $apiRawResponse An API response, as it returned
* @param bool $checkStatus TRUE whether the status code has to be checked, default FALSE
*
* @return object
*

View File

@@ -0,0 +1,148 @@
<?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\Sina;
use GuzzleHttp\Client;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\UrlShortenerProviderInterface;
/**
* Sina provider class.
*
* @author zacksleo <zacksleo@gmail.com>
*/
class SinaProvider implements UrlShortenerProviderInterface
{
/**
* @var string
*/
private $apiKey;
/**
* @var array
*/
private $options;
/**
* Constructor.
*
* @param string $apiKey A Sina API key, optional
* @param array $options An array of options used to do the shorten/expand request
*/
public function __construct($apiKey = null, array $options = [])
{
$this->apiKey = $apiKey;
$this->options = $options;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'sina';
}
/**
* {@inheritdoc}
*/
public function shorten(LinkInterface $link)
{
$client = $this->createClient();
$response = $client->get('shorten.json', array_merge(
[
'query' => [
'source' => $this->apiKey,
'url_long' => $link->getLongUrl(),
],
],
$this->options
));
$response = $this->validate($response->getBody()->getContents());
$link->setShortUrl($response->urls[0]->url_short);
}
/**
* {@inheritdoc}
*/
public function expand(LinkInterface $link)
{
$client = $this->createClient();
$response = $client->get('expand.json', array_merge(
[
'query' => [
'source' => $this->apiKey,
'url_short' => $link->getShortUrl(),
],
],
$this->options
));
$response = $this->validate($response->getBody()->getContents());
$link->setLongUrl($response->urls[0]->url_long);
}
/**
* 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([
'base_uri' => 'https://api.weibo.com/2/short_url/',
]);
}
/**
* Validates the Sina's response and returns it whether the status code is 200.
*
* @param string $apiRawResponse An API response, as it returned
*
* @return object
*
* @throws InvalidApiResponseException
*/
private function validate($apiRawResponse)
{
$response = json_decode($apiRawResponse);
if (null === $response) {
throw new InvalidApiResponseException('Sina response is probably mal-formed because cannot be json-decoded.');
}
if (property_exists($response, 'error')) {
throw new InvalidApiResponseException(sprintf(
'Sina returned status code "%s" with message "%s".',
property_exists($response, 'error_code') ? $response->error_code : '',
property_exists($response, 'error') ? $response->error : ''
));
}
if (property_exists($response, 'urls')) {
if (empty($response->urls[0]->url_long)) {
throw new InvalidApiResponseException('Property "longUrl" does not exist within Sina response.');
}
}
return $response;
}
}

View File

@@ -14,21 +14,21 @@ namespace Mremi\UrlShortener\Provider;
use Mremi\UrlShortener\Model\LinkInterface;
/**
* Url shortener provider interface
* Url shortener provider interface.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
interface UrlShortenerProviderInterface
{
/**
* Gets the provider name
* Gets the provider name.
*
* @return string
*/
public function getName();
/**
* Shortens the long given URL
* Shortens the long given URL.
*
* @param LinkInterface $link A link instance
*
@@ -37,7 +37,7 @@ interface UrlShortenerProviderInterface
public function shorten(LinkInterface $link);
/**
* Expands the short given URL
* Expands the short given URL.
*
* @param LinkInterface $link A link instance
*

View File

@@ -0,0 +1,78 @@
<?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\Wechat;
use GuzzleHttp\Client;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Provider\Bitly\AuthenticationInterface;
/**
* OAuth client class.
*
* @author zacksleo <zacksleo@gmail.com>
*/
class OAuthClient implements AuthenticationInterface
{
/**
* @var string
*/
private $appid;
/**
* @var string
*/
private $appsecret;
/**
* Constructor.
*
* @param string $appid A valid Wechat appid
* @param string $appsecret A valid Wechat appsecret
*/
public function __construct($appid, $appsecret)
{
$this->appid = $appid;
$this->appsecret = $appsecret;
}
/**
* {@inheritdoc}
*/
public function getAccessToken()
{
$client = new Client([
'base_uri' => 'https://api.weixin.qq.com',
]);
$apiRawResponse = $client->get('/cgi-bin/token', [
'query' => [
'grant_type' => 'client_credential',
'appid' => $this->appid,
'secret' => $this->appsecret,
],
]);
$response = json_decode($apiRawResponse->getBody()->getContents());
if (null === $response) {
throw new InvalidApiResponseException('Wechat response is probably mal-formed because cannot be json-decoded.');
}
if (property_exists($response, 'errcode')) {
throw new InvalidApiResponseException(sprintf(
'Wecaht returned status code "%s" with message "%s".',
property_exists($response, 'errcode') ? $response->errcode : '',
property_exists($response, 'errmsg') ? $response->errmsg : ''
));
}
return $response->access_token;
}
}

View File

@@ -0,0 +1,143 @@
<?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\Wechat;
use GuzzleHttp\Client;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\Bitly\AuthenticationInterface;
use Mremi\UrlShortener\Provider\UrlShortenerProviderInterface;
/**
* Wechat provider class.
*
* @author zacksleo <zacksleo@gmail.com>
*/
class WechatProvider 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 = [])
{
$this->auth = $auth;
$this->options = $options;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'wechat';
}
/**
* {@inheritdoc}
*
* @param LinkInterface $link A link instance
*
* @throws InvalidApiResponseException
*/
public function shorten(LinkInterface $link)
{
$client = $this->createClient();
$response = $client->post(sprintf('/cgi-bin/shorturl?access_token=%s',
$this->auth->getAccessToken()
), array_merge(
[
'json' => [
'action' => 'long2short',
'long_url' => $link->getLongUrl(),
],
],
$this->options
));
$response = $this->validate($response->getBody()->getContents());
$link->setShortUrl($response->short_url);
}
/**
* {@inheritdoc}
*
* @param LinkInterface $link A link instance
* @param string $hash A Wechat hash
*
* @throws InvalidApiResponseException
*/
public function expand(LinkInterface $link, $hash = null)
{
throw new InvalidApiResponseException('Wechat does not support expand url yet.');
}
/**
* 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([
'base_uri' => 'https://api.weixin.qq.com',
]);
}
/**
* Validates the Wechat'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('Wechat response is probably mal-formed because cannot be json-decoded.');
}
if (!property_exists($response, 'errcode')) {
throw new InvalidApiResponseException('Property "errcode" does not exist within Wechat response.');
}
if (0 !== $response->errcode) {
throw new InvalidApiResponseException(sprintf('Wechat returned status code "%s" with message "%s"',
$response->errcode,
property_exists($response, 'errmsg') ? $response->errmsg : ''
));
}
return $response;
}
}

View File

@@ -11,14 +11,18 @@
namespace Mremi\UrlShortener\Tests\Model;
use Mremi\UrlShortener\Model\Link;
use Mremi\UrlShortener\Model\LinkManager;
use Mremi\UrlShortener\Provider\ChainProvider;
use Mremi\UrlShortener\Provider\UrlShortenerProviderInterface;
use PHPUnit\Framework\TestCase;
/**
* Tests Link manager class
* Tests Link manager class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class LinkManagerTest extends \PHPUnit_Framework_TestCase
class LinkManagerTest extends TestCase
{
/**
* @var LinkManager
@@ -31,11 +35,11 @@ class LinkManagerTest extends \PHPUnit_Framework_TestCase
private $chainProvider;
/**
* Tests the findOneByProviderAndShortUrl method
* Tests the findOneByProviderAndShortUrl method.
*/
public function testFindOneByProviderAndShortUrl()
{
$provider = $this->getMock('Mremi\UrlShortener\Provider\UrlShortenerProviderInterface');
$provider = $this->createMock(UrlShortenerProviderInterface::class);
$provider
->expects($this->once())
@@ -54,16 +58,16 @@ class LinkManagerTest extends \PHPUnit_Framework_TestCase
$link = $this->manager->findOneByProviderAndShortUrl('bitly', 'http://bit.ly/ZGUlzK');
$this->assertInstanceOf('Mremi\UrlShortener\Model\Link', $link);
$this->assertEquals('http://bit.ly/ZGUlzK', $link->getShortUrl());
$this->assertInstanceOf(Link::class, $link);
$this->assertSame('http://bit.ly/ZGUlzK', $link->getShortUrl());
}
/**
* Tests the findOneByProviderAndLongUrl method
* Tests the findOneByProviderAndLongUrl method.
*/
public function testFindOneByProviderAndLongUrl()
{
$provider = $this->getMock('Mremi\UrlShortener\Provider\UrlShortenerProviderInterface');
$provider = $this->createMock(UrlShortenerProviderInterface::class);
$provider
->expects($this->once())
@@ -82,19 +86,19 @@ class LinkManagerTest extends \PHPUnit_Framework_TestCase
$link = $this->manager->findOneByProviderAndLongUrl('google', 'http://www.google.com/');
$this->assertInstanceOf('Mremi\UrlShortener\Model\Link', $link);
$this->assertEquals('http://www.google.com/', $link->getLongUrl());
$this->assertInstanceOf(Link::class, $link);
$this->assertSame('http://www.google.com/', $link->getLongUrl());
}
/**
* Initializes chainProvider & manager properties
* Initializes chainProvider & manager properties.
*/
protected function setUp()
{
$this->chainProvider = $this->getMockBuilder('Mremi\UrlShortener\Provider\ChainProvider')
$this->chainProvider = $this->getMockBuilder(ChainProvider::class)
->disableOriginalConstructor()
->getMock();
$this->manager = new LinkManager($this->chainProvider, 'Mremi\UrlShortener\Model\Link');
$this->manager = new LinkManager($this->chainProvider, Link::class);
}
}

View File

@@ -11,22 +11,24 @@
namespace Mremi\UrlShortener\Tests\Model;
use DateTime;
use Mremi\UrlShortener\Model\Link;
use PHPUnit\Framework\TestCase;
/**
* Tests Link class
* Tests Link class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class LinkTest extends \PHPUnit_Framework_TestCase
class LinkTest extends TestCase
{
/**
* Tests the createdAt property
* Tests the createdAt property.
*/
public function testCreatedAt()
{
$link = new Link;
$link = new Link();
$this->assertInstanceOf('\DateTime', $link->getCreatedAt());
$this->assertInstanceOf(DateTime::class, $link->getCreatedAt());
}
}

View File

@@ -0,0 +1,443 @@
<?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\Baidu;
use GuzzleHttp\ClientInterface;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\Baidu\BaiduProvider;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
/**
* Tests BaiduProvider class.
*
* @author zacksleo <zacksleo@gmail.com>
*/
class BaiduProviderTest extends TestCase
{
/**
* @var object
*/
private $provider;
/**
* Initializes the provider.
*/
protected function setUp()
{
$this->provider = $this->getMockBuilder(BaiduProvider::class)
->setMethods(['createClient'])
->getMock();
}
/**
* Cleanups the provider.
*/
protected function tearDown()
{
$this->provider = null;
}
/**
* Tests the shorten method throws exception if Baidu returns a string.
*/
public function testShortenThrowsExceptionIfResponseApiIsString()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Baidu response is probably mal-formed because cannot be json-decoded.');
$this->mockClient($this->getMockResponseAsString(), 'post');
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method throws exception if Baidu returns an error response.
*/
public function testShortenThrowsExceptionIfApiResponseIsError()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Baidu returned code error message "-1: long url is not valid');
$this->mockClient($this->getMockResponseWithError(), 'post');
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method throws exception if Baidu returns a response with no short url.
*/
public function testShortenThrowsExceptionIfApiResponseHasNoShortUrl()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Baidu returned code error message "-1: unsafe url');
$this->mockClient($this->getMockResponseWithNoShortUrl(), 'post');
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method with a valid Baidu's response.
*/
public function testShortenWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"Code": 0,
"ShortUrl": "https://dwz.cn/OErDnjcx",
"LongUrl": "http://www.google.com/",
"ErrMsg": ""
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
$link = $this->getMockLongLink();
$link
->expects($this->once())
->method('setShortUrl')
->with($this->equalTo('https://dwz.cn/OErDnjcx'));
$this->mockClient($response, 'post');
$this->provider->shorten($link);
}
/**
* Tests the expand method throws exception if Baidu returns a string.
*/
public function testExpandThrowsExceptionIfResponseApiIsString()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Baidu response is probably mal-formed because cannot be json-decoded.');
$this->mockClient($this->getMockResponseAsString(), 'post');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Baidu returns an error response.
*/
public function testExpandThrowsExceptionIfApiResponseIsError()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Baidu returned code error message "-1: long url is not valid');
$this->mockClient($this->getMockResponseWithError(), 'post');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Baidu returns a response with no longUrl.
*/
public function testExpandThrowsExceptionIfApiResponseHasNoLongUrl()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Baidu returned code error message "-2: short url dose not exist');
$this->mockClient($this->getMockResponseWithNoLongUrl(), 'post');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Baidu returns a response with no status.
*/
public function testExpandThrowsExceptionIfApiResponseHasNoStatus()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Property "Code" does not exist within Baidu response.');
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"ShortUrl": "https://dwz.cn/OErDnjcx",
"LongUrl": "http://www.google.com/",
"ErrMsg": ""
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
$this->mockClient($response, 'post');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method with a valid Baidu's response.
*/
public function testExpandWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"Code": 0,
"ShortUrl": "https://dwz.cn/OErDnjcx",
"LongUrl": "http://www.google.com/",
"ErrMsg": ""
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
$link = $this->getMockShortLink();
$link
->expects($this->once())
->method('setLongUrl')
->with($this->equalTo('http://www.google.com/'));
$this->mockClient($response, 'post');
$this->provider->expand($link);
}
/**
* Gets a mocked response.
*
* @return object
*/
private function getBaseMockResponse()
{
return $this->createMock(ResponseInterface::class);
}
/**
* Gets mock of stream.
*
* @return object
*/
private function getBaseMockStream()
{
return $this->createMock(StreamInterface::class);
}
/**
* Returns an invalid response string.
*
* @return object
*/
private function getMockResponseAsString()
{
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue('foo'));
$response = $this->getBaseMockResponse();
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
return $response;
}
/**
* Returns a response object with "error" node.
*
* @return object
*/
private function getMockResponseWithError()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"Code": -1,
"ShortUrl": "http://www.google.com/",
"LongUrl": ":",
"ErrMsg": "long url is not valid"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
return $response;
}
/**
* Returns a response object with no "id" node.
*
* @return object
*/
private function getMockResponseWithNoShortUrl()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"Code": -1,
"LongUrl": "http://www.google.com/",
"ErrMsg": "unsafe url"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
return $response;
}
/**
* Returns a response object with no "LongUrl" node.
*
* @return object
*/
private function getMockResponseWithNoLongUrl()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"Code": -2,
"ShortUrl": "https://dwz.cn/OErDnjcxd",
"LongUrl": "",
"ErrMsg": "short url dose not exist"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
return $response;
}
/**
* Mocks the client.
*
* @param object $response A mocked response
* @param string $requestMethod A request method (get|post)
*/
private function mockClient($response, $requestMethod)
{
$client = $this->getMockBuilder(ClientInterface::class)
->setMethods(['send', 'sendAsync', 'request', 'requestAsync', 'getConfig', 'get', 'post'])
->getMock();
$client
->expects($this->once())
->method($requestMethod)
->will($this->returnValue($response));
$this->provider
->expects($this->once())
->method('createClient')
->will($this->returnValue($client));
}
/**
* Gets mock of link.
*
* @return object
*/
private function getBaseMockLink()
{
return $this->createMock(LinkInterface::class);
}
/**
* Gets mock of short link.
*
* @return object
*/
private function getMockShortLink()
{
$link = $this->getBaseMockLink();
$link
->expects($this->once())
->method('getShortUrl')
->will($this->returnValue('https://dwz.cn/OErDnjcx'));
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

@@ -11,14 +11,21 @@
namespace Mremi\UrlShortener\Tests\Provider\Bitly;
use GuzzleHttp\ClientInterface;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\Bitly\AuthenticationInterface;
use Mremi\UrlShortener\Provider\Bitly\BitlyProvider;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
/**
* Tests BitlyProvider class
* Tests BitlyProvider class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class BitlyProviderTest extends \PHPUnit_Framework_TestCase
class BitlyProviderTest extends TestCase
{
/**
* @var object
@@ -26,69 +33,67 @@ class BitlyProviderTest extends \PHPUnit_Framework_TestCase
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.
* Tests the shorten method throws exception if Bit.ly returns a string.
*/
public function testShortenThrowsExceptionIfApiResponseIsString()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Bit.ly response is probably mal-formed because cannot be json-decoded.');
$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"
* Tests the shorten method throws exception if Bit.ly returns an invalid status code.
*/
public function testShortenThrowsExceptionIfApiResponseHasInvalidStatusCode()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Bit.ly returned status code "404" with message "NOT_FOUND"');
$this->mockClient($this->getMockResponseWithInvalidStatusCode());
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method with a valid Bit.ly's response
* Tests the shorten method with a valid Bit.ly's response.
*/
public function testShortenWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
$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"
"id": "bit.ly/ze6poY",
"link": "http://bit.ly/ze6poY",
"long_url": "http://www.google.com/",
"created_at": "2012-03-12T16:18:23+0000",
"created_by": "xyzzy",
"client_id": "3f5101961529477287d0714a17a68023",
"references": {
"group": "https://api-ssl.bitly.com/v4/groups/74a81764c9d9"
}
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
->will($this->returnValue($stream));
$response
->expects($this->once())
->method('getStatusCode')
->will($this->returnValue(201));
$link = $this->getMockLongLink();
$link
@@ -102,72 +107,62 @@ JSON;
}
/**
* 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.
* Tests the expand method throws exception if Bit.ly returns a string.
*/
public function testExpandThrowsExceptionIfApiResponseIsString()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Bit.ly response is probably mal-formed because cannot be json-decoded.');
$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"
* Tests the expand method throws exception if Bit.ly returns an invalid status code.
*/
public function testExpandThrowsExceptionIfApiResponseHasInvalidStatusCode()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Bit.ly returned status code "404" with message "NOT_FOUND"');
$this->mockClient($this->getMockResponseWithInvalidStatusCode());
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method with a valid Bit.ly's response
* Tests the expand method with a valid Bit.ly's response.
*/
public function testExpandWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
$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"
"id":"bit.ly/ze6poY",
"link":"http://bit.ly/ze6poY",
"long_url": "http://www.google.com/",
"created_at":"2012-03-12T16:18:23+0000"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
->will($this->returnValue($stream));
$response
->expects($this->once())
->method('getStatusCode')
->will($this->returnValue(200));
$link = $this->getMockShortLink();
$link
@@ -181,57 +176,71 @@ JSON;
}
/**
* Initializes the provider
* Initializes the provider.
*/
protected function setUp()
{
$auth = $this->getMock('Mremi\UrlShortener\Provider\Bitly\AuthenticationInterface');
$auth = $this->createMock(AuthenticationInterface::class);
$this->provider = $this->getMockBuilder('Mremi\UrlShortener\Provider\Bitly\BitlyProvider')
->setConstructorArgs(array($auth))
->setMethods(array('createClient'))
$this->provider = $this->getMockBuilder(BitlyProvider::class)
->setConstructorArgs([$auth])
->setMethods(['createClient'])
->getMock();
}
/**
* Cleanups the provider
* Cleanups the provider.
*/
protected function tearDown()
{
unset($this->provider);
$this->provider = null;
}
/**
* Gets mock of response
* Gets mock of response.
*
* @return object
*/
private function getBaseMockResponse()
{
return $this->getMockBuilder('Guzzle\Http\Message\Response')
->disableOriginalConstructor()
->getMock();
return $this->createMock(ResponseInterface::class);
}
/**
* Returns an invalid response string
* Gets mock of stream.
*
* @return object
*/
private function getBaseMockStream()
{
return $this->createMock(StreamInterface::class);
}
/**
* Returns an invalid response string.
*
* @return object
*/
private function getMockResponseAsString()
{
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue('foo'));
$response = $this->getBaseMockResponse();
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue('foo'));
->will($this->returnValue($stream));
return $response;
}
/**
* Returns an invalid response object
* Returns an invalid response object.
*
* @return object
*/
@@ -239,28 +248,36 @@ JSON;
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
$apiRawResponse = <<<'JSON'
{
"data": {
"global_hash": "900913",
"hash": "ze6poY",
"long_url": "http://www.google.com/",
"new_hash": 0,
"url": "http://bit.ly/ze6poY"
}
"id":"bit.ly/ze6poY",
"link":"http://bit.ly/ze6poY",
"longUrl": "http://www.google.com/",
"createdAt":"2012-03-12T16:18:23+0000"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
->will($this->returnValue($stream));
$response
->expects($this->once())
->method('getStatusCode')
->will($this->returnValue(200));
return $response;
}
/**
* Returns a response with an invalid status code
* Returns a response with an invalid status code.
*
* @return object
*/
@@ -268,46 +285,47 @@ JSON;
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
$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"
"message": "NOT_FOUND",
"resource": "bitlinks",
"description": "What you are looking for cannot be found."
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
->will($this->returnValue($stream));
$response
->expects($this->once())
->method('getStatusCode')
->will($this->returnValue(404));
return $response;
}
/**
* Mocks the client
* 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 = $this->getMockBuilder(ClientInterface::class)
->setMethods(['send', 'sendAsync', 'request', 'requestAsync', 'getConfig', 'get', 'post'])
->getMock();
$client
->expects($this->once())
->method('get')
->will($this->returnValue($request));
->method('post')
->will($this->returnValue($response));
$this->provider
->expects($this->once())
@@ -316,17 +334,17 @@ JSON;
}
/**
* Gets mock of link
* Gets mock of link.
*
* @return object
*/
private function getBaseMockLink()
{
return $this->getMock('Mremi\UrlShortener\Model\LinkInterface');
return $this->createMock(LinkInterface::class);
}
/**
* Gets mock of short link
* Gets mock of short link.
*
* @return object
*/
@@ -343,7 +361,7 @@ JSON;
}
/**
* Gets mock of long link
* Gets mock of long link.
*
* @return object
*/

View File

@@ -0,0 +1,46 @@
<?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\AuthenticationInterface;
use Mremi\UrlShortener\Provider\Bitly\GenericAccessTokenAuthenticator;
use PHPUnit\Framework\TestCase;
/**
* Tests GenericAccessTokenAuthenticator class.
*
* @author Marcus Sá <marcusesa@gmail.com>
*/
class GenericAccessTokenAuthenticatorTest extends TestCase
{
const GENERIC_ACCESS_TOKEN = '9a2j4kal4701mk2enk15lmi2';
/**
* Test if GenericAccessTokenAuthenticator implements AuthenticationInterface.
*/
public function testGenericAccessTokenShouldImplementsAuthenticationInterface()
{
$genericAccessTokenAuthenticator = new GenericAccessTokenAuthenticator(self::GENERIC_ACCESS_TOKEN);
$this->assertInstanceOf(AuthenticationInterface::class, $genericAccessTokenAuthenticator);
}
/**
* Test if getAccessToken method return the generic access token provided.
*/
public function testGetAccessTokenShouldReturnGenericAccessToken()
{
$genericAccessTokenAuthenticator = new GenericAccessTokenAuthenticator(self::GENERIC_ACCESS_TOKEN);
$this->assertSame(self::GENERIC_ACCESS_TOKEN, $genericAccessTokenAuthenticator->getAccessToken());
}
}

View File

@@ -11,35 +11,42 @@
namespace Mremi\UrlShortener\Tests\Provider;
use Mremi\UrlShortener\Provider\Baidu\BaiduProvider;
use Mremi\UrlShortener\Provider\Bitly\BitlyProvider;
use Mremi\UrlShortener\Provider\ChainProvider;
use Mremi\UrlShortener\Provider\Google\GoogleProvider;
use Mremi\UrlShortener\Provider\Sina\SinaProvider;
use Mremi\UrlShortener\Provider\Wechat\WechatProvider;
use PHPUnit\Framework\TestCase;
use RuntimeException;
/**
* Tests ChainProvider class
* Tests ChainProvider class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class ChainProviderTest extends \PHPUnit_Framework_TestCase
class ChainProviderTest extends TestCase
{
/**
* Tests that an unknown provider throws an exception
*
* @expectedException \RuntimeException
* @expectedExceptionMessage Unable to retrieve the provider named: "foo"
* Tests that an unknown provider throws an exception.
*/
public function testUnknownProvider()
{
$chainProvider = new ChainProvider;
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('Unable to retrieve the provider named: "foo"');
$chainProvider = new ChainProvider();
$chainProvider->getProvider('foo');
}
/**
* Tests to add and get some providers
* Tests to add and get some providers.
*/
public function testAddAndGetProviders()
{
$chainProvider = new ChainProvider;
$chainProvider = new ChainProvider();
$bitlyProvider = $this->getMockBuilder('Mremi\UrlShortener\Provider\Bitly\BitlyProvider')
$bitlyProvider = $this->getMockBuilder(BitlyProvider::class)
->disableOriginalConstructor()
->getMock();
@@ -50,12 +57,12 @@ class ChainProviderTest extends \PHPUnit_Framework_TestCase
$chainProvider->addProvider($bitlyProvider);
$this->assertEquals($bitlyProvider, $chainProvider->getProvider('bitly'));
$this->assertSame($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')
$googleProvider = $this->getMockBuilder(GoogleProvider::class)
->disableOriginalConstructor()
->getMock();
@@ -66,9 +73,57 @@ class ChainProviderTest extends \PHPUnit_Framework_TestCase
$chainProvider->addProvider($googleProvider);
$this->assertEquals($googleProvider, $chainProvider->getProvider('google'));
$this->assertSame($googleProvider, $chainProvider->getProvider('google'));
$this->assertArrayHasKey('google', $chainProvider->getProviders());
$this->assertTrue($chainProvider->hasProvider('google'));
$this->assertCount(2, $chainProvider->getProviders());
$baiduProvider = $this->getMockBuilder(BaiduProvider::class)
->disableOriginalConstructor()
->getMock();
$baiduProvider
->expects($this->once())
->method('getName')
->will($this->returnValue('baidu'));
$chainProvider->addProvider($baiduProvider);
$this->assertSame($baiduProvider, $chainProvider->getProvider('baidu'));
$this->assertArrayHasKey('baidu', $chainProvider->getProviders());
$this->assertTrue($chainProvider->hasProvider('baidu'));
$this->assertCount(3, $chainProvider->getProviders());
$sinaProvider = $this->getMockBuilder(SinaProvider::class)
->disableOriginalConstructor()
->getMock();
$sinaProvider
->expects($this->once())
->method('getName')
->will($this->returnValue('sina'));
$chainProvider->addProvider($sinaProvider);
$this->assertSame($sinaProvider, $chainProvider->getProvider('sina'));
$this->assertArrayHasKey('sina', $chainProvider->getProviders());
$this->assertTrue($chainProvider->hasProvider('sina'));
$this->assertCount(4, $chainProvider->getProviders());
$wechatProvider = $this->getMockBuilder(WechatProvider::class)
->disableOriginalConstructor()
->getMock();
$wechatProvider
->expects($this->once())
->method('getName')
->will($this->returnValue('wechat'));
$chainProvider->addProvider($wechatProvider);
$this->assertSame($wechatProvider, $chainProvider->getProvider('wechat'));
$this->assertArrayHasKey('wechat', $chainProvider->getProviders());
$this->assertTrue($chainProvider->hasProvider('google'));
$this->assertCount(5, $chainProvider->getProviders());
}
}

View File

@@ -11,14 +11,20 @@
namespace Mremi\UrlShortener\Tests\Provider\Google;
use GuzzleHttp\ClientInterface;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\Google\GoogleProvider;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
/**
* Tests GoogleProvider class
* Tests GoogleProvider class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class GoogleProviderTest extends \PHPUnit_Framework_TestCase
class GoogleProviderTest extends TestCase
{
/**
* @var object
@@ -26,7 +32,7 @@ class GoogleProviderTest extends \PHPUnit_Framework_TestCase
private $provider;
/**
* Tests the getUri method with no API key and no parameters
* Tests the getUri method with no API key and no parameters.
*/
public function testGetUriWithNoApiKeyAndNoParameters()
{
@@ -39,20 +45,20 @@ class GoogleProviderTest extends \PHPUnit_Framework_TestCase
}
/**
* Tests the getUri method with no API key and some parameters
* 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'));
$uri = $method->invoke($this->provider, ['foo' => 'bar']);
$this->assertEquals('?foo=bar', $uri);
$this->assertSame('?foo=bar', $uri);
}
/**
* Tests the getUri method with API key and no parameters
* Tests the getUri method with API key and no parameters.
*/
public function testGetUriWithApiKeyAndNoParameters()
{
@@ -63,11 +69,11 @@ class GoogleProviderTest extends \PHPUnit_Framework_TestCase
$uri = $method->invoke($provider);
$this->assertEquals('?key=secret', $uri);
$this->assertSame('?key=secret', $uri);
}
/**
* Tests the getUri method with API key and some parameters
* Tests the getUri method with API key and some parameters.
*/
public function testGetUriWithApiKeyAndSomeParameters()
{
@@ -76,71 +82,71 @@ class GoogleProviderTest extends \PHPUnit_Framework_TestCase
$method = new \ReflectionMethod($provider, 'getUri');
$method->setAccessible(true);
$uri = $method->invoke($provider, array('foo' => 'bar'));
$uri = $method->invoke($provider, ['foo' => 'bar']);
$this->assertEquals('?foo=bar&key=secret', $uri);
$this->assertSame('?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.
* Tests the shorten method throws exception if Google returns a string.
*/
public function testShortenThrowsExceptionIfResponseApiIsString()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Google response is probably mal-formed because cannot be json-decoded.');
$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"
* Tests the shorten method throws exception if Google returns an error response.
*/
public function testShortenThrowsExceptionIfApiResponseIsError()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Google returned status code "400" with message "Required"');
$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.
* Tests the shorten method throws exception if Google returns a response with no id.
*/
public function testShortenThrowsExceptionIfApiResponseHasNoId()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Property "id" does not exist within Google response.');
$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.
* Tests the shorten method throws exception if Google returns a response with no longUrl.
*/
public function testShortenThrowsExceptionIfApiResponseHasNoLongUrl()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Property "longUrl" does not exist within Google response.');
$this->mockClient($this->getMockResponseWithNoLongUrl(), 'post');
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method with a valid Google's response
* Tests the shorten method with a valid Google's response.
*/
public function testShortenWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
$apiRawResponse = <<<'JSON'
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS",
@@ -148,10 +154,16 @@ class GoogleProviderTest extends \PHPUnit_Framework_TestCase
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
->will($this->returnValue($stream));
$link = $this->getMockLongLink();
$link
@@ -165,68 +177,68 @@ JSON;
}
/**
* 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.
* Tests the expand method throws exception if Google returns a string.
*/
public function testExpandThrowsExceptionIfResponseApiIsString()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Google response is probably mal-formed because cannot be json-decoded.');
$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"
* Tests the expand method throws exception if Google returns an error response.
*/
public function testExpandThrowsExceptionIfApiResponseIsError()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Google returned status code "400" with message "Required"');
$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.
* Tests the expand method throws exception if Google returns a response with no id.
*/
public function testExpandThrowsExceptionIfApiResponseHasNoId()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Property "id" does not exist within Google response.');
$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.
* Tests the expand method throws exception if Google returns a response with no longUrl.
*/
public function testExpandThrowsExceptionIfApiResponseHasNoLongUrl()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Property "longUrl" does not exist within Google response.');
$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.
* Tests the expand method throws exception if Google returns a response with no status.
*/
public function testExpandThrowsExceptionIfApiResponseHasNoStatus()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Property "status" does not exist within Google response.');
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
$apiRawResponse = <<<'JSON'
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS",
@@ -234,10 +246,16 @@ JSON;
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
->will($this->returnValue($stream));
$this->mockClient($response, 'get');
@@ -245,16 +263,16 @@ JSON;
}
/**
* Tests the expand method throws exception if Google returns an invalid status code
*
* @expectedException \Mremi\UrlShortener\Exception\InvalidApiResponseException
* @expectedExceptionMessage Google returned status code "KO".
* Tests the expand method throws exception if Google returns an invalid status code.
*/
public function testExpandThrowsExceptionIfApiResponseHasInvalidStatusCode()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Google returned status code "KO".');
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
$apiRawResponse = <<<'JSON'
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS",
@@ -263,10 +281,16 @@ JSON;
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
->will($this->returnValue($stream));
$this->mockClient($response, 'get');
@@ -274,13 +298,13 @@ JSON;
}
/**
* Tests the expand method with a valid Google's response
* Tests the expand method with a valid Google's response.
*/
public function testExpandWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
$apiRawResponse = <<<'JSON'
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS",
@@ -289,10 +313,16 @@ JSON;
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
->will($this->returnValue($stream));
$link = $this->getMockShortLink();
$link
@@ -306,54 +336,68 @@ JSON;
}
/**
* Initializes the provider
* Initializes the provider.
*/
protected function setUp()
{
$this->provider = $this->getMockBuilder('Mremi\UrlShortener\Provider\Google\GoogleProvider')
->setMethods(array('createClient'))
$this->provider = $this->getMockBuilder(GoogleProvider::class)
->setMethods(['createClient'])
->getMock();
}
/**
* Cleanups the provider
* Cleanups the provider.
*/
protected function tearDown()
{
unset($this->provider);
$this->provider = null;
}
/**
* Gets a mocked response
* Gets a mocked response.
*
* @return object
*/
private function getBaseMockResponse()
{
return $this->getMockBuilder('Guzzle\Http\Message\Response')
->disableOriginalConstructor()
->getMock();
return $this->createMock(ResponseInterface::class);
}
/**
* Returns an invalid response string
* Gets mock of stream.
*
* @return object
*/
private function getBaseMockStream()
{
return $this->createMock(StreamInterface::class);
}
/**
* Returns an invalid response string.
*
* @return object
*/
private function getMockResponseAsString()
{
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue('foo'));
$response = $this->getBaseMockResponse();
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue('foo'));
->will($this->returnValue($stream));
return $response;
}
/**
* Returns a response object with "error" node
* Returns a response object with "error" node.
*
* @return object
*/
@@ -361,7 +405,7 @@ JSON;
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
$apiRawResponse = <<<'JSON'
{
"error": {
"errors": [
@@ -379,16 +423,22 @@ JSON;
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
->will($this->returnValue($stream));
return $response;
}
/**
* Returns a response object with no "id" node
* Returns a response object with no "id" node.
*
* @return object
*/
@@ -396,23 +446,29 @@ JSON;
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
$apiRawResponse = <<<'JSON'
{
"kind": "urlshortener#url",
"longUrl": "http://www.google.com/"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
->will($this->returnValue($stream));
return $response;
}
/**
* Returns a response object with no "longUrl" node
* Returns a response object with no "longUrl" node.
*
* @return object
*/
@@ -420,40 +476,42 @@ JSON;
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<JSON
$apiRawResponse = <<<'JSON'
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($apiRawResponse));
->will($this->returnValue($stream));
return $response;
}
/**
* Mocks the client
* 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 = $this->getMockBuilder(ClientInterface::class)
->setMethods(['send', 'sendAsync', 'request', 'requestAsync', 'getConfig', 'get', 'post'])
->getMock();
$client
->expects($this->once())
->method($requestMethod)
->will($this->returnValue($request));
->will($this->returnValue($response));
$this->provider
->expects($this->once())
@@ -462,17 +520,17 @@ JSON;
}
/**
* Gets mock of link
* Gets mock of link.
*
* @return object
*/
private function getBaseMockLink()
{
return $this->getMock('Mremi\UrlShortener\Model\LinkInterface');
return $this->createMock(LinkInterface::class);
}
/**
* Gets mock of short link
* Gets mock of short link.
*
* @return object
*/
@@ -489,7 +547,7 @@ JSON;
}
/**
* Gets mock of long link
* Gets mock of long link.
*
* @return object
*/

View File

@@ -0,0 +1,484 @@
<?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\Sina;
use GuzzleHttp\ClientInterface;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\Sina\SinaProvider;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
/**
* Tests SinaProvider class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class SinaProviderTest extends TestCase
{
/**
* @var object
*/
private $provider;
/**
* Initializes the provider.
*/
protected function setUp()
{
$this->provider = $this->getMockBuilder(SinaProvider::class)
->setMethods(['createClient'])
->getMock();
}
/**
* Cleanups the provider.
*/
protected function tearDown()
{
$this->provider = null;
}
/**
* Tests the shorten method throws exception if Sina returns a string.
*/
public function testShortenThrowsExceptionIfResponseApiIsString()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Sina response is probably mal-formed because cannot be json-decoded.');
$this->mockClient($this->getMockResponseAsString(), 'get');
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method throws exception if Sina returns an error response.
*/
public function testShortenThrowsExceptionIfApiResponseIsError()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Sina returned status code "10006" with message "source paramter(appkey) is missing');
$this->mockClient($this->getMockResponseWithError(), 'get');
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method throws exception if Sina returns a response with no id.
*/
public function testShortenThrowsExceptionIfApiResponseHasNoId()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Sina returned status code "10006" with message "source paramter(appkey) is missing');
$this->mockClient($this->getMockResponseWithNoId(), 'get');
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method throws exception if Sina returns a response with no longUrl.
*/
public function testShortenThrowsExceptionIfApiResponseHasNoLongUrl()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Property "longUrl" does not exist within Sina response.');
$this->mockClient($this->getMockResponseWithNoLongUrl(), 'get');
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method with a valid Sina's response.
*/
public function testShortenWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"urls": [
{
"result": true,
"url_short": "http://t.cn/h5ef4",
"url_long": "http://www.google.com/",
"object_type": "webpage",
"type": 39,
"object_id": "3000001411:ff90821feeb2b02a33a6f9fc8e5f3fcd"
}
]
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
$link = $this->getMockLongLink();
$link
->expects($this->once())
->method('setShortUrl')
->with($this->equalTo('http://t.cn/h5ef4'));
$this->mockClient($response, 'get');
$this->provider->shorten($link);
}
/**
* Tests the expand method throws exception if Sina returns a string.
*/
public function testExpandThrowsExceptionIfResponseApiIsString()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Sina response is probably mal-formed because cannot be json-decoded.');
$this->mockClient($this->getMockResponseAsString(), 'get');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Sina returns an error response.
*/
public function testExpandThrowsExceptionIfApiResponseIsError()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Sina returned status code "10006" with message "source paramter(appkey) is missing"');
$this->mockClient($this->getMockResponseWithError(), 'get');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Sina returns a response with no id.
*/
public function testExpandThrowsExceptionIfApiResponseHasNoId()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Sina returned status code "10006" with message "source paramter(appkey) is missing"');
$this->mockClient($this->getMockResponseWithNoId(), 'get');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Sina returns a response with no longUrl.
*/
public function testExpandThrowsExceptionIfApiResponseHasNoLongUrl()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Property "longUrl" does not exist within Sina response.');
$this->mockClient($this->getMockResponseWithNoLongUrl(), 'get');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method throws exception if Sina returns an invalid status code.
*/
public function testExpandThrowsExceptionIfApiResponseHasInvalidStatusCode()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Sina returned status code "21506" with message "Error: Parameter value is not valid!');
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"error": "Error: Parameter value is not valid!",
"error_code": 21506,
"request": "/2/sinaurl/public/expand.json"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
$this->mockClient($response, 'get');
$this->provider->expand($this->getBaseMockLink());
}
/**
* Tests the expand method with a valid Sina's response.
*/
public function testExpandWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"urls": [
{
"result": true,
"url_short": "http://t.cn/h5ef4",
"url_long": "http://www.google.com/",
"transcode": 0,
"type": 39
}
]
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
$link = $this->getMockShortLink();
$link
->expects($this->once())
->method('setLongUrl')
->with($this->equalTo('http://www.google.com/'));
$this->mockClient($response, 'get');
$this->provider->expand($link);
}
/**
* Gets a mocked response.
*
* @return object
*/
private function getBaseMockResponse()
{
return $this->createMock(ResponseInterface::class);
}
/**
* Gets mock of stream.
*
* @return object
*/
private function getBaseMockStream()
{
return $this->createMock(StreamInterface::class);
}
/**
* Returns an invalid response string.
*
* @return object
*/
private function getMockResponseAsString()
{
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue('foo'));
$response = $this->getBaseMockResponse();
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
return $response;
}
/**
* Returns a response object with "error" node.
*
* @return object
*/
private function getMockResponseWithError()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"error": "source paramter(appkey) is missing",
"error_code": 10006,
"request": "/2/short_url/expand.json"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
return $response;
}
/**
* Returns a response object with no "id" node.
*
* @return object
*/
private function getMockResponseWithNoId()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"error": "source paramter(appkey) is missing",
"error_code": 10006,
"request": "/2/short_url/shorten.json"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
return $response;
}
/**
* Returns a response object with no "longUrl" node.
*
* @return object
*/
private function getMockResponseWithNoLongUrl()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"urls": [
{
"result": true,
"url_short": "http://t.cn/RkXgjKTd",
"url_long": "",
"transcode": 0,
"type": 0
}
]
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
return $response;
}
/**
* Mocks the client.
*
* @param object $response A mocked response
* @param string $requestMethod A request method (get|post)
*/
private function mockClient($response, $requestMethod)
{
$client = $this->getMockBuilder(ClientInterface::class)
->setMethods(['send', 'sendAsync', 'request', 'requestAsync', 'getConfig', 'get', 'post'])
->getMock();
$client
->expects($this->once())
->method($requestMethod)
->will($this->returnValue($response));
$this->provider
->expects($this->once())
->method('createClient')
->will($this->returnValue($client));
}
/**
* Gets mock of link.
*
* @return object
*/
private function getBaseMockLink()
{
return $this->createMock(LinkInterface::class);
}
/**
* Gets mock of short link.
*
* @return object
*/
private function getMockShortLink()
{
$link = $this->getBaseMockLink();
$link
->expects($this->once())
->method('getShortUrl')
->will($this->returnValue('http://t.cn/h5ef4'));
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,312 @@
<?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\Wechat;
use GuzzleHttp\ClientInterface;
use Mremi\UrlShortener\Exception\InvalidApiResponseException;
use Mremi\UrlShortener\Model\LinkInterface;
use Mremi\UrlShortener\Provider\Bitly\AuthenticationInterface;
use Mremi\UrlShortener\Provider\Wechat\WechatProvider;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
/**
* Tests WechatProvider class.
*
* @author Rémi Marseille <marseille.remi@gmail.com>
*/
class WechatProviderTest extends TestCase
{
/**
* @var object
*/
private $provider;
/**
* Initializes the provider.
*/
protected function setUp()
{
$auth = $this->createMock(AuthenticationInterface::class);
$this->provider = $this->getMockBuilder(WechatProvider::class)
->setConstructorArgs([$auth])
->setMethods(['createClient'])
->getMock();
}
/**
* Cleanups the provider.
*/
protected function tearDown()
{
$this->provider = null;
}
/**
* Tests the shorten method throws exception if Wechat returns a string.
*/
public function testShortenThrowsExceptionIfApiResponseIsString()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Wechat response is probably mal-formed because cannot be json-decoded.');
$this->mockClient($this->getMockResponseAsString());
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method throws exception if Wechat returns a response with no errcode.
*/
public function testShortenThrowsExceptionIfApiResponseHasNoErrorCode()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Property "errcode" does not exist within Wechat response.');
$this->mockClient($this->getMockResponseAsInvalidObject());
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method throws exception if Wechat returns an invalid status code.
*/
public function testShortenThrowsExceptionIfApiResponseHasInvalidStatusCode()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Wechat returned status code "40001" with message "invalid credential, access_token is invalid or not latest hint: [miSs30226vr31!]"');
$this->mockClient($this->getMockResponseWithInvalidStatusCode());
$this->provider->shorten($this->getBaseMockLink());
}
/**
* Tests the shorten method with a valid Wechat's response.
*/
public function testShortenWithValidApiResponse()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"errcode": 0,
"errmsg": "ok",
"short_url": "https://w.url.cn/s/ATYfzFm"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
$link = $this->getMockLongLink();
$link
->expects($this->once())
->method('setShortUrl')
->with($this->equalTo('https://w.url.cn/s/ATYfzFm'));
$this->mockClient($response);
$this->provider->shorten($link);
}
/**
* Tests the expand method throws exception if Wechat returns a string.
*/
public function testExpandThrowsExceptionIfApiResponseIsString()
{
$this->expectException(InvalidApiResponseException::class);
$this->expectExceptionMessage('Wechat does not support expand url yet.');
//$this->mockClient($this->getMockResponseAsString());
$this->provider->expand($this->getBaseMockLink());
}
/**
* Gets mock of response.
*
* @return object
*/
private function getBaseMockResponse()
{
return $this->createMock(ResponseInterface::class);
}
/**
* Gets mock of stream.
*
* @return object
*/
private function getBaseMockStream()
{
return $this->createMock(StreamInterface::class);
}
/**
* Returns an invalid response string.
*
* @return object
*/
private function getMockResponseAsString()
{
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue('foo'));
$response = $this->getBaseMockResponse();
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
return $response;
}
/**
* Returns an invalid response object.
*
* @return object
*/
private function getMockResponseAsInvalidObject()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"errmsg": "ok",
"url": "https://w.url.cn/s/AK0wSn1"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
return $response;
}
/**
* Returns a response with an invalid status code.
*
* @return object
*/
private function getMockResponseWithInvalidStatusCode()
{
$response = $this->getBaseMockResponse();
$apiRawResponse = <<<'JSON'
{
"errcode": 40001,
"errmsg": "invalid credential, access_token is invalid or not latest hint: [miSs30226vr31!]"
}
JSON;
$stream = $this->getBaseMockStream();
$stream
->expects($this->once())
->method('getContents')
->will($this->returnValue($apiRawResponse));
$response
->expects($this->once())
->method('getBody')
->will($this->returnValue($stream));
return $response;
}
/**
* Mocks the client.
*
* @param object $response
*/
private function mockClient($response)
{
$client = $this->getMockBuilder(ClientInterface::class)
->setMethods(['send', 'sendAsync', 'request', 'requestAsync', 'getConfig', 'get', 'post'])
->getMock();
$client
->expects($this->once())
->method('post')
->will($this->returnValue($response));
$this->provider
->expects($this->once())
->method('createClient')
->will($this->returnValue($client));
}
/**
* Gets mock of link.
*
* @return object
*/
private function getBaseMockLink()
{
return $this->createMock(LinkInterface::class);
}
/**
* Gets mock of short link.
*
* @return object
*/
private function getMockShortLink()
{
$link = $this->getBaseMockLink();
$link
->expects($this->once())
->method('getShortUrl')
->will($this->returnValue('https://w.url.cn/s/ATYfzFm'));
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;
}
}