Compare commits

...

48 Commits

Author SHA1 Message Date
Alejandro Celaya
bf24660ddb Merge pull request #526 from acelaya-forks/feature/enhanced-not-found-redirect
Feature/enhanced not found redirect
2019-11-02 21:24:34 +01:00
Alejandro Celaya
b66268867a Updated to shlink-installer 3 2019-11-02 21:15:26 +01:00
Alejandro Celaya
9abaa243e0 Some extra minor improvements 2019-11-02 19:08:07 +01:00
Alejandro Celaya
7030138ff4 Updated changelog 2019-11-02 18:57:16 +01:00
Alejandro Celaya
906dfe60f8 Simplified code to render not-foubnd templates by infering the template to be used inside NotFoundHandler 2019-11-02 18:49:24 +01:00
Alejandro Celaya
01f60614ef Removed hardcoded route names for core routes and used action class names instead 2019-11-02 18:36:15 +01:00
Alejandro Celaya
eeb5306883 Moved all logic to redirect to specific URLs when a 404 is found to the NotFoundHandler 2019-11-02 18:33:26 +01:00
Alejandro Celaya
24c3a3e84c Defined new options for new redirect configuration 2019-11-02 17:23:21 +01:00
Alejandro Celaya
8b9663aea0 Created DeprecatedConfigParserTest 2019-11-02 17:04:49 +01:00
Alejandro Celaya
b59f4e2805 Defined new configs for not found redirects 2019-11-02 11:30:09 +01:00
Alejandro Celaya
6293d57fde Merge pull request #523 from acelaya-forks/feature/refactorings
Feature/refactorings
2019-11-01 17:31:43 +01:00
Alejandro Celaya
39ac2efe26 Updated to latest shlink-common with bug fixes 2019-11-01 17:16:56 +01:00
Alejandro Celaya
1f449e8ce1 Disabled coroutines on swoole during API tests 2019-11-01 10:10:43 +01:00
Alejandro Celaya
ad906000c7 Removed typehint making phpstan throw false positive 2019-11-01 10:04:25 +01:00
Alejandro Celaya
5361f33cc1 Some more refactorings 2019-11-01 09:52:56 +01:00
Alejandro Celaya
1937f3ea22 Trying to automatically persist tags 2019-10-26 09:01:51 +02:00
Alejandro Celaya
f4e9d0c8fe Merge pull request #517 from acelaya-forks/feature/too-long-lock
Updated to shlink-ip-geolocation v1.1
2019-10-25 20:12:54 +02:00
Alejandro Celaya
9b767ee9f3 Updated to shlink-ip-geolocation v1.1 2019-10-25 20:00:26 +02:00
Alejandro Celaya
43cb91bf52 Merge pull request #516 from acelaya-forks/feature/qr-code-with-domain
Feature/qr code with domain
2019-10-22 20:03:37 +02:00
Alejandro Celaya
f784ee5b28 Fixed unit tests 2019-10-22 19:52:28 +02:00
Alejandro Celaya
cd6f067fe5 Ensured domain is taken into account when generating QR codes 2019-10-22 19:43:53 +02:00
Alejandro Celaya
6d366188c9 Added github funding 2019-10-22 19:37:35 +02:00
Alejandro Celaya
c4ca59dcb0 Merge pull request #515 from acelaya-forks/feature/host-and-port
Feature/host and port
2019-10-20 11:14:44 +02:00
Alejandro Celaya
74675ad314 Updated changelog 2019-10-20 10:30:51 +02:00
Alejandro Celaya
b5e4da847a Allowed port number on domain field when creating shotr URLs 2019-10-20 10:30:11 +02:00
Alejandro Celaya
232bf5a68b Merge pull request #513 from acelaya-forks/feature/fix-long-urls
Feature/fix long urls
2019-10-20 10:15:38 +02:00
Alejandro Celaya
67958a78d3 Updated changelog 2019-10-20 09:55:00 +02:00
Alejandro Celaya
b8cdc29d8f Increased long URL size in DB to 2048 characters 2019-10-20 09:53:11 +02:00
Alejandro Celaya
30e4ddb950 Updated to latest infection version 2019-10-20 09:42:46 +02:00
Alejandro Celaya
a61a7db275 Merge pull request #510 from acelaya-forks/feature/update-common
Updated common and qr-code
2019-10-15 19:17:44 +02:00
Alejandro Celaya
0f5e4e7fa2 Updated common and qr-code 2019-10-15 19:06:37 +02:00
Alejandro Celaya
eb17eae781 Merge pull request #506 from acelaya-forks/feature/improved-shortcodes
Feature/improved shortcodes
2019-10-11 12:51:24 +02:00
Alejandro Celaya
740a65f880 Updated references to SHORTCODE_CHARS in docker docs 2019-10-11 11:41:14 +02:00
Alejandro Celaya
5bd7b53e0a Added more tests for new logics 2019-10-11 11:28:53 +02:00
Alejandro Celaya
9538f474de Added logic to check if a short code is in use and regenerate it otherwise 2019-10-11 11:09:33 +02:00
Alejandro Celaya
8f2e78c946 Moved logic to generate random short codes to external function 2019-10-11 09:35:09 +02:00
Alejandro Celaya
2f09ff456c Updated logic to generate random short codes, increasing entropy 2019-10-11 09:14:25 +02:00
Alejandro Celaya
c8d950e04d Merge pull request #504 from acelaya-forks/feature/mariadb
Feature/mariadb
2019-10-06 12:37:22 +02:00
Alejandro Celaya
0f6a0da7a4 Added MariaDB to documentation 2019-10-06 12:27:11 +02:00
Alejandro Celaya
4300fb225f Ensured tests on maria DB are not run on travis, since it would conflict with MySQL 2019-10-06 12:23:02 +02:00
Alejandro Celaya
159021e87c Added MariaDB to issue templates 2019-10-06 11:39:53 +02:00
Alejandro Celaya
9dc6ea9eeb Documented how to use maria db with docker image 2019-10-06 11:38:23 +02:00
Alejandro Celaya
42e84e526e Added mariadb container for development environment 2019-10-06 11:21:41 +02:00
Alejandro Celaya
700ee40109 Merge pull request #503 from acelaya-forks/feature/update-coding-standard
Feature/update coding standard
2019-10-05 18:07:12 +02:00
Alejandro Celaya
4909bd9550 Updated changelog 2019-10-05 17:29:07 +02:00
Alejandro Celaya
e0d20bf8ff Updated to coding styles v2 2019-10-05 17:26:10 +02:00
Alejandro Celaya
09a5284675 Merge pull request #501 from acelaya-forks/feature/v1.19-final
Updated changelog adding final release 1.19.0
2019-10-05 11:09:12 +02:00
Alejandro Celaya
1112f3acdd Updated changelog adding final release 1.19.0 2019-10-05 11:08:50 +02:00
333 changed files with 1311 additions and 503 deletions

View File

@@ -3,7 +3,6 @@ APP_ENV=
SECRET_KEY=
SHORTENED_URL_SCHEMA=
SHORTENED_URL_HOSTNAME=
SHORTCODE_CHARS=
# Database
DB_USER=

1
.github/FUNDING.yml vendored
View File

@@ -1 +1,2 @@
github: ['acelaya']
custom: ['https://acel.me/donate']

View File

@@ -18,7 +18,7 @@ With that said, please fill in the information requested next. More information
* Shlink Version: x.y.z
* PHP Version: x.y.z
* How do you serve Shlink: Self-hosted Apache|Self-hosted nginx|Self-hosted swoole|Docker image
* Database engine used: MySQL|PostgreSQL|SQLite (x.y.z)
* Database engine used: MySQL|MariaDB|PostgreSQL|SQLite (x.y.z)
#### Summary

View File

@@ -18,7 +18,7 @@ With that said, please fill in the information requested next. More information
* Shlink Version: x.y.z
* PHP Version: x.y.z
* How do you serve Shlink: Self-hosted Apache|Self-hosted nginx|Self-hosted swoole|Docker image
* Database engine used: MySQL|PostgreSQL|SQLite (x.y.z)
* Database engine used: MySQL|MariaDB|PostgreSQL|SQLite (x.y.z)
#### Summary

View File

@@ -4,7 +4,47 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org).
## [Unreleased]
## 1.20.0 - 2019-11-02
#### Added
* [#491](https://github.com/shlinkio/shlink/issues/491) Added improved short code generation logic.
Now, short codes are truly random, which removes the guessability factor existing in previous versions.
Generated short codes have 5 characters, and shlink makes sure they keep unique, while making it backwards-compatible.
* [#418](https://github.com/shlinkio/shlink/issues/418) and [#419](https://github.com/shlinkio/shlink/issues/419) Added support to redirect any 404 error to a custom URL.
It was already possible to configure this but only for invalid short URLs. Shlink now also support configuring redirects for the base URL and any other kind of "not found" error.
The three URLs can be different, and it is already possible to pass them to the docker image via configuration or env vars.
The installer also asks for these two new configuration options.
* [#497](https://github.com/shlinkio/shlink/issues/497) Officially added support for MariaDB.
#### Changed
* [#458](https://github.com/shlinkio/shlink/issues/458) Updated coding styles to use [shlinkio/php-coding-standard](https://github.com/shlinkio/php-coding-standard) v2.0.0.
#### Deprecated
* *Nothing*
#### Removed
* * *Nothing*
#### Fixed
* [#507](https://github.com/shlinkio/shlink/issues/507) Fixed error with too long original URLs by increasing size to the maximum value (2048) based on [the standard](https://stackoverflow.com/a/417184).
* [#502](https://github.com/shlinkio/shlink/issues/502) Fixed error when providing the port as part of the domain on short URLs.
* [#509](https://github.com/shlinkio/shlink/issues/509) Fixed error when trying to generate a QR code for a short URL which uses a custom domain.
* [#522](https://github.com/shlinkio/shlink/issues/522) Highly mitigated errors thrown when lots of short URLs are created concurrently including new and existing tags.
## 1.19.0 - 2019-10-05
#### Added

View File

@@ -3,7 +3,7 @@ LABEL maintainer="Alejandro Celaya <alejandro@alejandrocelaya.com>"
ARG SHLINK_VERSION=1.18.1
ENV SHLINK_VERSION ${SHLINK_VERSION}
ENV SWOOLE_VERSION 4.3.3
ENV SWOOLE_VERSION 4.4.8
ENV COMPOSER_VERSION 1.9.0
WORKDIR /etc/shlink

View File

@@ -22,7 +22,7 @@ A PHP-based self-hosted URL shortener that can be used to serve shortened URLs u
First make sure the host where you are going to run shlink fulfills these requirements:
* PHP 7.2 or greater with JSON, APCu, intl, curl, PDO and gd extensions enabled.
* MySQL, PostgreSQL or SQLite.
* MySQL, MariaDB, PostgreSQL or SQLite.
* The web server of your choice with PHP integration (Apache or Nginx recommended).
Then, you will need a built version of the project. There are a few ways to get it.
@@ -49,7 +49,7 @@ Then, you will need a built version of the project. There are a few ways to get
Despite how you built the project, you are going to need to install it now, by following these steps:
* If you are going to use MySQL or PostgreSQL, create an empty database with the name of your choice.
* If you are going to use MySQL, MariaDB or PostgreSQL, create an empty database with the name of your choice.
* Recursively grant write permissions to the `data` directory. Shlink uses it to cache some information.
* Setup the application by running the `bin/install` script. It is a command line tool that will guide you through the installation process. **Take into account that this tool has to be run directly on the server where you plan to host Shlink. Do not run it before uploading/moving it there.**
* Expose shlink to the web, either by using a traditional web server + fast CGI approach, or by using a [swoole](https://www.swoole.co.uk/) non-blocking server.

View File

@@ -1,7 +1,6 @@
#!/usr/bin/env sh
set -e
export APP_ENV=test
export DB_DRIVER=mysql
# Try to stop server just in case it hanged in last execution
vendor/bin/zend-expressive-swoole stop

View File

@@ -23,7 +23,7 @@
"doctrine/dbal": "^2.9",
"doctrine/migrations": "^2.0",
"doctrine/orm": "^2.5",
"endroid/qr-code": "^1.7",
"endroid/qr-code": "^3.6",
"firebase/php-jwt": "^4.0",
"geoip2/geoip2": "^2.9",
"guzzlehttp/guzzle": "^6.3",
@@ -33,10 +33,11 @@
"ocramius/proxy-manager": "~2.2.2",
"phly/phly-event-dispatcher": "^1.0",
"predis/predis": "^1.1",
"shlinkio/shlink-common": "^2.0",
"pugx/shortid-php": "^0.5",
"shlinkio/shlink-common": "^2.2.1",
"shlinkio/shlink-event-dispatcher": "^1.0",
"shlinkio/shlink-installer": "^2.0",
"shlinkio/shlink-ip-geolocation": "^1.0",
"shlinkio/shlink-installer": "^3.0",
"shlinkio/shlink-ip-geolocation": "^1.1",
"symfony/console": "^4.3",
"symfony/filesystem": "^4.3",
"symfony/lock": "^4.3",
@@ -59,12 +60,12 @@
"devster/ubench": "^2.0",
"eaglewu/swoole-ide-helper": "dev-master",
"filp/whoops": "^2.4",
"infection/infection": "^0.13.4",
"phpstan/phpstan": "^0.11.2",
"infection/infection": "^0.14.2",
"phpstan/phpstan": "^0.11.16",
"phpunit/phpcov": "^6.0",
"phpunit/phpunit": "^8.3",
"roave/security-advisories": "dev-master",
"shlinkio/php-coding-standard": "~1.2.2",
"shlinkio/php-coding-standard": "~2.0.0",
"shlinkio/shlink-test-utils": "^1.0",
"symfony/dotenv": "^4.3",
"symfony/var-dumper": "^4.3",
@@ -77,7 +78,10 @@
"Shlinkio\\Shlink\\Rest\\": "module/Rest/src",
"Shlinkio\\Shlink\\Core\\": "module/Core/src",
"Shlinkio\\Shlink\\PreviewGenerator\\": "module/PreviewGenerator/src/"
}
},
"files": [
"module/Core/functions/functions.php"
]
},
"autoload-dev": {
"psr-4": {
@@ -110,18 +114,25 @@
],
"test:ci": [
"@test:unit:ci",
"@test:db",
"@test:db:ci",
"@test:api"
],
"test:unit": "phpdbg -qrr vendor/bin/phpunit --order-by=random --colors=always --coverage-php build/coverage-unit.cov --testdox",
"test:unit:ci": "phpdbg -qrr vendor/bin/phpunit --order-by=random --colors=always --coverage-php build/coverage-unit.cov --coverage-clover=build/clover.xml --coverage-xml=build/coverage-xml --log-junit=build/phpunit.junit.xml --testdox",
"test:db": [
"@test:db:sqlite",
"@test:db:mysql",
"@test:db:maria",
"@test:db:postgres"
],
"test:db:ci": [
"@test:db:sqlite",
"@test:db:mysql",
"@test:db:postgres"
],
"test:db:sqlite": "APP_ENV=test phpdbg -qrr vendor/bin/phpunit --order-by=random --colors=always -c phpunit-db.xml --coverage-php build/coverage-db.cov --testdox",
"test:db:mysql": "DB_DRIVER=mysql composer test:db:sqlite",
"test:db:maria": "DB_DRIVER=maria composer test:db:sqlite",
"test:db:postgres": "DB_DRIVER=postgres composer test:db:sqlite",
"test:api": "bin/test/run-api-tests.sh",
@@ -140,7 +151,6 @@
]
},
"scripts-descriptions": {
"check": "<fg=blue;options=bold>Alias for \"cs\", \"stan\", \"test\" and \"infect\"</>",
"ci": "<fg=blue;options=bold>Alias for \"cs\", \"stan\", \"test:ci\" and \"infect:ci\"</>",
"cs": "<fg=blue;options=bold>Checks coding styles</>",
"cs:fix": "<fg=blue;options=bold>Fixes coding styles, when possible</>",
@@ -149,9 +159,11 @@
"test:ci": "<fg=blue;options=bold>Runs all test suites, generating all needed reports and logs for CI envs</>",
"test:unit": "<fg=blue;options=bold>Runs unit test suites</>",
"test:unit:ci": "<fg=blue;options=bold>Runs unit test suites, generating all needed reports and logs for CI envs</>",
"test:db": "<fg=blue;options=bold>Runs database test suites on a SQLite, MySQL and PostgreSQL</>",
"test:db": "<fg=blue;options=bold>Runs database test suites on a SQLite, MySQL, MariaDB and PostgreSQL</>",
"test:db:ci": "<fg=blue;options=bold>Runs database test suites on a SQLite, MySQL and PostgreSQL</>",
"test:db:sqlite": "<fg=blue;options=bold>Runs database test suites on a SQLite database</>",
"test:db:mysql": "<fg=blue;options=bold>Runs database test suites on a MySQL database</>",
"test:db:maria": "<fg=blue;options=bold>Runs database test suites on a MariaDB database</>",
"test:db:postgres": "<fg=blue;options=bold>Runs database test suites on a PostgreSQL database</>",
"test:api": "<fg=blue;options=bold>Runs API test suites</>",
"test:pretty": "<fg=blue;options=bold>Runs all test suites and generates an HTML code coverage report</>",

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
use function Shlinkio\Shlink\Common\env;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
return [

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
use Zend\ConfigAggregator\ConfigAggregator;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
use Zend\Expressive;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Common;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
return [

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
use Shlinkio\Shlink\Installer\Config\Plugin;
@@ -11,8 +12,6 @@ return [
Plugin\UrlShortenerConfigCustomizer::HOSTNAME,
Plugin\UrlShortenerConfigCustomizer::CHARS,
Plugin\UrlShortenerConfigCustomizer::VALIDATE_URL,
Plugin\UrlShortenerConfigCustomizer::ENABLE_NOT_FOUND_REDIRECTION,
Plugin\UrlShortenerConfigCustomizer::NOT_FOUND_REDIRECT_TO,
],
Plugin\ApplicationConfigCustomizer::class => [
@@ -31,6 +30,12 @@ return [
Plugin\DatabaseConfigCustomizer::HOST,
Plugin\DatabaseConfigCustomizer::PORT,
],
Plugin\RedirectsConfigCustomizer::class => [
Plugin\RedirectsConfigCustomizer::INVALID_SHORT_URL_REDIRECT_TO,
Plugin\RedirectsConfigCustomizer::REGULAR_404_REDIRECT_TO,
Plugin\RedirectsConfigCustomizer::BASE_URL_REDIRECT_TO,
],
],
'installation_commands' => [

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
use Shlinkio\Shlink\Common\Cache\RedisFactory;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink;

View File

@@ -1,7 +1,8 @@
<?php
declare(strict_types=1);
/** @deprecated */
/* @deprecated */
return [
'preview_generation' => [

View File

@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
return [
'not_found_redirects' => [
'invalid_short_url' => null, // Formerly url_shortener.not_found_short_url.redirect_to
'regular_404' => null,
'base_url' => null,
],
];

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
use Zend\Expressive\Router\FastRouteRouter;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
return [

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
return [

View File

@@ -1,7 +1,6 @@
<?php
declare(strict_types=1);
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
declare(strict_types=1);
use function Shlinkio\Shlink\Common\env;
@@ -12,12 +11,7 @@ return [
'schema' => env('SHORTENED_URL_SCHEMA', 'http'),
'hostname' => env('SHORTENED_URL_HOSTNAME'),
],
'shortcode_chars' => env('SHORTCODE_CHARS', UrlShortenerOptions::DEFAULT_CHARS),
'validate_url' => true,
'not_found_short_url' => [
'enable_redirection' => false,
'redirect_to' => null,
],
],
];

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
return [

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
use Doctrine\ORM\EntityManager;
@@ -6,8 +7,10 @@ use Doctrine\ORM\Tools\Console\ConsoleRunner;
use Psr\Container\ContainerInterface;
use Zend\ServiceManager\ServiceManager;
/** @var ContainerInterface|ServiceManager $container */
$container = include __DIR__ . '/container.php';
$em = $container->get(EntityManager::class);
return (function () {
/** @var ContainerInterface|ServiceManager $container */
$container = include __DIR__ . '/container.php';
$em = $container->get(EntityManager::class);
return ConsoleRunner::createHelperSet($em);
return ConsoleRunner::createHelperSet($em);
})();

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink;
@@ -30,4 +31,5 @@ return (new ConfigAggregator\ConfigAggregator([
], 'data/cache/app_config.php', [
Core\Config\SimplifiedConfigParser::class,
Core\Config\BasePathPrefixer::class,
Core\Config\DeprecatedConfigParser::class,
]))->getMergedConfig();

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
use Symfony\Component\Dotenv\Dotenv;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\TestUtils;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\TestUtils;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink;
@@ -15,40 +16,41 @@ use function sys_get_temp_dir;
$swooleTestingHost = '127.0.0.1';
$swooleTestingPort = 9999;
$buildDbConnection = function () {
$buildDbConnection = function (): array {
$driver = env('DB_DRIVER', 'sqlite');
$isCi = env('TRAVIS', false);
$getMysqlHost = function (string $driver) {
return sprintf('shlink_db%s', $driver === 'mysql' ? '' : '_maria');
};
switch ($driver) {
case 'sqlite':
return [
'driver' => 'pdo_sqlite',
'path' => sys_get_temp_dir() . '/shlink-tests.db',
];
case 'mysql':
return [
'driver' => 'pdo_mysql',
'host' => $isCi ? '127.0.0.1' : 'shlink_db',
'user' => 'root',
'password' => $isCi ? '' : 'root',
'dbname' => 'shlink_test',
'charset' => 'utf8',
'driverOptions' => [
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
],
];
case 'postgres':
return [
'driver' => 'pdo_pgsql',
'host' => $isCi ? '127.0.0.1' : 'shlink_db_postgres',
'user' => 'postgres',
'password' => $isCi ? '' : 'root',
'dbname' => 'shlink_test',
'charset' => 'utf8',
];
default:
return [];
}
$driverConfigMap = [
'sqlite' => [
'driver' => 'pdo_sqlite',
'path' => sys_get_temp_dir() . '/shlink-tests.db',
],
'mysql' => [
'driver' => 'pdo_mysql',
'host' => $isCi ? '127.0.0.1' : $getMysqlHost($driver),
'user' => 'root',
'password' => $isCi ? '' : 'root',
'dbname' => 'shlink_test',
'charset' => 'utf8',
'driverOptions' => [
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
],
],
'postgres' => [
'driver' => 'pdo_pgsql',
'host' => $isCi ? '127.0.0.1' : 'shlink_db_postgres',
'user' => 'postgres',
'password' => $isCi ? '' : 'root',
'dbname' => 'shlink_test',
'charset' => 'utf8',
],
];
$driverConfigMap['maria'] = $driverConfigMap['mysql'];
return $driverConfigMap[$driver] ?? [];
};
return [
@@ -64,6 +66,7 @@ return [
],
'zend-expressive-swoole' => [
'enable_coroutine' => false,
'swoole-http-server' => [
'host' => $swooleTestingHost,
'port' => $swooleTestingPort,
@@ -72,6 +75,7 @@ return [
'pid_file' => sys_get_temp_dir() . '/shlink-test-swoole.pid',
'worker_num' => 1,
'task_worker_num' => 1,
'enable_coroutine' => false,
],
],
],

2
data/infra/database_maria/.gitignore vendored Executable file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

View File

@@ -4,6 +4,7 @@ MAINTAINER Alejandro Celaya <alejandro@alejandrocelaya.com>
ENV APCU_VERSION 5.1.16
ENV APCU_BC_VERSION 1.0.4
ENV INOTIFY_VERSION 2.0.0
ENV SWOOLE_VERSION 4.4.8
RUN apk update
@@ -66,7 +67,7 @@ RUN rm /tmp/inotify.tar.gz
# Install swoole
# First line fixes an error when installing pecl extensions. Found in https://github.com/docker-library/php/issues/233
RUN apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS && \
pecl install swoole && \
pecl install swoole-${SWOOLE_VERSION} && \
docker-php-ext-enable swoole && \
apk del .phpize-deps

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;

View File

@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\Migrations\AbstractMigration;
final class Version20191020074522 extends AbstractMigration
{
/**
* @throws SchemaException
*/
public function up(Schema $schema): void
{
$this->getOriginalUrlColumn($schema)->setLength(2048);
}
/**
* @throws SchemaException
*/
public function down(Schema $schema): void
{
$this->getOriginalUrlColumn($schema)->setLength(1024);
}
/**
* @throws SchemaException
*/
private function getOriginalUrlColumn(Schema $schema): Column
{
return $schema->getTable('short_urls')->getColumn('original_url');
}
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace <namespace>;

View File

@@ -24,3 +24,9 @@ services:
volumes:
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro
shlink_db_maria:
user: 1000:1000
volumes:
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro

View File

@@ -24,6 +24,7 @@ services:
links:
- shlink_db
- shlink_db_postgres
- shlink_db_maria
- shlink_redis
shlink_swoole:
@@ -33,11 +34,13 @@ services:
dockerfile: ./data/infra/swoole.Dockerfile
ports:
- "8080:8080"
- "9001:9001"
volumes:
- ./:/home/shlink
links:
- shlink_db
- shlink_db_postgres
- shlink_db_maria
- shlink_redis
shlink_db:
@@ -65,6 +68,19 @@ services:
POSTGRES_DB: shlink
PGDATA: /var/lib/postgresql/data/pgdata
shlink_db_maria:
container_name: shlink_db_maria
image: mariadb:10.2
ports:
- "3308:3306"
volumes:
- ./:/home/shlink/www
- ./data/infra/database_maria:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: shlink
MYSQL_INITDB_SKIP_TZINFO: 1
shlink_redis:
container_name: shlink_redis
image: redis:5.0-alpine

View File

@@ -56,16 +56,16 @@ docker exec -it shlink_container shlink
The image comes with a working sqlite database, but in production you will probably want to usa a distributed database.
It is possible to use a set of env vars to make this shlink instance interact with an external MySQL or PostgreSQL database.
It is possible to use a set of env vars to make this shlink instance interact with an external MySQL, MariaDB or PostgreSQL database.
* `DB_DRIVER`: **[Mandatory]**. Use the value **mysql** or **postgres** to prevent the sqlite database to be used.
* `DB_DRIVER`: **[Mandatory]**. Use the value **mysql**, **maria** or **postgres** to prevent the sqlite database to be used.
* `DB_NAME`: [Optional]. The database name to be used. Defaults to **shlink**.
* `DB_USER`: **[Mandatory]**. The username credential for the database server.
* `DB_PASSWORD`: **[Mandatory]**. The password credential for the database server.
* `DB_HOST`: **[Mandatory]**. The host name of the server running the database engine.
* `DB_PORT`: [Optional]. The port in which the database service is running.
* Default value is based on the driver:
* **mysql** -> `3306`
* **mysql** or **maria** -> `3306`
* **postgres** -> `5432`
> PostgreSQL is supported since v1.16.1 of this image. Do not try to use it with previous versions.
@@ -92,8 +92,7 @@ This is the complete list of supported env vars:
* `SHORT_DOMAIN_HOST`: The custom short domain used for this shlink instance. For example **doma.in**.
* `SHORT_DOMAIN_SCHEMA`: Either **http** or **https**.
* `SHORTCODE_CHARS`: A charset to use when building short codes. Only needed when using more than one shlink instance ([Multi instance considerations](#multi-instance-considerations)).
* `DB_DRIVER`: **sqlite** (which is the default value), **mysql** or **postgres**.
* `DB_DRIVER`: **sqlite** (which is the default value), **mysql**, **maria** or **postgres**.
* `DB_NAME`: The database name to be used when using an external database driver. Defaults to **shlink**.
* `DB_USER`: The username credential to be used when using an external database driver.
* `DB_PASSWORD`: The password credential to be used when using an external database driver.
@@ -102,7 +101,9 @@ This is the complete list of supported env vars:
* `DISABLE_TRACK_PARAM`: The name of a query param that can be used to visit short URLs avoiding the visit to be tracked. This feature won't be available if not value is provided.
* `DELETE_SHORT_URL_THRESHOLD`: The amount of visits on short URLs which will not allow them to be deleted. Defaults to `15`.
* `VALIDATE_URLS`: Boolean which tells if shlink should validate a status 20x (after following redirects) is returned when trying to shorten a URL. Defaults to `true`.
* `NOT_FOUND_REDIRECT_TO`: If a URL is provided here, when a user tries to access an invalid short URL, he/she will be redirected to this value. If this env var is not provided, the user will see a generic `404 - not found` page.
* `INVALID_SHORT_URL_REDIRECT_TO`: If a URL is provided here, when a user tries to access an invalid short URL, he/she will be redirected to this value. If this env var is not provided, the user will see a generic `404 - not found` page.
* `REGULAR_404_REDIRECT_TO`: If a URL is provided here, when a user tries to access a URL not matching any one supported by the router, he/she will be redirected to this value. If this env var is not provided, the user will see a generic `404 - not found` page.
* `BASE_URL_REDIRECT_TO`: If a URL is provided here, when a user tries to access Shlink's base URL, he/she will be redirected to this value. If this env var is not provided, the user will see a generic `404 - not found` page.
* `BASE_PATH`: The base path from which you plan to serve shlink, in case you don't want to serve it from the root of the domain. Defaults to `''`.
* `REDIS_SERVERS`: A comma-separated list of redis servers where Shlink locks are stored (locks are used to prevent some operations to be run more than once in parallel).
@@ -112,6 +113,9 @@ This is the complete list of supported env vars:
In the future, these redis servers could be used for other caching operations performed by shlink.
* `NOT_FOUND_REDIRECT_TO`: **Deprecated since v1.20 in favor of `INVALID_SHORT_URL_REDIRECT_TO`** If a URL is provided here, when a user tries to access an invalid short URL, he/she will be redirected to this value. If this env var is not provided, the user will see a generic `404 - not found` page.
* `SHORTCODE_CHARS`: **Ignored when using Shlink 1.20 or newer**. A charset to use when building short codes. Only needed when using more than one shlink instance ([Multi instance considerations](#multi-instance-considerations)).
An example using all env vars could look like this:
```bash
@@ -129,7 +133,9 @@ docker run \
-e DISABLE_TRACK_PARAM="no-track" \
-e DELETE_SHORT_URL_THRESHOLD=30 \
-e VALIDATE_URLS=false \
-e "NOT_FOUND_REDIRECT_TO=https://www.google.com" \
-e "INVALID_SHORT_URL_REDIRECT_TO=https://my-landing-page.com" \
-e "REGULAR_404_REDIRECT_TO=https://my-landing-page.com" \
-e "BASE_URL_REDIRECT_TO=https://my-landing-page.com" \
-e "REDIS_SERVERS=tcp://172.20.0.1:6379,tcp://172.20.0.2:6379" \
-e "BASE_PATH=/my-campaign" \
shlinkio/shlink
@@ -150,7 +156,9 @@ The whole configuration should have this format, but it can be split into multip
"short_domain_schema": "https",
"short_domain_host": "doma.in",
"validate_url": false,
"not_found_redirect_to": "https://my-landing-page.com",
"invalid_short_url_redirect_to": "https://my-landing-page.com",
"regular_404_redirect_to": "https://my-landing-page.com",
"base_url_redirect_to": "https://my-landing-page.com",
"redis_servers": [
"tcp://172.20.0.1:6379",
"tcp://172.20.0.2:6379"
@@ -162,11 +170,13 @@ The whole configuration should have this format, but it can be split into multip
"password": "123abc",
"host": "something.rds.amazonaws.com",
"port": "3306"
}
},
"not_found_redirect_to": "https://my-landing-page.com"
}
```
> This is internally parsed to how shlink expects the config. If you are using a version previous to 1.17.0, this parser is not present and you need to provide a config structure like the one [documented previously](https://github.com/shlinkio/shlink-docker-image/tree/v1.16.3#provide-config-via-volumes).
> The `not_found_redirect_to` option has been deprecated when `regular_404_redirect_to` and `base_url_redirect_to` have been introduced. Use `invalid_short_url_redirect_to` instead (however, it will still work for backwards compatibility).
Once created just run shlink with the volume:
@@ -178,7 +188,13 @@ docker run --name shlink -p 8080:8080 -v ${PWD}/my/config/dir:/etc/shlink/config
These are some considerations to take into account when running multiple instances of shlink.
* The first time shlink is run, it generates a charset used to generate short codes, which is a shuffled base62 charset.
* Some operations performed by Shlink should never be run more than once at the same time (like creating the database for the first time, or downloading the GeoLite2 database). For this reason, Shlink uses a locking system.
However, these locks are locally scoped to each Shlink instance by default.
You can (and should) make the locks to be shared by all Shlink instances by using a redis server/cluster. Just define the `REDIS_SERVERS` env var with the list of servers.
* **Ignore this if using Shlink 1.20 or newer**. The first time shlink is run, it generates a charset used to generate short codes, which is a shuffled base62 charset.
If you are using several shlink instances, you will probably want all of them to use the same charset.
@@ -186,12 +202,6 @@ These are some considerations to take into account when running multiple instanc
If you don't do this, each shlink instance will use a different charset. However this shouldn't be a problem in practice, since the chances to get a collision will be very low.
* Some operations performed by Shlink should never be run more than once at the same time (like creating the database for the first time, or downloading the GeoLite2 database). For this reason, Shlink uses a locking system.
However, these locks are locally scoped to each Shlink instance by default.
You can (and should) make the locks to be shared by all Shlink instances by using a redis server/cluster. Just define the `REDIS_SERVERS` env var with the list of servers.
## Versions
Versions of this image match the shlink version it contains.

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink;
@@ -10,6 +11,7 @@ use function explode;
use function file_exists;
use function file_get_contents;
use function file_put_contents;
use function Functional\contains;
use function implode;
use function Shlinkio\Shlink\Common\env;
use function sprintf;
@@ -21,24 +23,24 @@ $helper = new class {
private const BASE62 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
private const DB_DRIVERS_MAP = [
'mysql' => 'pdo_mysql',
'maria' => 'pdo_mysql',
'postgres' => 'pdo_pgsql',
];
private const DB_PORTS_MAP = [
'mysql' => '3306',
'maria' => '3306',
'postgres' => '5432',
];
/** @var string */
private $charset;
/** @var string */
private $secretKey;
public function __construct()
{
[$this->charset, $this->secretKey] = $this->initShlinkKeys();
[, $this->secretKey] = $this->initShlinkSecretKey();
}
private function initShlinkKeys(): array
private function initShlinkSecretKey(): array
{
$keysFile = sprintf('%s/shlink.keys', sys_get_temp_dir());
if (file_exists($keysFile)) {
@@ -46,29 +48,19 @@ $helper = new class {
}
$keys = [
env('SHORTCODE_CHARS', $this->generateShortcodeChars()),
env('SECRET_KEY', $this->generateSecretKey()),
'', // This was the SHORTCODE_CHARS. Kept as empty string for BC
env('SECRET_KEY', $this->generateSecretKey()), // Deprecated
];
file_put_contents($keysFile, implode(',', $keys));
return $keys;
}
private function generateShortcodeChars(): string
{
return str_shuffle(self::BASE62);
}
private function generateSecretKey(): string
{
return substr(str_shuffle(self::BASE62), 0, 32);
}
public function getShortcodeChars(): string
{
return $this->charset;
}
public function getSecretKey(): string
{
return $this->secretKey;
@@ -84,8 +76,8 @@ $helper = new class {
];
}
$driverOptions = $driver !== 'mysql' ? [] : [
// PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
$driverOptions = ! contains(['maria', 'mysql'], $driver) ? [] : [
// 1002 -> PDO::MYSQL_ATTR_INIT_COMMAND
1002 => 'SET NAMES utf8',
];
return [
@@ -99,13 +91,12 @@ $helper = new class {
];
}
public function getNotFoundConfig(): array
public function getNotFoundRedirectsConfig(): array
{
$notFoundRedirectTo = env('NOT_FOUND_REDIRECT_TO');
return [
'enable_redirection' => $notFoundRedirectTo !== null,
'redirect_to' => $notFoundRedirectTo,
'invalid_short_url' => env('INVALID_SHORT_URL_REDIRECT_TO', env('NOT_FOUND_REDIRECT_TO')),
'regular_404' => env('REGULAR_404_REDIRECT_TO'),
'base_url' => env('BASE_URL_REDIRECT_TO'),
];
}
};
@@ -133,11 +124,11 @@ return [
'schema' => env('SHORT_DOMAIN_SCHEMA', 'http'),
'hostname' => env('SHORT_DOMAIN_HOST', ''),
],
'shortcode_chars' => $helper->getShortcodeChars(),
'validate_url' => (bool) env('VALIDATE_URLS', true),
'not_found_short_url' => $helper->getNotFoundConfig(),
],
'not_found_redirects' => $helper->getNotFoundRedirectsConfig(),
'logger' => [
'handlers' => [
'shlink_rotating_handler' => [

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Api;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Api;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Api;

View File

@@ -1,10 +1,10 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Config;
use Shlinkio\Shlink\CLI\Util\ExitCodes;
use Shlinkio\Shlink\Core\Options\UrlShortenerOptions;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -17,6 +17,7 @@ use function str_shuffle;
class GenerateCharsetCommand extends Command
{
public const NAME = 'config:generate-charset';
private const DEFAULT_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
protected function configure(): void
{
@@ -25,14 +26,14 @@ class GenerateCharsetCommand extends Command
->setDescription(sprintf(
'[DEPRECATED] Generates a character set sample just by shuffling the default one, "%s". '
. 'Then it can be set in the SHORTCODE_CHARS environment variable',
UrlShortenerOptions::DEFAULT_CHARS
self::DEFAULT_CHARS
))
->setHelp('<fg=red;options=bold>This command is deprecated. Better leave shlink generate the charset.</>');
}
protected function execute(InputInterface $input, OutputInterface $output): ?int
{
$charSet = str_shuffle(UrlShortenerOptions::DEFAULT_CHARS);
$charSet = str_shuffle(self::DEFAULT_CHARS);
(new SymfonyStyle($input, $output))->success(sprintf('Character set: "%s"', $charSet));
return ExitCodes::EXIT_SUCCESS;
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Config;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Db;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Db;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Db;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Tag;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Tag;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Tag;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Tag;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Util;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Util;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Visit;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Command\Visit;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Exception;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Exception;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Factory;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Util;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Util;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Util;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Util;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Api;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Api;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Api;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Config;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Db;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Db;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;
@@ -19,6 +20,11 @@ use Symfony\Component\Console\Tester\CommandTester;
class GenerateShortUrlCommandTest extends TestCase
{
private const DOMAIN_CONFIG = [
'schema' => 'http',
'hostname' => 'foo.com',
];
/** @var CommandTester */
private $commandTester;
/** @var ObjectProphecy */
@@ -27,10 +33,7 @@ class GenerateShortUrlCommandTest extends TestCase
public function setUp(): void
{
$this->urlShortener = $this->prophesize(UrlShortener::class);
$command = new GenerateShortUrlCommand($this->urlShortener->reveal(), [
'schema' => 'http',
'hostname' => 'foo.com',
]);
$command = new GenerateShortUrlCommand($this->urlShortener->reveal(), self::DOMAIN_CONFIG);
$app = new Application();
$app->add($command);
$this->commandTester = new CommandTester($command);
@@ -39,9 +42,8 @@ class GenerateShortUrlCommandTest extends TestCase
/** @test */
public function properShortCodeIsCreatedIfLongUrlIsCorrect(): void
{
$urlToShortCode = $this->urlShortener->urlToShortCode(Argument::cetera())->willReturn(
(new ShortUrl(''))->setShortCode('abc123')
);
$shortUrl = new ShortUrl('');
$urlToShortCode = $this->urlShortener->urlToShortCode(Argument::cetera())->willReturn($shortUrl);
$this->commandTester->execute([
'longUrl' => 'http://domain.com/foo/bar',
@@ -50,7 +52,7 @@ class GenerateShortUrlCommandTest extends TestCase
$output = $this->commandTester->getDisplay();
$this->assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode());
$this->assertStringContainsString('http://foo.com/abc123', $output);
$this->assertStringContainsString($shortUrl->toString(self::DOMAIN_CONFIG), $output);
$urlToShortCode->shouldHaveBeenCalledOnce();
}
@@ -85,6 +87,7 @@ class GenerateShortUrlCommandTest extends TestCase
/** @test */
public function properlyProcessesProvidedTags(): void
{
$shortUrl = new ShortUrl('');
$urlToShortCode = $this->urlShortener->urlToShortCode(
Argument::type(UriInterface::class),
Argument::that(function (array $tags) {
@@ -92,7 +95,7 @@ class GenerateShortUrlCommandTest extends TestCase
return $tags;
}),
Argument::cetera()
)->willReturn((new ShortUrl(''))->setShortCode('abc123'));
)->willReturn($shortUrl);
$this->commandTester->execute([
'longUrl' => 'http://domain.com/foo/bar',
@@ -101,7 +104,7 @@ class GenerateShortUrlCommandTest extends TestCase
$output = $this->commandTester->getDisplay();
$this->assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode());
$this->assertStringContainsString('http://foo.com/abc123', $output);
$this->assertStringContainsString($shortUrl->toString(self::DOMAIN_CONFIG), $output);
$urlToShortCode->shouldHaveBeenCalledOnce();
}
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Tag;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI\Command\Tag;

Some files were not shown because too many files have changed in this diff Show More