mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-22 12:48:24 +03:00
First commit
This commit is contained in:
commit
901fbd61a3
21 changed files with 525 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
build
|
||||
composer.lock
|
||||
vendor/
|
28
.travis.yml
Normal file
28
.travis.yml
Normal file
|
@ -0,0 +1,28 @@
|
|||
sudo: false
|
||||
|
||||
language: php
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- php: 5.5
|
||||
- php: 5.6
|
||||
env:
|
||||
- EXECUTE_CS_CHECK=true
|
||||
- php: 7
|
||||
- php: hhvm
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
|
||||
before_install:
|
||||
- composer self-update
|
||||
|
||||
install:
|
||||
- travis_retry composer install --no-interaction --ignore-platform-reqs --prefer-source --no-scripts
|
||||
|
||||
script:
|
||||
- composer test
|
||||
- if [[ $EXECUTE_CS_CHECK == 'true' ]]; then composer cs ; fi
|
||||
|
||||
notifications:
|
||||
email: true
|
52
composer.json
Normal file
52
composer.json
Normal file
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
"name": "acelaya/url-shortener",
|
||||
"type": "project",
|
||||
"homepage": "https://github.com/acelaya/url-shortener",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alejandro Celaya ALastrué",
|
||||
"homepage": "http://www.alejandrocelaya.com",
|
||||
"email": "alejandro@alejandrocelaya.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^5.5 || ^7.0",
|
||||
"zendframework/zend-expressive": "^1.0",
|
||||
"zendframework/zend-expressive-helpers": "^2.0",
|
||||
"zendframework/zend-stdlib": "^2.7",
|
||||
"zendframework/zend-expressive-aurarouter": "^1.0",
|
||||
"zendframework/zend-servicemanager": "^3.0",
|
||||
"zendframework/zend-expressive-twigrenderer": "^1.0",
|
||||
"acelaya/expressive-slim-router": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8",
|
||||
"squizlabs/php_codesniffer": "^2.3",
|
||||
"roave/security-advisories": "dev-master",
|
||||
"filp/whoops": "^2.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "src/App/",
|
||||
"Acelaya\\UrlShortener\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"AppTest\\": "tests/AppTest/",
|
||||
"AcelayaTest\\UrlShortener\\": "tests"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"check": [
|
||||
"@cs",
|
||||
"@test"
|
||||
],
|
||||
"cs": "phpcs",
|
||||
"cs-fix": "phpcbf",
|
||||
"serve": "php -S 0.0.0.0:8000 -t public/",
|
||||
"test": "phpunit",
|
||||
"pretty-test": "phpunit -c tests/phpunit.xml --coverage-html build/coverage"
|
||||
}
|
||||
}
|
2
config/autoload/.gitignore
vendored
Normal file
2
config/autoload/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
local.php
|
||||
*.local.php
|
7
config/autoload/local.php.dist
Normal file
7
config/autoload/local.php.dist
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'debug' => true,
|
||||
|
||||
'config_cache_enabled' => false,
|
||||
];
|
30
config/autoload/middleware-pipeline.global.php
Normal file
30
config/autoload/middleware-pipeline.global.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
use Zend\Expressive\Container\ApplicationFactory;
|
||||
use Zend\Expressive\Helper;
|
||||
|
||||
return [
|
||||
|
||||
'middleware_pipeline' => [
|
||||
'always' => [
|
||||
'middleware' => [
|
||||
Helper\ServerUrlMiddleware::class,
|
||||
],
|
||||
'priority' => 10000,
|
||||
],
|
||||
|
||||
'routing' => [
|
||||
'middleware' => [
|
||||
ApplicationFactory::ROUTING_MIDDLEWARE,
|
||||
Helper\UrlHelperMiddleware::class,
|
||||
ApplicationFactory::DISPATCH_MIDDLEWARE,
|
||||
],
|
||||
'priority' => 1,
|
||||
],
|
||||
|
||||
'error' => [
|
||||
'middleware' => [],
|
||||
'error' => true,
|
||||
'priority' => -10000,
|
||||
],
|
||||
],
|
||||
];
|
17
config/autoload/routes.global.php
Normal file
17
config/autoload/routes.global.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'routes' => [
|
||||
[
|
||||
'name' => 'home',
|
||||
'path' => '/',
|
||||
'middleware' => function ($req, $resp) {
|
||||
$resp->getBody()->write('Hello world');
|
||||
return $resp;
|
||||
},
|
||||
'allowed_methods' => ['GET'],
|
||||
],
|
||||
],
|
||||
|
||||
];
|
29
config/autoload/services.global.php
Normal file
29
config/autoload/services.global.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
use Zend\Expressive\Application;
|
||||
use Zend\Expressive\Container;
|
||||
use Zend\Expressive\Helper;
|
||||
use Zend\Expressive\Router;
|
||||
use Zend\Expressive\Template;
|
||||
|
||||
return [
|
||||
|
||||
'services' => [
|
||||
'invokables' => [
|
||||
Helper\ServerUrlHelper::class => Helper\ServerUrlHelper::class,
|
||||
Router\RouterInterface::class => Router\AuraRouter::class,
|
||||
],
|
||||
'factories' => [
|
||||
Application::class => Container\ApplicationFactory::class,
|
||||
|
||||
// Url helpers
|
||||
Helper\UrlHelper::class => Helper\UrlHelperFactory::class,
|
||||
Helper\ServerUrlMiddleware::class => Helper\ServerUrlMiddlewareFactory::class,
|
||||
Helper\UrlHelperMiddleware::class => Helper\UrlHelperMiddlewareFactory::class,
|
||||
|
||||
// View
|
||||
'Zend\Expressive\FinalHandler' => Container\TemplatedErrorHandlerFactory::class,
|
||||
Template\TemplateRendererInterface::class => Zend\Expressive\Twig\TwigRendererFactory::class,
|
||||
],
|
||||
],
|
||||
|
||||
];
|
16
config/autoload/templates.global.php
Normal file
16
config/autoload/templates.global.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'templates' => [
|
||||
'extension' => 'html.twig',
|
||||
],
|
||||
|
||||
'twig' => [
|
||||
'cache_dir' => 'data/cache/twig',
|
||||
'extensions' => [
|
||||
// extension service names or instances
|
||||
],
|
||||
],
|
||||
|
||||
];
|
9
config/autoload/templates.local.php.dist
Normal file
9
config/autoload/templates.local.php.dist
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'twig' => [
|
||||
'cache_dir' => false,
|
||||
],
|
||||
|
||||
];
|
14
config/autoload/zend-expressive.global.php
Normal file
14
config/autoload/zend-expressive.global.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'debug' => false,
|
||||
|
||||
'config_cache_enabled' => false,
|
||||
|
||||
'zend-expressive' => [
|
||||
'error_handler' => [
|
||||
'template_404' => 'error/404.html.twig',
|
||||
'template_error' => 'error/error.html.twig',
|
||||
],
|
||||
],
|
||||
];
|
35
config/config.php
Normal file
35
config/config.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Zend\Stdlib\ArrayUtils;
|
||||
use Zend\Stdlib\Glob;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
$cachedConfigFile = 'data/cache/app_config.php';
|
||||
|
||||
$config = [];
|
||||
if (is_file($cachedConfigFile)) {
|
||||
// Try to load the cached config
|
||||
$config = include $cachedConfigFile;
|
||||
} else {
|
||||
// Load configuration from autoload path
|
||||
foreach (Glob::glob('config/autoload/{{,*.}global,{,*.}local}.php', Glob::GLOB_BRACE) as $file) {
|
||||
$config = ArrayUtils::merge($config, include $file);
|
||||
}
|
||||
|
||||
// Cache config if enabled
|
||||
if (isset($config['config_cache_enabled']) && $config['config_cache_enabled'] === true) {
|
||||
file_put_contents($cachedConfigFile, '<?php return ' . var_export($config, true) . ';');
|
||||
}
|
||||
}
|
||||
|
||||
// Return an ArrayObject so we can inject the config as a service in Aura.Di
|
||||
// and still use array checks like ``is_array``.
|
||||
return new ArrayObject($config, ArrayObject::ARRAY_AS_PROPS);
|
16
config/container.php
Normal file
16
config/container.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
use Zend\ServiceManager\Config;
|
||||
use Zend\ServiceManager\ServiceManager;
|
||||
|
||||
// Load configuration
|
||||
$config = require __DIR__ . '/config.php';
|
||||
|
||||
// Build container
|
||||
$container = new ServiceManager();
|
||||
(new Config($config['services']))->configureServiceManager($container);
|
||||
|
||||
// Inject config
|
||||
$container->setService('config', $config);
|
||||
|
||||
return $container;
|
2
data/.gitignore
vendored
Normal file
2
data/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
23
phpcs.xml
Normal file
23
phpcs.xml
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0"?>
|
||||
<ruleset name="Coding standard">
|
||||
<description>Coding standard</description>
|
||||
|
||||
<!-- display progress -->
|
||||
<arg value="p"/>
|
||||
<arg name="colors"/>
|
||||
|
||||
<!-- inherit rules from: -->
|
||||
<rule ref="PSR2"/>
|
||||
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
|
||||
<rule ref="Squiz.WhiteSpace.SuperfluousWhitespace">
|
||||
<properties>
|
||||
<property name="ignoreBlankLines" value="false"/>
|
||||
</properties>
|
||||
</rule>
|
||||
|
||||
<!-- Paths to check -->
|
||||
<file>src</file>
|
||||
<file>tests</file>
|
||||
<file>config</file>
|
||||
<file>public/index.php</file>
|
||||
</ruleset>
|
13
phpunit.xml.dist
Normal file
13
phpunit.xml.dist
Normal file
|
@ -0,0 +1,13 @@
|
|||
<phpunit bootstrap="./vendor/autoload.php" colors="true">
|
||||
<testsuites>
|
||||
<testsuite name="App\\Tests">
|
||||
<directory>./test</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
11
public/index.php
Normal file
11
public/index.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
chdir(dirname(__DIR__));
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
/** @var \Interop\Container\ContainerInterface $container */
|
||||
$container = require 'config/container.php';
|
||||
|
||||
/** @var \Zend\Expressive\Application $app */
|
||||
$app = $container->get(\Zend\Expressive\Application::class);
|
||||
$app->run();
|
113
templates/app/home-page.html.twig
Normal file
113
templates/app/home-page.html.twig
Normal file
|
@ -0,0 +1,113 @@
|
|||
{% extends '@layout/default.html.twig' %}
|
||||
|
||||
{% block title %}Home{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="jumbotron">
|
||||
<h1>Welcome to <span class="zf-green">zend-expressive</span></h1>
|
||||
<p>
|
||||
Congratulations! You have successfully installed the
|
||||
<a href="https://github.com/zendframework/zend-expressive-skeleton" target="_blank">zend-expressive skeleton application</a>.
|
||||
This skeleton can serve as a simple starting point for you to begin building your application.
|
||||
</p>
|
||||
<p>
|
||||
Expressive builds on zend-stratigility to provide a minimalist PSR-7 middleware framework for PHP.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<h2>
|
||||
<a href="https://zendframework.github.io/zend-expressive/getting-started/features/" target="_blank">
|
||||
<i class="fa fa-refresh"></i> Agile & Lean
|
||||
</a>
|
||||
</h2>
|
||||
<p>
|
||||
Expressive is fast, small and perfect for rapid application development, prototyping and api's. You decide how you
|
||||
extend it and choose the best packages from major framework or standalone projects.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<h2>
|
||||
<a href="https://github.com/zendframework/zend-diactoros" target="_blank">
|
||||
<i class="fa fa-exchange"></i> HTTP Messages
|
||||
</a>
|
||||
</h2>
|
||||
<p>
|
||||
HTTP messages are the foundation of web development. Web browsers and HTTP clients such as cURL create
|
||||
HTTP request messages that are sent to a web server, which provides an HTTP response message.
|
||||
Server-side code receives an HTTP request message, and returns an HTTP response message.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<h2>
|
||||
<a href="https://github.com/zendframework/zend-stratigility" target="_blank">
|
||||
<i class="fa fa-dot-circle-o"></i> Middleware
|
||||
</a>
|
||||
</h2>
|
||||
<p>
|
||||
Middleware is code that exists between the request and response, and which can take the incoming
|
||||
request, perform actions based on it, and either complete the response or pass delegation on to the
|
||||
next middleware in the queue. Your application is easily extended with custom middleware created by
|
||||
yourself or <a href="https://packagist.org/search/?q=middleware" target="_blank">others</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<h2>
|
||||
<a href="https://zendframework.github.io/zend-expressive/features/container/intro/" target="_blank">
|
||||
<i class="fa fa-cube"></i> Containers
|
||||
</a>
|
||||
</h2>
|
||||
<p>
|
||||
Expressive promotes and advocates the usage of Dependency Injection/Inversion of Control containers
|
||||
when writing your applications. Expressive supports multiple containers which typehints against
|
||||
<a href="https://github.com/container-interop/container-interop" target="_blank">container-interop</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<h2>
|
||||
<a href="https://zendframework.github.io/zend-expressive/features/router/intro/" target="_blank">
|
||||
<i class="fa fa-plane"></i> Routers
|
||||
</a>
|
||||
</h2>
|
||||
<p>
|
||||
One fundamental feature of zend-expressive is that it provides mechanisms for implementing dynamic
|
||||
routing, a feature required in most modern web applications. Expressive ships with multiple adapters.
|
||||
</p>
|
||||
{% if routerName is defined %}
|
||||
<p>
|
||||
<a href="{{ routerDocs }}" target="_blank">
|
||||
Get started with {{ routerName }}.
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<h2>
|
||||
<a href="https://zendframework.github.io/zend-expressive/features/template/twig/" target="_blank">
|
||||
<i class="fa fa-files-o"></i> Templating
|
||||
</a>
|
||||
</h2>
|
||||
<p>
|
||||
By default, no middleware in Expressive is templated. We do not even provide a default templating
|
||||
engine, as the choice of templating engine is often very specific to the project and/or organization.
|
||||
However, Expressive does provide abstraction for templating, which allows you to write middleware that
|
||||
is engine-agnostic.
|
||||
</p>
|
||||
{% if templateName is defined %}
|
||||
<p>
|
||||
<a href="{{ templateDocs }}" target="_blank">
|
||||
Get started with {{ templateName }}.
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
13
templates/error/404.html.twig
Normal file
13
templates/error/404.html.twig
Normal file
|
@ -0,0 +1,13 @@
|
|||
{% extends 'layout/default.html.twig' %}
|
||||
|
||||
{% block title %}404 Not Found{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Oops!</h1>
|
||||
<h2>This is awkward.</h2>
|
||||
<p>We encountered a 404 Not Found error.</p>
|
||||
<p>
|
||||
You are looking for something that doesn't exist or may have moved. Check out one of the links on this page
|
||||
or head back to <a href="{{ path('home') }}">Home</a>.
|
||||
</p>
|
||||
{% endblock %}
|
15
templates/error/error.html.twig
Normal file
15
templates/error/error.html.twig
Normal file
|
@ -0,0 +1,15 @@
|
|||
{% extends 'layout/default.html.twig' %}
|
||||
|
||||
{% block title %}{{ status }} {{ reason }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Oops!</h1>
|
||||
<h2>This is awkward.</h2>
|
||||
<p>We encountered a {{ status }} {{ reason }} error.</p>
|
||||
{% if status == 404 %}
|
||||
<p>
|
||||
You are looking for something that doesn't exist or may have moved. Check out one of the links on this page
|
||||
or head back to <a href="{{ path('home') }}">Home</a>.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
77
templates/layout/default.html.twig
Normal file
77
templates/layout/default.html.twig
Normal file
|
@ -0,0 +1,77 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>{% block title %}{% endblock %} - zend-expressive</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" />
|
||||
<style>
|
||||
body { padding-top: 60px; }
|
||||
.app { display: flex; min-height: 100vh; flex-direction: column; }
|
||||
.app-content { flex: 1; }
|
||||
.app-footer { padding-bottom: 1em; }
|
||||
.zf-green, h2 a { color: #68b604; }
|
||||
</style>
|
||||
{% block stylesheets %}{% endblock %}
|
||||
</head>
|
||||
<body class="app">
|
||||
<header class="app-header">
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="{{ path('home') }}">
|
||||
<img src="{{ asset('zf-logo.png') }}" alt="Zend Expressive" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li>
|
||||
<a href="https://zendframework.github.io/zend-expressive/" target="_blank">
|
||||
<i class="fa fa-book"></i> Docs
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/zendframework/zend-expressive" target="_blank">
|
||||
<i class="fa fa-wrench"></i> Contribute
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('api.ping') }}">
|
||||
Ping Test
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<div class="app-content">
|
||||
<main class="container">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="app-footer">
|
||||
<div class="container">
|
||||
<hr />
|
||||
{% block footer %}
|
||||
<p>
|
||||
© 2005 - {{ "now"|date("Y") }} by Zend Technologies Ltd. All rights reserved.
|
||||
</p>
|
||||
{% endblock %}
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
{% block javascript %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue