First commit

This commit is contained in:
Alejandro Celaya 2016-04-10 09:38:07 +02:00
commit 901fbd61a3
21 changed files with 525 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
build
composer.lock
vendor/

28
.travis.yml Normal file
View 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
View 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
View file

@ -0,0 +1,2 @@
local.php
*.local.php

View file

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

View 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,
],
],
];

View 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'],
],
],
];

View 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,
],
],
];

View file

@ -0,0 +1,16 @@
<?php
return [
'templates' => [
'extension' => 'html.twig',
],
'twig' => [
'cache_dir' => 'data/cache/twig',
'extensions' => [
// extension service names or instances
],
],
];

View file

@ -0,0 +1,9 @@
<?php
return [
'twig' => [
'cache_dir' => false,
],
];

View 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
View 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
View 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
View file

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

23
phpcs.xml Normal file
View 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
View 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
View 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();

View 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 &amp; 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 %}

View 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 %}

View 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 %}

View 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>
&copy; 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>