Compare commits

...

822 Commits

Author SHA1 Message Date
Alejandro Celaya
35950a6294 Added release title to changelog 2019-05-13 20:07:33 +02:00
Alejandro Celaya
c104eee2b1 Merge pull request #408 from acelaya/feature/improve-logs
Renamed Swoole logger to Access logger
2019-05-13 19:30:39 +02:00
Alejandro Celaya
f0972c6220 Removed optional dependency constraints used for no longer support PHP versions 2019-05-13 19:21:59 +02:00
Alejandro Celaya
42a5145895 Renamed Swoole logger to Access logger 2019-05-13 19:16:14 +02:00
Alejandro Celaya
8d412e7d4c Merge pull request #407 from acelaya/feature/edit-patch
Feature/edit patch
2019-05-05 10:22:52 +02:00
Alejandro Celaya
f45e34cfcf Documented deprecated endpoint 2019-05-05 09:52:49 +02:00
Alejandro Celaya
320c8e2d6b Ensured accepted methods on CORS requests are dynamically fetched from route match when possible 2019-05-05 09:45:35 +02:00
Alejandro Celaya
988de0b96e Updated edit short URL endpoint to be used with patch instead of put 2019-05-05 09:21:57 +02:00
Alejandro Celaya
25a785dfa7 Merge pull request #404 from acelaya/feature/config-post-processor
Feature/config post processor
2019-04-18 10:59:50 +02:00
Alejandro Celaya
c993bbd993 Updated changelog 2019-04-18 10:47:26 +02:00
Alejandro Celaya
479760c0ee Created config post processor that parses a simplified config to what shlink expects 2019-04-18 10:37:38 +02:00
Alejandro Celaya
e186237410 Merge pull request #403 from acelaya/feature/tweaks
Removed superfluous option from command tester
2019-04-14 22:28:00 +02:00
Alejandro Celaya
4084e3f0d8 Removed superfluous option from command tester 2019-04-14 22:20:58 +02:00
Alejandro Celaya
dddf64031f Merge pull request #402 from acelaya/feature/update-db-on-process
Feature/update db on process
2019-04-14 18:15:40 +02:00
Alejandro Celaya
8f1477e893 Updated changelog 2019-04-14 18:07:23 +02:00
Alejandro Celaya
4866fe241e Updated LocateVisitsCommand to update the database if needed 2019-04-14 18:00:19 +02:00
Alejandro Celaya
6613cb5c60 Updated amount of days to wait for the GeoLite2 database to be updated 2019-04-14 13:18:03 +02:00
Alejandro Celaya
0f48dd567f Registered GeolocationDbUpdater service and added callable which is invoked when db is going to be updated 2019-04-14 11:19:21 +02:00
Alejandro Celaya
b24511b7b5 Created service that updated GeoLite database when it is older than 7 days 2019-04-14 10:54:01 +02:00
Alejandro Celaya
df40199134 Renamed common config files so that they have the same preffix 2019-04-14 10:25:32 +02:00
Alejandro Celaya
935562acc9 Created exception to handle cases in which downloading a new geolite db fails 2019-04-14 10:10:20 +02:00
Alejandro Celaya
feb67e76f0 Updated commands 2019-04-14 09:10:00 +02:00
Alejandro Celaya
fdbe93f0fb Merge pull request #401 from acelaya/feature/templates
Feature/templates
2019-04-14 09:07:04 +02:00
Alejandro Celaya
f27058e255 Updated lang files 2019-04-14 08:59:55 +02:00
Alejandro Celaya
6ddbbb4ba0 Restyled error templates and removed copyright 2019-04-14 08:57:48 +02:00
Alejandro Celaya
ef32f2c129 Merge pull request #400 from acelaya/feature/simplify-cache
Dropped support for all caches other than APCu and Array
2019-04-11 22:56:54 +02:00
Alejandro Celaya
760bb2db2a Removed redis from dockerfiles for dev 2019-04-11 22:39:55 +02:00
Alejandro Celaya
68f38fd9fe Dropped support for all caches other than APCu and Array 2019-04-11 22:36:50 +02:00
Alejandro Celaya
5c6829fb62 Merge pull request #398 from acelaya/feature/issue-template
Created issue template with some reminders
2019-04-11 22:11:21 +02:00
Alejandro Celaya
91c48919c6 Excluded gihub dir from build 2019-04-11 22:01:35 +02:00
Alejandro Celaya
72313800fa Created issue template with some reminders 2019-04-11 21:57:12 +02:00
Alejandro Celaya
478d5a16fd Merge pull request #395 from acelaya/feature/drop-php7.1
Feature/drop php7.1
2019-04-09 22:51:17 +02:00
Alejandro Celaya
b8909d8043 Updated changelog 2019-04-09 22:43:01 +02:00
Alejandro Celaya
c2c659b0fe Dropped support for PHP 7.1 2019-04-09 22:40:15 +02:00
Alejandro Celaya
20c3bde036 Merge pull request #387 from acelaya/feature/fix-check-exists
Feature/fix check exists
2019-03-30 08:04:44 +01:00
Alejandro Celaya
e77e37076f Updated changelog 2019-03-30 07:48:54 +01:00
Alejandro Celaya
734fdf83c1 Added test covering the case in which fetching existing short URLs, more than one result is found 2019-03-30 07:45:57 +01:00
Alejandro Celaya
2906d42f97 Updated how existing short URLs are checked, so that not only the first one matching the slug or url is checked 2019-03-30 07:36:57 +01:00
Alejandro Celaya
0135f205df Updated changelog 2019-03-17 17:54:57 +01:00
Alejandro Celaya
781c6e94a0 Merge pull request #381 from acelaya/feature/update-db-errors
Feature/update db errors
2019-03-16 11:25:32 +01:00
Alejandro Celaya
1d64dc8a26 Updated changelog 2019-03-16 11:11:39 +01:00
Alejandro Celaya
34ff831473 Added support to ignore errors in UpdateDbCommand 2019-03-16 11:08:12 +01:00
Alejandro Celaya
3734160cb4 Used phpcov v6 stable 2019-03-16 10:31:13 +01:00
Alejandro Celaya
21234cacfb Merge pull request #380 from acelaya/feature/reload-swoole
Feature/reload swoole
2019-03-16 10:29:13 +01:00
Alejandro Celaya
eb4dc85006 Updated to expressive swoole 2.4 2019-03-16 10:15:21 +01:00
Alejandro Celaya
249b8a4768 Added config to reload swoole during development 2019-03-16 09:57:09 +01:00
Alejandro Celaya
1a1868c7f4 Merge pull request #374 from acelaya/feature/migrations-v2
Feature/migrations v2
2019-03-09 18:54:51 +01:00
Alejandro Celaya
487659d5b4 Updated changelog 2019-03-09 18:47:58 +01:00
Alejandro Celaya
f46de4d3e1 Updated to doctrine migrations 2 2019-03-09 18:45:58 +01:00
Alejandro Celaya
6314315db7 Merge pull request #370 from acelaya/feature/extended-db-tests
Feature/extended db tests
2019-03-05 21:10:16 +01:00
Alejandro Celaya
a22beeed08 Replaced localhost name by 127.0.0.1 for databases when in travis 2019-03-05 21:01:52 +01:00
Alejandro Celaya
840e377245 Added execution of db tests with mysql and postgres to travis 2019-03-05 20:50:32 +01:00
Alejandro Celaya
6fa255386b Defined config to run database tests against mysql and postgres 2019-03-05 20:36:35 +01:00
Alejandro Celaya
f563e777cc Merge pull request #369 from acelaya/feature/postgres-query-error
Feature/postgres query error
2019-03-05 14:26:36 +01:00
Alejandro Celaya
a63447b12b Updated changelog 2019-03-05 14:17:47 +01:00
Alejandro Celaya
0f81c3ab92 Fixed error when using postgres in a SELECT count query where a ORDER BY was added by mistake 2019-03-05 13:50:44 +01:00
Alejandro Celaya
425f254453 Added posgres container for development 2019-03-05 13:39:45 +01:00
Alejandro Celaya
a9d9ec5bf9 Merge pull request #365 from acelaya/feature/coding-styles
Feature/coding styles
2019-02-26 23:06:08 +01:00
Alejandro Celaya
0c5c752ffe Updated changelog 2019-02-26 22:58:03 +01:00
Alejandro Celaya
4b556cd79f Updated to shlinkio coding standard 1.1.0 2019-02-26 22:56:43 +01:00
Alejandro Celaya
3d32a90f8e Merge pull request #364 from acelaya/bugfix/non-locatable-addresses
Bugfix/non locatable addresses
2019-02-26 22:53:07 +01:00
Alejandro Celaya
0b4c334163 Fixed typo 2019-02-26 22:42:33 +01:00
Alejandro Celaya
312fc0984b Fixed mutation score by provideing more tests 2019-02-26 22:41:04 +01:00
Alejandro Celaya
30bf1c2641 Added tests for new cases with non-locatable addresses 2019-02-26 22:31:07 +01:00
Alejandro Celaya
2d1d7357a3 Given more semantic cases in which a visit cannot be located 2019-02-26 21:39:45 +01:00
Alejandro Celaya
c70077c525 Merge pull request #361 from acelaya/feature/paginated-visits
Feature/paginated visits
2019-02-23 10:09:46 +01:00
Alejandro Celaya
d2fad0128f Fixed bug missing unprocessed visits while iterating and updating, while drastically improving the performance 2019-02-23 09:58:02 +01:00
Alejandro Celaya
62133c994f Tagged v1.16 in changelog 2019-02-23 08:30:35 +01:00
Alejandro Celaya
091ea974eb Simplified implementation iterating unlocated visits 2019-02-23 07:29:07 +01:00
Alejandro Celaya
955ae00036 Updated changelog 2019-02-22 19:54:23 +01:00
Alejandro Celaya
7d4de590e5 Created ImplicitLoopPaginatorTest 2019-02-22 19:53:10 +01:00
Alejandro Celaya
292937b962 Updated VisitRepository::findUnlocatedVisits methods so that it paginates the amount of elements loaded in memory 2019-02-22 19:31:03 +01:00
Alejandro Celaya
08bd4f131c Merge pull request #359 from acelaya/feature/memory-leak
Feature/memory leak
2019-02-20 18:09:00 +01:00
Alejandro Celaya
38cc83a4ee Removed uneeded inline type hints 2019-02-17 20:32:18 +01:00
Alejandro Celaya
687a1cc9c7 Reduced amount of dead lines in tests 2019-02-17 20:28:34 +01:00
Alejandro Celaya
1bcd03b150 Renamed method 2019-02-17 13:21:07 +01:00
Alejandro Celaya
e2abe23895 Defined stricter model to represent one geo location 2019-02-17 13:01:21 +01:00
Alejandro Celaya
5c5dde48de Ensured install and update script change to the project dir 2019-02-17 10:51:22 +01:00
Alejandro Celaya
d9f11e190f Merge pull request #357 from acelaya/feature/phpstan0.11
Feature/phpstan0.11
2019-02-17 10:19:14 +01:00
Alejandro Celaya
1ab2d7a240 Increased scrutinizer timeout while waiting for code coverage, from 5 min to 10 min 2019-02-17 10:12:13 +01:00
Alejandro Celaya
580050cb7d Updated to phpstan 0.11 2019-02-17 10:06:34 +01:00
Alejandro Celaya
eab5659163 Added status codes returned by CLI commands 2019-02-16 23:21:40 +01:00
Alejandro Celaya
397b350cfc Merge pull request #356 from acelaya/feature/deprecated-commands
Deprecated commands to generate secret and charset
2019-02-16 23:20:55 +01:00
Alejandro Celaya
c0130c997a Deprecated commands to generate secret and charset 2019-02-16 22:53:49 +01:00
Alejandro Celaya
fd7f1b32dd Merge pull request #354 from acelaya/feature/infection
Feature/infection
2019-02-16 22:25:13 +01:00
Alejandro Celaya
0e286d8261 Temporarely downgrading phpstan 2019-02-16 22:17:01 +01:00
Alejandro Celaya
ce7d2d1fb0 Fixed coding styles 2019-02-16 22:04:11 +01:00
Alejandro Celaya
2175b8a7bb Improved tests to increase MSI to 70% 2019-02-16 21:58:14 +01:00
Alejandro Celaya
6c0893cdf8 Improved tests to increase MSI to 69% 2019-02-16 21:24:32 +01:00
Alejandro Celaya
25927a296d Merge pull request #353 from acelaya/feature/testing-tools
Updated testing tools
2019-02-16 20:50:22 +01:00
Alejandro Celaya
ee4db44fe8 Fixed phpcov dep not properly resolved on PHP 7.1 envs 2019-02-16 20:39:46 +01:00
Alejandro Celaya
b8cb38ae5c Updated testing tools 2019-02-16 10:53:45 +01:00
Alejandro Celaya
899bfdce2b Merge pull request #352 from acelaya/feature/configure-installer
Updated required shlink-installer version and added config for instal…
2019-02-10 22:05:03 +01:00
Alejandro Celaya
456960e1f0 Updated required shlink-installer version and added config for installer plugins 2019-02-10 21:57:29 +01:00
Alejandro Celaya
04e03e9b6e Merge pull request #348 from acelaya/feature/external-installer
Feature/external installer
2019-02-06 23:56:10 +01:00
Alejandro Celaya
a7283da016 Updated changelog 2019-02-06 23:31:37 +01:00
Alejandro Celaya
672321abab Removed class which is now part of the installer package 2019-02-04 20:16:29 +01:00
Alejandro Celaya
2059b4050b Removed installer and used external package instead 2019-02-04 20:14:59 +01:00
Alejandro Celaya
171b43c517 Fixed some configs 2019-02-04 19:43:21 +01:00
Alejandro Celaya
ccb7c8f8d9 Merge pull request #345 from acelaya/bugfix/charset-installation
Bugfix/charset installation
2019-02-03 13:19:23 +01:00
Alejandro Celaya
abbc66ac07 Unified config for installer tool 2019-02-03 13:12:17 +01:00
Alejandro Celaya
2d18ef5cee Updated installer so that it no longer asks for a charset and instead just generates one 2019-02-03 13:02:12 +01:00
Alejandro Celaya
79c132219b Merge pull request #343 from acelaya/feature/allow-check-duplicates
Feature/allow check duplicates
2019-02-03 12:22:22 +01:00
Alejandro Celaya
04d4d4a8d7 Updated GenerateShortUrlCommand to accept the findIfExists flag 2019-02-03 12:11:22 +01:00
Alejandro Celaya
a918113ba0 Documented new findIfExists flag 2019-02-03 11:24:26 +01:00
Alejandro Celaya
810b25ff14 Added API tests covering creating short URLs with new findIfExists param 2019-02-03 11:01:38 +01:00
Alejandro Celaya
c4fd8d5120 Implemented feature to optionally return an existing short url when all provided params match an existing one 2019-02-03 09:40:32 +01:00
Alejandro Celaya
772494f46f Moved process of sluggifying custom slug to a filter 2019-02-03 08:17:27 +01:00
Alejandro Celaya
594e7da256 Created new findIfExists meta param 2019-02-02 11:05:28 +01:00
Alejandro Celaya
49668547d7 Fixed typo 2019-02-02 11:05:28 +01:00
Alejandro Celaya
4c46aaead8 Improved API tests and added test for short URLs creation 2019-02-02 11:05:28 +01:00
Alejandro Celaya
d61f5faf59 Refactored UrlShortener public method to receibe DTOs instead of primitive params 2019-02-02 11:05:28 +01:00
Alejandro Celaya
5756609531 Deleted deprecated constant 2019-02-02 11:05:28 +01:00
Alejandro Celaya
ea1b285d52 Little refactopring on tests config file 2019-02-02 11:05:28 +01:00
Alejandro Celaya
bc61b55b94 Merge pull request #344 from acelaya/feature/update-dev-docker
Updated docker containers used in development
2019-02-02 11:04:39 +01:00
Alejandro Celaya
48f6a96da8 Updated docker containers used in development 2019-02-02 10:53:34 +01:00
Alejandro Celaya
967f1657d2 Merge pull request #340 from acelaya/bugfix/preview-error
Bugfix/preview error
2019-01-28 11:00:23 +01:00
Alejandro Celaya
f90a323374 Updated changelog 2019-01-28 10:53:24 +01:00
Alejandro Celaya
d289c62532 Fixed config file being deleted by mistake by build script 2019-01-28 10:52:05 +01:00
Alejandro Celaya
05695e8cd6 Merge pull request #339 from acelaya/feature/api-test
Feature/api test
2019-01-27 12:49:59 +01:00
Alejandro Celaya
d6a7a6ce66 Created new API test 2019-01-27 12:36:22 +01:00
Alejandro Celaya
05c7672de3 Improved API tests by adding fixtures 2019-01-27 12:14:22 +01:00
Alejandro Celaya
ce515767ce Updated changelog 2019-01-27 10:56:14 +01:00
Alejandro Celaya
76d8fd1023 Improved how API tests are executed 2019-01-27 10:54:04 +01:00
Alejandro Celaya
558e259b84 Minor refactorings 2019-01-27 10:30:38 +01:00
Alejandro Celaya
f467bed24c Used multiple commands with && instead of composer array for API tests command 2019-01-27 10:15:48 +01:00
Alejandro Celaya
fa753ad6fb Added api test to test:ci command 2019-01-26 11:04:50 +01:00
Alejandro Celaya
22d61fead7 Prepared configs for API tests 2019-01-26 10:19:20 +01:00
Alejandro Celaya
c4af1471f0 Simplified and united configs for tests 2019-01-26 09:42:08 +01:00
Alejandro Celaya
87ba7a7179 Updated structure for tests config files 2019-01-26 09:09:57 +01:00
Alejandro Celaya
e7c5cf0846 Merge pull request #337 from acelaya/feature/db-tests
Feature/db tests
2019-01-21 21:34:30 +01:00
Alejandro Celaya
1aaedb8d90 Udated changelog 2019-01-21 21:27:16 +01:00
Alejandro Celaya
284de28f76 Removed duplicated code to define testing database connection params 2019-01-20 22:08:32 +01:00
Alejandro Celaya
687d8d91a9 Changed references to functional tests by database tests 2019-01-20 21:49:07 +01:00
Alejandro Celaya
771087c6c6 Happy 2019! 2019-01-05 08:41:48 +01:00
Alejandro Celaya
1fd3e6365e Merge pull request #331 from acelaya/feature/health
Feature/health
2018-12-29 14:51:08 +01:00
Alejandro Celaya
28989296eb Updated changelog 2018-12-29 14:45:20 +01:00
Alejandro Celaya
fd8d73af38 Documented health endpoint 2018-12-29 14:39:31 +01:00
Alejandro Celaya
144a5415da Handled connection exceptions in Health action 2018-12-29 13:50:42 +01:00
Alejandro Celaya
d58e24bce5 Created health action related tests 2018-12-29 11:54:28 +01:00
Alejandro Celaya
0f86123ccb Finished health action implementation 2018-12-29 11:54:28 +01:00
Alejandro Celaya
3f65ef998c Created HealthAction 2018-12-29 11:54:28 +01:00
Alejandro Celaya
29d49dfbf4 Merge pull request #332 from acelaya/feature/php7.3
Do not allow failures on PHP 7.3 build
2018-12-29 11:53:44 +01:00
Alejandro Celaya
701d17f6f2 Do not allow failures on PHP 7.3 build 2018-12-29 11:43:28 +01:00
Alejandro Celaya
642431c43e Reverted to diactoros v2.0.1 while a bug is fixed 2018-12-29 11:13:23 +01:00
Alejandro Celaya
3c5b47784d Merge pull request #329 from PeterDaveHello/Update-Travis-CI-Config
Drop deprecated Travis CI container-based env config
2018-12-29 09:36:02 +01:00
Peter Dave Hello
64d7fe8bbf Drop deprecated Travis CI container-based env config
Ref: https://blog.travis-ci.com/2018-10-04-combining-linux-infrastructures
2018-12-29 16:20:18 +08:00
Alejandro Celaya
32070b1fa7 Do not use ServerRequestFactory::fromGlobals in tests 2018-12-25 23:19:36 +01:00
Alejandro Celaya
8b3324e143 Merge pull request #327 from PeterDaveHello/Add-Table-of-Contents
Add Table of Contents in README.md
2018-12-25 10:52:21 +01:00
Peter Dave Hello
f40a5a029c Add Table of Contents in README.md 2018-12-25 14:12:16 +08:00
Alejandro Celaya
eac82a602c Merge pull request #325 from acelaya/feature/dql
Feature/dql
2018-12-19 17:47:10 +01:00
Alejandro Celaya
d1312e0934 Added unreleased changes to changelog 2018-12-19 14:37:47 +01:00
Alejandro Celaya
58dbee10c5 Used DQL for non-dynamic query in VisitRepository 2018-12-19 14:36:03 +01:00
Alejandro Celaya
f8207994dc Removed superfluous method docs 2018-12-19 14:31:52 +01:00
Alejandro Celaya
2030401859 Migrated non-dynamic query to DQL in ShortUrlRepository 2018-12-19 14:29:43 +01:00
Alejandro Celaya
8966cf9910 Merge pull request #323 from acelaya/feature/docker-build
Feature/docker build
2018-12-16 19:40:32 +01:00
Alejandro Celaya
4eb4df9ca2 Updated changelog 2018-12-16 13:19:44 +01:00
Alejandro Celaya
32861b1c72 Added new travis deployment which will build the docker image 2018-12-16 13:19:17 +01:00
Alejandro Celaya
7248ca2e9b Merge pull request #324 from acelaya/feature/entities-config
Moved entities mappings from annotations to external config files
2018-12-16 13:18:19 +01:00
Alejandro Celaya
a6ec93f883 Updated changelog 2018-12-16 12:14:13 +01:00
Alejandro Celaya
a28c1d17c5 Moved entities mappings from annotations to external config files 2018-12-16 12:08:03 +01:00
Alejandro Celaya
fb705b44a4 Merge pull request #318 from acelaya/feature/document-non-rest
Feature/document non rest
2018-12-09 16:35:59 +01:00
Alejandro Celaya
a32bab9fd0 Updated changelog 2018-12-09 16:25:24 +01:00
Alejandro Celaya
6396e7f964 Added other of non-rest endpoints 2018-12-09 15:43:56 +01:00
Alejandro Celaya
c898cef277 Documented first non-rest endpoint 2018-12-09 15:18:10 +01:00
Alejandro Celaya
baeba54b06 Merge branch 'master' of github.com:shlinkio/shlink 2018-12-09 14:22:40 +01:00
Alejandro Celaya
f5ee5bf7fb Documented that swoole server needs to be restarted when it is being used ot serve shlink 2018-12-09 14:22:21 +01:00
Alejandro Celaya
73605414f9 Merge pull request #316 from acelaya/feature/symfony-42
Feature/symfony 42
2018-12-08 14:30:20 +01:00
Alejandro Celaya
6045c371e1 Updated changelog 2018-12-08 14:12:50 +01:00
Alejandro Celaya
97a9289d5f Created ShlinkTableTest 2018-12-08 14:11:14 +01:00
Alejandro Celaya
1983fc9b67 Added current page message in list short urls CLI command 2018-12-08 12:16:39 +01:00
Alejandro Celaya
bb40d84212 Used ShlinkTable on every location rendering a CLI table 2018-12-08 12:12:11 +01:00
Alejandro Celaya
46a35c553e Created class to wrap CLI table rendering behavior 2018-12-08 11:32:16 +01:00
Alejandro Celaya
080943e810 Updated how Symfony commands are used to fulfill API from v4.2 2018-12-08 10:34:04 +01:00
Alejandro Celaya
62fb3863c6 Merge pull request #315 from acelaya/feature/config
Updated how config is imported and merged, so that it includes any co…
2018-12-07 20:56:57 +01:00
Alejandro Celaya
2db03a163d Updated how config is imported and merged, so that it includes any config file in json format from config/params dir 2018-12-07 20:48:20 +01:00
Alejandro Celaya
9e3dd82efe Merge pull request #314 from acelaya/feature/fix-context
Feature/fix context
2018-12-07 20:30:53 +01:00
Alejandro Celaya
9f1989bfef Updated changelog 2018-12-07 19:49:17 +01:00
Alejandro Celaya
c0bdd8fc77 Removed concept of execution context and piped CloseDbConnectionMiddleware always 2018-12-07 19:46:46 +01:00
Alejandro Celaya
8a23c90e46 Merge pull request #313 from acelaya/feature/favicon
Feature/favicon
2018-12-07 09:45:55 +01:00
Alejandro Celaya
9095e5b057 Enabled static files with swoole, otherwise, robots.txt and favicon.ico are never served when running shlink with swoole 2018-12-07 09:38:07 +01:00
Alejandro Celaya
52c18115af Updated changelog 2018-12-07 09:18:56 +01:00
Alejandro Celaya
737137b19f Added favicon 2018-12-07 09:17:31 +01:00
Alejandro Celaya
7b78bee135 Merge pull request #311 from acelaya/feature/improvements
Feature/improvements
2018-12-07 02:55:27 +01:00
Alejandro Celaya
accda36a7b Updated default secret_key value 2018-12-07 02:49:50 +01:00
Alejandro Celaya
69dd9eb067 Updated readme mentioning docker image 2018-12-07 02:41:06 +01:00
Alejandro Celaya
a562bc661d Improved CacheFactory class 2018-12-06 21:05:11 +01:00
Alejandro Celaya
258f12f684 Merge pull request #303 from acelaya/feature/expressive-swoole-2.2
Feature/expressive swoole 2.2
2018-12-05 21:46:48 +01:00
Alejandro Celaya
4dc8d77a5a Updated changelog 2018-12-05 21:29:16 +01:00
Alejandro Celaya
7c5825d1bc Removed custom AccessLogFactory by updating to zend-expressive-swoole 2.2 2018-12-05 21:26:19 +01:00
Alejandro Celaya
6ba4d8e947 Merge pull request #299 from acelaya/feature/repository-tests
Improved repository tests
2018-12-02 19:24:19 +01:00
Alejandro Celaya
3faf6e967f Updated changelog adding v1.15 2018-12-02 19:15:58 +01:00
Alejandro Celaya
a7a5667301 Improved repository tests 2018-12-02 19:13:49 +01:00
Alejandro Celaya
d4924897b2 Merge pull request #298 from acelaya/feature/document-swoole
Feature/document swoole
2018-12-02 10:10:00 +01:00
Alejandro Celaya
f2d39ca55a Added missing comma 2018-12-02 10:05:33 +01:00
Alejandro Celaya
743d052f55 Documented how to serve shlink using swoole 2018-12-02 09:56:52 +01:00
Alejandro Celaya
17dbab5ee8 Created config file examples to serve shlink using different approaches 2018-12-02 09:41:25 +01:00
Alejandro Celaya
8cb5e07c7b Merge pull request #297 from acelaya/feature/remove-helpers
Removed non-needed services from expressive-helpers
2018-12-01 21:59:24 +01:00
Alejandro Celaya
e9972783d2 Removed non-needed services from expressive-helpers 2018-12-01 21:53:46 +01:00
Alejandro Celaya
84f6080a38 Merge pull request #296 from acelaya/feature/fix-lowercase
Feature/fix lowercase
2018-12-01 21:47:40 +01:00
Alejandro Celaya
1b5c1e4e52 Updated changelog 2018-12-01 21:40:11 +01:00
Alejandro Celaya
d7e89ebdae Ensured custom slugs are case sensitive 2018-12-01 21:38:29 +01:00
Alejandro Celaya
aa413dab6d Configured improvements introduced in expressive swoole 2.1 2018-11-29 21:14:24 +01:00
Alejandro Celaya
b876870bd8 Encapsulated in VisitsParams how the itemsPerPage param is handled 2018-11-29 08:02:22 +01:00
Alejandro Celaya
05e56cc845 Merge pull request #293 from acelaya/feature/visits-pagination
Feature/visits pagination
2018-11-28 21:00:37 +01:00
Alejandro Celaya
d6c158ce98 Updated changelog 2018-11-28 20:55:07 +01:00
Alejandro Celaya
1d4ef4e9a4 Ensured pagination params in visits list are properly parsed to integer 2018-11-28 20:53:04 +01:00
Alejandro Celaya
4d2684be52 Updated swagger docs for visits including everything related to pagination 2018-11-28 20:46:52 +01:00
Alejandro Celaya
6947805b5c Updated to zend-expressive-swoole 2.0.1 removing all workarounds 2018-11-28 20:43:44 +01:00
Alejandro Celaya
d0e0aea0f1 Updated visits to support pagination 2018-11-28 20:39:08 +01:00
Alejandro Celaya
b0f250ed8a Created factory method to build VisitParams from a raw dataset 2018-11-28 19:58:45 +01:00
Alejandro Celaya
45254606d4 Added DTO used to pass filtering params to VisitsTracker 2018-11-27 21:09:27 +01:00
Alejandro Celaya
03ee46d903 Merge pull request #290 from acelaya/feature/coding-standard
Updated project to use external coding standard
2018-11-26 20:53:51 +01:00
Alejandro Celaya
c4afc7a923 Updated project to use external coding standard 2018-11-26 20:46:43 +01:00
Alejandro Celaya
afa2a5b0f0 Merge pull request #284 from acelaya/feature/swoole
Feature/swoole
2018-11-25 22:12:50 +01:00
Alejandro Celaya
b40057d423 Fixed typo in changelog 2018-11-25 21:33:25 +01:00
Alejandro Celaya
282ffef200 Ensured different loggers are used for swoole and for the app regular logs 2018-11-25 17:14:03 +01:00
Alejandro Celaya
22b02de405 Updated swoole docker image so that it retries the start command until status code is 0 2018-11-25 12:44:49 +01:00
Alejandro Celaya
f0330e9ae3 Ensured CloseDbConnectionMiddleware clears the entity manager 2018-11-24 13:24:43 +01:00
Alejandro Celaya
0c26490e3f Added info about swoole in changelog 2018-11-24 13:18:50 +01:00
Alejandro Celaya
cfaecd93e4 Added swoole extension to travis 2018-11-24 13:11:26 +01:00
Alejandro Celaya
ccbc6c7a75 Created middleware which closes DB connection after every request 2018-11-24 12:55:00 +01:00
Alejandro Celaya
2fc2ad98aa Updated config so that shlink logger dynamically uses standard output when running with swoole 2018-11-24 09:38:00 +01:00
Alejandro Celaya
16590b2dbb Prepared project to support both swoole and regular app servers with fast cgi 2018-11-24 08:43:48 +01:00
Alejandro Celaya
f40349479e Used more strict types in UrlShortener private methods 2018-11-24 07:52:57 +01:00
Alejandro Celaya
9f60c8dffe Merge pull request #280 from acelaya/feature/oneliner-type
Feature/oneliner type
2018-11-20 19:42:23 +01:00
Alejandro Celaya
5abd9d1a40 Made test properties to be private instead of protected 2018-11-20 19:37:22 +01:00
Alejandro Celaya
0ae5a53d86 Enforced property types comments in one line 2018-11-20 19:30:27 +01:00
Alejandro Celaya
15a70d0157 Merge pull request #278 from acelaya/feature/del-translations
Feature/del translations
2018-11-18 20:30:53 +01:00
Alejandro Celaya
ededb68ef1 Added changelog for unreleased changes 2018-11-18 20:20:30 +01:00
Alejandro Celaya
09add5fbff Moved locale middleware to before the not found handler, so that it never gets executed otherwise 2018-11-18 20:15:37 +01:00
Alejandro Celaya
e30f49a791 Simplified error templates 2018-11-18 20:04:12 +01:00
Alejandro Celaya
64737b741b Removed CLI language param from installation 2018-11-18 19:55:23 +01:00
Alejandro Celaya
d4d65bdf37 Added missing X-Api-Key header to cross domain middleware 2018-11-18 17:03:50 +01:00
Alejandro Celaya
90732a4fad Removed translations from Rest module 2018-11-18 16:28:04 +01:00
Alejandro Celaya
c5015f5828 Removed translations from CLI module 2018-11-18 16:02:52 +01:00
Alejandro Celaya
aa77c944d8 Merge pull request #277 from acelaya/feature/increase-msi
Feature/increase msi
2018-11-17 19:37:11 +01:00
Alejandro Celaya
b8faa6714a Increased MSI to 65% (for sure this time) 2018-11-17 19:32:31 +01:00
Alejandro Celaya
f48f98f4d7 Updated changelog for v1.14.1 2018-11-17 19:27:00 +01:00
Alejandro Celaya
79b2a0839f Increased MSI to 65% 2018-11-17 19:23:49 +01:00
Alejandro Celaya
6094d17718 Increased MSI to 64% 2018-11-17 18:40:53 +01:00
Alejandro Celaya
d2ed7d6417 Increased MSI to 62% 2018-11-17 18:06:21 +01:00
Alejandro Celaya
a705ef21a9 Increased MSI to 61% 2018-11-17 17:36:22 +01:00
Alejandro Celaya
67e465c479 Merge pull request #276 from acelaya/feature/locking
Feature/locking
2018-11-17 14:33:58 +01:00
Alejandro Celaya
ed3883b52c Updated translations 2018-11-17 14:29:54 +01:00
Alejandro Celaya
71ea0bcb5e Updated changelog with locking capabilities 2018-11-17 14:24:38 +01:00
Alejandro Celaya
dd2cffeee9 Reused ProcessVisitsCommand name as the lock name 2018-11-17 14:16:45 +01:00
Alejandro Celaya
1ceabf3bc3 Added locking capabilities to process visits command 2018-11-17 14:11:16 +01:00
Alejandro Celaya
17fcd637f2 Merge pull request #275 from acelaya/feature/doctrine-performance
Feature/doctrine performance
2018-11-17 09:59:53 +01:00
Alejandro Celaya
d44bc4b182 Added small hint in README 2018-11-17 09:49:44 +01:00
Alejandro Celaya
4760406221 Updated changelog 2018-11-17 09:47:14 +01:00
Alejandro Celaya
0aae0d888c Moved visits iteration logic from command to service to allow lazy loading of entries in resultset 2018-11-17 09:42:15 +01:00
Alejandro Celaya
1bc01057f3 Reduced the number of arguments in private method 2018-11-17 08:02:42 +01:00
Alejandro Celaya
c1906606c6 Updated VisitService to have a method which locates visits and allows entity manager to be cleared 2018-11-17 07:47:42 +01:00
Alejandro Celaya
1363194909 Improved code in LoggerFactory 2018-11-17 07:31:51 +01:00
Alejandro Celaya
d945e0c31b Updated CLI help in README file 2018-11-16 17:17:25 +01:00
Alejandro Celaya
0af7b75af5 Merge pull request #269 from acelaya/feature/missing-resp-examples
Feature/missing resp examples
2018-11-16 17:07:38 +01:00
Alejandro Celaya
36a42cb064 Added missing entries for v1.14.0 2018-11-16 17:02:40 +01:00
Alejandro Celaya
4db0acc0e7 Updated swagger response schemas and added missing response examples 2018-11-16 16:58:21 +01:00
Alejandro Celaya
8f4800aa47 Merge pull request #268 from acelaya/feature/phpstan-fix
feature/phpstan-fix
2018-11-16 16:57:30 +01:00
Alejandro Celaya
4745a37549 Used a lower level on phpstan to avoid errors produced by Symfony 4.1.5 new phpdocs 2018-11-16 16:44:48 +01:00
Alejandro Celaya
8fc949898b Excluded GeoLite2 db from build process 2018-11-12 21:51:14 +01:00
Alejandro Celaya
d4758b0e91 Merge pull request #258 from acelaya/feature/geolocation
Feature/geolocation
2018-11-12 21:46:33 +01:00
Alejandro Celaya
a07e4b17be Updated docs 2018-11-12 21:37:04 +01:00
Alejandro Celaya
b9dd975bc6 Updated changelog with new geolocation service 2018-11-12 21:34:45 +01:00
Alejandro Celaya
9964d3e24b Added progress bar to command downloading new GeoLite2 database file 2018-11-12 21:30:30 +01:00
Alejandro Celaya
58e8c8e182 Updated spanish translations 2018-11-12 21:04:02 +01:00
Alejandro Celaya
c7339f6cfa Created an EmptyIpLocationResolver which always returns an empty resolution and can be used as a fallback while resolving IP addresses 2018-11-12 20:58:14 +01:00
Alejandro Celaya
1aa78f766a Added step to download GeoLite2 db during installation 2018-11-12 20:51:53 +01:00
Alejandro Celaya
bf56e6adaf Created UpdateDbCommandTest 2018-11-12 20:37:30 +01:00
Alejandro Celaya
e915b7e499 Updated GeoLite2 db reader service so that it is lazily created 2018-11-12 20:22:42 +01:00
Alejandro Celaya
de0470d200 Created command to update GeoLite2 database 2018-11-12 20:06:12 +01:00
Alejandro Celaya
3d7cf6992e Created service to update geolite2 database file 2018-11-11 21:28:42 +01:00
Alejandro Celaya
06db082e3f Updated translations 2018-11-11 21:28:42 +01:00
Alejandro Celaya
4a383cecaf Set chain IP resolver as the default IP resolver 2018-11-11 21:28:42 +01:00
Alejandro Celaya
9a0f9207be Fixed region resolved in GeoLite2 2018-11-11 21:28:42 +01:00
Alejandro Celaya
0e3a0a1eec Created chain IP resolver which wrapps multiple resolver to fallback until one is capable of resolving an address 2018-11-11 21:28:42 +01:00
Alejandro Celaya
fd6d180eba Created chainIpLocationResolver 2018-11-11 21:28:42 +01:00
Alejandro Celaya
d152e2ef9a Removed the concept of API limits in IP location resolvers 2018-11-11 21:28:42 +01:00
Alejandro Celaya
b530cf4461 Created new namespace for IP geolocation elements 2018-11-11 21:28:42 +01:00
Alejandro Celaya
bbe85cde31 Migrated to GeoLite2 for IP location resolution 2018-11-11 21:28:42 +01:00
Alejandro Celaya
2c3cbe7146 Installed geoip2 and added to docs 2018-11-11 21:28:42 +01:00
Alejandro Celaya
2358308f4d Merge pull request #259 from acelaya/feature/infection
Updated to infection v0.11
2018-11-11 21:28:12 +01:00
Alejandro Celaya
58bff4fa73 Updated to infection v0.11 2018-11-11 21:24:11 +01:00
Alejandro Celaya
098f7afc70 Merge pull request #255 from acelaya/feature/user-agent-length
Updated user agent column in visits table to have a length of 512
2018-11-10 19:07:22 +01:00
Alejandro Celaya
4070b1e23d Updated user agent column in visits table to have a length of 512 2018-11-10 19:01:59 +01:00
Alejandro Celaya
d9d4c8a70c Merge pull request #252 from acelaya/feature/redirect-not-found
Feature/redirect not found
2018-11-04 12:19:03 +01:00
Alejandro Celaya
05abe49d8b Updated changelog 2018-11-04 12:11:36 +01:00
Alejandro Celaya
a71245b883 Improved UrlShortenerConfigCustomizerTest covering new config options 2018-11-04 12:05:22 +01:00
Alejandro Celaya
057f88a36a Added new not found short url config to installer 2018-11-04 11:58:35 +01:00
Alejandro Celaya
32fcdd9d94 Ensured phpcov is run with phpdbg in travis pipeline 2018-11-03 12:15:25 +01:00
Alejandro Celaya
313927827d Updated RedirectAction so that it makes use of the not found short url options 2018-11-03 12:10:02 +01:00
Alejandro Celaya
358b2b661e Deprecated ci composer command, since it does the same as check, but slower 2018-11-03 11:40:57 +01:00
Alejandro Celaya
3eddacdff8 Created options to enable redirection to external page when short code is not found 2018-11-03 11:37:43 +01:00
Alejandro Celaya
95d4cde649 Merge pull request #251 from acelaya/feature/improve-infection
Feature/improve infection
2018-11-03 11:07:20 +01:00
Alejandro Celaya
d1d947bf12 Disabled xdebug in travis env 2018-11-03 11:02:52 +01:00
Alejandro Celaya
40815e5b38 Ensured phpunit is run using phpdbg, to avoid the requirement on xdebug 2018-11-03 11:02:19 +01:00
Alejandro Celaya
8fc1d23e03 Created needed commands and updated pipeline config file to run infection using an existing code coverage report 2018-11-03 10:58:46 +01:00
Alejandro Celaya
5ec8c229a1 Merge pull request #250 from acelaya/feature/functional
Feature/functional
2018-11-02 12:19:07 +01:00
Alejandro Celaya
2412ec2195 Updated changelog 2018-11-02 12:08:43 +01:00
Alejandro Celaya
bfb96b0ae8 Fixed coding style 2018-11-02 12:07:13 +01:00
Alejandro Celaya
f64920e510 Replaced some array_map by Functional\map 2018-11-02 12:05:01 +01:00
Alejandro Celaya
664dc333ac Used select_keys function in place of custom pick function 2018-11-02 11:08:20 +01:00
Alejandro Celaya
521f6f2b18 Added functional-php library 2018-11-02 10:54:42 +01:00
Alejandro Celaya
6986d03c53 Merge pull request #248 from acelaya/feature/fix-anemic-model
Feature/fix anemic model
2018-10-28 16:27:14 +01:00
Alejandro Celaya
e6e38e3ca2 Added change to changelog 2018-10-28 16:22:30 +01:00
Alejandro Celaya
951d08f914 Improved public API in Visit entity, reducing anemic model 2018-10-28 16:20:54 +01:00
Alejandro Celaya
8e1e8ba7de Improved public API in ShortUrl entity, reducing anemic model 2018-10-28 16:00:54 +01:00
Alejandro Celaya
877b098b09 Improved public API in ApiKey entity, reducing anemic model 2018-10-28 15:24:41 +01:00
Alejandro Celaya
e046eddda9 Improved public API in VisitLocation entity, reducing anemic model 2018-10-28 15:13:45 +01:00
Alejandro Celaya
084b1169d7 Improved public API in Tag entity, avoiding anemic model 2018-10-28 14:38:43 +01:00
Alejandro Celaya
f7ceeff05a Added task to changelog 2018-10-28 09:15:26 +01:00
Alejandro Celaya
e0d41a2b8a Merge pull request #246 from acelaya/feature/enforce-global-imports
Feature/enforce global imports
2018-10-28 09:12:46 +01:00
Alejandro Celaya
6b9f9f0f44 Added scrutinizer config to enforce using the new environment 2018-10-28 09:05:20 +01:00
Alejandro Celaya
025135b8c6 Added all missing use statements from global functions and constants 2018-10-28 08:34:02 +01:00
Alejandro Celaya
77d810b735 Replaced all FQ global function and constants by explicit imports 2018-10-28 08:24:06 +01:00
Alejandro Celaya
e1222de05b Explicitly imported global functions in UrlShortener 2018-10-28 08:07:33 +01:00
Alejandro Celaya
459f807e67 Added link to shlink CLI help when mentioning CLI available commands 2018-10-20 13:09:41 +02:00
Alejandro Celaya
32df1370a6 Updated changelog 2018-10-20 13:08:03 +02:00
Alejandro Celaya
f18f8c89ec Merge pull request #244 from acelaya/feature/psr-logs
Feature/psr logs
2018-10-20 13:06:20 +02:00
Alejandro Celaya
787b791651 Replaced hardcoded exceptions concatenations by PSR approach 2018-10-20 12:50:10 +02:00
Alejandro Celaya
2eca0da852 Updated logger to properly format exceptions using processors 2018-10-20 12:37:35 +02:00
Alejandro Celaya
9e49604ce2 Replaced usages of mt_rand by random_int 2018-10-20 09:21:26 +02:00
Alejandro Celaya
5f85c61d6a Merge pull request #243 from acelaya/feature/snake-case-table
Feature/snake case table
2018-10-20 09:20:48 +02:00
Alejandro Celaya
cd58855e1f Updated changelog 2018-10-20 09:10:27 +02:00
Alejandro Celaya
13c64b0db0 Fixed coding styles 2018-10-20 09:10:27 +02:00
Alejandro Celaya
55e021ba20 Added snake case column names to VisitLocation entity 2018-10-20 09:10:27 +02:00
Alejandro Celaya
26fd61a3ed Created migrations to rename camel case columns to snake case 2018-10-20 09:10:27 +02:00
Alejandro Celaya
46482522bb Merge pull request #242 from acelaya/feature/functions-as-object
Moved global functions to handle array paths to a wrapper class
2018-10-20 08:59:40 +02:00
Alejandro Celaya
98e3e22896 Moved global functions to handle array paths to a wrapper class 2018-10-20 08:00:33 +02:00
Alejandro Celaya
15d49e97c0 Deleted ocular.phar before building assets for deployment 2018-10-18 21:53:24 +02:00
Alejandro Celaya
d5e7ce38ac Updated changelog 2018-10-18 21:47:00 +02:00
Alejandro Celaya
162d0560db Merge pull request #238 from acelaya/feature/fix-ip-address
Feature/fix ip address
2018-10-18 21:44:15 +02:00
Alejandro Celaya
1de05047ca Merge pull request #235 from tivyhosting/master
Improved update instructions + command fix
2018-10-18 21:28:13 +02:00
tivyhosting
2af5de1199 Made required fixes. 2018-10-18 12:06:07 -07:00
Alejandro Celaya
e66a724d2b Added fix on IP addresses discovery to changelog 2018-10-18 20:34:55 +02:00
Alejandro Celaya
9f4c2ac8d7 Inlined instructions to enable apcu and memcached in travis 2018-10-18 20:26:44 +02:00
Alejandro Celaya
44f0011445 Moved logic to create a visitor from a request to the visitor itself 2018-10-18 20:24:25 +02:00
Alejandro Celaya
545094cddf Used middleware from library to actually find visitor IP addresses 2018-10-18 20:19:29 +02:00
Alejandro Celaya
99f45d8853 Installed and registered new middleware to process IP addresses from request 2018-10-18 19:53:50 +02:00
Alejandro Celaya
c25b5f9938 Allowed failures on PHP 7.3 until a fix is found 2018-10-18 19:36:03 +02:00
Alejandro Celaya
db1304c11a Added unreleased changes to changelog 2018-10-18 19:24:02 +02:00
Alejandro Celaya
57714b373c Added php 7.3 to the travis build matrix 2018-10-18 19:23:07 +02:00
Alejandro Celaya
5be7f839f3 Ensured visits with empty remote address are not tried to be located 2018-10-18 19:22:24 +02:00
tivyhosting
aa441eb58b Update README.md 2018-10-16 11:00:25 -07:00
tivyhosting
e6b6a40fa6 added CLI info 2018-10-16 10:59:33 -07:00
tivyhosting
f6dde6f4c1 Improved update instructions + command fix 2018-10-16 10:56:15 -07:00
Alejandro Celaya
36ab475578 Merge pull request #232 from acelaya/feature/float-locations
Feature/float locations
2018-10-16 18:34:07 +02:00
Alejandro Celaya
a74fe62da6 Added v1.13.1 to changelog 2018-10-16 18:27:56 +02:00
Alejandro Celaya
1e4de7fec4 Forced explicit string casting when hydrating a VisitLocation from an array 2018-10-16 18:25:03 +02:00
Alejandro Celaya
47117d1fb7 Added version 1.13 to changelog 2018-10-06 20:03:19 +02:00
Alejandro Celaya
cb8ef408a4 Merge pull request #227 from acelaya/feature/visits-threshold-config
Feature/visits threshold config
2018-10-06 12:22:44 +02:00
Alejandro Celaya
e5f21a88fa Fixed typo 2018-10-06 12:13:55 +02:00
Alejandro Celaya
0458c4f798 Updated changelog 2018-10-06 12:08:51 +02:00
Alejandro Celaya
75f6160432 Improved ApplicationConfigCustomizer while asking for visits threshold 2018-10-06 12:02:06 +02:00
Alejandro Celaya
5337eb48e7 Added missing type hint 2018-10-06 11:43:34 +02:00
Alejandro Celaya
86c30ee731 Added new visits_threshold config to installation 2018-10-06 11:41:26 +02:00
Alejandro Celaya
d68dc38959 Merge pull request #224 from acelaya/feature/config-params
Feature/config params
2018-10-06 11:25:56 +02:00
Alejandro Celaya
0525639329 Created CustomizableAppConfigTest 2018-10-06 11:19:02 +02:00
Alejandro Celaya
0d9c7282df Used constants when possible when parsing app config 2018-10-06 11:12:42 +02:00
Alejandro Celaya
3b95925217 Fixed consig customizer tests 2018-10-06 10:05:25 +02:00
Alejandro Celaya
fa595f7aa3 Fixed non-existing keys not being set with default values in imported config 2018-10-06 09:40:18 +02:00
Alejandro Celaya
ff80f32f72 Created json_encode function which always maps to array and converts errors into exceptions 2018-10-05 19:19:44 +02:00
Alejandro Celaya
e55dbef2fc Replaced in_array by contains 2018-10-05 18:52:42 +02:00
Alejandro Celaya
ebf2e459e8 Refactored Databa config customizer so that it uses new structure 2018-10-05 18:43:39 +02:00
Alejandro Celaya
1b5081ae21 Refactored Language and UrlShortener config customizers 2018-10-03 18:55:20 +02:00
Alejandro Celaya
d5736756f7 Ensured asking for previous shlink path is a mandatory question when updating shlink 2018-09-30 18:26:52 +02:00
Alejandro Celaya
757cf2e193 Updated ApplicationConfigCustomizer to support new keys in the future 2018-09-30 18:20:27 +02:00
Alejandro Celaya
3a75ac0486 Merge pull request #222 from acelaya/feature/required-installation-config
Feature/required installation config
2018-09-30 14:10:02 +02:00
Alejandro Celaya
3c3ef6fa05 Fixed installer tests 2018-09-30 11:14:38 +02:00
Alejandro Celaya
3282bfd03b Ensured symfony/console stays in v4.1.4, since the next one throws a lot of phpstan errors 2018-09-30 11:02:01 +02:00
Alejandro Celaya
0813df6b29 Added unreleased entry to Changelog with already merged tasks from v1.13 mi8lestone 2018-09-30 10:52:11 +02:00
Alejandro Celaya
df74a04085 Fixed coding style 2018-09-30 09:47:47 +02:00
Alejandro Celaya
8323b87076 Ensured required config options cannot be left empty 2018-09-30 09:40:43 +02:00
Alejandro Celaya
48f01921e1 Used modern PHP features in CustomizableAppCOnfig 2018-09-30 09:04:00 +02:00
Alejandro Celaya
ae9d99257e Merge pull request #221 from acelaya/feature/chronos
Migrated from standard datetime objects to chronos objects
2018-09-29 13:02:43 +02:00
Alejandro Celaya
0183c8a4b7 Migrated from standard datetime objects to chronos objects 2018-09-29 12:52:32 +02:00
Alejandro Celaya
9a2ca35e6e Merge pull request #220 from acelaya/feature/installer-module
Feature/installer module
2018-09-29 10:24:22 +02:00
Alejandro Celaya
2edb48e314 Documented where the installer command has to be run 2018-09-29 10:15:39 +02:00
Alejandro Celaya
a81fd497d4 Updated Rest translations 2018-09-29 10:09:12 +02:00
Alejandro Celaya
49cca5cd69 Removed FQCN 2018-09-29 10:07:10 +02:00
Alejandro Celaya
f92cff6241 Removed not used translator config 2018-09-29 10:05:13 +02:00
Alejandro Celaya
1b4343ffc2 Moved update and install duplicated code to common config file 2018-09-29 10:00:17 +02:00
Alejandro Celaya
d5392a5f59 Added missing void return type hint 2018-09-29 09:55:13 +02:00
Alejandro Celaya
a65ce649ac Created new Installer module and moved everything from CLI there 2018-09-29 09:52:32 +02:00
Alejandro Celaya
d5dc6cea99 Merge pull request #218 from acelaya/feature/api-key
Feature/api key
2018-09-29 09:05:37 +02:00
Alejandro Celaya
5ecfe9f0f0 Implemented ApiKeyHeaderPlugin 2018-09-29 08:34:47 +02:00
Alejandro Celaya
0f5fb066d1 Converted AuthenticationpluginManager in a plain plugin manager and encasulated in new service adding extra behavior 2018-09-29 08:16:40 +02:00
Alejandro Celaya
8e61639598 Created system of authentication plugins 2018-09-28 22:08:01 +02:00
Alejandro Celaya
e88468d867 Renamed CheckAuthenticationMiddleware to just AuthenticationMiddleware 2018-09-24 23:07:10 +02:00
Alejandro Celaya
bc46e2f509 Defined API key authentication type in swagger docs 2018-09-24 23:07:10 +02:00
Alejandro Celaya
2241279bb6 Merge pull request #217 from acelaya/feature/deprecated-endpoints
Noticed that old endpoints will keep working
2018-09-24 23:05:38 +02:00
Alejandro Celaya
25ffbed756 Fixed references to short codes where actually short URLs are being managed 2018-09-24 23:01:15 +02:00
Alejandro Celaya
8784843a7a Noticed that old endpoints will keep working 2018-09-24 22:49:30 +02:00
Alejandro Celaya
a964e2b3c9 Added note in readme file that travis is the one creating Github releases 2018-09-24 19:47:00 +02:00
Alejandro Celaya
7f7efd45ab Merge pull request #215 from acelaya/feature/automatic-release
Automatic release
2018-09-24 19:44:10 +02:00
Alejandro Celaya
af8f5afef8 Added automatic release generation to travis config 2018-09-24 19:38:22 +02:00
Alejandro Celaya
dcfaed437c Improved build process to not require parent dir, sudo and exclude dirs 2018-09-24 19:35:45 +02:00
Alejandro Celaya
47e2322e33 Merge pull request #213 from acelaya/feature/rename-rest-actions
Feature/rename rest actions
2018-09-20 21:03:43 +02:00
Alejandro Celaya
00e7d57245 Improved API descriptions 2018-09-20 20:53:57 +02:00
Alejandro Celaya
d53a3222d0 Changed documented paths on short URL-related endpoints from short-code to short-url 2018-09-20 20:52:27 +02:00
Alejandro Celaya
80fe3a73e2 More classes renamed and fixes for usage of the short code concept in place of short URL 2018-09-20 20:38:51 +02:00
Alejandro Celaya
7ab993b764 Created and registered middleware which replaces short-code from short-url on rest paths 2018-09-20 20:27:34 +02:00
Alejandro Celaya
622edd2ed1 Renamed rest middlewares to use the short-url concept instead of the short-code concept 2018-09-20 20:00:53 +02:00
Alejandro Celaya
1f5faee356 Renamed rest actions to use the short-url concept instead of the short-code concept 2018-09-20 19:55:24 +02:00
Alejandro Celaya
076b0cf867 Merge pull request #209 from acelaya/feature/cli-refactoring
CLI Refactoring
2018-09-16 19:28:05 +02:00
Alejandro Celaya
d4168bebc6 Ensured install tool knows the install command is the only one 2018-09-16 18:48:10 +02:00
Alejandro Celaya
13c3629cd6 Updated few translations 2018-09-16 18:37:54 +02:00
Alejandro Celaya
1eff9801e8 Updated references to short code and replaced them to short URL where appropriate 2018-09-16 18:36:02 +02:00
Alejandro Celaya
92858aebd6 Merge pull request #204 from acelaya/master
Updated changelog with v1.12
2018-09-15 18:52:38 +02:00
Alejandro Celaya
1910724a98 Updated changelog with v1.12 2018-09-15 18:47:10 +02:00
Alejandro Celaya
ff8441fa95 Merge pull request #199 from acelaya/feature/delete-short-codes
Delete short URLs
2018-09-15 18:20:06 +02:00
Alejandro Celaya
9d8fb055b1 Updated translations 2018-09-15 18:03:54 +02:00
Alejandro Celaya
9651b3d692 Created command to delete short URLs 2018-09-15 17:57:12 +02:00
Alejandro Celaya
9d10c8627a Created migration fixing cascade delete on visits table 2018-09-15 13:20:13 +02:00
Alejandro Celaya
929d7670cb Documented delete short URLs endpoint in swagger 2018-09-15 13:07:52 +02:00
Alejandro Celaya
5714a8f884 Created action to delete short URLs 2018-09-15 12:56:17 +02:00
Alejandro Celaya
159529937d Created specific service to delete short URLs 2018-09-15 11:54:58 +02:00
Alejandro Celaya
394d9ff4d2 Defined config and implementation to delete short URLs 2018-09-15 11:01:28 +02:00
Alejandro Celaya
07165f344f Normalized entities adding missing type hints and removing superfluous comments 2018-09-15 10:03:42 +02:00
Alejandro Celaya
4f2146dd9c Replaced commands namespace shortcode by short-code, using the old one as an alias 2018-09-14 19:38:52 +02:00
Alejandro Celaya
5b9784cd9e Merge pull request #195 from acelaya/feature/gdpr
Fix GDPR compliance
2018-09-14 19:30:14 +02:00
Alejandro Celaya
9d9b61cf14 Fixed message displayed during installation process 2018-09-14 19:18:10 +02:00
Alejandro Celaya
9d7db96e4b Added country name to console comand that lists visits 2018-09-14 19:12:23 +02:00
Alejandro Celaya
3d0bca2781 Finally dropped the hashing of the address 2018-09-14 19:04:40 +02:00
Alejandro Celaya
ffb54c4f7a Fixed typehint 2018-09-13 23:52:22 +02:00
Alejandro Celaya
a01031303f Created migration which parses existing IP addresses, generating hashes and droping already used IPs 2018-09-13 23:50:09 +02:00
Alejandro Celaya
7808f6d182 Added remoteAddrHash field to Visit entity 2018-09-13 22:46:28 +02:00
Alejandro Celaya
a0c3b9412f Updated system to obfuscate IP addresses before persisting them 2018-09-13 22:36:28 +02:00
Alejandro Celaya
c32e2053c3 Merge pull request #194 from acelaya/feature/create-url-resp
Updated short URL creation responses to include more information
2018-09-12 20:49:03 +02:00
Alejandro Celaya
a33151248d Removed duplicated code by using a utils trait 2018-09-12 20:40:32 +02:00
Alejandro Celaya
038ba3b006 Fixed wrong typehint 2018-09-12 20:34:36 +02:00
Alejandro Celaya
f3c92f4110 Updated short URL creation responses to include more information 2018-09-12 20:32:58 +02:00
Alejandro Celaya
17779dbbc6 Merge pull request #192 from acelaya/feature/non-unique-long-urls
Ensured same long URL can be used multiple times for different short URLs
2018-09-11 20:44:40 +02:00
Alejandro Celaya
c2dd5b8c47 Ensured same long URL can be used multiple times for different short URLs 2018-09-11 19:44:33 +02:00
Alejandro Celaya
fcb9121e5a Merge pull request #191 from acelaya/feature/how-to-release
Added release instructions to readme file
2018-09-11 19:28:41 +02:00
Alejandro Celaya
0af1004860 Ordered gitignore placing all composer-related files together 2018-09-11 19:25:13 +02:00
Alejandro Celaya
917f668cf3 Added release instructions to readme file, and improved how to build instructions 2018-09-11 19:17:29 +02:00
Alejandro Celaya
436499b7c4 Merge pull request #186 from robwent/robots-txt
Adds robots.txt and disallows all
2018-09-09 18:50:53 +02:00
Robert Went
66af9866f0 Adds robots.txt and disallows all 2018-09-09 17:41:57 +01:00
Alejandro Celaya
3703dedad9 Merge pull request #184 from acelaya/master
Improved documentation in README file
2018-09-09 18:28:35 +02:00
Alejandro Celaya
37502151ef Updated date in license 2018-09-09 18:23:36 +02:00
Alejandro Celaya
3816a10de3 Improved documentation in README file 2018-09-09 18:20:12 +02:00
Alejandro Celaya
bdda6067ab Replaced hardcoded donate link by short URL 2018-09-02 08:05:39 +02:00
Alejandro Celaya
0f62af241f Updated badges and added donate badge 2018-08-30 19:43:11 +02:00
Alejandro Celaya
987919e87a Merge pull request #179 from acelaya/feature/1.11.0
v1.11.0
2018-08-13 16:40:37 +02:00
Alejandro Celaya
0c03a4b7ff Added v1.11.0 to changelog 2018-08-13 16:29:40 +02:00
Alejandro Celaya
5d6d13c95f Updated API docs including new response structure 2018-08-13 16:17:43 +02:00
Alejandro Celaya
563021bdc1 Updated resolve short url action to return all data for that short url 2018-08-11 10:40:44 +02:00
Alejandro Celaya
2d6d35a398 Added shortUrl field to serialized ShortUrl objects, both from CLI and REST 2018-08-10 23:14:45 +02:00
Alejandro Celaya
30297ac5ac Merge pull request #176 from acelaya/feature/1.10.2
feature/1.10.2
2018-08-04 16:51:01 +02:00
Alejandro Celaya
416c56dee2 Added new spanish translations 2018-08-04 16:37:54 +02:00
Alejandro Celaya
6b968a6843 Updated changelog including v1.10.2 2018-08-04 16:28:12 +02:00
Alejandro Celaya
080965e166 Improved ShortUrlRepositoryTest covering listing case with filter by tag and search term at the same time 2018-08-04 16:21:01 +02:00
Alejandro Celaya
c7239aaca2 Fixed duplicated join with same table performed while filtering short codes by search term and tags 2018-08-04 16:15:09 +02:00
Alejandro Celaya
110e8cb78d Added test to cover new IP resolution API limits 2018-08-04 15:50:02 +02:00
Alejandro Celaya
ed859767a8 Updated IpLocation resolver to be able to provide limits in order to apply sleeps 2018-08-02 23:02:48 +02:00
Alejandro Celaya
d54b823c88 Merge branch 'develop' 2018-08-02 17:56:38 +02:00
Alejandro Celaya
0ae44d3331 Merge pull request #168 from acelaya/feature/1.10.1
Feature/1.10.1
2018-08-02 17:55:25 +02:00
Alejandro Celaya
8063e643a3 Updated changelog with version 1.10.1 2018-08-01 20:58:48 +02:00
Alejandro Celaya
3883ed15c4 Fixed short codes DB length too short 2018-08-01 20:40:24 +02:00
Alejandro Celaya
a79c1f580e Fixed visits count multiplied by the number of tags when ordering and filtering by text 2018-08-01 20:31:54 +02:00
Alejandro Celaya
f4b569c245 Improved code 2018-08-01 20:28:05 +02:00
Alejandro Celaya
899771cc2e Fixed geolocation by switching to different API 2018-07-31 20:24:13 +02:00
Alejandro Celaya
863803b614 Fixed tests failing with new typehints 2018-07-31 19:59:41 +02:00
Alejandro Celaya
5be5e0bc60 Fixed coding styles 2018-07-31 19:53:59 +02:00
Alejandro Celaya
0b8e305533 Improved error management in process visits command 2018-07-31 19:42:33 +02:00
Alejandro Celaya
39d79366a3 Documented date range params for visits endpoint 2018-07-30 20:28:41 +02:00
Alejandro Celaya
d5b78f2a7e Fixed date fields not properly parsed depending if originally they were datetimes or strings 2018-07-28 18:57:24 +02:00
Alejandro Celaya
b2a63f734a Simplified how built shlink version is found out 2018-07-26 20:35:02 +02:00
Alejandro Celaya
82f41de87b Added build step which sets shlink's version 2018-07-26 18:44:04 +02:00
Alejandro Celaya
af4c66d40a Added version placeholder in place of hardcoded version in config 2018-07-26 18:42:53 +02:00
Alejandro Celaya
975260f126 Merge pull request #164 from shlinkio/develop
Develop
2018-07-09 18:48:28 +02:00
Alejandro Celaya
bd678b41f7 Merge pull request #163 from acelaya/develop
v1.10.0
2018-07-09 18:41:28 +02:00
Alejandro Celaya
66898b6ddc Added v1.10.0 to changelog 2018-07-09 18:40:48 +02:00
Alejandro Celaya
5eee683978 Added release datesto changelog 2018-07-09 17:48:23 +02:00
Alejandro Celaya
e92446df9b Updated changelog to use the keepachangelog format 2018-07-09 17:30:25 +02:00
Alejandro Celaya
63a69b05a1 Added Zend expressive swoole config provider to global config when present 2018-07-04 20:40:38 +02:00
Alejandro Celaya
c79ca1d13c Fixed phpstan issues 2018-07-04 20:28:05 +02:00
Alejandro Celaya
87c4851d7e Simplified ListKeysCommand reducing cyclomatic complexity on nested callbacks 2018-07-04 20:24:13 +02:00
Alejandro Celaya
a125c93ca3 Updated to phpstan 0.10 and infection 0.9 2018-07-04 12:08:27 +02:00
Alejandro Celaya
a8465094c1 Merge branch 'develop' 2018-06-18 20:49:32 +02:00
Alejandro Celaya
16f7359ac6 Merge pull request #156 from acelaya/feature/1.9.1
Improved paginator properties
2018-06-18 20:48:41 +02:00
Alejandro Celaya
f9f4817ee2 Aded v1.9.1 to changelog 2018-06-18 20:40:50 +02:00
Alejandro Celaya
c7e49f223f Fixed filtered lists not being properly paginated 2018-06-18 20:38:25 +02:00
Alejandro Celaya
6e79b4ba7b Fixed php binary used in child commands while installkation not properly inherited 2018-06-18 20:14:51 +02:00
Alejandro Celaya
f78a7f12a9 Improved paginator properties 2018-06-17 18:29:40 +02:00
Alejandro Celaya
b3664597b0 Merge branch 'develop' 2018-05-07 11:27:13 +02:00
Alejandro Celaya
8cfb4f61ca Merge pull request #148 from acelaya/feature/1.9.0
Version 1.9.0
2018-05-07 11:26:27 +02:00
Alejandro Celaya
b0dbb2dae4 Updated CreateShortCodeContentNegotiationMiddleware so that query parameter takes precedence over Accept header 2018-05-07 11:17:10 +02:00
Alejandro Celaya
7c6da4985d Updated build script to delete more development-specific files 2018-05-07 11:09:32 +02:00
Alejandro Celaya
386b0dfb7b Updated changelog 2018-05-07 11:03:28 +02:00
Alejandro Celaya
1437ff48ce Ensured all core actions log errors 2018-05-07 10:58:49 +02:00
Alejandro Celaya
63294f20ee Updated language files 2018-05-06 12:36:07 +02:00
Alejandro Celaya
d8acc3c247 Removed unused use statement 2018-05-06 12:34:21 +02:00
Alejandro Celaya
52d8ffa212 Improved CreateShortCodeContentNegotiationMiddleware sho that it takes into account the case in which an error is returned from next middleware 2018-05-06 12:28:22 +02:00
Alejandro Celaya
98ad2816e8 Documented new endpoint to create short URLs in a single step 2018-05-06 12:19:08 +02:00
Alejandro Celaya
9d890f4227 Created CreateShortCodeContentNegotiationMiddleware 2018-05-03 19:04:40 +02:00
Alejandro Celaya
0932d04907 Fixed tests namespaces to match their subject under test 2018-05-03 18:34:45 +02:00
Alejandro Celaya
1f78b5c524 Improved CreateShortCodeContentNegotiationMiddleware so that it can determine the format based on a query partameter 2018-05-03 18:32:32 +02:00
Alejandro Celaya
59f10619ba Created middleware used with short codes creation actions to handle content negotiation 2018-05-03 18:26:31 +02:00
Alejandro Celaya
334710e92c Added middleware which injects the content-length header in the response if not present 2018-05-03 18:25:57 +02:00
Alejandro Celaya
75b8175824 Fixed coding styles in config file 2018-05-03 18:05:16 +02:00
Alejandro Celaya
8a74ef2a33 Moved action to subnamespace 2018-05-03 18:04:00 +02:00
Alejandro Celaya
d05ac5ce9d Moved action to subnamespace 2018-05-03 18:03:10 +02:00
Alejandro Celaya
3100fffa2b Moved action to subnamespace 2018-05-03 18:02:45 +02:00
Alejandro Celaya
6bbacb1017 Moved action to subnamespace 2018-05-03 18:01:57 +02:00
Alejandro Celaya
4403dc5df9 Moved action to subnamespace 2018-05-03 18:00:32 +02:00
Alejandro Celaya
fdc637c23d Moved action to subnamespace 2018-05-03 17:59:28 +02:00
Alejandro Celaya
b99d662417 Created SingleStepCreateShortCodeActionTest 2018-05-03 17:57:43 +02:00
Alejandro Celaya
eb9a964c66 Removed unused use statement 2018-05-03 13:34:13 +02:00
Alejandro Celaya
e5ef8d7f8c Created action which allows short URLs to be created on a single API request 2018-05-03 13:21:43 +02:00
Alejandro Celaya
28650aee2b Fixed case sensitivity errors 2018-05-03 12:19:51 +02:00
Alejandro Celaya
a2294704e6 Split try catch to prevent undefined variables 2018-05-01 19:38:44 +02:00
Alejandro Celaya
e5e1aa2ff4 Defined abstract action which handles short codes generations 2018-05-01 19:35:12 +02:00
Alejandro Celaya
2f5290b9d3 Moved whitelisted routes in CheckAuthenticationMiddleware to external configuration 2018-05-01 18:36:42 +02:00
Alejandro Celaya
ef3c4aadf2 Moved most of rest routes config to their actions 2018-05-01 18:28:37 +02:00
Alejandro Celaya
c9ce56eea5 Added public method in AbstractRestAction which builds route definition 2018-05-01 18:16:44 +02:00
Alejandro Celaya
4fee656f96 Prepared version 1.9.0 2018-05-01 10:10:19 +02:00
Alejandro Celaya
d2a04259f5 Merge branch 'develop' 2018-04-07 09:06:45 +02:00
Alejandro Celaya
e504daa1ba Merge pull request #142 from acelaya/develop
Develop
2018-04-07 09:05:56 +02:00
Alejandro Celaya
8793a67ce9 Reduced the number of includes by pointing to dcotrine scripts with extension 2018-04-07 08:37:41 +02:00
Alejandro Celaya
b4ded374e9 Updated changelog 2018-04-07 08:32:06 +02:00
Alejandro Celaya
91d350b12f Removed path workaround in PathVersionMiddleware and simplified code 2018-04-07 08:31:03 +02:00
Alejandro Celaya
b3e25f28fd Added v1.8.1 to changelog 2018-04-07 08:25:01 +02:00
Alejandro Celaya
aca89f9abe Updated links to doctrine CLI scripts to avoid depending on symlinks 2018-04-07 08:21:34 +02:00
Alejandro Celaya
243075dd78 Merge branch 'develop' 2018-03-29 09:52:00 +02:00
Alejandro Celaya
7130425896 Merge pull request #133 from acelaya/feature/1.8.0
1.8.0
2018-03-29 09:50:58 +02:00
Alejandro Celaya
fe9ab20cbb Applied some improvements 2018-03-27 23:57:29 +02:00
Alejandro Celaya
6935b2ebe2 Updated system so that NotFoundDelegate is used 2018-03-26 20:37:04 +02:00
Alejandro Celaya
3dcc510da1 Updated to symfony 4 2018-03-26 20:32:12 +02:00
Alejandro Celaya
2f26c82fa6 Removed expressive migration tool from dev dependencies 2018-03-26 20:25:30 +02:00
Alejandro Celaya
9ddb60a882 Updated changelog including v1.8.0 2018-03-26 20:22:57 +02:00
Alejandro Celaya
210b08b61f Created PixelActionTest 2018-03-26 20:17:38 +02:00
Alejandro Celaya
42fe4bd5ce Created new action to track visits, which returns an empty pixel 2018-03-26 20:13:03 +02:00
Alejandro Celaya
1b2a0820e5 Updated to phpunit 7 and dropped dbunit dependency 2018-03-26 19:09:10 +02:00
Alejandro Celaya
6cf0155417 Updated minimum required MSI 2018-03-26 19:06:49 +02:00
Alejandro Celaya
9b8be3e5b8 Fixed phpstan errors 2018-03-26 19:05:26 +02:00
Alejandro Celaya
a27b01b895 Fixed tests 2018-03-26 19:02:41 +02:00
Alejandro Celaya
16dd1838aa Updated to expressive 3 2018-03-26 18:49:28 +02:00
Alejandro Celaya
f788d6872f Added infection to the build matrix 2018-03-26 18:16:59 +02:00
Alejandro Celaya
d0df007812 Dropped support for PHP 7.0 2018-03-26 18:16:59 +02:00
Alejandro Celaya
f60c217fae Merge pull request #136 from acelaya/feature/1.7.2
Feature/1.7.2
2018-03-26 18:13:48 +02:00
Alejandro Celaya
d3fc7d543a Updated changelog 2018-03-26 18:13:08 +02:00
Alejandro Celaya
4d0fc1da07 Fixed PathVersionMiddleware not being properly propagated 2018-03-26 17:53:22 +02:00
Alejandro Celaya
ee2233c6dd Updated PathVersionMiddleware to single-pass middleware 2018-03-26 17:36:58 +02:00
Alejandro Celaya
ea6e0d7c7f Merge branch 'develop' 2018-03-21 16:31:27 +01:00
Alejandro Celaya
d9d599eab4 Updated changelog 2018-03-21 16:31:00 +01:00
Alejandro Celaya
d1ba44e1b3 Merge pull request #128 from weirdan/upgrade-to-expressive-2.2
Upgrade to expressive 2.2
2018-03-21 16:27:09 +01:00
Bruce Weirdan
dff2ad3740 define property to please scrutinizer 2018-03-21 12:13:03 +02:00
Bruce Weirdan
f7e63710e4 updated tests to fix deprecations
also fixed cs errors in middleware-pipeline
2018-03-21 02:05:55 +02:00
Bruce Weirdan
d3b5cd5c57 fixed middleware deprecations 2018-03-21 01:46:26 +02:00
Alejandro Celaya
86ed83d25e Merge branch 'develop' 2018-02-03 10:23:18 +01:00
Alejandro Celaya
f96d0fe30a Merge pull request #124 from acelaya/feature/o-a-s-3
Feature/o a s 3
2018-02-03 10:14:32 +01:00
Alejandro Celaya
be406bd676 Removed no-longer used Authorization parameter 2018-02-03 10:13:10 +01:00
Alejandro Celaya
044278752b Fixed server 2018-02-03 10:09:42 +01:00
Alejandro Celaya
343d2ab44a Added domain 2018-02-03 10:07:37 +01:00
Alejandro Celaya
66992f644e Added default value for server 2018-02-03 10:06:04 +01:00
Alejandro Celaya
cf245524dd Added missing base path in server 2018-02-03 10:01:16 +01:00
Alejandro Celaya
ad520811a3 Fixed dynamic host 2018-02-03 09:55:53 +01:00
Alejandro Celaya
ee1e1d5688 Updated swagger docs to OAS3 2018-02-03 09:53:40 +01:00
Alejandro Celaya
8ef0e7c25b Merge pull request #121 from shlinkio/develop
Develop
2018-01-21 10:11:12 +01:00
Alejandro Celaya
c3d555ef3c Added missing null coalescing operator 2018-01-21 10:01:18 +01:00
Alejandro Celaya
bf8e14708b Merge pull request #116 from acelaya/feature/1.7.0
Feature/1.7.0
2018-01-21 10:00:11 +01:00
Alejandro Celaya
6ea59b1e4d Updated changelog 2018-01-21 09:43:01 +01:00
Alejandro Celaya
cf8b778711 Updated language files 2018-01-21 09:40:38 +01:00
Alejandro Celaya
1e79969c3b Made visits not to be tracked if query param has been provided 2018-01-14 09:24:33 +01:00
Alejandro Celaya
5fd34e03fc Added new app config param to allow disabling short URL visits tracking 2018-01-14 09:13:49 +01:00
Alejandro Celaya
ce9d6642d4 Fixed edit short code action not being properly registered 2018-01-07 21:13:06 +01:00
Alejandro Celaya
ecebdbbfa8 Updated API docs including new endpoint and updating params for short code creation 2018-01-07 20:54:02 +01:00
Alejandro Celaya
6f7ce709ca Fixed PhpStan error 2018-01-07 20:46:28 +01:00
Alejandro Celaya
84094a51a2 Implemented EditShortCodeAction 2018-01-07 20:45:05 +01:00
Alejandro Celaya
7ba9eb8e2c Fixed coding styles 2018-01-07 20:08:07 +01:00
Alejandro Celaya
e8a0c5484c Added test for ShortUrlMeta 2018-01-07 20:07:12 +01:00
Alejandro Celaya
0521227127 Tested new method to update short URLs metadata 2018-01-07 20:00:21 +01:00
Alejandro Celaya
fac9455a1e Created method to updated already created short URLs 2018-01-07 19:51:25 +01:00
Alejandro Celaya
3243ade4fd Improved error message when installation fails 2017-12-31 19:31:35 +01:00
Alejandro Celaya
da21eb4a5c Removed return type incompatible with PHP 7.0 2017-12-31 19:24:22 +01:00
Alejandro Celaya
5ec6d538db Improved and simplified ProcessVisitsCommand thanks to SymfonyStyle 2017-12-31 19:13:42 +01:00
Alejandro Celaya
08228d9d98 Improved and simplified RenameTagCommand thanks to SymfonyStyle 2017-12-31 19:10:27 +01:00
Alejandro Celaya
7856d64299 Improved and simplified ListTagsCommand thanks to SymfonyStyle 2017-12-31 19:08:10 +01:00
Alejandro Celaya
057bbae729 Improved and simplified DeleteTagCommand thanks to SymfonyStyle 2017-12-31 19:06:04 +01:00
Alejandro Celaya
09b161304c Improved and simplified CreateTagCommand thanks to SymfonyStyle 2017-12-31 19:03:41 +01:00
Alejandro Celaya
a60c45ca4d Simplified and improved ResolveUrlCommand with SymfonyStyle 2017-12-31 18:58:11 +01:00
Alejandro Celaya
89ed84ce28 Removed unused use statements 2017-12-31 18:38:25 +01:00
Alejandro Celaya
a6c547c4da Improved and simplified ListShortcodesCommand with SymfonyStyle 2017-12-31 18:37:39 +01:00
Alejandro Celaya
3e2c5abaa4 Improved GetVisitsCommand by using SymfonyStyle 2017-12-31 18:17:58 +01:00
Alejandro Celaya
c202b3e518 Improved GenerateShortcodeCommand by using SymfonyStyle 2017-12-31 18:12:43 +01:00
Alejandro Celaya
e15b67b5dc Improved GeneratePreviewCommand using SymfonyStyle 2017-12-31 18:04:11 +01:00
Alejandro Celaya
7ddc180487 Simplified InstallCommand 2017-12-31 17:59:50 +01:00
Alejandro Celaya
f3fbfc3692 Fixed phpstan error 2017-12-31 17:54:01 +01:00
Alejandro Celaya
b289e3bac2 Applied more improvements on InstallCommand with SymfonyStyle 2017-12-31 17:52:17 +01:00
Alejandro Celaya
4d4aafa6db Fixed config customizer tests 2017-12-31 17:45:27 +01:00
Alejandro Celaya
2705070063 Renamed tests 2017-12-31 17:22:25 +01:00
Alejandro Celaya
5e3770c105 Renamed ConfigCustomizerPluginManager to CongigCustomizerManager 2017-12-31 17:20:03 +01:00
Alejandro Celaya
0f0213aa87 Removed plugin suffix on config ustomizers 2017-12-31 17:18:54 +01:00
Alejandro Celaya
0e2ad0dbca Updated ConfigCustomizer api to expect a SymfonyStyle object instead of a set of input and output 2017-12-31 17:14:01 +01:00
Alejandro Celaya
d275316acd Applied SymfonyStyle to all installation config customizers 2017-12-31 17:07:39 +01:00
Alejandro Celaya
0a681f0efa Simplified UrlShortenerConfigCustomizerPlugin thanks to SymfonyStyle 2017-12-31 17:00:26 +01:00
Alejandro Celaya
b17f96043a Simplified and standardized DatabaseConfigCustomizerPlugin thanks to SymfonyStyle 2017-12-31 16:53:18 +01:00
Alejandro Celaya
6f9b727673 Merge branch 'feature/1.7.0' of github.com:acelaya/shlink into feature/1.7.0 2017-12-31 16:29:55 +01:00
Alejandro Celaya
79427d08d7 Added phpstan config file to export-ignore list 2017-12-30 21:39:18 +01:00
Alejandro Celaya
2ec807ba70 Increased phpstan required level 2017-12-30 21:36:33 +01:00
Alejandro Celaya
ede4525332 Refactored exceptions to properly use package exceptions 2017-12-30 21:35:26 +01:00
Alejandro Celaya
4dffc9f0c1 Improved and simplified all installation process thanks to symfony style 2017-12-28 15:52:10 +01:00
Alejandro Celaya
5de845c258 Improved GenerateSecretCommand by using SymfonyStyle 2017-12-28 15:17:12 +01:00
Alejandro Celaya
745ff51150 Ensured phpstan config is properly loaded in Ci envs 2017-12-28 15:07:14 +01:00
Alejandro Celaya
88b9f9fc56 Fixed GenerateCharsetCommandTest 2017-12-28 14:59:52 +01:00
Alejandro Celaya
fdbe076bf2 Added phpstan config file excluding a file that fails 2017-12-28 14:55:55 +01:00
Alejandro Celaya
0760550767 Removed unnecessary type hints 2017-12-28 09:48:34 +01:00
Alejandro Celaya
1b94083188 Improved GenerateCharsetCommand by using SymfonyStyle 2017-12-28 09:48:17 +01:00
Alejandro Celaya
1993d01110 Dimplified GenerateKeyCommand by using SymfonyStyle 2017-12-27 17:36:07 +01:00
Alejandro Celaya
37fb7e76d9 Simplified DisableKeyCommand using SymfonyStyle 2017-12-27 17:32:39 +01:00
Alejandro Celaya
cc3362837b Simplified ListKeysCommand using SymfonyStyle 2017-12-27 17:28:51 +01:00
Alejandro Celaya
2012cc453c Fixed PHPStan errors due to API inconsistency in EntityManager and EntityManagerInterface 2017-12-27 17:22:51 +01:00
Alejandro Celaya
ea80b6d48a Replaced vlucas/phpdotenv package by symfony/dotenv 2017-12-27 16:33:06 +01:00
Alejandro Celaya
db956a1f40 Fixed all possible PHPStan errors 2017-12-27 16:23:54 +01:00
Alejandro Celaya
4f3995ea80 Fixed phpstan errors in ListKeysCommand 2017-12-27 15:56:26 +01:00
Alejandro Celaya
e024ba5d94 Added phpstan to build matrix 2017-12-27 15:43:59 +01:00
Alejandro Celaya
af0ff0f65b Console commands are now lazy loaded 2017-12-27 15:37:26 +01:00
Alejandro Celaya
a9094dc0f6 Updated dependency constraints 2017-12-27 15:25:59 +01:00
Alejandro Celaya
aca90ef907 Merge pull request #111 from shlinkio/develop
Develop
2017-10-25 16:25:39 +02:00
Alejandro Celaya
ddfccea901 Updated changelog 2017-10-25 16:21:34 +02:00
Alejandro Celaya
6c6cfb4fc3 Fixed typo 2017-10-25 16:19:08 +02:00
Alejandro Celaya
482b792adf Merge branch 'develop' 2017-10-24 17:45:54 +02:00
Alejandro Celaya
d3a86f4fae Added v1.6.1 to CHANGELOG 2017-10-24 17:45:19 +02:00
Alejandro Celaya
6de1d1057b Created gitattributes file 2017-10-24 17:43:19 +02:00
Alejandro Celaya
d7e68d29de Merge branch 'develop' 2017-10-23 14:01:22 +02:00
Alejandro Celaya
b8f24c3584 Merge pull request #107 from acelaya/feature/1.6
Feature/1.6
2017-10-23 14:00:24 +02:00
Alejandro Celaya
26c455616b Ensured validate_url does not fail when importing config, and instead, it gets a default BC value 2017-10-23 13:56:07 +02:00
Alejandro Celaya
909ecc2387 Ensured build does not fail when trying to delete missing optional files 2017-10-23 13:44:50 +02:00
Alejandro Celaya
a9dff56a92 Updated config aggregator version 2017-10-23 13:33:23 +02:00
Alejandro Celaya
ef0dd416f9 Updated CHANGELOG 2017-10-23 13:30:26 +02:00
Alejandro Celaya
781ca39938 Fixed merge conflicts 2017-10-23 13:28:09 +02:00
Alejandro Celaya
ccb9d5e83a Merge pull request #105 from gogus/feature/url-validation-option
Added option for enable/disable URL Validation by response status code.
2017-10-23 13:18:30 +02:00
Alejandro Celaya
91f08c9ead Updated CHANGELOG 2017-10-23 13:09:10 +02:00
Alejandro Celaya
433a5a923d Improved ShortUrlRepositoryTest 2017-10-23 13:06:29 +02:00
Alejandro Celaya
501a933d2e Created ShortUrlRepositoryTest 2017-10-23 13:03:23 +02:00
Alejandro Celaya
633f3b728f Created composer command to generate merge pretty code coverage 2017-10-23 12:54:54 +02:00
Alejandro Celaya
be34600494 Updated CI process to generate a merged coverage file 2017-10-23 12:51:06 +02:00
Alejandro Celaya
9577a4da4b Refactored ShortUrlRepository to make it more readable 2017-10-23 12:36:03 +02:00
Alejandro Celaya
a24688b92a Created VisitRepositoryTest 2017-10-23 12:33:46 +02:00
Alejandro Celaya
91442a3379 Ensured same testing database is used to generate with entities and to run functional tests 2017-10-23 12:19:28 +02:00
Alejandro Celaya
0bd9f1e19f Removed wrong extension for travis 2017-10-23 12:09:07 +02:00
Alejandro Celaya
c233e807c2 Added sqlite extensions to PDO 2017-10-23 11:42:13 +02:00
Alejandro Celaya
a002c60183 Updated travis config so that it loads apcu extension 2017-10-23 11:37:16 +02:00
Alejandro Celaya
c522879c64 Updated composer check to ru functional tests too 2017-10-23 11:29:37 +02:00
Mikolaj Gogula
d04abd1f75 Added validate_url config key for development. 2017-10-23 11:28:04 +02:00
Alejandro Celaya
c2feffa50c First version of functional tests working 2017-10-23 11:21:00 +02:00
Alejandro Celaya
e282521040 Updated migrations to prevent duplication when running after orm schema tool 2017-10-23 11:11:26 +02:00
Alejandro Celaya
d7b7db670f Created first common elements for functional tests 2017-10-22 18:03:35 +02:00
Alejandro Celaya
5a500a00d7 Added another feature to CHANGELOG 2017-10-22 09:18:28 +02:00
Alejandro Celaya
9fb07f4039 Fixed tests 2017-10-22 09:17:19 +02:00
Alejandro Celaya
cb23d38b38 Used maxVisits field when creating or fetching a ShortUrl 2017-10-22 09:15:37 +02:00
Alejandro Celaya
af7c11665c Added max_visits field to short_urls 2017-10-22 09:00:32 +02:00
Alejandro Celaya
7f4678261e Added first tasks to the CHANGELOG 2017-10-21 20:27:19 +02:00
Alejandro Celaya
a1c8c51f70 Updated translations 2017-10-21 20:21:08 +02:00
Alejandro Celaya
6bbe66e8f1 Improved CreateShortcodeActiontest 2017-10-21 20:16:39 +02:00
Alejandro Celaya
5f0d281255 Updated create shortcode action to accept the custom slug 2017-10-21 20:09:30 +02:00
Alejandro Celaya
fd468cd4e9 Added support for custom slug in shortcode command 2017-10-21 17:32:05 +02:00
Alejandro Celaya
1f7a94794d Added option to provide custom slug when creating a short url 2017-10-21 17:19:02 +02:00
Alejandro Celaya
0232f68b91 Updated action and command to create short urls so that it accepts validity dates 2017-10-21 12:24:53 +02:00
Alejandro Celaya
070055a8b9 Fixed type hints 2017-10-21 11:59:31 +02:00
Alejandro Celaya
a3bbd06fe3 Updated UrlShortener so that it does not match a short code which is out of the validity dat erange 2017-10-21 11:58:20 +02:00
Alejandro Celaya
68b4cfbae0 Added valid_since and valid_until columns to shoirt_urls table 2017-10-21 11:39:27 +02:00
Alejandro Celaya
97a54aef06 Imported function in config file 2017-10-21 11:28:44 +02:00
Mikolaj Gogula
297c88c334 Change variable name for validation enabled. 2017-10-17 11:44:30 +02:00
Mikolaj Gogula
fef5390a62 Codestyle fixes. 2017-10-17 11:35:32 +02:00
Mikolaj Gogula
08d18b1dc1 Codestyle fixes. 2017-10-17 11:33:11 +02:00
Mikolaj Gogula
16a2349d86 Composer fixes. 2017-10-17 11:28:05 +02:00
Mikolaj Gogula
18d9815e88 Added option for enable/disable URL Validation by response status code. 2017-10-17 11:03:12 +02:00
Alejandro Celaya
c8346bc5f8 Added target php platform in composer.json to prevent building versions that cannot be executed in older versions 2017-10-16 18:23:13 +02:00
Alejandro Celaya
2d85a207d1 Removed comented translations 2017-10-13 12:31:44 +02:00
Alejandro Celaya
0df8f17e7b Added new translations 2017-10-13 12:30:54 +02:00
Alejandro Celaya
29645e77cf Created DottedAccessConfigAbstractFactory 2017-10-13 12:27:20 +02:00
Alejandro Celaya
ea76092681 Ensured a generic template is used to render generic 404 errors, and a more specific one to render 'invalid short url' errors 2017-10-13 12:22:19 +02:00
Alejandro Celaya
c12e13dfd7 Created NotFoundDelegateTest 2017-10-13 12:02:00 +02:00
Alejandro Celaya
566940349f Created default delegate that returns a JSON response when accepted type is json 2017-10-13 11:55:14 +02:00
Alejandro Celaya
391ef5c323 Added return typehint 2017-10-12 11:59:22 +02:00
Alejandro Celaya
70264be8e7 Fixed coding styles 2017-10-12 11:29:11 +02:00
Alejandro Celaya
6208f6f0d5 Improved Exception management to be more specific 2017-10-12 11:28:45 +02:00
Alejandro Celaya
c422a14c5c Improved coding styles 2017-10-12 10:13:20 +02:00
Alejandro Celaya
fbeb959317 Fixed tests 2017-10-12 10:03:43 +02:00
Alejandro Celaya
e53ffc8d43 Migrated templates to plates 2017-10-12 10:03:20 +02:00
Alejandro Celaya
453ca1728e Updated system to use plates instead of twig 2017-10-12 09:40:42 +02:00
Alejandro Celaya
d10583c7c5 Udated minimum PHP version and docker stuff 2017-10-12 09:24:47 +02:00
Alejandro Celaya
a9d213990e Merge branch 'feature/1.6' of github.com:acelaya/shlink into feature/1.6 2017-09-30 12:14:05 +02:00
Alejandro Celaya
6321cc0f2d Added security-advisories dependency 2017-09-30 12:13:47 +02:00
Alejandro Celaya
3e5f0b2451 Ensured a doctrine/cache version which requires PHP 7.1 is not installed 2017-09-30 12:13:47 +02:00
Alejandro Celaya
4ad167eb30 Ensured all doctrine components are not updated to latest releases, which require PHP 7.1 2017-09-30 12:13:47 +02:00
Alejandro Celaya
01a4f9f867 Removed any remaining reference to AnnotatedFactory 2017-09-30 12:13:47 +02:00
Alejandro Celaya
b93d65ddc1 Replaced more ussages of AnnotatedFactory by ConfigAbstractFactory 2017-09-30 12:13:47 +02:00
Alejandro Celaya
9ef9da0870 Replaced more ussages of AnnotatedFactory by ConfigAbstractFactory 2017-09-30 12:13:47 +02:00
Alejandro Celaya
ba2053bd3a Dropped AnnotatedFactory in commands and replaced by ConfigAbstractFactory 2017-09-30 12:13:47 +02:00
Alejandro Celaya
1260da85a7 Added PHP 7.2 to the build matrix 2017-09-30 12:13:12 +02:00
Alejandro Celaya
960c7a0835 Added security-advisories dependency 2017-08-19 19:41:07 +02:00
Alejandro Celaya
574f407a90 Ensured a doctrine/cache version which requires PHP 7.1 is not installed 2017-07-23 11:51:47 +02:00
Alejandro Celaya
abf802093c Ensured all doctrine components are not updated to latest releases, which require PHP 7.1 2017-07-23 08:42:57 +02:00
Alejandro Celaya
7ca22f8629 Removed any remaining reference to AnnotatedFactory 2017-07-22 14:20:40 +02:00
Alejandro Celaya
6300982b07 Replaced more ussages of AnnotatedFactory by ConfigAbstractFactory 2017-07-22 13:48:30 +02:00
Alejandro Celaya
54cb40f6ed Replaced more ussages of AnnotatedFactory by ConfigAbstractFactory 2017-07-22 13:41:41 +02:00
Alejandro Celaya
8256f0c757 Dropped AnnotatedFactory in commands and replaced by ConfigAbstractFactory 2017-07-22 13:33:32 +02:00
Alejandro Celaya
1009f9e7c6 Merge pull request #98 from shlinkio/develop
Develop
2017-07-16 10:08:38 +02:00
Alejandro Celaya
9c8eef12ba Merge pull request #97 from acelaya/feature/1.5
Feature/1.5
2017-07-16 10:01:50 +02:00
Alejandro Celaya
9260b3ac6b Fixed coding styles 2017-07-16 09:58:03 +02:00
Alejandro Celaya
ff98e1fb3d Added v1.5.0 to CHANGELOG 2017-07-16 09:43:35 +02:00
Alejandro Celaya
f3389d3738 Updated language files 2017-07-16 09:40:34 +02:00
Alejandro Celaya
a138f4153d Created DeleteTagsCommand 2017-07-16 09:35:24 +02:00
Alejandro Celaya
602e11d5e7 Added namespace to functions 2017-07-16 09:28:40 +02:00
Alejandro Celaya
3cd14153ca Created command to rename tag 2017-07-16 09:24:21 +02:00
Alejandro Celaya
095d8e73b8 Created ListTagsCommand 2017-07-16 09:13:25 +02:00
Alejandro Celaya
b37f303e76 Created CreateTagCommand 2017-07-16 09:09:11 +02:00
Alejandro Celaya
c8368c9098 Updated language files 2017-07-15 12:16:15 +02:00
Alejandro Celaya
8d0bac9478 Documented delete and edit tags endpoints 2017-07-15 12:13:59 +02:00
Alejandro Celaya
286c24f8c0 Improved TagServiceTest 2017-07-15 12:09:25 +02:00
Alejandro Celaya
963d26f59b Created UpdateTagAction 2017-07-15 12:04:12 +02:00
Alejandro Celaya
e07c464de8 Removed strict declarations 2017-07-15 09:15:45 +02:00
Alejandro Celaya
575509c45b Created CreateTagsActiontest 2017-07-15 09:12:07 +02:00
Alejandro Celaya
563e654b99 Created DeleteTagsActionTest 2017-07-15 09:10:09 +02:00
Alejandro Celaya
3e268e2012 Improved TagServiceTest 2017-07-15 09:05:02 +02:00
Alejandro Celaya
b2d9f2fc01 Added Create and Delete tag actions 2017-07-15 09:00:53 +02:00
Alejandro Celaya
6717102dd2 Updated tag actions namespace 2017-07-15 08:31:21 +02:00
Alejandro Celaya
1ba7fc81ac Created ListTagsCommand 2017-07-08 13:17:46 +02:00
Alejandro Celaya
caf4fa7fdd Documented list tags endpoint 2017-07-08 12:55:38 +02:00
Alejandro Celaya
5c7962966d Created ListTagsActionTest 2017-07-07 13:28:58 +02:00
Alejandro Celaya
95ec7e0afa Registered action to list tags 2017-07-07 13:12:45 +02:00
Alejandro Celaya
c37660f763 Created TagService 2017-07-07 12:49:41 +02:00
Alejandro Celaya
486ea10c3c Renamed EditTagsAction to EditShortcodeTagsAction 2017-07-07 11:45:20 +02:00
Alejandro Celaya
e0f18f8d1f Created InstallApplicationFactoryTest 2017-07-06 18:06:11 +02:00
Alejandro Celaya
a66f116d66 Created DatabaseConfigCustomizerPluginTest 2017-07-06 18:00:38 +02:00
Alejandro Celaya
dd099dc39c Removed declare strict types added by mistake 2017-07-06 17:49:05 +02:00
Alejandro Celaya
c05aeabdee Improved if statements reducing indentation 2017-07-06 17:38:16 +02:00
Alejandro Celaya
23922f6c7b Created UrlShortenerConfigCustomizerPluginTest 2017-07-06 17:28:32 +02:00
Alejandro Celaya
69a99949e1 Created LanguageConfigCustomizerPluginTest 2017-07-06 17:22:03 +02:00
Alejandro Celaya
d56cde72a3 Created ApplicationConfigCustomizerPluginTest 2017-07-06 17:12:32 +02:00
Alejandro Celaya
99ffff11c7 Created DefaultConfigCustomizerPluginFactoryTest 2017-07-06 13:43:36 +02:00
Alejandro Celaya
bb050cc1b6 Improved InstallCommandTest coverage 2017-07-06 13:38:15 +02:00
Alejandro Celaya
3547889ad5 Fixed InstallCommandTest 2017-07-06 10:04:35 +02:00
Alejandro Celaya
479e694478 Moved all configuration customization steps to individual plugins 2017-07-05 20:04:44 +02:00
Alejandro Celaya
2368b634e3 Moved command and app creation logic to a factory for install scripts 2017-07-05 18:12:03 +02:00
Alejandro Celaya
dcc09975a9 Abstracted filesystem manipulation in InstallCommand 2017-07-04 20:14:22 +02:00
Alejandro Celaya
102f5c4e12 Updated instalation script to import sqlte database file when importing the rets of the config 2017-07-04 20:01:42 +02:00
Alejandro Celaya
cc688fa3ce Implemented method to deserialize customizable config 2017-07-04 19:48:53 +02:00
Alejandro Celaya
e7f7cbcaac Improved installation command, reducing duplication and moving serialization logic to specific model 2017-07-03 20:46:35 +02:00
Alejandro Celaya
f9c56d7cb1 Added process to import previous configuration when updating shlink 2017-07-03 13:43:53 +02:00
Alejandro Celaya
1fe2e6f6bd Improved check on update and install commands 2017-07-03 13:17:44 +02:00
Alejandro Celaya
c3cc88f03e Fixed inspections 2017-07-03 13:11:45 +02:00
Alejandro Celaya
584e1f5643 Created common abstract command for update and install 2017-07-03 13:10:16 +02:00
Alejandro Celaya
04c479148a Updated build script so that generated zip contains one folder 2017-07-03 12:54:50 +02:00
Alejandro Celaya
c45cb7bacb Updated build script 2017-07-03 12:49:32 +02:00
Alejandro Celaya
17be221920 Added response examples to swagger docs 2017-04-16 10:45:52 +02:00
Alejandro Celaya
10da57572f Fixed date format returned by the API 2017-04-16 10:27:27 +02:00
Alejandro Celaya
52478ca60a Returned all allowed methods until fast route router is fixed 2017-04-14 13:27:41 +02:00
Alejandro Celaya
62b49dcb19 Set cross domain allow-methods header with the same value as the allow header 2017-04-14 12:55:59 +02:00
Alejandro Celaya
a365faef9c Removed requirement of OPTIONS on every route 2017-04-14 12:52:24 +02:00
Alejandro Celaya
5d2698e8a1 Created EmptyResponseImplicitOptionsMiddlewareFactoryTest 2017-04-13 09:52:17 +02:00
Alejandro Celaya
ec4a413a5b Removed options bypass in actions in favor of implicit options middleware 2017-04-13 09:45:31 +02:00
Alejandro Celaya
596d1ee797 Registered implicit options middleware 2017-04-13 09:43:11 +02:00
Alejandro Celaya
d117f82bcb Installed expressive tooling 2017-04-13 09:39:35 +02:00
Alejandro Celaya
18abe9d0f9 Merge branch 'develop' of github.com:shlinkio/shlink into develop 2017-04-13 09:34:52 +02:00
Alejandro Celaya
b53e51de33 Merge branch 'develop' 2017-03-25 10:13:11 +01:00
Alejandro Celaya
9478c71af1 Merge pull request #90 from acelaya/feature/expressive-2
Feature/expressive 2
2017-03-25 10:11:46 +01:00
Alejandro Celaya
a2c4eebec8 Updated CHANGELOG 2017-03-25 10:09:30 +01:00
Alejandro Celaya
2e5a7d76df Migrated rest actions to psr-15 middleware 2017-03-25 10:04:48 +01:00
Alejandro Celaya
288249d0b8 Renamed JsonErrorHandler to JsonErrorResponseGenerator 2017-03-25 09:46:29 +01:00
Alejandro Celaya
cd47aae902 Migrated CrossDomainMiddleware to psr-15 middleware 2017-03-25 09:44:34 +01:00
Alejandro Celaya
9bd18ee041 Migrated CheckAuthenticationMiddleware to psr-15 middleware 2017-03-25 09:37:13 +01:00
Alejandro Celaya
22c76df8e6 Migrated BodyParserMiddleware to psr-15 middleware 2017-03-25 09:22:00 +01:00
Alejandro Celaya
6c87436a96 Migrated QrCodeCacheMiddleware to psr-15 middleware 2017-03-24 23:34:17 +01:00
Alejandro Celaya
734dac9456 Migrated RedirectAction to psr-15 middleware 2017-03-24 23:24:11 +01:00
Alejandro Celaya
85ca366893 Migrated QrCodeAction to psr-15 middleware 2017-03-24 23:19:42 +01:00
Alejandro Celaya
46db736af8 Migrated PreviewAction to psr-15 middleware 2017-03-24 22:07:28 +01:00
Alejandro Celaya
7530048fbd Removed exception catch that used to return a 500, and now returns a 404 due to a behavior change 2017-03-24 21:59:45 +01:00
Alejandro Celaya
c3c03a3a3b Migrated LocaleMiddleware to psr-15 middleware 2017-03-24 21:49:31 +01:00
Alejandro Celaya
d1018b6da7 Fixed tests 2017-03-24 21:38:43 +01:00
Alejandro Celaya
fe7928ae0e Fixed JsonErrorHandler and prevented AuthorizationMiddleware to eat exceptions 2017-03-24 21:31:55 +01:00
Alejandro Celaya
f6c39285c9 Updated to expressive 2 and used new error handling system 2017-03-24 21:10:25 +01:00
Alejandro Celaya
0e2a289f9f Updated to phpunit 6 2017-03-24 20:34:18 +01:00
Alejandro Celaya
f7424da16b Merge branch 'develop' 2017-01-22 11:37:35 +01:00
Alejandro Celaya
2e10ee66b7 Merge pull request #87 from acelaya/feature/1.3.1
Feature/1.3.1
2017-01-22 11:36:04 +01:00
Alejandro Celaya
7e442671c3 Updated build script 2017-01-22 11:27:56 +01:00
Alejandro Celaya
ca646ec2b7 Updated changelog including v1.3.1 2017-01-22 11:17:44 +01:00
Alejandro Celaya
4df1af5fd8 Fixed searching short URLs list not querying tag names 2017-01-22 11:14:25 +01:00
Alejandro Celaya
b4548f3401 Added configs to enable fastroute cache 2017-01-22 11:07:18 +01:00
Alejandro Celaya
1819481710 Updated license year 2017-01-22 10:59:35 +01:00
Alejandro Celaya
e59ae654c0 Increased number of followed redirects to 15 2017-01-22 10:53:41 +01:00
Alejandro Celaya
a8bf699f2d Fixed error with non-registered service on latest expressive-twig-renderer version 2017-01-21 20:19:30 +01:00
Alejandro Celaya
de9d9d8667 Updated PathVersionMiddleware so that it is only applied to rest routes 2017-01-21 20:12:12 +01:00
Alejandro Celaya
869865f22a Added option to customize database hostname and port 2017-01-21 13:45:28 +01:00
Alejandro Celaya
29fd313337 Added memcached to php docker image 2017-01-21 13:33:51 +01:00
Alejandro Celaya
7781f07352 Added local entity manager config that allows db host name to be set 2017-01-21 09:16:00 +01:00
Alejandro Celaya
072371d459 Created docker-related files 2017-01-19 22:56:45 +01:00
Alejandro Celaya
51bf948458 Fixed schema definition on order by argument 2016-10-29 12:42:36 +02:00
Alejandro Celaya
48acded6ed Merge branch 'develop' 2016-10-23 10:30:36 +02:00
Alejandro Celaya
6821f5cf97 Merge branch 'develop' of https://github.com/shlinkio/shlink into develop 2016-10-23 10:30:11 +02:00
Alejandro Celaya
a15b17e08b Fixed regression bug while processing versionning for rest paths 2016-10-23 10:29:54 +02:00
Alejandro Celaya
275b17e1e8 Merge pull request #74 from acelaya/develop
Develop
2016-10-23 00:18:22 +02:00
Alejandro Celaya
27b08ff47b Merge branch 'develop' 2016-10-23 00:17:00 +02:00
Alejandro Celaya
bf7c760ca9 Updated changelog with last versions 2016-10-23 00:13:00 +02:00
Alejandro Celaya
8af9b0ee02 Tagged and summarized all endpoints in swagger docs 2016-10-23 00:07:31 +02:00
Alejandro Celaya
b225c03ef1 Improved swagger definition 2016-10-23 00:02:13 +02:00
Alejandro Celaya
8a12ed6b8c Separated swagger specification into multiple files 2016-10-22 23:44:14 +02:00
Alejandro Celaya
c3fd433446 Merge branch 'feature/67' into develop 2016-10-22 23:15:57 +02:00
Alejandro Celaya
0b9753582d Documented how to order results 2016-10-22 23:13:54 +02:00
Alejandro Celaya
9ac48bfbc5 Added support for ordering in shortcode:list command 2016-10-22 23:10:30 +02:00
Alejandro Celaya
85146e5676 Added support to order short URL lists 2016-10-22 23:02:12 +02:00
Alejandro Celaya
18ae541c93 Improved body parsing on BodyParserMiddleware 2016-10-22 22:17:04 +02:00
Alejandro Celaya
7a665ec26f Merge branch 'feature/72' into develop 2016-10-22 22:11:45 +02:00
Alejandro Celaya
e3cbac38ce Improved output on api-key:list command 2016-10-22 22:11:36 +02:00
Alejandro Celaya
31594d47b3 Created PathVersionMiddlewareTest 2016-10-22 18:52:40 +02:00
Alejandro Celaya
42f86a4a24 Added versioning to API endpoints, allowing not to pass the version which will default to v1 2016-10-22 18:46:53 +02:00
Alejandro Celaya
850ce152cd Merge branch 'feature/58' into develop 2016-10-22 13:16:13 +02:00
Alejandro Celaya
c22bbecdc5 Updated languages 2016-10-22 13:15:35 +02:00
Alejandro Celaya
230f2d155b Documented tags param in GET /short-codes endpoint 2016-10-22 13:13:50 +02:00
Alejandro Celaya
47a2c18c7e Added the ability to filter by tag in shotcodes:list command 2016-10-22 13:11:24 +02:00
Alejandro Celaya
52bb14bd66 Implemented filtering by tags in ListShortcodesAction 2016-10-22 13:04:17 +02:00
Alejandro Celaya
8b9caf02d2 Added tags param to paginable repository adapter 2016-10-22 12:57:24 +02:00
Alejandro Celaya
4580d11d32 Noticed in swagger docs that the searchTerm param is only available from v 1.3.0 of shlink 2016-10-22 12:50:35 +02:00
Alejandro Celaya
8610a158d4 Added searchTerm param to shortcode:list command 2016-10-22 12:48:24 +02:00
Alejandro Celaya
0a6030b35d Documented searchTerm query param for GET /short-codes endpoint 2016-10-22 12:43:22 +02:00
Alejandro Celaya
543c0e62d0 Added search term filtering to short codes list 2016-10-22 12:40:51 +02:00
Alejandro Celaya
4c76e17178 Changed swagger file format from yaml to json 2016-10-22 12:11:31 +02:00
470 changed files with 19184 additions and 7289 deletions

27
.gitattributes vendored Normal file
View File

@@ -0,0 +1,27 @@
/config/test export-ignore
/data/infra export-ignore
/docs export-ignore
/module/CLI/test export-ignore
/module/CLI/test-resources export-ignore
/module/Common/test export-ignore
/module/Common/test-db export-ignore
/module/Core/test export-ignore
/module/Core/test-db export-ignore
/module/Rest/test export-ignore
/module/Rest/test-api export-ignore
.env.dist export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.phpstorm.meta.php export-ignore
.scrutinizer.yml export-ignore
.travis.yml export-ignore
build.sh export-ignore
CHANGELOG.md export-ignore
docker-compose.override.yml.dist export-ignore
docker-compose.yml export-ignore
indocker export-ignore
phpcs.xml export-ignore
phpunit.xml.dist export-ignore
phpunit-api.xml export-ignore
phpunit-db.xml export-ignore
phpstan.neon

6
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,6 @@
<!--
Before opening an issue, just take into account that this is a completely free of charge open source project.
I'm always happy to help and provide support, but some understanding will be required.
I do this in my own free time, so expect some delays when implementing new features and fixing bugs, and don't take it personal if an issue gets eventually closed.
Try to be polite, and understand it is impossible for a project to cover all use cases.
-->

6
.gitignore vendored
View File

@@ -1,6 +1,12 @@
.idea
build
composer.lock
composer.phar
vendor/
.env
data/database.sqlite
data/shlink-tests.db
data/GeoLite2-City.mmdb
docs/swagger-ui*
docker-compose.override.yml
.phpunit.result.cache

View File

@@ -1,7 +1,8 @@
<?php
namespace PHPSTORM_META;
use Interop\Container\ContainerInterface;
use Psr\Container\ContainerInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
/**
* PhpStorm Container Interop code completion
@@ -16,4 +17,7 @@ $STATIC_METHOD_TYPES = [
ContainerInterface::get('') => [
'' == '@',
],
ServiceLocatorInterface::build('') => [
'' == '@',
],
];

View File

@@ -1,6 +1,13 @@
tools:
external_code_coverage: true
external_code_coverage:
timeout: 600
checks:
php:
code_rating: true
duplication: true
php:
code_rating: true
duplication: true
build:
nodes:
analysis:
tests:
override:
- php-scrutinizer-run

View File

@@ -1 +0,0 @@
extension="memcached.so"

View File

@@ -2,26 +2,56 @@ language: php
branches:
only:
- master
- develop
- /.*/
php:
- 5.6
- 7
- 7.1
- 7.2
- 7.3
before_install: phpenv config-add .travis-php.ini
services:
- mysql
- postgresql
before_script:
before_install:
- echo 'extension = apcu.so' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- yes | pecl install swoole
- phpenv config-rm xdebug.ini || return 0
install:
- composer self-update
- composer install --no-interaction
script:
before_script:
- mysql -e 'CREATE DATABASE shlink_test;'
- psql -c 'create database shlink_test;' -U postgres
- mkdir build
- composer check
after_script:
script:
- composer ci
after_success:
- rm -f build/clover.xml
- phpdbg -qrr vendor/bin/phpcov merge build --clover build/clover.xml
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover build/clover.xml
sudo: false
# Before deploying, build dist file for current travis tag
before_deploy:
- rm -f ocular.phar
- ./build.sh ${TRAVIS_TAG#?}
deploy:
- provider: releases
api_key:
secure: a9dbZchocqeuOViwUeNH54bQR5Sz7rEYXx5b9WPFtnFn9LGKKUaLbA2U91UQ9QKPrcTpsALubUYbw2CnNmvCwzaY+R8lCD3gkU4ohsEnbpnw3deOeixI74sqBHJAuCH9FSaRDGILoBMtUKx2xlzIymFxkIsgIukkGbdkWHDlRWY3oTUUuw1SQ2Xk9KDsbJQtjIc1+G/O6gHaV4qv/R9W8NPmJExKTNDrAZbC1vIUnxqp4UpVo1hst8qPd1at94CndDYM5rG+7imGbdtxTxzamt819qdTO1OfvtctKawNAm7YXZrrWft6c7gI6j6SI4hxd+ZrrPBqbaRFHkZHjnNssO/yn4SaOHFFzccmu0MzvpPCf0qWZwd3sGHVYer1MnR2mHYqU84QPlW3nrHwJjkrpq3+q0JcBY6GsJs+RskHNtkMTKV05Iz6QUI5YZGwTpuXaRm036SmavjGc4IDlMaYCk/NmbB9BKpthJxLdUpczOHpnjXXHziotWD6cfEnbjU3byfD8HY5WrxSjsNT7SKmXN3hRof7bk985ewQVjGT42O3NbnfnqjQQWr/B7/zFTpLR4f526Bkq12CdCyf5lvrbq+POkLVdJ+uFfR7ds248Ue/jBQy6kM1tWmKF9QiwisFlA84eQ4CW3I93Rp97URv+AQa9zmbD0Ve3Udp+g6nF5I=
file: "./build/shlink_${TRAVIS_TAG#?}_dist.zip"
skip_cleanup: true
on:
tags: true
php: 7.2
- provider: script
script: bash data/travis/trigger_docker_build.sh
skip_cleanup: true
on:
tags: true
php: 7.2

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2016 Alejandro Celaya
Copyright (c) 2016-2019 Alejandro Celaya
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

291
README.md
View File

@@ -1,9 +1,288 @@
# Shlink
[![Build Status](https://travis-ci.org/shlinkio/shlink.svg?branch=master)](https://travis-ci.org/shlinkio/shlink)
[![Code Coverage](https://scrutinizer-ci.com/g/shlinkio/shlink/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/shlinkio/shlink/?branch=master)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/shlinkio/shlink/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/shlinkio/shlink/?branch=master)
[![Latest Stable Version](https://poser.pugx.org/shlinkio/shlink/v/stable.png)](https://packagist.org/packages/shlinkio/shlink)
[![License](https://poser.pugx.org/shlinkio/shlink/license.png)](https://packagist.org/packages/shlinkio/shlink)
[![Build Status](https://img.shields.io/travis/shlinkio/shlink.svg?style=flat-square)](https://travis-ci.org/shlinkio/shlink)
[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/shlinkio/shlink.svg?style=flat-square)](https://scrutinizer-ci.com/g/shlinkio/shlink/?branch=master)
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/shlinkio/shlink.svg?style=flat-square)](https://scrutinizer-ci.com/g/shlinkio/shlink/?branch=master)
[![Latest Stable Version](https://img.shields.io/github/release/shlinkio/shlink.svg?style=flat-square)](https://packagist.org/packages/shlinkio/shlink)
[![License](https://img.shields.io/github/license/shlinkio/shlink.svg?style=flat-square)](https://github.com/shlinkio/shlink/blob/master/LICENSE)
[![Paypal donate](https://img.shields.io/badge/Donate-paypal-blue.svg?style=flat-square&logo=paypal&colorA=aaaaaa)](https://acel.me/donate)
A PHP-based URL shortener application with analytics and management
A PHP-based self-hosted URL shortener that can be used to serve shortened URLs under your own custom domain.
## Table of Contents
- [Installation](#installation)
- [Update to new version](#update-to-new-version)
- [Using a docker image](#using-a-docker-image)
- [Using shlink](#using-shlink)
- [Shlink CLI Help](#shlink-cli-help)
## Installation
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.
* 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.
* **Using a dist file**
The easiest way to install shlink is by using one of the pre-bundled distributable packages.
Just go to the [latest version](https://github.com/shlinkio/shlink/releases/latest) and download the `shlink_X.X.X_dist.zip` file you will find there.
Finally, decompress the file in the location of your choice.
* **Building from sources**
If for any reason you want to build the project yourself, follow these steps:
* Clone the project with git (`git clone https://github.com/shlinkio/shlink.git`), or download it by clicking the **Clone or download** green button.
* Download the [Composer](https://getcomposer.org/download/) PHP package manager inside the project folder.
* Run `./build.sh 1.0.0`, replacing the version with the version number you are going to build (the version number is only used for the generated dist file).
After that, you will have a `shlink_x.x.x_dist.zip` dist file inside the `build` directory.
This is the process used when releasing new shlink versions. After tagging the new version with git, the Github release is automatically created by [travis](https://travis-ci.org/shlinkio/shlink), attaching generated dist file to it.
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.
* 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.
* **Using a web server:**
For example, assuming your domain is doma.in and shlink is in the `/path/to/shlink` folder, these would be the basic configurations for Nginx and Apache.
*Nginx:*
```nginx
server {
server_name doma.in;
listen 80;
root /path/to/shlink/public;
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
location ~ /\.ht {
deny all;
}
}
```
*Apache:*
```apache
<VirtualHost *:80>
ServerName doma.in
DocumentRoot "/path/to/shlink/public"
<Directory "/path/to/shlink/public">
Options FollowSymLinks Includes ExecCGI
AllowOverride all
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
```
* **Using swoole:**
**Important!** Swoole support is still experimental. Use it with care, and report any found issue.
First you need to install the swoole PHP extension with [pecl](https://pecl.php.net/package/swoole), `pecl install swoole`.
Once installed, it's actually pretty easy to get shlink up and running with swoole. Just run `./vendor/bin/zend-expressive-swoole start -d` and you will get shlink running on port 8080.
However, by doing it this way, you are loosing all the access logs, and the service won't be automatically run if the server has to be restarted.
For that reason, you should create a daemon script, in `/etc/init.d/shlink_swoole`, like this one, replacing `/path/to/shlink` by the path to your shlink installation:
```bash
#!/bin/bash
### BEGIN INIT INFO
# Provides: shlink_swoole
# Required-Start: $local_fs $network $named $time $syslog
# Required-Stop: $local_fs $network $named $time $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: Shlink non-blocking server with swoole
### END INIT INFO
SCRIPT=/path/to/shlink/vendor/bin/zend-expressive-swoole\ start
RUNAS=root
PIDFILE=/var/run/shlink_swoole.pid
LOGDIR=/var/log/shlink
LOGFILE=${LOGDIR}/shlink_swoole.log
start() {
if [[ -f "$PIDFILE" ]] && kill -0 $(cat "$PIDFILE"); then
echo 'Shlink with swoole already running' >&2
return 1
fi
echo 'Starting shlink with swoole' >&2
mkdir -p "$LOGDIR"
touch "$LOGFILE"
local CMD="$SCRIPT &> \"$LOGFILE\" & echo \$!"
su -c "$CMD" $RUNAS > "$PIDFILE"
echo 'Shlink started' >&2
}
stop() {
if [[ ! -f "$PIDFILE" ]] || ! kill -0 $(cat "$PIDFILE"); then
echo 'Shlink with swoole not running' >&2
return 1
fi
echo 'Stopping shlink with swoole' >&2
kill -15 $(cat "$PIDFILE") && rm -f "$PIDFILE"
echo 'Shlink stopped' >&2
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo "Usage: $0 {start|stop|restart}"
esac
```
Then run these commands to enable the service and start it:
* `sudo chmod +x /etc/init.d/shlink_swoole`
* `sudo update-rc.d shlink_swoole defaults`
* `sudo update-rc.d shlink_swoole enable`
* `/etc/init.d/shlink_swoole start`
Now again, you can access shlink on port 8080, but this time the service will be automatically run at system start-up, and all access logs will be written in `/var/log/shlink/shlink_swoole.log` (you will probably want to [rotate those logs](https://www.digitalocean.com/community/tutorials/how-to-manage-logfiles-with-logrotate-on-ubuntu-16-04). You can find an example logrotate config file [here](data/infra/examples/shlink-daemon-logrotate.conf)).
* Generate your first API key by running `bin/cli api-key:generate`. You will need the key in order to interact with shlink's API.
* Finally access to [https://app.shlink.io](https://app.shlink.io) and configure your server to start creating short URLs.
**Bonus**
There are a couple of time-consuming tasks that shlink expects you to do manually, or at least it is recommended, since it will improve runtime performance.
Those tasks can be performed using shlink's CLI, so it should be easy to schedule them to be run in the background (for example, using cron jobs):
* Resolve IP address locations: `/path/to/shlink/bin/cli visit:locate`
If you don't run this command regularly, the stats will say all visits come from *unknown* locations.
* Generate website previews: `/path/to/shlink/bin/cli short-url:process-previews`
Running this will improve the performance of the `doma.in/abc123/preview` URLs, which return a preview of the site.
* **For shlink older than v1.17.0**: Update IP geolocation database: `/path/to/shlink/bin/cli visit:update-db`
When shlink is installed it downloads a fresh [GeoLite2](https://dev.maxmind.com/geoip/geoip2/geolite2/) db file. Running this command will update this file.
The file is updated the first Tuesday of every month, so it should be enough running this command the first Wednesday.
*Any of these commands accept the `-q` flag, which makes it not display any output. This is recommended when configuring the commands as cron jobs.*
In future versions, it is planed that, when using **swoole** to serve shlink, some of these tasks are automatically run without blocking the request and also, without having to configure cron jobs. Probably resolving IP locations and generating previews.
## Update to new version
When a new Shlink version is available, you don't need to repeat the entire process yourself. Instead, follow these steps:
1. Rename your existing Shlink directory to something else (ie. `shlink` ---> `shlink-old`).
2. Download and extract the new version of Shlink, and set the directories name to that of the old version. (ie. `shlink`).
3. Run the `bin/update` script in the new version's directory to migrate your configuration over.
4. If you are using shlink with swoole, restart the service by running `/etc/init.d/shlink_swoole restart`.
The `bin/update` script will ask you for the location from previous shlink version, and use it in order to import the configuration. It will then update the database and generate some assets shlink needs to work.
Right now, it does not import cached info (like website previews), but it will. For now you will need to regenerate them again.
**Important!** It is recommended that you don't skip any version when using this process. The update gets better on every version, but older versions might make assumptions.
## Using a docker image
Starting with version 1.15.0, an official docker image is provided. You can find the docs on how to use it [here](https://hub.docker.com/r/shlinkio/shlink/).
The idea is that you can just generate a container using the image and provide custom config via env vars.
## Using shlink
Once shlink is installed, there are two main ways to interact with it:
* **The command line**. Try running `bin/cli` and see all the [available commands](#shlink-cli-help).
All of those commands can be run with the `--help`/`-h` flag in order to see how to use them and all the available options.
It is probably a good idea to symlink the CLI entry point (`bin/cli`) to somewhere in your path, so that you can run shlink from any directory.
* **The REST API**. The complete docs on how to use the API can be found [here](https://shlink.io/api-docs), and a sandbox which also documents every endpoint can be found [here](https://shlink.io/swagger-ui/index.html).
However, you probably don't want to consume the raw API yourself. That's why a nice [web client](https://github.com/shlinkio/shlink-web-client) is provided that can be directly used from [https://app.shlink.io](https://app.shlink.io), or you can host it yourself too.
Both the API and CLI allow you to do the same operations, except for API key management, which can be done from the command line interface only.
### Shlink CLI Help
```
Usage:
command [options] [arguments]
Options:
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
-n, --no-interaction Do not ask any interactive question
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
Available commands:
help Displays help for a command
list Lists commands
api-key
api-key:disable Disables an API key.
api-key:generate Generates a new valid API key.
api-key:list Lists all the available API keys.
config
config:generate-charset [DEPRECATED] Generates a character set sample just by shuffling the default one, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ". Then it can be set in the SHORTCODE_CHARS environment variable
config:generate-secret [DEPRECATED] Generates a random secret string that can be used for JWT token encryption
short-url
short-url:delete [short-code:delete] Deletes a short URL
short-url:generate [shortcode:generate|short-code:generate] Generates a short URL for provided long URL and returns it
short-url:list [shortcode:list|short-code:list] List all short URLs
short-url:parse [shortcode:parse|short-code:parse] Returns the long URL behind a short code
short-url:process-previews [shortcode:process-previews|short-code:process-previews] Processes and generates the previews for every URL, improving performance for later web requests.
short-url:visits [shortcode:visits|short-code:visits] Returns the detailed visits information for provided short code
tag
tag:create Creates one or more tags.
tag:delete Deletes one or more tags.
tag:list Lists existing tags.
tag:rename Renames one existing tag.
visit
visit:locate [visit:process] Resolves visits origin locations.
visit:update-db [DEPRECATED] Updates the GeoLite2 database file used to geolocate IP addresses
```
> This product includes GeoLite2 data created by MaxMind, available from [https://www.maxmind.com](https://www.maxmind.com)

View File

@@ -1,11 +1,10 @@
#!/usr/bin/env php
<?php
declare(strict_types=1);
use Interop\Container\ContainerInterface;
use Symfony\Component\Console\Application as CliApp;
/** @var ContainerInterface $container */
$container = include __DIR__ . '/../config/container.php';
/** @var CliApp $app */
$app = $container->get(CliApp::class);
$app->run();
$container->get(CliApp::class)->run();

View File

@@ -1,14 +1,12 @@
#!/usr/bin/env php
<?php
use Shlinkio\Shlink\CLI\Command\Install\InstallCommand;
use Symfony\Component\Console\Application;
use Zend\Config\Writer\PhpArray;
declare(strict_types=1);
namespace Shlinkio\Shlink;
use function chdir;
use function dirname;
chdir(dirname(__DIR__));
require __DIR__ . '/../vendor/autoload.php';
$app = new Application();
$app->add(new InstallCommand(new PhpArray()));
$app->setDefaultCommand('shlink:install');
$app->run();
$run = require __DIR__ . '/../vendor/shlinkio/shlink-installer/bin/run.php';
$run(false);

14
bin/test/run-api-tests.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env sh
set -e
export APP_ENV=test
# Try to stop server just in case it hanged in last execution
vendor/bin/zend-expressive-swoole stop
echo 'Starting server...'
vendor/bin/zend-expressive-swoole start -d
sleep 2
vendor/bin/phpunit --order-by=random -c phpunit-api.xml --testdox
vendor/bin/zend-expressive-swoole stop

View File

@@ -1,14 +1,12 @@
#!/usr/bin/env php
<?php
use Shlinkio\Shlink\CLI\Command\Install\UpdateCommand;
use Symfony\Component\Console\Application;
use Zend\Config\Writer\PhpArray;
declare(strict_types=1);
namespace Shlinkio\Shlink;
use function chdir;
use function dirname;
chdir(dirname(__DIR__));
require __DIR__ . '/../vendor/autoload.php';
$app = new Application();
$app->add(new UpdateCommand(new PhpArray()));
$app->setDefaultCommand('shlink:install');
$app->run();
$run = require __DIR__ . '/../vendor/shlinkio/shlink-installer/bin/run.php';
$run(true);

View File

@@ -1,44 +1,63 @@
#!/usr/bin/env bash
set -e
if [ "$#" -ne 1 ]; then
if [[ "$#" -ne 1 ]]; then
echo "Usage:" >&2
echo " $0 {version}" >&2
exit 1
fi
version=$1
builtcontent=$(readlink -f '../shlink_build_tmp')
builtcontent="./build/shlink_${version}_dist"
projectdir=$(pwd)
[[ -f ./composer.phar ]] && composerBin='./composer.phar' || composerBin='composer'
# Copy project content to temp dir
echo 'Copying project files...'
rm -rf "${builtcontent}"
mkdir "${builtcontent}"
cp -R "${projectdir}"/* "${builtcontent}"
mkdir -p "${builtcontent}"
rsync -av * "${builtcontent}" \
--exclude=bin/test \
--exclude=data/infra \
--exclude=data/travis \
--exclude=data/migrations_template.txt \
--exclude=data/GeoLite2-City.mmdb \
--exclude=**/.gitignore \
--exclude=CHANGELOG.md \
--exclude=composer.lock \
--exclude=vendor \
--exclude=docs \
--exclude=indocker \
--exclude=docker* \
--exclude=php* \
--exclude=infection.json \
--exclude=phpstan.neon \
--exclude=config/autoload/*local* \
--exclude=config/test \
--exclude=**/test* \
--exclude=build* \
--exclude=.github
cd "${builtcontent}"
# Install dependencies
rm -r vendor
rm composer.lock
composer self-update
composer install --no-dev --optimize-autoloader
echo "Installing dependencies with $composerBin..."
${composerBin} self-update
${composerBin} install --no-dev --optimize-autoloader --apcu-autoloader --no-progress --no-interaction
# Delete development files
echo 'Deleting dev files...'
rm build.sh
rm CHANGELOG.md
rm composer.*
rm LICENSE
rm php*
rm README.md
rm -r build
rm -f data/database.sqlite
rm -rf data/{cache,log,proxies}/{*,.gitignore}
rm -rf config/params/{*,.gitignore}
rm -rf config/autoload/{{,*.}local.php{,.dist},.gitignore}
# Update shlink version in config
sed -i "s/%SHLINK_VERSION%/${version}/g" config/autoload/app_options.global.php
# Compressing file
rm -f "${projectdir}"/build/shlink_${version}_dist.zip
zip -ry "${projectdir}"/build/shlink_${version}_dist.zip .
echo 'Compressing files...'
cd "${projectdir}"/build
rm -f ./shlink_${version}_dist.zip
zip -ry ./shlink_${version}_dist.zip ./shlink_${version}_dist
cd "${projectdir}"
rm -rf "${builtcontent}"
echo 'Done!'

View File

@@ -1,48 +1,68 @@
{
"name": "shlinkio/shlink",
"type": "project",
"homepage": "http://shlink.io",
"homepage": "https://shlink.io",
"description": "A self-hosted and PHP-based URL shortener application with CLI and REST interfaces",
"license": "MIT",
"authors": [
{
"name": "Alejandro Celaya Alastrué",
"homepage": "http://www.alejandrocelaya.com",
"homepage": "https://www.alejandrocelaya.com",
"email": "alejandro@alejandrocelaya.com"
}
],
"require": {
"php": "^5.6 || ^7.0",
"zendframework/zend-expressive": "^1.0",
"zendframework/zend-expressive-fastroute": "^1.1",
"zendframework/zend-expressive-twigrenderer": "^1.0",
"zendframework/zend-stdlib": "^2.7",
"zendframework/zend-servicemanager": "^3.0",
"zendframework/zend-paginator": "^2.6",
"zendframework/zend-config": "^2.6",
"zendframework/zend-i18n": "^2.7",
"mtymek/expressive-config-manager": "^0.4",
"acelaya/zsm-annotated-services": "^0.2.0",
"acelaya/ze-content-based-error-handler": "^1.0",
"php": "^7.2",
"ext-json": "*",
"ext-pdo": "*",
"acelaya/ze-content-based-error-handler": "^2.2",
"akrabat/ip-address-middleware": "^1.0",
"cakephp/chronos": "^1.2",
"cocur/slugify": "^3.0",
"doctrine/cache": "^1.6",
"doctrine/migrations": "^2.0",
"doctrine/orm": "^2.5",
"guzzlehttp/guzzle": "^6.2",
"symfony/console": "^3.0",
"symfony/process": "^3.0",
"symfony/filesystem": "^3.0",
"endroid/qr-code": "^1.7",
"firebase/php-jwt": "^4.0",
"monolog/monolog": "^1.21",
"theorchard/monolog-cascade": "^0.4",
"endroid/qrcode": "^1.7",
"geoip2/geoip2": "^2.9",
"guzzlehttp/guzzle": "^6.2",
"lstrojny/functional-php": "^1.8",
"mikehaertl/phpwkhtmltopdf": "^2.2",
"doctrine/migrations": "^1.4"
"monolog/monolog": "^1.21",
"shlinkio/shlink-installer": "^1.1",
"symfony/console": "^4.2",
"symfony/filesystem": "^4.2",
"symfony/lock": "^4.2",
"symfony/process": "^4.2",
"theorchard/monolog-cascade": "^0.4",
"zendframework/zend-config": "^3.0",
"zendframework/zend-config-aggregator": "^1.0",
"zendframework/zend-diactoros": "^2.1.1",
"zendframework/zend-expressive": "^3.0",
"zendframework/zend-expressive-fastroute": "^3.0",
"zendframework/zend-expressive-helpers": "^5.0",
"zendframework/zend-expressive-platesrenderer": "^2.0",
"zendframework/zend-expressive-swoole": "^2.4",
"zendframework/zend-i18n": "^2.7",
"zendframework/zend-inputfilter": "^2.8",
"zendframework/zend-paginator": "^2.6",
"zendframework/zend-servicemanager": "^3.2",
"zendframework/zend-stdlib": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "^5.0",
"squizlabs/php_codesniffer": "^2.3",
"roave/security-advisories": "dev-master",
"devster/ubench": "^2.0",
"doctrine/data-fixtures": "^1.3",
"filp/whoops": "^2.0",
"symfony/var-dumper": "^3.0",
"vlucas/phpdotenv": "^2.2"
"infection/infection": "^0.12.2",
"phpstan/phpstan": "^0.11.2",
"phpunit/phpcov": "^6.0",
"phpunit/phpunit": "^8.0",
"roave/security-advisories": "dev-master",
"shlinkio/php-coding-standard": "~1.1.0",
"symfony/dotenv": "^4.2",
"symfony/var-dumper": "^4.2",
"zendframework/zend-component-installer": "^2.1",
"zendframework/zend-expressive-tooling": "^1.0"
},
"autoload": {
"psr-4": {
@@ -59,22 +79,84 @@
"psr-4": {
"ShlinkioTest\\Shlink\\CLI\\": "module/CLI/test",
"ShlinkioTest\\Shlink\\Rest\\": "module/Rest/test",
"ShlinkioTest\\Shlink\\Core\\": "module/Core/test",
"ShlinkioTest\\Shlink\\Common\\": "module/Common/test"
"ShlinkioApiTest\\Shlink\\Rest\\": "module/Rest/test-api",
"ShlinkioTest\\Shlink\\Core\\": [
"module/Core/test",
"module/Core/test-db"
],
"ShlinkioTest\\Shlink\\Common\\": [
"module/Common/test",
"module/Common/test-db"
]
}
},
"scripts": {
"check": [
"ci": [
"@cs",
"@test"
"@stan",
"@test:ci",
"@infect:ci"
],
"cs": "phpcs",
"cs-fix": "phpcbf",
"serve": "php -S 0.0.0.0:8000 -t public/",
"test": "phpunit --coverage-clover build/clover.xml",
"pretty-test": "phpunit --coverage-html build/coverage"
"cs:fix": "phpcbf",
"stan": "phpstan analyse module/*/src/ --level=5 -c phpstan.neon",
"test": [
"@test:unit",
"@test:db",
"@test:api"
],
"test:ci": [
"@test:unit:ci",
"@test:db",
"@test:db:mysql",
"@test:db:postgres",
"@test:api"
],
"test:unit": "phpdbg -qrr vendor/bin/phpunit --order-by=random --coverage-php build/coverage-unit.cov --testdox",
"test:unit:ci": "phpdbg -qrr vendor/bin/phpunit --order-by=random --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": "APP_ENV=test phpdbg -qrr vendor/bin/phpunit --order-by=random -c phpunit-db.xml --coverage-php build/coverage-db.cov --testdox",
"test:db:mysql": "DB_DRIVER=mysql composer test:db",
"test:db:postgres": "DB_DRIVER=postgres composer test:db",
"test:api": "bin/test/run-api-tests.sh",
"test:pretty": [
"@test",
"phpdbg -qrr vendor/bin/phpcov merge build --html build/html"
],
"test:unit:pretty": "phpdbg -qrr vendor/bin/phpunit --coverage-html build/coverage --order-by=random",
"infect": "infection --threads=4 --min-msi=70 --log-verbosity=default --only-covered",
"infect:ci": "infection --threads=4 --min-msi=70 --log-verbosity=default --only-covered --coverage=build",
"infect:show": "infection --threads=4 --min-msi=70 --log-verbosity=default --only-covered --show-mutations",
"infect:test": [
"@test:unit:ci",
"@infect:ci"
]
},
"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</>",
"stan": "<fg=blue;options=bold>Inspects code with phpstan</>",
"test": "<fg=blue;options=bold>Runs all test suites</>",
"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 database</>",
"test:db:mysql": "<fg=blue;options=bold>Runs database test suites on a MySQL 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</>",
"test:unit:pretty": "<fg=blue;options=bold>Runs unit test suites and generates an HTML code coverage report</>",
"infect": "<fg=blue;options=bold>Checks unit tests quality applying mutation testing</>",
"infect:ci": "<fg=blue;options=bold>Checks unit tests quality applying mutation testing with existing reports and logs</>",
"infect:show": "<fg=blue;options=bold>Checks unit tests quality applying mutation testing and shows applied mutators</>",
"infect:test": "<fg=blue;options=bold>Checks unit tests quality applying mutation testing</>"
},
"config": {
"process-timeout": 0
"sort-packages": true
}
}

View File

@@ -1,10 +1,15 @@
<?php
declare(strict_types=1);
use function Shlinkio\Shlink\Common\env;
return [
'app_options' => [
'name' => 'Shlink',
'version' => '1.2.0',
'secret_key' => env('SECRET_KEY'),
'version' => '%SHLINK_VERSION%',
'secret_key' => env('SECRET_KEY', ''),
'disable_track_param' => null,
],
];

View File

@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
use Zend\ConfigAggregator\ConfigAggregator;
return [
'debug' => false,
ConfigAggregator::ENABLE_CACHE => true,
];

View File

@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
use Zend\ConfigAggregator\ConfigAggregator;
return [
'debug' => true,
ConfigAggregator::ENABLE_CACHE => false,
];

View File

@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink;
return [
'delete_short_urls' => [
'visits_threshold' => 15,
'check_visits_threshold' => true,
],
];

View File

@@ -1,21 +1,28 @@
<?php
declare(strict_types=1);
use Shlinkio\Shlink\Common\Factory\EmptyResponseImplicitOptionsMiddlewareFactory;
use Zend\Expressive;
use Zend\Expressive\Container;
use Zend\Expressive\Router;
use Zend\Expressive\Template;
use Zend\Expressive\Twig;
use Zend\ServiceManager\Factory\InvokableFactory;
use Zend\Expressive\Router\Middleware\ImplicitOptionsMiddleware;
return [
'dependencies' => [
'factories' => [
Expressive\Application::class => Container\ApplicationFactory::class,
Router\FastRouteRouter::class => InvokableFactory::class,
Template\TemplateRendererInterface::class => Twig\TwigRendererFactory::class,
ImplicitOptionsMiddleware::class => EmptyResponseImplicitOptionsMiddlewareFactory::class,
],
'aliases' => [
Router\RouterInterface::class => Router\FastRouteRouter::class,
'delegators' => [
Expressive\Application::class => [
Container\ApplicationConfigInjectionDelegator::class,
],
],
'lazy_services' => [
'proxies_target_dir' => 'data/proxies',
'proxies_namespace' => 'ShlinkProxy',
'write_proxy_files' => true,
],
],

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
use Psr\Container\ContainerInterface;
use Psr\Log;
return [
'dependencies' => [
'lazy_services' => [
'write_proxy_files' => false,
],
'initializers' => [
function (ContainerInterface $container, $instance) {
if ($instance instanceof Log\LoggerAwareInterface) {
$instance->setLogger($container->get(Log\LoggerInterface::class));
}
},
],
],
];

View File

@@ -1,4 +1,8 @@
<?php
declare(strict_types=1);
use function Shlinkio\Shlink\Common\env;
return [
'entity_manager' => [
@@ -6,14 +10,10 @@ return [
'proxies_dir' => 'data/proxies',
],
'connection' => [
'driver' => 'pdo_mysql',
'user' => env('DB_USER'),
'password' => env('DB_PASSWORD'),
'dbname' => env('DB_NAME', 'shlink'),
'charset' => 'utf8',
'driverOptions' => [
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
],
],
],

View File

@@ -0,0 +1,14 @@
<?php
return [
'entity_manager' => [
'connection' => [
'driver' => 'pdo_mysql',
'host' => 'shlink_db',
'driverOptions' => [
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
],
],
],
];

View File

@@ -1,6 +1,7 @@
<?php
use Acelaya\ExpressiveErrorHandler\ErrorHandler\ContentBasedErrorHandler;
use Zend\Expressive\Container\WhoopsErrorHandlerFactory;
declare(strict_types=1);
use Zend\Expressive\Container\WhoopsErrorResponseGeneratorFactory;
return [
'dependencies' => [
@@ -21,7 +22,7 @@ return [
'error_handler' => [
'plugins' => [
'factories' => [
ContentBasedErrorHandler::DEFAULT_CONTENT => WhoopsErrorHandlerFactory::class,
'text/html' => WhoopsErrorResponseGeneratorFactory::class,
],
],
],

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
return [
'geolite2' => [
'db_location' => __DIR__ . '/../../data/GeoLite2-City.mmdb',
'temp_dir' => sys_get_temp_dir(),
'download_from' => 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz',
],
];

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
use Shlinkio\Shlink\Installer\Config\Plugin;
return [
'installer_plugins_expected_config' => [
Plugin\LanguageConfigCustomizer::class => [
Plugin\LanguageConfigCustomizer::DEFAULT_LANG,
],
Plugin\UrlShortenerConfigCustomizer::class => [
Plugin\UrlShortenerConfigCustomizer::SCHEMA,
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 => [
Plugin\ApplicationConfigCustomizer::SECRET,
Plugin\ApplicationConfigCustomizer::DISABLE_TRACK_PARAM,
Plugin\ApplicationConfigCustomizer::CHECK_VISITS_THRESHOLD,
Plugin\ApplicationConfigCustomizer::VISITS_THRESHOLD,
],
Plugin\DatabaseConfigCustomizer::class => [
Plugin\DatabaseConfigCustomizer::DRIVER,
Plugin\DatabaseConfigCustomizer::NAME,
Plugin\DatabaseConfigCustomizer::USER,
Plugin\DatabaseConfigCustomizer::PASSWORD,
Plugin\DatabaseConfigCustomizer::HOST,
Plugin\DatabaseConfigCustomizer::PORT,
],
],
];

View File

@@ -1,8 +0,0 @@
<?php
return [
'debug' => true,
'config_cache_enabled' => false,
];

View File

@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
use Symfony\Component\Lock;
use Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory;
return [
'locks' => [
'locks_dir' => __DIR__ . '/../../data/locks',
],
'dependencies' => [
'factories' => [
Lock\Store\FlockStore::class => ConfigAbstractFactory::class,
Lock\Factory::class => ConfigAbstractFactory::class,
],
],
ConfigAbstractFactory::class => [
Lock\Store\FlockStore::class => ['config.locks.locks_dir'],
Lock\Factory::class => [Lock\Store\FlockStore::class],
],
];

View File

@@ -1,30 +1,72 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Monolog\Processor;
use const PHP_EOL;
return [
'logger' => [
'formatters' => [
'dashed' => [
'format' => '[%datetime%] %channel%.%level_name% - %message% %context%' . PHP_EOL,
'format' => '[%datetime%] %channel%.%level_name% - %message%' . PHP_EOL,
'include_stacktraces' => true,
],
],
'handlers' => [
'rotating_file_handler' => [
'shlink_rotating_handler' => [
'class' => RotatingFileHandler::class,
'level' => Logger::INFO,
'filename' => 'data/log/shlink_log.log',
'max_files' => 30,
'formatter' => 'dashed',
],
'access_handler' => [
'class' => StreamHandler::class,
'level' => Logger::INFO,
'stream' => 'php://stdout',
],
],
'processors' => [
'exception_with_new_line' => [
'class' => Common\Logger\Processor\ExceptionWithNewLineProcessor::class,
],
'psr3' => [
'class' => Processor\PsrLogMessageProcessor::class,
],
],
'loggers' => [
'Shlink' => [
'handlers' => ['rotating_file_handler'],
'handlers' => ['shlink_rotating_handler'],
'processors' => ['exception_with_new_line', 'psr3'],
],
'Access' => [
'handlers' => ['access_handler'],
'processors' => ['exception_with_new_line', 'psr3'],
],
],
],
'dependencies' => [
'factories' => [
'Logger_Shlink' => Common\Factory\LoggerFactory::class,
'Logger_Access' => Common\Factory\LoggerFactory::class,
],
],
'zend-expressive-swoole' => [
'swoole-http-server' => [
'logger' => [
'logger-name' => 'Logger_Access',
],
],
],

View File

@@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
use Monolog\Logger;
return [
'logger' => [
'handlers' => [
'rotating_file_handler' => [
'shlink_rotating_handler' => [
'level' => Logger::DEBUG,
],
],

View File

@@ -1,19 +1,56 @@
<?php
use Zend\Expressive\Container\ApplicationFactory;
declare(strict_types=1);
namespace Shlinkio\Shlink;
use Zend\Expressive;
use Zend\Stratigility\Middleware\ErrorHandler;
return [
'middleware_pipeline' => [
'pre-routing' => [
'middleware' => [
ErrorHandler::class,
Expressive\Helper\ContentLengthMiddleware::class,
Common\Middleware\CloseDbConnectionMiddleware::class,
],
'priority' => 12,
],
'pre-routing-rest' => [
'path' => '/rest',
'middleware' => [
Rest\Middleware\PathVersionMiddleware::class,
Rest\Middleware\ShortUrl\ShortCodePathMiddleware::class,
],
'priority' => 11,
],
'routing' => [
'middleware' => [
ApplicationFactory::ROUTING_MIDDLEWARE,
Expressive\Router\Middleware\RouteMiddleware::class,
],
'priority' => 10,
],
'rest' => [
'path' => '/rest',
'middleware' => [
Rest\Middleware\CrossDomainMiddleware::class,
Expressive\Router\Middleware\ImplicitOptionsMiddleware::class,
Rest\Middleware\BodyParserMiddleware::class,
Rest\Middleware\AuthenticationMiddleware::class,
],
'priority' => 5,
],
'post-routing' => [
'middleware' => [
ApplicationFactory::DISPATCH_MIDDLEWARE,
Expressive\Router\Middleware\DispatchMiddleware::class,
// Only if a not found error is triggered, set-up the locale to be used
Common\Middleware\LocaleMiddleware::class,
Core\Response\NotFoundHandler::class,
],
'priority' => 1,
],

View File

@@ -1,11 +0,0 @@
<?php
return [
'phpwkhtmltopdf' => [
'images' => [
'binary' => 'bin/wkhtmltoimage',
'type' => 'jpg',
],
],
];

View File

@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);
return [
'preview_generation' => [

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
use Zend\Expressive\Router\FastRouteRouter;
return [
'router' => [
'fastroute' => [
FastRouteRouter::CONFIG_CACHE_ENABLED => true,
FastRouteRouter::CONFIG_CACHE_FILE => 'data/cache/fastroute_cached_routes.php',
],
],
];

View File

@@ -0,0 +1,12 @@
<?php
use Zend\Expressive\Router\FastRouteRouter;
return [
'router' => [
'fastroute' => [
FastRouteRouter::CONFIG_CACHE_ENABLED => false,
],
],
];

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
return [
'zend-expressive-swoole' => [
'enable_coroutine' => true,
'swoole-http-server' => [
'host' => '0.0.0.0',
'process-name' => 'shlink',
],
],
];

View File

@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
use Zend\Expressive\Swoole\HotCodeReload\FileWatcher\InotifyFileWatcher;
use Zend\ServiceManager\Factory\InvokableFactory;
return [
'zend-expressive-swoole' => [
'hot-code-reload' => [
'enable' => true,
],
],
'dependencies' => [
'factories' => [
InotifyFileWatcher::class => InvokableFactory::class,
],
],
];

View File

@@ -1,9 +1,13 @@
<?php
declare(strict_types=1);
return [
'twig' => [
'cache_dir' => 'data/cache/twig',
'templates' => [
'extension' => 'phtml',
],
'plates' => [
'extensions' => [
// extension service names or instances
],

View File

@@ -1,8 +1,12 @@
<?php
declare(strict_types=1);
use Shlinkio\Shlink\Common;
return [
'translator' => [
'locale' => env('DEFAULT_LOCALE', 'en'),
'locale' => Common\env('DEFAULT_LOCALE', 'en'),
],
];

View File

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

View File

@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
return [
'wkhtmltopdf' => [
'images' => [
'binary' => __DIR__ . '/../../bin/wkhtmltoimage',
'type' => 'jpg',
],
],
];

View File

@@ -1,8 +0,0 @@
<?php
return [
'debug' => false,
'config_cache_enabled' => true,
];

View File

@@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\Console\ConsoleRunner;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\ServiceManager;
/** @var ContainerInterface $container */
/** @var ContainerInterface|ServiceManager $container */
$container = include __DIR__ . '/container.php';
/** @var EntityManager $em */
$em = $container->get(EntityManager::class);
return ConsoleRunner::createHelperSet($em);

View File

@@ -1,25 +1,30 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink;
use Acelaya\ExpressiveErrorHandler;
use Shlinkio\Shlink\CLI;
use Shlinkio\Shlink\Common;
use Shlinkio\Shlink\Core;
use Shlinkio\Shlink\Rest;
use Zend\Expressive\ConfigManager;
use Zend\ConfigAggregator;
use Zend\Expressive;
/**
* Configuration files are loaded in a specific order. First ``global.php``, then ``*.global.php``.
* then ``local.php`` and finally ``*.local.php``. This way local settings overwrite global settings.
*
* The configuration can be cached. This can be done by setting ``config_cache_enabled`` to ``true``.
*
* Obviously, if you use closures in your config you can't cache it.
*/
use function Shlinkio\Shlink\Common\env;
return (new ConfigManager\ConfigManager([
return (new ConfigAggregator\ConfigAggregator([
Expressive\ConfigProvider::class,
Expressive\Router\ConfigProvider::class,
Expressive\Router\FastRouteRouter\ConfigProvider::class,
Expressive\Plates\ConfigProvider::class,
Expressive\Swoole\ConfigProvider::class,
ExpressiveErrorHandler\ConfigProvider::class,
Common\ConfigProvider::class,
Core\ConfigProvider::class,
CLI\ConfigProvider::class,
Rest\ConfigProvider::class,
new ConfigManager\ZendConfigProvider('config/{autoload/{{,*.}global,{,*.}local},params/generated_config}.php'),
], 'data/cache/app_config.php'))->getMergedConfig();
new ConfigAggregator\PhpFileProvider('config/autoload/{{,*.}global,{,*.}local}.php'),
new ConfigAggregator\ZendConfigProvider('config/params/{generated_config.php,*.config.{php,json}}'),
env('APP_ENV') === 'test'
? new ConfigAggregator\PhpFileProvider('config/test/*.global.php')
: new ConfigAggregator\ArrayProvider([]),
], 'data/cache/app_config.php', [
Core\ConfigPostProcessor::class,
]))->getMergedConfig();

View File

@@ -1,5 +1,7 @@
<?php
use Dotenv\Dotenv;
declare(strict_types=1);
use Symfony\Component\Dotenv\Dotenv;
use Zend\ServiceManager\ServiceManager;
chdir(dirname(__DIR__));
@@ -9,9 +11,9 @@ require 'vendor/autoload.php';
// If the Dotenv class exists, load env vars and enable errors
if (class_exists(Dotenv::class)) {
error_reporting(E_ALL);
ini_set('display_errors', 1);
$dotenv = new Dotenv(__DIR__ . '/..');
$dotenv->load();
ini_set('display_errors', '1');
$dotenv = new Dotenv();
$dotenv->load(__DIR__ . '/../.env');
}
// Build container

View File

@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\Common;
use Doctrine\ORM\EntityManager;
use Psr\Container\ContainerInterface;
use function file_exists;
use function touch;
// Create an empty .env file
if (! file_exists('.env')) {
touch('.env');
}
/** @var ContainerInterface $container */
$container = require __DIR__ . '/../container.php';
$testHelper = $container->get(TestHelper::class);
$config = $container->get('config');
$em = $container->get(EntityManager::class);
$testHelper->createTestDb();
ApiTest\ApiTestCase::setApiClient($container->get('shlink_test_api_client'));
ApiTest\ApiTestCase::setSeedFixturesCallback(function () use ($testHelper, $em, $config) {
$testHelper->seedFixtures($em, $config['data_fixtures'] ?? []);
});

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink\Common;
use Psr\Container\ContainerInterface;
use function file_exists;
use function touch;
// Create an empty .env file
if (! file_exists('.env')) {
touch('.env');
}
/** @var ContainerInterface $container */
$container = require __DIR__ . '/../container.php';
$container->get(TestHelper::class)->createTestDb();
DbTest\DatabaseTestCase::setEntityManager($container->get('em'));

View File

@@ -0,0 +1,99 @@
<?php
declare(strict_types=1);
namespace ShlinkioTest\Shlink;
use GuzzleHttp\Client;
use PDO;
use Zend\ConfigAggregator\ConfigAggregator;
use Zend\ServiceManager\Factory\InvokableFactory;
use function Shlinkio\Shlink\Common\env;
use function sprintf;
use function sys_get_temp_dir;
$swooleTestingHost = '127.0.0.1';
$swooleTestingPort = 9999;
$buildDbConnection = function () {
$driver = env('DB_DRIVER', 'sqlite');
$isCi = env('TRAVIS', false);
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 [];
}
};
return [
'debug' => true,
ConfigAggregator::ENABLE_CACHE => false,
'url_shortener' => [
'domain' => [
'schema' => 'http',
'hostname' => 'doma.in',
],
],
'zend-expressive-swoole' => [
'swoole-http-server' => [
'host' => $swooleTestingHost,
'port' => $swooleTestingPort,
'process-name' => 'shlink_test',
'options' => [
'pid_file' => sys_get_temp_dir() . '/shlink-test-swoole.pid',
],
],
],
'dependencies' => [
'services' => [
'shlink_test_api_client' => new Client([
'base_uri' => sprintf('http://%s:%s/', $swooleTestingHost, $swooleTestingPort),
'http_errors' => false,
]),
],
'factories' => [
Common\TestHelper::class => InvokableFactory::class,
],
],
'entity_manager' => [
'connection' => $buildDbConnection(),
],
'data_fixtures' => [
'paths' => [
__DIR__ . '/../../module/Rest/test-api/Fixtures',
],
],
];

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

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

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

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

View File

@@ -0,0 +1,11 @@
<VirtualHost *:80>
ServerName doma.in
DocumentRoot "/path/to/shlink/public"
<Directory "/path/to/shlink/public">
Options FollowSymLinks Includes ExecCGI
AllowOverride all
Order allow,deny
Allow from all
</Directory>
</VirtualHost>

View File

@@ -0,0 +1,22 @@
server {
server_name doma.in;
listen 80;
root /path/to/shlink/public;
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
location ~ /\.ht {
deny all;
}
}

View File

@@ -0,0 +1,13 @@
/var/log/shlink/shlink_swoole.log {
su root root
daily
missingok
rotate 120
compress
delaycompress
notifempty
create 0640 root root
postrotate
/etc/init.d/shlink_swoole restart
endscript
}

View File

@@ -0,0 +1,54 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: shlink_swoole
# Required-Start: $local_fs $network $named $time $syslog
# Required-Stop: $local_fs $network $named $time $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: Shlink non-blocking server with swoole
### END INIT INFO
SCRIPT=/path/to/shlink/vendor/bin/zend-expressive-swoole\ start
RUNAS=root
PIDFILE=/var/run/shlink_swoole.pid
LOGDIR=/var/log/shlink
LOGFILE=${LOGDIR}/shlink_swoole.log
start() {
if [[ -f "$PIDFILE" ]] && kill -0 $(cat "$PIDFILE"); then
echo 'Shlink with swoole already running' >&2
return 1
fi
echo 'Starting shlink with swoole' >&2
mkdir -p "$LOGDIR"
touch "$LOGFILE"
local CMD="$SCRIPT &> \"$LOGFILE\" & echo \$!"
su -c "$CMD" $RUNAS > "$PIDFILE"
echo 'Shlink started' >&2
}
stop() {
if [[ ! -f "$PIDFILE" ]] || ! kill -0 $(cat "$PIDFILE"); then
echo 'Shlink with swoole not running' >&2
return 1
fi
echo 'Stopping shlink with swoole' >&2
kill -15 $(cat "$PIDFILE") && rm -f "$PIDFILE"
echo 'Shlink stopped' >&2
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo "Usage: $0 {start|stop|restart}"
esac

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

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

72
data/infra/php.Dockerfile Normal file
View File

@@ -0,0 +1,72 @@
FROM php:7.3.1-fpm-alpine3.8
MAINTAINER Alejandro Celaya <alejandro@alejandrocelaya.com>
ENV APCU_VERSION 5.1.16
ENV APCU_BC_VERSION 1.0.4
ENV XDEBUG_VERSION "2.7.0RC1"
RUN apk update
# Install common php extensions
RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-install iconv
RUN docker-php-ext-install mbstring
RUN docker-php-ext-install calendar
RUN apk add --no-cache --virtual sqlite-libs
RUN apk add --no-cache --virtual sqlite-dev
RUN docker-php-ext-install pdo_sqlite
RUN apk add --no-cache --virtual icu-dev
RUN docker-php-ext-install intl
RUN apk add --no-cache --virtual libzip-dev zlib-dev
RUN docker-php-ext-install zip
RUN apk add --no-cache --virtual libpng-dev
RUN docker-php-ext-install gd
RUN apk add --no-cache postgresql-dev
RUN docker-php-ext-install pdo_pgsql
# Install APCu extension
ADD https://pecl.php.net/get/apcu-$APCU_VERSION.tgz /tmp/apcu.tar.gz
RUN mkdir -p /usr/src/php/ext/apcu\
&& tar xf /tmp/apcu.tar.gz -C /usr/src/php/ext/apcu --strip-components=1
# configure and install
RUN docker-php-ext-configure apcu\
&& docker-php-ext-install apcu
# cleanup
RUN rm /tmp/apcu.tar.gz
# Install APCu-BC extension
ADD https://pecl.php.net/get/apcu_bc-$APCU_BC_VERSION.tgz /tmp/apcu_bc.tar.gz
RUN mkdir -p /usr/src/php/ext/apcu-bc\
&& tar xf /tmp/apcu_bc.tar.gz -C /usr/src/php/ext/apcu-bc --strip-components=1
# configure and install
RUN docker-php-ext-configure apcu-bc\
&& docker-php-ext-install apcu-bc
# cleanup
RUN rm /tmp/apcu_bc.tar.gz
# Load APCU.ini before APC.ini
RUN rm /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini
RUN echo extension=apcu.so > /usr/local/etc/php/conf.d/20-php-ext-apcu.ini
# Install xdebug
ADD https://pecl.php.net/get/xdebug-$XDEBUG_VERSION /tmp/xdebug.tar.gz
RUN mkdir -p /usr/src/php/ext/xdebug\
&& tar xf /tmp/xdebug.tar.gz -C /usr/src/php/ext/xdebug --strip-components=1
# configure and install
RUN docker-php-ext-configure xdebug\
&& docker-php-ext-install xdebug
# cleanup
RUN rm /tmp/xdebug.tar.gz
# Install composer
RUN php -r "readfile('https://getcomposer.org/installer');" | php
RUN chmod +x composer.phar
RUN mv composer.phar /usr/local/bin/composer
# Make home directory writable by anyone
RUN chmod 777 /home

1
data/infra/php.ini Normal file
View File

@@ -0,0 +1 @@
date.timezone = Europe/Madrid

View File

@@ -0,0 +1,90 @@
FROM php:7.3.1-cli-alpine3.8
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
RUN apk update
# Install common php extensions
RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-install iconv
RUN docker-php-ext-install mbstring
RUN docker-php-ext-install calendar
RUN apk add --no-cache --virtual sqlite-libs
RUN apk add --no-cache --virtual sqlite-dev
RUN docker-php-ext-install pdo_sqlite
RUN apk add --no-cache --virtual icu-dev
RUN docker-php-ext-install intl
RUN apk add --no-cache --virtual libzip-dev zlib-dev
RUN docker-php-ext-install zip
RUN apk add --no-cache --virtual libpng-dev
RUN docker-php-ext-install gd
RUN apk add --no-cache postgresql-dev
RUN docker-php-ext-install pdo_pgsql
# Install APCu extension
ADD https://pecl.php.net/get/apcu-$APCU_VERSION.tgz /tmp/apcu.tar.gz
RUN mkdir -p /usr/src/php/ext/apcu\
&& tar xf /tmp/apcu.tar.gz -C /usr/src/php/ext/apcu --strip-components=1
# configure and install
RUN docker-php-ext-configure apcu\
&& docker-php-ext-install apcu
# cleanup
RUN rm /tmp/apcu.tar.gz
# Install APCu-BC extension
ADD https://pecl.php.net/get/apcu_bc-$APCU_BC_VERSION.tgz /tmp/apcu_bc.tar.gz
RUN mkdir -p /usr/src/php/ext/apcu-bc\
&& tar xf /tmp/apcu_bc.tar.gz -C /usr/src/php/ext/apcu-bc --strip-components=1
# configure and install
RUN docker-php-ext-configure apcu-bc\
&& docker-php-ext-install apcu-bc
# cleanup
RUN rm /tmp/apcu_bc.tar.gz
# Load APCU.ini before APC.ini
RUN rm /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini
RUN echo extension=apcu.so > /usr/local/etc/php/conf.d/20-php-ext-apcu.ini
# Install inotify extension
ADD https://pecl.php.net/get/inotify-$INOTIFY_VERSION.tgz /tmp/inotify.tar.gz
RUN mkdir -p /usr/src/php/ext/inotify\
&& tar xf /tmp/inotify.tar.gz -C /usr/src/php/ext/inotify --strip-components=1
# configure and install
RUN docker-php-ext-configure inotify\
&& docker-php-ext-install inotify
# cleanup
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 && \
docker-php-ext-enable swoole && \
apk del .phpize-deps
# Install composer
RUN php -r "readfile('https://getcomposer.org/installer');" | php
RUN chmod +x composer.phar
RUN mv composer.phar /usr/local/bin/composer
# Make home directory writable by anyone
RUN chmod 777 /home
VOLUME /home/shlink
WORKDIR /home/shlink
# Expose swoole port
EXPOSE 8080
CMD /usr/local/bin/composer update && \
# When restarting the container, swoole might think it is already in execution
# This forces the app to be started every second until the exit code is 0
until php ./vendor/bin/zend-expressive-swoole start; do sleep 1 ; done

21
data/infra/vhost.conf Normal file
View File

@@ -0,0 +1,21 @@
server {
listen 80 default_server;
server_name shlink.local;
root /home/shlink/www/public;
index index.php;
charset utf-8;
error_log /home/shlink/www/data/infra/nginx/shlink.error.log;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
root /home/shlink/www/public;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass shlink_php:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}

2
data/locks/.gitignore vendored Normal file
View File

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

View File

@@ -1,22 +1,26 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20160819142757 extends AbstractMigration
{
const MYSQL = 'mysql';
const SQLITE = 'sqlite';
private const MYSQL = 'mysql';
private const SQLITE = 'sqlite';
/**
* @param Schema $schema
* @throws DBALException
* @throws SchemaException
*/
public function up(Schema $schema)
public function up(Schema $schema): void
{
$db = $this->connection->getDatabasePlatform()->getName();
$table = $schema->getTable('short_urls');
@@ -30,9 +34,9 @@ class Version20160819142757 extends AbstractMigration
}
/**
* @param Schema $schema
* @throws DBALException
*/
public function down(Schema $schema)
public function down(Schema $schema): void
{
$db = $this->connection->getDatabasePlatform()->getName();
}

View File

@@ -1,20 +1,18 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Types\Type;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20160820191203 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema)
public function up(Schema $schema): void
{
// Check if the tables already exist
$tables = $schema->getTables();
@@ -28,7 +26,7 @@ class Version20160820191203 extends AbstractMigration
$this->createShortUrlsInTagsTable($schema);
}
protected function createTagsTable(Schema $schema)
private function createTagsTable(Schema $schema): void
{
$table = $schema->createTable('tags');
$table->addColumn('id', Type::BIGINT, [
@@ -45,7 +43,7 @@ class Version20160820191203 extends AbstractMigration
$table->setPrimaryKey(['id']);
}
protected function createShortUrlsInTagsTable(Schema $schema)
private function createShortUrlsInTagsTable(Schema $schema): void
{
$table = $schema->createTable('short_urls_in_tags');
$table->addColumn('short_url_id', Type::BIGINT, [
@@ -69,10 +67,7 @@ class Version20160820191203 extends AbstractMigration
$table->setPrimaryKey(['short_url_id', 'tag_id']);
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
public function down(Schema $schema): void
{
$schema->dropTable('short_urls_in_tags');
$schema->dropTable('tags');

View File

@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\DBAL\Types\Type;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20171021093246 extends AbstractMigration
{
/**
* @throws SchemaException
*/
public function up(Schema $schema): void
{
$shortUrls = $schema->getTable('short_urls');
if ($shortUrls->hasColumn('valid_since')) {
return;
}
$shortUrls->addColumn('valid_since', Type::DATETIME, [
'notnull' => false,
]);
$shortUrls->addColumn('valid_until', Type::DATETIME, [
'notnull' => false,
]);
}
/**
* @throws SchemaException
*/
public function down(Schema $schema): void
{
$shortUrls = $schema->getTable('short_urls');
if (! $shortUrls->hasColumn('valid_since')) {
return;
}
$shortUrls->dropColumn('valid_since');
$shortUrls->dropColumn('valid_until');
}
}

View File

@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\DBAL\Types\Type;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20171022064541 extends AbstractMigration
{
/**
* @throws SchemaException
*/
public function up(Schema $schema): void
{
$shortUrls = $schema->getTable('short_urls');
if ($shortUrls->hasColumn('max_visits')) {
return;
}
$shortUrls->addColumn('max_visits', Type::INTEGER, [
'unsigned' => true,
'notnull' => false,
]);
}
/**
* @throws SchemaException
*/
public function down(Schema $schema): void
{
$shortUrls = $schema->getTable('short_urls');
if (! $shortUrls->hasColumn('max_visits')) {
return;
}
$shortUrls->dropColumn('max_visits');
}
}

View File

@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20180801183328 extends AbstractMigration
{
private const NEW_SIZE = 255;
private const OLD_SIZE = 10;
/**
* @param Schema $schema
* @throws SchemaException
*/
public function up(Schema $schema): void
{
$this->setSize($schema, self::NEW_SIZE);
}
/**
* @param Schema $schema
* @throws SchemaException
*/
public function down(Schema $schema): void
{
$this->setSize($schema, self::OLD_SIZE);
}
/**
* @param Schema $schema
* @param int $size
* @throws SchemaException
*/
private function setSize(Schema $schema, int $size): void
{
$schema->getTable('short_urls')->getColumn('short_code')->setLength($size);
}
}

View File

@@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
use PDO;
use Shlinkio\Shlink\Common\Exception\WrongIpException;
use Shlinkio\Shlink\Common\Util\IpAddress;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20180913205455 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema): void
{
// Nothing to create
}
/**
* @param Schema $schema
* @throws DBALException
*/
public function postUp(Schema $schema): void
{
$qb = $this->connection->createQueryBuilder();
$qb->select('id', 'remote_addr')
->from('visits');
$st = $this->connection->executeQuery($qb->getSQL());
$qb = $this->connection->createQueryBuilder();
$qb->update('visits', 'v')
->set('v.remote_addr', ':obfuscatedAddr')
->where('v.id=:id');
while ($row = $st->fetch(PDO::FETCH_ASSOC)) {
$addr = $row['remote_addr'] ?? null;
if ($addr === null) {
continue;
}
$qb->setParameters([
'id' => $row['id'],
'obfuscatedAddr' => $this->determineAddress((string) $addr),
])->execute();
}
}
private function determineAddress(string $addr): ?string
{
if ($addr === IpAddress::LOCALHOST) {
return $addr;
}
try {
return (string) IpAddress::fromString($addr)->getObfuscatedCopy();
} catch (WrongIpException $e) {
return null;
}
}
/**
* @param Schema $schema
*/
public function down(Schema $schema): void
{
// Nothing to rollback
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20180915110857 extends AbstractMigration
{
private const ON_DELETE_MAP = [
'visit_locations' => 'SET NULL',
'short_urls' => 'CASCADE',
];
/**
* @param Schema $schema
* @throws SchemaException
*/
public function up(Schema $schema): void
{
$visits = $schema->getTable('visits');
$foreignKeys = $visits->getForeignKeys();
// Remove all existing foreign keys and add them again with CASCADE delete
foreach ($foreignKeys as $foreignKey) {
$visits->removeForeignKey($foreignKey->getName());
$foreignTable = $foreignKey->getForeignTableName();
$visits->addForeignKeyConstraint(
$foreignTable,
$foreignKey->getLocalColumns(),
$foreignKey->getForeignColumns(),
[
'onDelete' => self::ON_DELETE_MAP[$foreignTable],
'onUpdate' => 'RESTRICT',
]
);
}
}
public function down(Schema $schema): void
{
// Nothing to run
}
}

View File

@@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Types\Type;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20181020060559 extends AbstractMigration
{
private const COLUMNS = [
'countryCode' => 'country_code',
'countryName' => 'country_name',
'regionName' => 'region_name',
'cityName' => 'city_name',
];
/**
* @param Schema $schema
* @throws SchemaException
*/
public function up(Schema $schema): void
{
$this->createColumns($schema->getTable('visit_locations'), self::COLUMNS);
}
private function createColumns(Table $visitLocations, array $columnNames): void
{
foreach ($columnNames as $name) {
if (! $visitLocations->hasColumn($name)) {
$visitLocations->addColumn($name, Type::STRING, ['notnull' => false]);
}
}
}
/**
* @throws SchemaException
* @throws DBALException
*/
public function postUp(Schema $schema): void
{
$visitLocations = $schema->getTable('visit_locations');
// If the camel case columns do not exist, do nothing
if (! $visitLocations->hasColumn('countryCode')) {
return;
}
$qb = $this->connection->createQueryBuilder();
$qb->update('visit_locations');
foreach (self::COLUMNS as $camelCaseName => $snakeCaseName) {
$qb->set($snakeCaseName, $camelCaseName);
}
$qb->execute();
}
public function down(Schema $schema): void
{
// No down
}
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20181020065148 extends AbstractMigration
{
private const CAMEL_CASE_COLUMNS = [
'countryCode',
'countryName',
'regionName',
'cityName',
];
/**
* @throws SchemaException
*/
public function up(Schema $schema): void
{
$visitLocations = $schema->getTable('visit_locations');
foreach (self::CAMEL_CASE_COLUMNS as $name) {
if ($visitLocations->hasColumn($name)) {
$visitLocations->dropColumn($name);
}
}
}
public function down(Schema $schema): void
{
// No down
}
}

View File

@@ -0,0 +1,36 @@
<?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 Version20181110175521 extends AbstractMigration
{
/**
* @throws SchemaException
*/
public function up(Schema $schema): void
{
$this->getUserAgentColumn($schema)->setLength(512);
}
/**
* @throws SchemaException
*/
public function down(Schema $schema): void
{
$this->getUserAgentColumn($schema)->setLength(256);
}
/**
* @throws SchemaException
*/
private function getUserAgentColumn(Schema $schema): Column
{
return $schema->getTable('visits')->getColumn('user_agent');
}
}

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace <namespace>;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version<version> extends AbstractMigration
{
public function up(Schema $schema): void
{
<up>
}
public function down(Schema $schema): void
{
<down>
}
}

0
data/proxies/.gitignore vendored Normal file → Executable file
View File

View File

@@ -0,0 +1,20 @@
#!/bin/bash
set -e
# Get latest commit in master, in plain text
LATEST_MASTER_COMMIT=$(curl -H "Accept: application/vnd.github.sha" -X GET https://api.github.com/repos/shlinkio/shlink-docker-image/commits/master)
# Create new tag and a ref to the tag, which will trigger image build on it
curl -u acelaya:${GITHUB_OAUTH_KEY} \
-H "Content-Type: application/json" \
--data "{ \"tag\": \"${TRAVIS_TAG}\", \"message\": \"${TRAVIS_TAG}\", \"object\": \"${LATEST_MASTER_COMMIT}\", \"type\": \"commit\" }" \
-X POST https://api.github.com/repos/shlinkio/shlink-docker-image/git/tags
curl -u acelaya:${GITHUB_OAUTH_KEY} \
-H "Content-Type: application/json" \
--data "{ \"ref\": \"refs/tags/${TRAVIS_TAG}\", \"sha\": \"${LATEST_MASTER_COMMIT}\" }" \
-X POST https://api.github.com/repos/shlinkio/shlink-docker-image/git/refs
# Trigger image build for "latest
curl -H "Content-Type: application/json" \
--data '{ "docker_tag": "latest" }' \
-X POST https://registry.hub.docker.com/u/shlinkio/shlink/trigger/${DOCKER_TRIGGER_TOKEN}/

View File

@@ -0,0 +1,26 @@
version: '3'
services:
shlink_php:
user: 1000:1000
volumes:
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro
shlink_swoole:
user: 1000:1000
volumes:
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro
shlink_db:
user: 1000:1000
volumes:
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro
shlink_db_postgres:
user: 1000:1000
volumes:
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro

64
docker-compose.yml Normal file
View File

@@ -0,0 +1,64 @@
version: '3'
services:
shlink_nginx:
container_name: shlink_nginx
image: nginx:1.15.9-alpine
ports:
- "8000:80"
volumes:
- ./:/home/shlink/www
- ./docs:/home/shlink/www/public/docs
- ./data/infra/vhost.conf:/etc/nginx/conf.d/default.conf
links:
- shlink_php
shlink_php:
container_name: shlink_php
build:
context: .
dockerfile: ./data/infra/php.Dockerfile
volumes:
- ./:/home/shlink/www
- ./data/infra/php.ini:/usr/local/etc/php/php.ini
links:
- shlink_db
- shlink_db_postgres
shlink_swoole:
container_name: shlink_swoole
build:
context: .
dockerfile: ./data/infra/swoole.Dockerfile
ports:
- "8080:8080"
volumes:
- ./:/home/shlink
links:
- shlink_db
- shlink_db_postgres
shlink_db:
container_name: shlink_db
image: mysql:5.7
ports:
- "3307:3306"
volumes:
- ./:/home/shlink/www
- ./data/infra/database:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: shlink
shlink_db_postgres:
container_name: shlink_db_postgres
image: postgres:10.7-alpine
ports:
- "5433:5432"
volumes:
- ./:/home/shlink/www
- ./data/infra/database_pg:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: root
POSTGRES_DB: shlink
PGDATA: /var/lib/postgresql/data/pgdata

View File

@@ -1,289 +0,0 @@
swagger: '2.0'
info:
title: Shlink
description: Shlink, the self-hosted URL shortener
version: "1.2.0"
schemes:
- https
basePath: /rest
produces:
- application/json
paths:
/authenticate:
post:
description: Performs an authentication
parameters:
- name: apiKey
in: formData
description: The API key to authenticate with
required: true
type: string
responses:
200:
description: The authentication worked.
schema:
type: object
properties:
token:
type: string
description: The authentication token that needs to be sent in the Authorization header
400:
description: An API key was not provided.
schema:
$ref: '#/definitions/Error'
401:
description: The API key is incorrect, is disabled or has expired.
schema:
$ref: '#/definitions/Error'
500:
description: Unexpected error.
schema:
$ref: '#/definitions/Error'
/short-codes:
get:
description: Returns the list of short codes
parameters:
- name: page
in: query
description: The page to be displayed. Defaults to 1
required: false
type: integer
- name: Authorization
in: header
description: The authorization token with Bearer type
required: true
type: string
responses:
200:
description: The list of short URLs
schema:
type: object
properties:
shortUrls:
type: object
properties:
data:
type: array
items:
$ref: '#/definitions/ShortUrl'
pagination:
$ref: '#/definitions/Pagination'
500:
description: Unexpected error.
schema:
$ref: '#/definitions/Error'
post:
description: Creates a new short code
parameters:
- name: longUrl
in: formData
description: The URL to parse
required: true
type: string
- name: tags
in: formData
description: The URL to parse
required: false
type: array
items:
type: string
- name: Authorization
in: header
description: The authorization token with Bearer type
required: true
type: string
responses:
200:
description: The result of parsing the long URL
schema:
type: object
properties:
longUrl:
type: string
description: The original long URL that has been parsed
shortUrl:
type: string
description: The generated short URL
shortCode:
type: string
description: the short code that is being used in the short URL
400:
description: The long URL was not provided or is invalid.
schema:
$ref: '#/definitions/Error'
500:
description: Unexpected error.
schema:
$ref: '#/definitions/Error'
/short-codes/{shortCode}:
get:
description: Get the long URL behind a short code.
parameters:
- name: shortCode
in: path
type: string
description: The short code to resolve.
required: true
- name: Authorization
in: header
description: The authorization token with Bearer type
required: true
type: string
responses:
200:
description: The long URL behind a short code.
schema:
type: object
properties:
longUrl:
type: string
description: The original long URL behind the short code.
404:
description: No URL was found for provided short code.
schema:
$ref: '#/definitions/Error'
400:
description: Provided shortCode does not match the character set currently used by the app to generate short codes.
schema:
$ref: '#/definitions/Error'
500:
description: Unexpected error.
schema:
$ref: '#/definitions/Error'
/short-codes/{shortCode}/visits:
get:
description: Get the list of visits on provided short code.
parameters:
- name: shortCode
in: path
type: string
description: The shortCode from which we want to get the visits.
required: true
- name: Authorization
in: header
description: The authorization token with Bearer type
required: true
type: string
responses:
200:
description: List of visits.
schema:
type: object
properties:
visits:
type: object
properties:
data:
type: array
items:
$ref: '#/definitions/Visit'
404:
description: The short code does not belong to any short URL.
schema:
$ref: '#/definitions/Error'
500:
description: Unexpected error.
schema:
$ref: '#/definitions/Error'
/short-codes/{shortCode}/tags:
put:
description: Edit the tags on provided short code.
parameters:
- name: shortCode
in: path
type: string
description: The shortCode in which we want to edit tags.
required: true
- name: tags
in: formData
type: array
items:
type: string
description: The list of tags to set to the short URL.
required: true
- name: Authorization
in: header
description: The authorization token with Bearer type
required: true
type: string
responses:
200:
description: List of tags.
schema:
type: object
properties:
tags:
type: array
items:
type: string
400:
description: The request body does not contain a "tags" param with array type.
schema:
$ref: '#/definitions/Error'
404:
description: No short URL was found for provided short code.
schema:
$ref: '#/definitions/Error'
500:
description: Unexpected error.
schema:
$ref: '#/definitions/Error'
definitions:
ShortUrl:
type: object
properties:
shortCode:
type: string
description: The short code for this short URL.
originalUrl:
type: string
description: The original long URL.
dateCreated:
type: string
format: date-time
description: The date in which the short URL was created in ISO format.
visitsCount:
type: integer
description: The number of visits that this short URL has recieved.
tags:
type: array
items:
type: string
description: A list of tags applied to this short URL
Visit:
type: object
properties:
referer:
type: string
date:
type: string
format: date-time
remoteAddr:
type: string
userAgent:
type: string
Error:
type: object
properties:
code:
type: string
description: A machine unique code
message:
type: string
description: A human-friendly error message
Pagination:
type: object
properties:
currentPage:
type: integer
description: The number of current page being displayed.
pagesCount:
type: integer
description: The total number of pages that can be displayed.

View File

@@ -0,0 +1,13 @@
{
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "A machine unique code"
},
"message": {
"type": "string",
"description": "A human-friendly error message"
}
}
}

View File

@@ -0,0 +1,31 @@
{
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"pass",
"fail"
],
"description": "The status of the service"
},
"version": {
"type": "string",
"description": "Shlink version"
},
"links": {
"type": "object",
"properties": {
"about": {
"type": "string",
"description": "About shlink"
},
"project": {
"type": "string",
"description": "Shlink project repository"
}
},
"description": "A list of links"
}
}
}

View File

@@ -0,0 +1,25 @@
{
"type": "object",
"properties": {
"currentPage": {
"type": "integer",
"description": "The number of current page."
},
"pagesCount": {
"type": "integer",
"description": "The total number of pages that can be obtained."
},
"itemsPerPage": {
"type": "integer",
"description": "The number of items for every page."
},
"itemsInCurrentPage": {
"type": "integer",
"description": "The number of items in current page (could be smaller than itemsPerPage)."
},
"totalItems": {
"type": "integer",
"description": "The total number of items among all pages."
}
}
}

View File

@@ -0,0 +1,38 @@
{
"type": "object",
"properties": {
"shortCode": {
"type": "string",
"description": "The short code for this short URL."
},
"shortUrl": {
"type": "string",
"description": "The short URL."
},
"longUrl": {
"type": "string",
"description": "The original long URL."
},
"dateCreated": {
"type": "string",
"format": "date-time",
"description": "The date in which the short URL was created in ISO format."
},
"visitsCount": {
"type": "integer",
"description": "The number of visits that this short URL has recieved."
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "A list of tags applied to this short URL"
},
"originalUrl": {
"deprecated": true,
"type": "string",
"description": "The original long URL. [DEPRECATED. Use longUrl instead]"
}
}
}

View File

@@ -0,0 +1,26 @@
{
"type": "object",
"properties": {
"referer": {
"type": "string",
"description": "The origin from which the visit was performed"
},
"date": {
"type": "string",
"format": "date-time",
"description": "The date in which the visit was performed"
},
"userAgent": {
"type": "string",
"description": "The user agent from which the visit was performed"
},
"visitLocation": {
"$ref": "./VisitLocation.json"
},
"remoteAddr": {
"type": "string",
"description": "This value is deprecated and will always be null",
"deprecated": true
}
}
}

View File

@@ -0,0 +1,26 @@
{
"type": "object",
"properties": {
"cityName": {
"type": "string"
},
"countryCode": {
"type": "string"
},
"countryName": {
"type": "string"
},
"latitude": {
"type": "string"
},
"longitude": {
"type": "string"
},
"regionName": {
"type": "string"
},
"timezone": {
"type": "string"
}
}
}

View File

@@ -0,0 +1,62 @@
{
"get": {
"operationId": "health",
"tags": [
"Monitoring"
],
"summary": "Check healthiness",
"description": "Checks the healthiness of the service, making sure it can access required resources.",
"responses": {
"200": {
"description": "The passing health status",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Health.json"
}
}
},
"examples": {
"application/json": {
"status": "pass",
"version": "1.16.0",
"links": {
"about": "https://shlink.io",
"project": "https://github.com/shlinkio/shlink"
}
}
}
},
"503": {
"description": "The failing health status",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Health.json"
}
}
},
"examples": {
"application/json": {
"status": "fail",
"version": "1.16.0",
"links": {
"about": "https://shlink.io",
"project": "https://github.com/shlinkio/shlink"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,84 @@
{
"post": {
"deprecated": true,
"operationId": "authenticate",
"tags": [
"Authentication"
],
"summary": "[Deprecated] Perform authentication",
"description": "**This endpoint is deprecated, since the authentication can be performed via API key now**. Performs an authentication.",
"requestBody": {
"description": "Request body.",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"apiKey"
],
"properties": {
"apiKey": {
"description": "The API key to authenticate with",
"type": "string"
}
}
}
}
}
},
"responses": {
"200": {
"description": "The authentication worked.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"token": {
"type": "string",
"description": "The authentication token that needs to be sent in the Authorization header"
}
}
}
}
},
"examples": {
"application/json": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"
}
}
},
"400": {
"description": "An API key was not provided.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"401": {
"description": "The API key is incorrect, is disabled or has expired.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,256 @@
{
"get": {
"operationId": "listShortUrls",
"tags": [
"Short URLs"
],
"summary": "List short URLs",
"description": "Returns the list of short URLs.<br><br>**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
"parameters": [
{
"name": "page",
"in": "query",
"description": "The page to be displayed. Defaults to 1",
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "searchTerm",
"in": "query",
"description": "A query used to filter results by searching for it on the longUrl and shortCode fields. (Since v1.3.0)",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "tags[]",
"in": "query",
"description": "A list of tags used to filter the resultset. Only short URLs tagged with at least one of the provided tags will be returned. (Since v1.3.0)",
"required": false,
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
{
"name": "orderBy",
"in": "query",
"description": "The field from which you want to order the result. (Since v1.3.0)",
"required": false,
"schema": {
"type": "string",
"enum": [
"longUrl",
"shortCode",
"dateCreated",
"visits"
]
}
}
],
"security": [
{
"ApiKey": []
},
{
"Bearer": []
}
],
"responses": {
"200": {
"description": "The list of short URLs",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"shortUrls": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "../definitions/ShortUrl.json"
}
},
"pagination": {
"$ref": "../definitions/Pagination.json"
}
}
}
}
}
}
},
"examples": {
"application/json": {
"shortUrls": {
"data": [
{
"shortCode": "12C18",
"shortUrl": "https://doma.in/12C18",
"longUrl": "https://store.steampowered.com",
"dateCreated": "2016-08-21T20:34:16+02:00",
"visitsCount": 328,
"tags": [
"games",
"tech"
]
},
{
"shortCode": "12Kb3",
"shortUrl": "https://doma.in/12Kb3",
"longUrl": "https://shlink.io",
"dateCreated": "2016-05-01T20:34:16+02:00",
"visitsCount": 1029,
"tags": [
"shlink"
]
},
{
"shortCode": "123bA",
"shortUrl": "https://doma.in/123bA",
"longUrl": "https://www.google.com",
"dateCreated": "2015-10-01T20:34:16+02:00",
"visitsCount": 25,
"tags": []
}
],
"pagination": {
"currentPage": 5,
"pagesCount": 12,
"itemsPerPage": 10,
"itemsInCurrentPage": 10,
"totalItems": 115
}
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
},
"post": {
"operationId": "createShortUrl",
"tags": [
"Short URLs"
],
"summary": "Create short URL",
"description": "Creates a new short URL.<br><br>**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.<br></br>**Param findIfExists:**: Starting with v1.16, this new param allows to force shlink to return existing short URLs when found based on provided params, instead of creating a new one. However, it might add complexity and have unexpected outputs.\n\nThese are the use cases:\n* Only the long URL is provided: It will return the newest match or create a new short URL if none is found.\n* Long url and custom slug are provided: It will return the short URL when both params match, return an error when the slug is in use for another long URL, or create a new short URL otherwise.\n* Any of the above but including other params (tags, validSince, validUntil, maxVisits): It will behave the same as the previous two cases, but it will try to exactly match existing results using all the params. If any of them does not match, it will try to create a new short URL.",
"security": [
{
"ApiKey": []
},
{
"Bearer": []
}
],
"requestBody": {
"description": "Request body.",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"longUrl"
],
"properties": {
"longUrl": {
"description": "The URL to parse",
"type": "string"
},
"tags": {
"description": "The URL to parse",
"type": "array",
"items": {
"type": "string"
}
},
"validSince": {
"description": "The date (in ISO-8601 format) from which this short code will be valid",
"type": "string"
},
"validUntil": {
"description": "The date (in ISO-8601 format) until which this short code will be valid",
"type": "string"
},
"customSlug": {
"description": "A unique custom slug to be used instead of the generated short code",
"type": "string"
},
"maxVisits": {
"description": "The maximum number of allowed visits for this short code",
"type": "number"
},
"findIfExists": {
"description": "Will force existing matching URL to be returned if found, instead of creating a new one",
"type": "boolean"
}
}
}
}
}
},
"responses": {
"200": {
"description": "The result of parsing the long URL",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/ShortUrl.json"
}
}
},
"examples": {
"application/json": {
"shortCode": "12C18",
"shortUrl": "https://doma.in/12C18",
"longUrl": "https://store.steampowered.com",
"dateCreated": "2016-08-21T20:34:16+02:00",
"visitsCount": 0,
"tags": [
"games",
"tech"
]
}
}
},
"400": {
"description": "The long URL was not provided or is invalid.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,118 @@
{
"get": {
"operationId": "shortenUrl",
"tags": [
"Short URLs"
],
"summary": "Create a short URL",
"description": "Creates a short URL in a single API call. Useful for third party integrations.<br><br>**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
"parameters": [
{
"name": "apiKey",
"in": "query",
"description": "The API key used to authenticate the request",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "longUrl",
"in": "query",
"description": "The URL to be shortened",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "format",
"in": "query",
"description": "The format in which you want the response to be returned. You can also use the \"Accept\" header instead of this",
"required": false,
"schema": {
"type": "string",
"enum": [
"txt",
"json"
]
}
}
],
"responses": {
"200": {
"description": "The list of short URLs",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/ShortUrl.json"
}
},
"text/plain": {
"schema": {
"type": "string"
}
}
},
"examples": {
"application/json": {
"longUrl": "https://github.com/shlinkio/shlink",
"shortUrl": "https://doma.in/abc123",
"shortCode": "abc123",
"dateCreated": "2016-08-21T20:34:16+02:00",
"visitsCount": 0,
"tags": [
"games",
"tech"
]
},
"text/plain": "https://doma.in/abc123"
}
},
"400": {
"description": "The long URL was not provided or is invalid.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
},
"text/plain": {
"schema": {
"type": "string"
}
}
},
"examples": {
"application/json": {
"error": "INVALID_URL",
"message": "Provided URL foo is invalid. Try with a different one."
},
"text/plain": "INVALID_URL"
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
},
"text/plain": {
"schema": {
"type": "string"
}
}
},
"examples": {
"application/json": {
"error": "UNKNOWN_ERROR",
"message": "Unexpected error occurred"
},
"text/plain": "UNKNOWN_ERROR"
}
}
}
}
}

View File

@@ -0,0 +1,329 @@
{
"get": {
"operationId": "getShortUrl",
"tags": [
"Short URLs"
],
"summary": "Parse short code",
"description": "Get the long URL behind a short URL's short code.<br><br>**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
"parameters": [
{
"name": "shortCode",
"in": "path",
"description": "The short code to resolve.",
"required": true,
"schema": {
"type": "string"
}
}
],
"security": [
{
"ApiKey": []
},
{
"Bearer": []
}
],
"responses": {
"200": {
"description": "The URL info behind a short code.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/ShortUrl.json"
}
}
},
"examples": {
"application/json": {
"shortCode": "12Kb3",
"shortUrl": "https://doma.in/12Kb3",
"longUrl": "https://shlink.io",
"dateCreated": "2016-05-01T20:34:16+02:00",
"visitsCount": 1029,
"tags": [
"shlink"
]
}
}
},
"400": {
"description": "Provided shortCode does not match the character set currently used by the app to generate short codes.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"404": {
"description": "No URL was found for provided short code.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
},
"patch": {
"operationId": "editShortUrl",
"tags": [
"Short URLs"
],
"summary": "Edit short URL",
"description": "Update certain meta arguments from an existing short URL.<br><br>**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
"parameters": [
{
"name": "shortCode",
"in": "path",
"description": "The short code to edit.",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "Request body.",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"validSince": {
"description": "The date (in ISO-8601 format) from which this short code will be valid",
"type": "string"
},
"validUntil": {
"description": "The date (in ISO-8601 format) until which this short code will be valid",
"type": "string"
},
"maxVisits": {
"description": "The maximum number of allowed visits for this short code",
"type": "number"
}
}
}
}
}
},
"security": [
{
"ApiKey": []
},
{
"Bearer": []
}
],
"responses": {
"204": {
"description": "The short code has been properly updated."
},
"400": {
"description": "Provided meta arguments are invalid.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"404": {
"description": "No short URL was found for provided short code.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
},
"put": {
"deprecated": true,
"operationId": "editShortUrlPut",
"tags": [
"Short URLs"
],
"summary": "[DEPRECATED] Edit short URL",
"description": "**[DEPRECATED]** Use [editShortUrl](#/Short_URLs/getShortUrl) instead",
"parameters": [
{
"name": "shortCode",
"in": "path",
"description": "The short code to edit.",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "Request body.",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"validSince": {
"description": "The date (in ISO-8601 format) from which this short code will be valid",
"type": "string"
},
"validUntil": {
"description": "The date (in ISO-8601 format) until which this short code will be valid",
"type": "string"
},
"maxVisits": {
"description": "The maximum number of allowed visits for this short code",
"type": "number"
}
}
}
}
}
},
"security": [
{
"ApiKey": []
},
{
"Bearer": []
}
],
"responses": {
"204": {
"description": "The short code has been properly updated."
},
"400": {
"description": "Provided meta arguments are invalid.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"404": {
"description": "No short URL was found for provided short code.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
},
"delete": {
"operationId": "deleteShortUrl",
"tags": [
"Short URLs"
],
"summary": "Delete short URL",
"description": "Deletes the short URL for provided short code.<br><br>**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
"parameters": [
{
"name": "shortCode",
"in": "path",
"description": "The short code to edit.",
"required": true,
"schema": {
"type": "string"
}
}
],
"security": [
{
"ApiKey": []
},
{
"Bearer": []
}
],
"responses": {
"204": {
"description": "The short URL has been properly deleted."
},
"400": {
"description": "The visits threshold in shlink does not allow this short URL to be deleted.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
},
"examples": {
"application/json": {
"error": "INVALID_SHORTCODE_DELETION",
"message": "It is not possible to delete URL with short code \"abc123\" because it has reached more than \"15\" visits."
}
}
},
"404": {
"description": "No short URL was found for provided short code.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,110 @@
{
"put": {
"operationId": "editShortUrlTags",
"tags": [
"Short URLs"
],
"summary": "Edit tags on short URL",
"description": "Edit the tags on URL identified by provided short code.<br><br>**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
"parameters": [
{
"name": "shortCode",
"in": "path",
"description": "The short code for the short URL in which we want to edit tags.",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "Request body.",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"tags"
],
"properties": {
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The list of tags to set to the short URL."
}
}
}
}
}
},
"security": [
{
"ApiKey": []
},
{
"Bearer": []
}
],
"responses": {
"200": {
"description": "List of tags.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"tags": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"examples": {
"application/json": {
"tags": [
"games",
"tech"
]
}
}
},
"400": {
"description": "The request body does not contain a \"tags\" param with array type.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"404": {
"description": "No short URL was found for provided short code.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,154 @@
{
"get": {
"operationId": "getShortUrlVisits",
"tags": [
"Visits"
],
"summary": "List visits for short URL",
"description": "Get the list of visits on the short URL behind provided short code.<br><br>**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
"parameters": [
{
"name": "shortCode",
"in": "path",
"description": "The short code for the short URL from which we want to get the visits.",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "startDate",
"in": "query",
"description": "The date (in ISO-8601 format) from which we want to get visits.",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "endDate",
"in": "query",
"description": "The date (in ISO-8601 format) until which we want to get visits.",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "page",
"in": "query",
"description": "The page to display. Defaults to 1",
"required": false,
"schema": {
"type": "number"
}
},
{
"name": "itemsPerPage",
"in": "query",
"description": "The amount of items to return on every page. Defaults to all the items",
"required": false,
"schema": {
"type": "number"
}
}
],
"security": [
{
"ApiKey": []
},
{
"Bearer": []
}
],
"responses": {
"200": {
"description": "List of visits.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"visits": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "../definitions/Visit.json"
}
},
"pagination": {
"$ref": "../definitions/Pagination.json"
}
}
}
}
}
}
},
"examples": {
"application/json": {
"visits": {
"data": [
{
"referer": "https://twitter.com",
"date": "2015-08-20T05:05:03+04:00",
"userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0 Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0",
"visitLocation": null
},
{
"referer": "https://t.co",
"date": "2015-08-20T05:05:03+04:00",
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"visitLocation": {
"cityName": "Cupertino",
"countryCode": "US",
"countryName": "United States",
"latitude": "37.3042",
"longitude": "-122.0946",
"regionName": "California",
"timezone": "America/Los_Angeles"
}
},
{
"referer": null,
"date": "2015-08-20T05:05:03+04:00",
"userAgent": "some_web_crawler/1.4",
"visitLocation": null
}
],
"pagination": {
"currentPage": 5,
"pagesCount": 12,
"itemsPerPage": 10,
"itemsInCurrentPage": 10,
"totalItems": 115
}
}
}
}
},
"404": {
"description": "The short code does not belong to any short URL.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,275 @@
{
"get": {
"operationId": "listTags",
"tags": [
"Tags"
],
"summary": "List existing tags",
"description": "Returns the list of all tags used in any short URL, ordered by name",
"security": [
{
"ApiKey": []
},
{
"Bearer": []
}
],
"responses": {
"200": {
"description": "The list of tags",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"tags": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
}
},
"examples": {
"application/json": {
"tags": {
"data": [
"games",
"php",
"shlink",
"tech"
]
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
},
"post": {
"operationId": "createTags",
"tags": [
"Tags"
],
"summary": "Create tags",
"description": "Provided a list of tags, creates all that do not yet exist",
"security": [
{
"ApiKey": []
},
{
"Bearer": []
}
],
"requestBody": {
"description": "Request body.",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"tags"
],
"properties": {
"tags": {
"description": "The list of tag names to create",
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
},
"responses": {
"200": {
"description": "The list of tags",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"tags": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
}
},
"examples": {
"application/json": {
"tags": {
"data": [
"games",
"php",
"shlink",
"tech"
]
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
},
"put": {
"operationId": "renameTag",
"tags": [
"Tags"
],
"summary": "Rename tag",
"description": "Renames one existing tag",
"security": [
{
"ApiKey": []
},
{
"Bearer": []
}
],
"requestBody": {
"description": "Request body.",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"oldName",
"newName"
],
"properties": {
"oldName": {
"description": "Current name of the tag",
"type": "string"
},
"newName": {
"description": "New name of the tag",
"type": "string"
}
}
}
}
}
},
"responses": {
"204": {
"description": "The tag has been properly renamed"
},
"400": {
"description": "You have not provided either the oldName or the newName params.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"404": {
"description": "There's no tag found with the name provided in oldName param.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
},
"delete": {
"operationId": "deleteTags",
"tags": [
"Tags"
],
"summary": "Delete tags",
"description": "Deletes provided list of tags",
"parameters": [
{
"name": "tags[]",
"in": "query",
"description": "The names of the tags to delete",
"required": true,
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
}
],
"security": [
{
"ApiKey": []
},
{
"Bearer": []
}
],
"responses": {
"204": {
"description": "Tags properly deleted"
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
{
"get": {
"operationId": "shortUrl",
"tags": [
"URL Shortener"
],
"summary": "Short URL",
"description": "Represents a short URL. Tracks the visit and redirects tio the corresponding long URL",
"parameters": [
{
"name": "shortCode",
"in": "path",
"description": "The short code to resolve.",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"302": {
"description": "Visit properly tracked and redirected"
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,44 @@
{
"get": {
"operationId": "shortUrlPreview",
"tags": [
"URL Shortener"
],
"summary": "Short URL preview image",
"description": "Returns the preview of the page behind a short URL",
"parameters": [
{
"name": "shortCode",
"in": "path",
"description": "The short code to resolve.",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Image in PNG format",
"content": {
"image/png": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,56 @@
{
"get": {
"operationId": "shortUrlQrCode",
"tags": [
"URL Shortener"
],
"summary": "Short URL QR code",
"description": "Generates a QR code image pointing to a short URL",
"parameters": [
{
"name": "shortCode",
"in": "path",
"description": "The short code to resolve.",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "size",
"in": "path",
"description": "The size of the image to be returned.",
"required": false,
"schema": {
"type": "integer",
"minimum": 50,
"maximum": 1000,
"default": 300
}
}
],
"responses": {
"200": {
"description": "QR code in PNG format",
"content": {
"image/png": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,44 @@
{
"get": {
"operationId": "trackShortUrl",
"tags": [
"URL Shortener"
],
"summary": "Short URL tracking pixel",
"description": "Generates a 1px transparent image which can be used to track emails with a short URL",
"parameters": [
{
"name": "shortCode",
"in": "path",
"description": "The short code to resolve.",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Image in GIF format",
"content": {
"image/gif": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"500": {
"description": "Unexpected error.",
"content": {
"application/json": {
"schema": {
"$ref": "../definitions/Error.json"
}
}
}
}
}
}
}

116
docs/swagger/swagger.json Normal file
View File

@@ -0,0 +1,116 @@
{
"openapi": "3.0.0",
"info": {
"title": "Shlink",
"description": "Shlink, the self-hosted URL shortener",
"version": "1.0"
},
"externalDocs": {
"url": "https://shlink.io/api-docs",
"description": "Find more info on how to start using this API here"
},
"servers": [
{
"url": "{scheme}://{host}",
"variables": {
"scheme": {
"default": "https",
"enum": ["https", "http"]
},
"host": {
"default": ""
}
}
}
],
"components": {
"securitySchemes": {
"ApiKey": {
"description": "A valid shlink API key",
"type": "apiKey",
"in": "header",
"name": "X-Api-Key"
},
"Bearer": {
"description": "**[DEPRECATED]** The JWT identifying a previously authenticated API key",
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
},
"tags": [
{
"name": "Short URLs",
"description": "Operations that can be performed on short URLs"
},
{
"name": "Tags",
"description": "Let you handle the list of available tags"
},
{
"name": "Visits",
"description": "Operations to manage visits on short URLs"
},
{
"name": "Monitoring",
"description": "Public endpoints designed to monitor the service"
},
{
"name": "URL Shortener",
"description": "Non-rest endpoints, used to be publicly exposed"
},
{
"name": "Authentication",
"description": "**[DEPRECATED]** Authentication-related endpoints"
}
],
"paths": {
"/rest/v1/short-urls": {
"$ref": "paths/v1_short-urls.json"
},
"/rest/v1/short-urls/shorten": {
"$ref": "paths/v1_short-urls_shorten.json"
},
"/rest/v1/short-urls/{shortCode}": {
"$ref": "paths/v1_short-urls_{shortCode}.json"
},
"/rest/v1/short-urls/{shortCode}/tags": {
"$ref": "paths/v1_short-urls_{shortCode}_tags.json"
},
"/rest/v1/tags": {
"$ref": "paths/v1_tags.json"
},
"/rest/v1/short-urls/{shortCode}/visits": {
"$ref": "paths/v1_short-urls_{shortCode}_visits.json"
},
"/rest/health": {
"$ref": "paths/health.json"
},
"/{shortCode}": {
"$ref": "paths/{shortCode}.json"
},
"/{shortCode}/track": {
"$ref": "paths/{shortCode}_track.json"
},
"/{shortCode}/qr-code": {
"$ref": "paths/{shortCode}_qr-code.json"
},
"/{shortCode}/preview": {
"$ref": "paths/{shortCode}_preview.json"
},
"/rest/v1/authenticate": {
"$ref": "paths/v1_authenticate.json"
}
}
}

8
indocker Executable file
View File

@@ -0,0 +1,8 @@
#!/usr/bin/env bash
# Run docker containers if they are not up yet
if ! [[ $(docker ps | grep shlink_swoole) ]]; then
docker-compose up -d
fi
docker exec -it shlink_swoole /bin/sh -c "$*"

22
infection.json Normal file
View File

@@ -0,0 +1,22 @@
{
"source": {
"directories": [
"module/*/src"
]
},
"timeout": 5,
"logs": {
"text": "build/infection/infection-log.txt",
"summary": "build/infection/summary-log.txt",
"debug": "build/infection/debug-log.txt"
},
"tmpDir": "build/infection/temp",
"phpUnit": {
"configDir": "."
},
"mutators": {
"@default": true,
"IdenticalEqual": false,
"NotIdenticalNotEqual": false
}
}

View File

@@ -2,3 +2,4 @@ name: ShlinkMigrations
migrations_namespace: ShlinkMigrations
table_name: migrations
migrations_directory: data/migrations
custom_template: data/migrations_template.txt

View File

@@ -1,23 +1,34 @@
<?php
use Shlinkio\Shlink\CLI\Command;
declare(strict_types=1);
namespace Shlinkio\Shlink\CLI;
return [
'cli' => [
'locale' => env('CLI_LOCALE', 'en'),
'commands' => [
Command\Shortcode\GenerateShortcodeCommand::class,
Command\Shortcode\ResolveUrlCommand::class,
Command\Shortcode\ListShortcodesCommand::class,
Command\Shortcode\GetVisitsCommand::class,
Command\Shortcode\GeneratePreviewCommand::class,
Command\Visit\ProcessVisitsCommand::class,
Command\Config\GenerateCharsetCommand::class,
Command\Config\GenerateSecretCommand::class,
Command\Api\GenerateKeyCommand::class,
Command\Api\DisableKeyCommand::class,
Command\Api\ListKeysCommand::class,
]
Command\ShortUrl\GenerateShortUrlCommand::NAME => Command\ShortUrl\GenerateShortUrlCommand::class,
Command\ShortUrl\ResolveUrlCommand::NAME => Command\ShortUrl\ResolveUrlCommand::class,
Command\ShortUrl\ListShortUrlsCommand::NAME => Command\ShortUrl\ListShortUrlsCommand::class,
Command\ShortUrl\GetVisitsCommand::NAME => Command\ShortUrl\GetVisitsCommand::class,
Command\ShortUrl\GeneratePreviewCommand::NAME => Command\ShortUrl\GeneratePreviewCommand::class,
Command\ShortUrl\DeleteShortUrlCommand::NAME => Command\ShortUrl\DeleteShortUrlCommand::class,
Command\Visit\LocateVisitsCommand::NAME => Command\Visit\LocateVisitsCommand::class,
Command\Visit\UpdateDbCommand::NAME => Command\Visit\UpdateDbCommand::class,
Command\Config\GenerateCharsetCommand::NAME => Command\Config\GenerateCharsetCommand::class,
Command\Config\GenerateSecretCommand::NAME => Command\Config\GenerateSecretCommand::class,
Command\Api\GenerateKeyCommand::NAME => Command\Api\GenerateKeyCommand::class,
Command\Api\DisableKeyCommand::NAME => Command\Api\DisableKeyCommand::class,
Command\Api\ListKeysCommand::NAME => Command\Api\ListKeysCommand::class,
Command\Tag\ListTagsCommand::NAME => Command\Tag\ListTagsCommand::class,
Command\Tag\CreateTagCommand::NAME => Command\Tag\CreateTagCommand::class,
Command\Tag\RenameTagCommand::NAME => Command\Tag\RenameTagCommand::class,
Command\Tag\DeleteTagsCommand::NAME => Command\Tag\DeleteTagsCommand::class,
],
],
];

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