Full Code of fabpot/Silex for AI

master f9eadbcd1836 cached
168 files
545.5 KB
131.2k tokens
628 symbols
10 requests
Download .txt
Showing preview only (592K chars total). Download the full file or copy to clipboard to get everything.
Repository: fabpot/Silex
Branch: master
Commit: f9eadbcd1836
Files: 168
Total size: 545.5 KB

Directory structure:
gitextract_b59cn358/

├── .gitignore
├── .travis.yml
├── LICENSE
├── README.rst
├── bin/
│   ├── build
│   └── skeleton/
│       ├── fat_composer.json
│       ├── index.php
│       └── slim_composer.json
├── composer.json
├── doc/
│   ├── changelog.rst
│   ├── conf.py
│   ├── contributing.rst
│   ├── cookbook/
│   │   ├── error_handler.rst
│   │   ├── form_no_csrf.rst
│   │   ├── guard_authentication.rst
│   │   ├── index.rst
│   │   ├── json_request_body.rst
│   │   ├── multiple_loggers.rst
│   │   ├── session_storage.rst
│   │   ├── sub_requests.rst
│   │   └── validator_yaml.rst
│   ├── index.rst
│   ├── internals.rst
│   ├── intro.rst
│   ├── middlewares.rst
│   ├── organizing_controllers.rst
│   ├── providers/
│   │   ├── asset.rst
│   │   ├── csrf.rst
│   │   ├── doctrine.rst
│   │   ├── form.rst
│   │   ├── http_cache.rst
│   │   ├── http_fragment.rst
│   │   ├── index.rst
│   │   ├── locale.rst
│   │   ├── monolog.rst
│   │   ├── remember_me.rst
│   │   ├── security.rst
│   │   ├── serializer.rst
│   │   ├── service_controller.rst
│   │   ├── session.rst
│   │   ├── swiftmailer.rst
│   │   ├── translation.rst
│   │   ├── twig.rst
│   │   ├── validator.rst
│   │   └── var_dumper.rst
│   ├── providers.rst
│   ├── services.rst
│   ├── testing.rst
│   ├── usage.rst
│   └── web_servers.rst
├── phpunit.xml.dist
├── src/
│   └── Silex/
│       ├── Api/
│       │   ├── BootableProviderInterface.php
│       │   ├── ControllerProviderInterface.php
│       │   ├── EventListenerProviderInterface.php
│       │   ├── LICENSE
│       │   └── composer.json
│       ├── AppArgumentValueResolver.php
│       ├── Application/
│       │   ├── FormTrait.php
│       │   ├── MonologTrait.php
│       │   ├── SecurityTrait.php
│       │   ├── SwiftmailerTrait.php
│       │   ├── TranslationTrait.php
│       │   ├── TwigTrait.php
│       │   └── UrlGeneratorTrait.php
│       ├── Application.php
│       ├── CallbackResolver.php
│       ├── Controller.php
│       ├── ControllerCollection.php
│       ├── ControllerResolver.php
│       ├── EventListener/
│       │   ├── ConverterListener.php
│       │   ├── LogListener.php
│       │   ├── MiddlewareListener.php
│       │   └── StringToResponseListener.php
│       ├── Exception/
│       │   └── ControllerFrozenException.php
│       ├── ExceptionHandler.php
│       ├── ExceptionListenerWrapper.php
│       ├── Provider/
│       │   ├── AssetServiceProvider.php
│       │   ├── CsrfServiceProvider.php
│       │   ├── DoctrineServiceProvider.php
│       │   ├── ExceptionHandlerServiceProvider.php
│       │   ├── Form/
│       │   │   └── SilexFormExtension.php
│       │   ├── FormServiceProvider.php
│       │   ├── HttpCache/
│       │   │   └── HttpCache.php
│       │   ├── HttpCacheServiceProvider.php
│       │   ├── HttpFragmentServiceProvider.php
│       │   ├── HttpKernelServiceProvider.php
│       │   ├── LICENSE
│       │   ├── Locale/
│       │   │   └── LocaleListener.php
│       │   ├── LocaleServiceProvider.php
│       │   ├── MonologServiceProvider.php
│       │   ├── RememberMeServiceProvider.php
│       │   ├── Routing/
│       │   │   ├── LazyRequestMatcher.php
│       │   │   └── RedirectableUrlMatcher.php
│       │   ├── RoutingServiceProvider.php
│       │   ├── SecurityServiceProvider.php
│       │   ├── SerializerServiceProvider.php
│       │   ├── ServiceControllerServiceProvider.php
│       │   ├── Session/
│       │   │   ├── SessionListener.php
│       │   │   └── TestSessionListener.php
│       │   ├── SessionServiceProvider.php
│       │   ├── SwiftmailerServiceProvider.php
│       │   ├── TranslationServiceProvider.php
│       │   ├── TwigServiceProvider.php
│       │   ├── Validator/
│       │   │   └── ConstraintValidatorFactory.php
│       │   ├── ValidatorServiceProvider.php
│       │   ├── VarDumperServiceProvider.php
│       │   └── composer.json
│       ├── Route/
│       │   └── SecurityTrait.php
│       ├── Route.php
│       ├── ServiceControllerResolver.php
│       ├── ViewListenerWrapper.php
│       └── WebTestCase.php
└── tests/
    └── Silex/
        └── Tests/
            ├── Application/
            │   ├── FormApplication.php
            │   ├── FormTraitTest.php
            │   ├── MonologApplication.php
            │   ├── MonologTraitTest.php
            │   ├── SecurityApplication.php
            │   ├── SecurityTraitTest.php
            │   ├── SwiftmailerApplication.php
            │   ├── SwiftmailerTraitTest.php
            │   ├── TranslationApplication.php
            │   ├── TranslationTraitTest.php
            │   ├── TwigApplication.php
            │   ├── TwigTraitTest.php
            │   ├── UrlGeneratorApplication.php
            │   └── UrlGeneratorTraitTest.php
            ├── ApplicationTest.php
            ├── CallbackResolverTest.php
            ├── CallbackServicesTest.php
            ├── ControllerCollectionTest.php
            ├── ControllerResolverTest.php
            ├── ControllerTest.php
            ├── EventListener/
            │   └── LogListenerTest.php
            ├── ExceptionHandlerTest.php
            ├── Fixtures/
            │   └── Php7Controller.php
            ├── FunctionalTest.php
            ├── JsonTest.php
            ├── LazyDispatcherTest.php
            ├── LazyRequestMatcherTest.php
            ├── LocaleTest.php
            ├── MiddlewareTest.php
            ├── Provider/
            │   ├── AssetServiceProviderTest.php
            │   ├── DoctrineServiceProviderTest.php
            │   ├── FormServiceProviderTest/
            │   │   └── DisableCsrfExtension.php
            │   ├── FormServiceProviderTest.php
            │   ├── HttpCacheServiceProviderTest.php
            │   ├── HttpFragmentServiceProviderTest.php
            │   ├── MonologServiceProviderTest.php
            │   ├── RememberMeServiceProviderTest.php
            │   ├── RoutingServiceProviderTest.php
            │   ├── SecurityServiceProviderTest/
            │   │   └── TokenAuthenticator.php
            │   ├── SecurityServiceProviderTest.php
            │   ├── SerializerServiceProviderTest.php
            │   ├── SessionServiceProviderTest.php
            │   ├── SpoolStub.php
            │   ├── SwiftmailerServiceProviderTest.php
            │   ├── TranslationServiceProviderTest.php
            │   ├── TwigServiceProviderTest.php
            │   ├── ValidatorServiceProviderTest/
            │   │   └── Constraint/
            │   │       ├── Custom.php
            │   │       └── CustomValidator.php
            │   └── ValidatorServiceProviderTest.php
            ├── Route/
            │   ├── SecurityRoute.php
            │   └── SecurityTraitTest.php
            ├── RouterTest.php
            ├── ServiceControllerResolverRouterTest.php
            ├── ServiceControllerResolverTest.php
            ├── StreamTest.php
            └── WebTestCaseTest.php

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
/phpunit.xml
/vendor
/build
/composer.lock



================================================
FILE: .travis.yml
================================================
language: php

sudo: false

env:
    global:
        - SYMFONY_DEPRECATIONS_HELPER=weak

cache:
    directories:
      - $HOME/.composer/cache

before_install:
    - if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then phpenv config-rm xdebug.ini; fi

before_script:
    # symfony/*
    - sh -c "if [ '$TWIG_VERSION' != '2.0' ]; then sed -i 's/~1.8|~2.0/~1.8/g' composer.json; composer update; fi"
    - sh -c "if [ '$SYMFONY_DEPS_VERSION' = '3.0' ]; then sed -i 's/~2\.8|^3\.0/3.0.*@dev/g' composer.json; composer update; fi"
    - sh -c "if [ '$SYMFONY_DEPS_VERSION' = '3.1' ]; then sed -i 's/~2\.8|^3\.0/3.1.*@dev/g' composer.json; composer update; fi"
    - sh -c "if [ '$SYMFONY_DEPS_VERSION' = '' ]; then sed -i 's/~2\.8|^3\.0/2.8.*@dev/g' composer.json; composer update; fi"
    - composer install

script: phpunit

matrix:
    include:
        - php: 5.5
        - php: 5.6
          env: TWIG_VERSION=2.0
        - php: 5.6
          env: SYMFONY_DEPS_VERSION=3.0
        - php: 5.6
          env: SYMFONY_DEPS_VERSION=3.1
        - php: 7.0
        - php: hhvm


================================================
FILE: LICENSE
================================================
Copyright (c) 2010-2016 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: README.rst
================================================
Silex, a simple Web Framework
=============================

Silex is a PHP micro-framework to develop websites based on `Symfony
components`_::

    <?php

    require_once __DIR__.'/../vendor/autoload.php';

    $app = new Silex\Application();

    $app->get('/hello/{name}', function ($name) use ($app) {
      return 'Hello '.$app->escape($name);
    });

    $app->run();

Silex works with PHP 5.5.9 or later.

Installation
------------

The recommended way to install Silex is through `Composer`_:

.. code-block:: bash

    composer require silex/silex "~2.0"

Alternatively, you can download the `silex.zip`_ file and extract it.

More Information
----------------

Read the `documentation`_ for more information and `changelog
<doc/changelog.rst>`_ for upgrading information.

Tests
-----

To run the test suite, you need `Composer`_ and `PHPUnit`_:

.. code-block:: bash

    $ composer install
    $ phpunit

Community
---------

Check out #silex-php on irc.freenode.net.

License
-------

Silex is licensed under the MIT license.

.. _Symfony components: http://symfony.com
.. _Composer:           http://getcomposer.org
.. _PHPUnit:            https://phpunit.de
.. _silex.zip:          http://silex.sensiolabs.org/download
.. _documentation:      http://silex.sensiolabs.org/documentation


================================================
FILE: bin/build
================================================
#!/bin/sh

PHP=`which php`
GIT=`which git`
DIR=`$PHP -r "echo dirname(dirname(realpath('$0')));"`

if [ ! -d "$DIR/build" ]; then
    mkdir -p $DIR/build
fi

cd $DIR/build

if [ ! -f "composer.phar" ]; then
    curl -s http://getcomposer.org/installer 2>/dev/null | $PHP >/dev/null 2>/dev/null
else
    $PHP composer.phar self-update >/dev/null 2>/dev/null
fi

for TYPE in slim fat
do
    if [ -d "$DIR/build/skeleton" ]; then
        rm -rf $DIR/build/skeleton
    fi
    mkdir -p $DIR/build/skeleton

    cd "$DIR/build/skeleton"

    mkdir -p web/
    COMPOSER=$TYPE"_composer.json"
    cp $DIR/bin/skeleton/$COMPOSER composer.json
    cp $DIR/bin/skeleton/index.php web/index.php

    $PHP ../composer.phar install -q

    if [ -d "$DIR/build/tmp/silex" ]; then
        rm -rf $DIR/build/tmp/silex
    fi
    mkdir -p $DIR/build/tmp/silex

    cd "$DIR/build/tmp/silex"
    cp -r ../../skeleton/* .

    find . -name .DS_Store | xargs rm -rf -
    find . -name .git | xargs rm -rf -
    find . -name phpunit.xml.* | xargs rm -rf -
    find . -type d -name Tests | xargs rm -rf -
    find . -type d -name test* | xargs rm -rf -
    find . -type d -name doc | xargs rm -rf -
    find . -type d -name ext | xargs rm -rf -

    export COPY_EXTENDED_ATTRIBUTES_DISABLE=true
    export COPYFILE_DISABLE=true

    cd "$DIR/build/tmp"

    if [ "slim" = "$TYPE" ]; then
        NAME="silex"
    else
        NAME="silex_fat"
    fi

    rm -f "$DIR/build/$NAME.*"
    tar zcpf "$DIR/build/$NAME.tgz" silex
    zip -rq "$DIR/build/$NAME.zip" silex
    rm -rf "$DIR/build/tmp"
    rm -rf "$DIR/build/skeleton"
done


================================================
FILE: bin/skeleton/fat_composer.json
================================================
{
    "require": {
        "silex/silex": "~1.1",
        "symfony/browser-kit": "~2.3",
        "symfony/console": "~2.3",
        "symfony/config": "~2.3",
        "symfony/css-selector": "~2.3",
        "symfony/dom-crawler": "~2.3",
        "symfony/filesystem": "~2.3",
        "symfony/finder": "~2.3",
        "symfony/form": "~2.3",
        "symfony/locale": "~2.3",
        "symfony/process": "~2.3",
        "symfony/security": "~2.3",
        "symfony/serializer": "~2.3",
        "symfony/translation": "~2.3",
        "symfony/validator": "~2.3",
        "symfony/monolog-bridge": "~2.3",
        "symfony/twig-bridge": "~2.3",
        "doctrine/dbal": ">=2.2.0,<2.4.0-dev",
        "swiftmailer/swiftmailer": "5.*"
    }
}


================================================
FILE: bin/skeleton/index.php
================================================
<?php

require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

$app->get('/hello', function () {
    return 'Hello!';
});

$app->run();


================================================
FILE: bin/skeleton/slim_composer.json
================================================
{
    "require": {
        "silex/silex": "~1.1"
    }
}


================================================
FILE: composer.json
================================================
{
    "name": "silex/silex",
    "description": "The PHP micro-framework based on the Symfony Components",
    "keywords": ["microframework"],
    "homepage": "http://silex.sensiolabs.org",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Igor Wiedler",
            "email": "igor@wiedler.ch"
        }
    ],
    "require": {
        "php": ">=5.5.9",
        "pimple/pimple": "~3.0",
        "symfony/event-dispatcher": "~2.8|^3.0",
        "symfony/http-foundation": "~2.8|^3.0",
        "symfony/http-kernel": "~2.8|^3.0",
        "symfony/routing": "~2.8|^3.0"
    },
    "require-dev": {
        "symfony/asset": "~2.8|^3.0",
        "symfony/expression-language": "~2.8|^3.0",
        "symfony/security": "~2.8|^3.0",
        "symfony/config": "~2.8|^3.0",
        "symfony/form": "~2.8|^3.0",
        "symfony/browser-kit": "~2.8|^3.0",
        "symfony/css-selector": "~2.8|^3.0",
        "symfony/debug": "~2.8|^3.0",
        "symfony/dom-crawler": "~2.8|^3.0",
        "symfony/finder": "~2.8|^3.0",
        "symfony/intl": "~2.8|^3.0",
        "symfony/monolog-bridge": "~2.8|^3.0",
        "symfony/doctrine-bridge": "~2.8|^3.0",
        "symfony/options-resolver": "~2.8|^3.0",
        "symfony/phpunit-bridge": "~2.8|^3.0",
        "symfony/process": "~2.8|^3.0",
        "symfony/serializer": "~2.8|^3.0",
        "symfony/translation": "~2.8|^3.0",
        "symfony/twig-bridge": "~2.8|^3.0",
        "symfony/validator": "~2.8|^3.0",
        "symfony/var-dumper": "~2.8|^3.0",
        "twig/twig": "~1.8|~2.0",
        "doctrine/dbal": "~2.2",
        "swiftmailer/swiftmailer": "~5",
        "monolog/monolog": "^1.4.1"
    },
    "replace": {
        "silex/api": "self.version",
        "silex/providers": "self.version"
    },
    "autoload": {
        "psr-4": { "Silex\\": "src/Silex" }
    },
    "autoload-dev" : {
        "psr-4": { "Silex\\Tests\\" : "tests/Silex/Tests" }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.0.x-dev"
        }
    },
    "minimum-stability": "dev"
}


================================================
FILE: doc/changelog.rst
================================================
Changelog
=========

2.0.4 (2016-XX-XX)
------------------

* n/a

2.0.3 (2016-08-22)
------------------

* fixed lazy evaluation of 'monolog.use_error_handler'
* fixed PHP7 type hint on controllers

2.0.2 (2016-06-14)
------------------

* fixed Symfony 3.1 deprecations

2.0.1 (2016-05-27)
------------------

* fixed the silex form extension registration to allow overriding default ones
* removed support for the obsolete Locale Symfony component (uses the Intl one now)
* added support for Symfony 3.1

2.0.0 (2016-05-18)
------------------

* decoupled the exception handler from HttpKernelServiceProvider
* Switched to BCrypt as the default encoder in the security provider
* added full support for RequestMatcher
* added support for Symfony Guard
* added support for callables in CallbackResolver
* added FormTrait::namedForm()
* added support for delivery_addresses, delivery_whitelist, and sender_address
* added support to register form types / form types extensions / form types guessers as services
* added support for callable in mounts (allow nested route collection to be built easily)
* added support for conditions on routes
* added support for the Symfony VarDumper Component
* added a global Twig variable (an AppVariable instance)
* [BC BREAK] CSRF has been moved to a standalone provider (``form.secret`` is not available anymore)
* added support for the Symfony HttpFoundation Twig bridge extension
* added support for the Symfony Asset Component
* bumped minimum version of Symfony to 2.8
* bumped minimum version of PHP to 5.5.0
* Updated Pimple to 3.0
* Updated session listeners to extends HttpKernel ones
* [BC BREAK] Locale management has been moved to LocaleServiceProvider which must be registered
  if you want Silex to manage your locale (must also be registered for the translation service provider)
* [BC BREAK] Provider interfaces moved to Silex\Api namespace, published as
  separate package via subtree split
* [BC BREAK] ServiceProviderInterface split in to EventListenerProviderInterface
  and BootableProviderInterface
* [BC BREAK] Service Provider support files moved under Silex\Provider
  namespace, allowing publishing as separate package via sub-tree split
* ``monolog.exception.logger_filter`` option added to Monolog service provider
* [BC BREAK] ``$app['request']`` service removed, use ``$app['request_stack']`` instead

1.3.6 (2016-XX-XX)
------------------

* n/a

1.3.5 (2016-01-06)
------------------

* fixed typo in SecurityServiceProvider

1.3.4 (2015-09-15)
------------------

* fixed some new deprecations
* fixed translation registration for the validators

1.3.3 (2015-09-08)
------------------

* added support for Symfony 3.0 and Twig 2.0
* fixed some Form deprecations
* removed deprecated method call in the exception handler
* fixed Swiftmailer spool flushing when spool is not enabled

1.3.2 (2015-08-24)
------------------

* no changes

1.3.1 (2015-08-04)
------------------

* added missing support for the Expression constraint
* fixed the possibility to override translations for validator error messages
* fixed sub-mounts with same name clash
* fixed session logout handler when a firewall is stateless

1.3.0 (2015-06-05)
------------------

* added a `$app['user']` to get the current user (security provider)
* added view handlers
* added support for the OPTIONS HTTP method
* added caching for the Translator provider
* deprecated `$app['exception_handler']->disable()` in favor of `unset($app['exception_handler'])`
* made Silex compatible with Symfony 2.7 an 2.8 (and keep compatibility with Symfony 2.3, 2.5, and 2.6)
* removed deprecated TwigCoreExtension class (register the new HttpFragmentServiceProvider instead)
* bumped minimum version of PHP to 5.3.9

1.2.5 (2015-06-04)
------------------

* no code changes (last version of the 1.2 branch)

1.2.4 (2015-04-11)
------------------

* fixed the exception message when mounting a collection that doesn't return a ControllerCollection
* fixed Symfony dependencies (Silex 1.2 is not compatible with Symfony 2.7)

1.2.3 (2015-01-20)
------------------

* fixed remember me listener
* fixed translation files loading when they do not exist
* allowed global after middlewares to return responses like route specific ones

1.2.2 (2014-09-26)
------------------

* fixed Translator locale management
* added support for the $app argument in application middlewares (to make it consistent with route middlewares)
* added form.types to the Form provider

1.2.1 (2014-07-01)
------------------

* added support permissions in the Monolog provider
* fixed Switfmailer spool where the event dispatcher is different from the other ones
* fixed locale when changing it on the translator itself

1.2.0 (2014-03-29)
------------------

* Allowed disabling the boot logic of MonologServiceProvider
* Reverted "convert attributes on the request that actually exist"
* [BC BREAK] Routes are now always added in the order of their registration (even for mounted routes)
* Added run() on Route to be able to define the controller code
* Deprecated TwigCoreExtension (register the new HttpFragmentServiceProvider instead)
* Added HttpFragmentServiceProvider
* Allowed a callback to be a method call on a service (before, after, finish, error, on Application; convert, before, after on Controller)

1.1.3 (2013-XX-XX)
------------------

* Fixed translator locale management

1.1.2 (2013-10-30)
------------------

* Added missing "security.hide_user_not_found" support in SecurityServiceProvider
* Fixed event listeners that are registered after the boot via the on() method

1.0.2 (2013-10-30)
------------------

* Fixed SecurityServiceProvider to use null as a fake controller so that routes can be dumped

1.1.1 (2013-10-11)
------------------

* Removed or replaced deprecated Symfony code
* Updated code to take advantages of 2.3 new features
* Only convert attributes on the request that actually exist.

1.1.0 (2013-07-04)
------------------

* Support for any ``Psr\Log\LoggerInterface`` as opposed to the monolog-bridge
  one.
* Made dispatcher proxy methods ``on``, ``before``, ``after`` and ``error``
  lazy, so that they will not instantiate the dispatcher early.
* Dropped support for 2.1 and 2.2 versions of Symfony.

1.0.1 (2013-07-04)
------------------

* Fixed RedirectableUrlMatcher::redirect() when Silex is configured to use a logger
* Make ``DoctrineServiceProvider`` multi-db support lazy.

1.0.0 (2013-05-03)
------------------

* **2013-04-12**: Added support for validators as services.

* **2013-04-01**: Added support for host matching with symfony 2.2::

      $app->match('/', function() {
          // app-specific action
      })->host('example.com');

      $app->match('/', function ($user) {
          // user-specific action
      })->host('{user}.example.com');

* **2013-03-08**: Added support for form type extensions and guessers as
  services.

* **2013-03-08**: Added support for remember-me via the
  ``RememberMeServiceProvider``.

* **2013-02-07**: Added ``Application::sendFile()`` to ease sending
  ``BinaryFileResponse``.

* **2012-11-05**: Filters have been renamed to application middlewares in the
  documentation.

* **2012-11-05**: The ``before()``, ``after()``, ``error()``, and ``finish()``
  listener priorities now set the priority of the underlying Symfony event
  instead of a custom one before.

* **2012-11-05**: Removing the default exception handler should now be done
  via its ``disable()`` method:

    Before:

        unset($app['exception_handler']);

    After:

        $app['exception_handler']->disable();

* **2012-07-15**: removed the ``monolog.configure`` service. Use the
  ``extend`` method instead:

    Before::

        $app['monolog.configure'] = $app->protect(function ($monolog) use ($app) {
            // do something
        });

    After::

        $app['monolog'] = $app->share($app->extend('monolog', function($monolog, $app) {
            // do something

            return $monolog;
        }));


* **2012-06-17**: ``ControllerCollection`` now takes a required route instance
  as a constructor argument.

    Before::

        $controllers = new ControllerCollection();

    After::

        $controllers = new ControllerCollection(new Route());

        // or even better
        $controllers = $app['controllers_factory'];

* **2012-06-17**: added application traits for PHP 5.4

* **2012-06-16**: renamed ``request.default_locale`` to ``locale``

* **2012-06-16**: Removed the ``translator.loader`` service. See documentation
  for how to use XLIFF or YAML-based translation files.

* **2012-06-15**: removed the ``twig.configure`` service. Use the ``extend``
  method instead:

    Before::

        $app['twig.configure'] = $app->protect(function ($twig) use ($app) {
            // do something
        });

    After::

        $app['twig'] = $app->share($app->extend('twig', function($twig, $app) {
            // do something

            return $twig;
        }));

* **2012-06-13**: Added a route ``before`` middleware

* **2012-06-13**: Renamed the route ``middleware`` to ``before``

* **2012-06-13**: Added an extension for the Symfony Security component

* **2012-05-31**: Made the ``BrowserKit``, ``CssSelector``, ``DomCrawler``,
  ``Finder`` and ``Process`` components optional dependencies. Projects that
  depend on them (e.g. through functional tests) should add those dependencies
  to their ``composer.json``.

* **2012-05-26**: added ``boot()`` to ``ServiceProviderInterface``.

* **2012-05-26**: Removed ``SymfonyBridgesServiceProvider``. It is now implicit
  by checking the existence of the bridge.

* **2012-05-26**: Removed the ``translator.messages`` parameter (use
  ``translator.domains`` instead).

* **2012-05-24**: Removed the ``autoloader`` service (use composer instead).
  The ``*.class_path`` settings on all the built-in providers have also been
  removed in favor of Composer.

* **2012-05-21**: Changed error() to allow handling specific exceptions.

* **2012-05-20**: Added a way to define settings on a controller collection.

* **2012-05-20**: The Request instance is not available anymore from the
  Application after it has been handled.

* **2012-04-01**: Added ``finish`` filters.

* **2012-03-20**: Added ``json`` helper::

        $data = array('some' => 'data');
        $response = $app->json($data);

* **2012-03-11**: Added route middlewares.

* **2012-03-02**: Switched to use Composer for dependency management.

* **2012-02-27**: Updated to Symfony 2.1 session handling.

* **2012-01-02**: Introduced support for streaming responses.

* **2011-09-22**: ``ExtensionInterface`` has been renamed to
  ``ServiceProviderInterface``. All built-in extensions have been renamed
  accordingly (for instance, ``Silex\Extension\TwigExtension`` has been
  renamed to ``Silex\Provider\TwigServiceProvider``).

* **2011-09-22**: The way reusable applications work has changed. The
  ``mount()`` method now takes an instance of ``ControllerCollection`` instead
  of an ``Application`` one.

    Before::

        $app = new Application();
        $app->get('/bar', function() { return 'foo'; });

        return $app;

    After::

        $app = new ControllerCollection();
        $app->get('/bar', function() { return 'foo'; });

        return $app;

* **2011-08-08**: The controller method configuration is now done on the Controller itself

    Before::

        $app->match('/', function () { echo 'foo'; }, 'GET|POST');

    After::

        $app->match('/', function () { echo 'foo'; })->method('GET|POST');


================================================
FILE: doc/conf.py
================================================
import sys, os
from sphinx.highlighting import lexers
from pygments.lexers.web import PhpLexer

sys.path.append(os.path.abspath('_exts'))

extensions = []
master_doc = 'index'
highlight_language = 'php'

project = u'Silex'
copyright = u'2010 Fabien Potencier'

version = '0'
release = '0.0.0'

lexers['php'] = PhpLexer(startinline=True)


================================================
FILE: doc/contributing.rst
================================================
Contributing
============

We are open to contributions to the Silex code. If you find a bug or want to
contribute a provider, just follow these steps:

* Fork `the Silex repository <https://github.com/silexphp/Silex>`_;

* Make your feature addition or bug fix;

* Add tests for it;

* Optionally, add some documentation;

* `Send a pull request
  <https://help.github.com/articles/creating-a-pull-request>`_, to the correct
  target branch (1.3 for bug fixes, master for new features).

.. note::

    Any code you contribute must be licensed under the MIT
    License.

Writing Documentation
=====================

The documentation is written in `reStructuredText
<http://docutils.sourceforge.net/rst.html>`_ and can be generated using `sphinx
<http://sphinx-doc.org>`_.

.. code-block:: bash

    $ cd doc
    $ sphinx-build -b html . build


================================================
FILE: doc/cookbook/error_handler.rst
================================================
Converting Errors to Exceptions
===============================

Silex catches exceptions that are thrown from within a request/response cycle.
However, it does *not* catch PHP errors and notices. This recipe tells you how
to catch them by converting them to exceptions.

Registering the ErrorHandler
----------------------------

The ``Symfony/Debug`` package has an ``ErrorHandler`` class that solves this
problem. It converts all errors to exceptions, and exceptions are then caught
by Silex.

Register it by calling the static ``register`` method::

    use Symfony\Component\Debug\ErrorHandler;

    ErrorHandler::register();

It is recommended that you do this as early as possible.

Handling fatal errors
---------------------

To handle fatal errors, you can additionally register a global
``ExceptionHandler``::

    use Symfony\Component\Debug\ExceptionHandler;

    ExceptionHandler::register();

In production you may want to disable the debug output by passing ``false`` as
the ``$debug`` argument::

    use Symfony\Component\Debug\ExceptionHandler;

    ExceptionHandler::register(false);


================================================
FILE: doc/cookbook/form_no_csrf.rst
================================================
Disabling CSRF Protection on a Form using the FormExtension
===========================================================

The *FormExtension* provides a service for building form in your application
with the Symfony Form component. When the :doc:`CSRF Service Provider
</providers/csrf>` is registered, the *FormExtension* uses the CSRF Protection
avoiding Cross-site request forgery, a method by which a malicious user
attempts to make your legitimate users unknowingly submit data that they don't
intend to submit.

You can find more details about CSRF Protection and CSRF token in the
`Symfony Book
<http://symfony.com/doc/current/book/forms.html#csrf-protection>`_.

In some cases (for example, when embedding a form in an html email) you might
want not to use this protection. The easiest way to avoid this is to
understand that it is possible to give specific options to your form builder
through the ``createBuilder()`` function.

Example
-------

.. code-block:: php

    $form = $app['form.factory']->createBuilder('form', null, array('csrf_protection' => false));

That's it, your form could be submitted from everywhere without CSRF Protection.

Going further
-------------

This specific example showed how to change the ``csrf_protection`` in the
``$options`` parameter of the ``createBuilder()`` function. More of them could
be passed through this parameter, it is as simple as using the Symfony
``getDefaultOptions()`` method in your form classes. `See more here
<http://symfony.com/doc/current/book/forms.html#book-form-creating-form-classes>`_.


================================================
FILE: doc/cookbook/guard_authentication.rst
================================================
How to Create a Custom Authentication System with Guard
=======================================================

Whether you need to build a traditional login form, an API token
authentication system or you need to integrate with some proprietary
single-sign-on system, the Guard component can make it easy... and fun!

In this example, you'll build an API token authentication system and
learn how to work with Guard.

Step 1) Create the Authenticator Class
--------------------------------------

Suppose you have an API where your clients will send an X-AUTH-TOKEN
header on each request. This token is composed of the username followed
by a password, separated by a colon (e.g. ``X-AUTH-TOKEN: coolguy:awesomepassword``).
Your job is to read this, find theassociated user (if any) and check
the password.

To create a custom authentication system, just create a class and make
it implement GuardAuthenticatorInterface. Or, extend the simpler
AbstractGuardAuthenticator. This requires you to implement six methods:

.. code-block:: php

    <?php

    namespace App\Security;

    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\JsonResponse;
    use Symfony\Component\Security\Core\User\UserInterface;
    use Symfony\Component\Security\Core\User\UserProviderInterface;
    use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
    use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
    use Symfony\Component\Security\Core\Exception\AuthenticationException;

    class TokenAuthenticator extends AbstractGuardAuthenticator
    {
        private $encoderFactory;

        public function __construct(EncoderFactoryInterface $encoderFactory)
        {
            $this->encoderFactory = $encoderFactory;
        }

        public function getCredentials(Request $request)
        {
            // Checks if the credential header is provided
            if (!$token = $request->headers->get('X-AUTH-TOKEN')) {
                return;
            }

            // Parse the header or ignore it if the format is incorrect.
            if (false === strpos($token, ':')) {
                return;
            }
            list($username, $secret) = explode(':', $token, 2);

            return array(
                'username' => $username,
                'secret' => $secret,
            );
        }

        public function getUser($credentials, UserProviderInterface $userProvider)
        {
            return $userProvider->loadUserByUsername($credentials['username']);
        }

        public function checkCredentials($credentials, UserInterface $user)
        {
            // check credentials - e.g. make sure the password is valid
            // return true to cause authentication success

            $encoder = $this->encoderFactory->getEncoder($user);

            return $encoder->isPasswordValid(
                $user->getPassword(),
                $credentials['secret'],
                $user->getSalt()
            );
        }

        public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
        {
            // on success, let the request continue
            return;
        }

        public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
        {
            $data = array(
                'message' => strtr($exception->getMessageKey(), $exception->getMessageData()),

                // or to translate this message
                // $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())
            );

            return new JsonResponse($data, 403);
        }

        /**
         * Called when authentication is needed, but it's not sent
         */
        public function start(Request $request, AuthenticationException $authException = null)
        {
            $data = array(
                // you might translate this message
                'message' => 'Authentication Required',
            );

            return new JsonResponse($data, 401);
        }

        public function supportsRememberMe()
        {
            return false;
        }
    }


Step 2) Configure the Authenticator
-----------------------------------

To finish this, register the class as a service:

.. code-block:: php

    $app['app.token_authenticator'] = function ($app) {
        return new App\Security\TokenAuthenticator($app['security.encoder_factory']);
    };


Finally, configure your `security.firewalls` key to use this authenticator:

.. code-block:: php

    $app['security.firewalls'] => array(
        'main' => array(
            'guard' => array(
                'authenticators' => array(
                    'app.token_authenticator'
                ),

                // Using more than 1 authenticator, you must specify
                // which one is used as entry point.
                // 'entry_point' => 'app.token_authenticator',
            ),
            // configure where your users come from. Hardcode them, or load them from somewhere
            // http://silex.sensiolabs.org/doc/providers/security.html#defining-a-custom-user-provider
            'users' => array(
                'victoria' => array('ROLE_USER', 'randomsecret'),
            ),
            // 'anonymous' => true
        ),
    );

.. note::
    You can use many authenticators, they are executed by the order
    they are configured.

You did it! You now have a fully-working API token authentication
system. If your homepage required ROLE_USER, then you could test it
under different conditions:

.. code-block:: bash

    # test with no token
    curl http://localhost:8000/
    # {"message":"Authentication Required"}

    # test with a bad token
    curl -H "X-AUTH-TOKEN: alan" http://localhost:8000/
    # {"message":"Username could not be found."}

    # test with a working token
    curl -H "X-AUTH-TOKEN: victoria:randomsecret" http://localhost:8000/
    # the homepage controller is executed: the page loads normally

For more details read the Symfony cookbook entry on
`How to Create a Custom Authentication System with Guard <http://symfony.com/doc/current/cookbook/security/guard-authentication.html>`_.


================================================
FILE: doc/cookbook/index.rst
================================================
Cookbook
========

The cookbook section contains recipes for solving specific problems.

.. toctree::
    :maxdepth: 1
    :hidden:

    json_request_body
    session_storage
    form_no_csrf
    validator_yaml
    sub_requests
    error_handler
    multiple_loggers
    guard_authentication

Recipes
-------

* :doc:`Accepting a JSON Request Body <json_request_body>` A common need when
  building a restful API is the ability to accept a JSON encoded entity from
  the request body.

* :doc:`Using PdoSessionStorage to store Sessions in the Database
  <session_storage>`.

* :doc:`Disabling the CSRF Protection on a Form using the FormExtension
  <form_no_csrf>`.

* :doc:`Using YAML to configure Validation <validator_yaml>`.

* :doc:`Making sub-Requests <sub_requests>`.

* :doc:`Converting Errors to Exceptions <error_handler>`.

* :doc:`Using multiple Monolog Loggers <multiple_loggers>`.

* :doc:`How to Create a Custom Authentication System with Guard <guard_authentication>`.


================================================
FILE: doc/cookbook/json_request_body.rst
================================================
Accepting a JSON Request Body
=============================

A common need when building a restful API is the ability to accept a JSON
encoded entity from the request body.

An example for such an API could be a blog post creation.

Example API
-----------

In this example we will create an API for creating a blog post. The following
is a spec of how we want it to work.

Request
~~~~~~~

In the request we send the data for the blog post as a JSON object. We also
indicate that using the ``Content-Type`` header:

.. code-block:: text

    POST /blog/posts
    Accept: application/json
    Content-Type: application/json
    Content-Length: 57

    {"title":"Hello World!","body":"This is my first post!"}

Response
~~~~~~~~

The server responds with a 201 status code, telling us that the post was
created. It tells us the ``Content-Type`` of the response, which is also
JSON:

.. code-block:: text

    HTTP/1.1 201 Created
    Content-Type: application/json
    Content-Length: 65
    Connection: close

    {"id":"1","title":"Hello World!","body":"This is my first post!"}

Parsing the request body
------------------------

The request body should only be parsed as JSON if the ``Content-Type`` header
begins with ``application/json``. Since we want to do this for every request,
the easiest solution is to use an application before middleware.

We simply use ``json_decode`` to parse the content of the request and then
replace the request data on the ``$request`` object::

    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\ParameterBag;

    $app->before(function (Request $request) {
        if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
            $data = json_decode($request->getContent(), true);
            $request->request->replace(is_array($data) ? $data : array());
        }
    });

Controller implementation
-------------------------

Our controller will create a new blog post from the data provided and will
return the post object, including its ``id``, as JSON::

    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;

    $app->post('/blog/posts', function (Request $request) use ($app) {
        $post = array(
            'title' => $request->request->get('title'),
            'body'  => $request->request->get('body'),
        );

        $post['id'] = createPost($post);

        return $app->json($post, 201);
    });

Manual testing
--------------

In order to manually test our API, we can use the ``curl`` command line
utility, which allows sending HTTP requests:

.. code-block:: bash

    $ curl http://blog.lo/blog/posts -d '{"title":"Hello World!","body":"This is my first post!"}' -H 'Content-Type: application/json'
    {"id":"1","title":"Hello World!","body":"This is my first post!"}


================================================
FILE: doc/cookbook/multiple_loggers.rst
================================================
Using multiple Monolog Loggers
==============================

Having separate instances of Monolog for different parts of your system is
often desirable and allows you to configure them independently, allowing for fine
grained control of where your logging goes and in what detail.

This simple example allows you to quickly configure several monolog instances,
using the bundled handler, but each with a different channel. 

.. code-block:: php

    $app['monolog.factory'] = $app->protect(function ($name) use ($app) {
        $log = new $app['monolog.logger.class']($name);
        $log->pushHandler($app['monolog.handler']);

        return $log;
    });

    foreach (array('auth', 'payments', 'stats') as $channel) {
        $app['monolog.'.$channel] = function ($app) use ($channel) {
            return $app['monolog.factory']($channel);
        };
    }

As your application grows, or your logging needs for certain areas of the
system become apparent, it should be straightforward to then configure that
particular service separately, including your customizations.

.. code-block:: php

    use Monolog\Handler\StreamHandler;

    $app['monolog.payments'] = function ($app) {
        $log = new $app['monolog.logger.class']('payments');
        $handler = new StreamHandler($app['monolog.payments.logfile'], $app['monolog.payment.level']);
        $log->pushHandler($handler);

        return $log;
    };

Alternatively, you could attempt to make the factory more complicated, and rely
on some conventions, such as checking for an array of handlers registered with
the container with the channel name, defaulting to the bundled handler.

.. code-block:: php

    use Monolog\Handler\StreamHandler;
    use Monolog\Logger;

    $app['monolog.factory'] = $app->protect(function ($name) use ($app) {
        $log = new $app['monolog.logger.class']($name);

        $handlers = isset($app['monolog.'.$name.'.handlers'])
            ? $app['monolog.'.$name.'.handlers']
            : array($app['monolog.handler']);

        foreach ($handlers as $handler) {
            $log->pushHandler($handler);
        }

        return $log;
    });

    $app['monolog.payments.handlers'] = function ($app) {
        return array(
            new StreamHandler(__DIR__.'/../payments.log', Logger::DEBUG),
        );
    };


================================================
FILE: doc/cookbook/session_storage.rst
================================================
Using PdoSessionStorage to store Sessions in the Database
=========================================================

By default, the :doc:`SessionServiceProvider </providers/session>` writes
session information in files using Symfony NativeFileSessionStorage. Most
medium to large websites use a database to store sessions instead of files,
because databases are easier to use and scale in a multi-webserver environment.

Symfony's `NativeSessionStorage
<http://api.symfony.com/master/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.html>`_
has multiple storage handlers and one of them uses PDO to store sessions,
`PdoSessionHandler
<http://api.symfony.com/master/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.html>`_.
To use it, replace the ``session.storage.handler`` service in your application
like explained below.

With a dedicated PDO service
----------------------------

.. code-block:: php

    use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;

    $app->register(new Silex\Provider\SessionServiceProvider());

    $app['pdo.dsn'] = 'mysql:dbname=mydatabase';
    $app['pdo.user'] = 'myuser';
    $app['pdo.password'] = 'mypassword';

    $app['session.db_options'] = array(
        'db_table'      => 'session',
        'db_id_col'     => 'session_id',
        'db_data_col'   => 'session_value',
        'db_time_col'   => 'session_time',
    );

    $app['pdo'] = function () use ($app) {
        return new PDO(
            $app['pdo.dsn'],
            $app['pdo.user'],
            $app['pdo.password']
        );
    };

    $app['session.storage.handler'] = function () use ($app) {
        return new PdoSessionHandler(
            $app['pdo'],
            $app['session.db_options'],
            $app['session.storage.options']
        );
    };

Using the DoctrineServiceProvider
---------------------------------

When using the :doc:`DoctrineServiceProvider </providers/doctrine>` You don't
have to make another database connection, simply pass the getWrappedConnection method.

.. code-block:: php

    use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;

    $app->register(new Silex\Provider\SessionServiceProvider());

    $app['session.db_options'] = array(
        'db_table'        => 'session',
        'db_id_col'       => 'session_id',
        'db_data_col'     => 'session_value',
        'db_lifetime_col' => 'session_lifetime',
        'db_time_col'     => 'session_time',
    );

    $app['session.storage.handler'] = function () use ($app) {
        return new PdoSessionHandler(
            $app['db']->getWrappedConnection(),
            $app['session.db_options'],
            $app['session.storage.options']
        );
    };

Database structure
------------------

PdoSessionStorage needs a database table with 3 columns:

* ``session_id``: ID column (VARCHAR(255) or larger)
* ``session_value``: Value column (TEXT or CLOB)
* ``session_lifetime``: Lifetime column (INTEGER)
* ``session_time``: Time column (INTEGER)

You can find examples of SQL statements to create the session table in the
`Symfony cookbook
<http://symfony.com/doc/current/cookbook/configuration/pdo_session_storage.html#example-sql-statements>`_


================================================
FILE: doc/cookbook/sub_requests.rst
================================================
Making sub-Requests
===================

Since Silex is based on the ``HttpKernelInterface``, it allows you to simulate
requests against your application. This means that you can embed a page within
another, it also allows you to forward a request which is essentially an
internal redirect that does not change the URL.

Basics
------

You can make a sub-request by calling the ``handle`` method on the
``Application``. This method takes three arguments:

* ``$request``: An instance of the ``Request`` class which represents the
   HTTP request.

* ``$type``: Must be either ``HttpKernelInterface::MASTER_REQUEST`` or
  ``HttpKernelInterface::SUB_REQUEST``. Certain listeners are only executed for
  the master request, so it's important that this is set to ``SUB_REQUEST``.

* ``$catch``: Catches exceptions and turns them into a response with status code
  ``500``. This argument defaults to ``true``. For sub-requests you will most
  likely want to set it to ``false``.

By calling ``handle``, you can make a sub-request manually. Here's an example::

    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpKernel\HttpKernelInterface;

    $subRequest = Request::create('/');
    $response = $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);

There's some more things that you need to keep in mind though. In most cases
you will want to forward some parts of the current master request to the
sub-request like cookies, server information, or the session.

Here is a more advanced example that forwards said information (``$request``
holds the master request)::

    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpKernel\HttpKernelInterface;

    $subRequest = Request::create('/', 'GET', array(), $request->cookies->all(), array(), $request->server->all());
    if ($request->getSession()) {
        $subRequest->setSession($request->getSession());
    }

    $response = $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);

To forward this response to the client, you can simply return it from a
controller::

    use Silex\Application;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpKernel\HttpKernelInterface;

    $app->get('/foo', function (Application $app, Request $request) {
        $subRequest = Request::create('/', ...);
        $response = $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);

        return $response;
    });

If you want to embed the response as part of a larger page you can call
``Response::getContent``::

    $header = ...;
    $footer = ...;
    $body = $response->getContent();

    return $header.$body.$footer;

Rendering pages in Twig templates
---------------------------------

The :doc:`TwigServiceProvider </providers/twig>` provides a ``render``
function that you can use in Twig templates. It gives you a convenient way to
embed pages.

.. code-block:: jinja

    {{ render('/sidebar') }}

For details, refer to the :doc:`TwigServiceProvider </providers/twig>` docs.

Edge Side Includes
------------------

You can use ESI either through the :doc:`HttpCacheServiceProvider
</providers/http_cache>` or a reverse proxy cache such as Varnish. This also
allows you to embed pages, however it also gives you the benefit of caching
parts of the page.

Here is an example of how you would embed a page via ESI:

.. code-block:: jinja

    <esi:include src="/sidebar" />

For details, refer to the :doc:`HttpCacheServiceProvider
</providers/http_cache>` docs.

Dealing with the request base URL
---------------------------------

One thing to watch out for is the base URL. If your application is not
hosted at the webroot of your web server, then you may have an URL like
``http://example.org/foo/index.php/articles/42``.

In this case, ``/foo/index.php`` is your request base path. Silex accounts for
this path prefix in the routing process, it reads it from
``$request->server``. In the context of sub-requests this can lead to issues,
because if you do not prepend the base path the request could mistake a part
of the path you want to match as the base path and cut it off.

You can prevent that from happening by always prepending the base path when
constructing a request::

    $url = $request->getUriForPath('/');
    $subRequest = Request::create($url, 'GET', array(), $request->cookies->all(), array(), $request->server->all());

This is something to be aware of when making sub-requests by hand.

Services depending on the Request
---------------------------------

The container is a concept that is global to a Silex application, since the
application object **is** the container. Any request that is run against an
application will re-use the same set of services. Since these services are
mutable, code in a master request can affect the sub-requests and vice versa.
Any services depending on the ``request`` service will store the first request
that they get (could be master or sub-request), and keep using it, even if
that request is already over.

Instead of injecting the ``request`` service, you should always inject the
``request_stack`` one instead.


================================================
FILE: doc/cookbook/validator_yaml.rst
================================================
Using YAML to configure Validation
==================================

Simplicity is at the heart of Silex so there is no out of the box solution to
use YAML files for validation. But this doesn't mean that this is not
possible. Let's see how to do it.

First, you need to install the YAML Component:

.. code-block:: bash

    composer require symfony/yaml

Next, you need to tell the Validation Service that you are not using
``StaticMethodLoader`` to load your class metadata but a YAML file::

    $app->register(new ValidatorServiceProvider());

    $app['validator.mapping.class_metadata_factory'] = new Symfony\Component\Validator\Mapping\ClassMetadataFactory(
        new Symfony\Component\Validator\Mapping\Loader\YamlFileLoader(__DIR__.'/validation.yml')
    );

Now, we can replace the usage of the static method and move all the validation
rules to ``validation.yml``:

.. code-block:: yaml

    # validation.yml
    Post:
      properties:
        title:
          - NotNull: ~
          - NotBlank: ~
        body:
          - Min: 100


================================================
FILE: doc/index.rst
================================================
The Book
========

.. toctree::
    :maxdepth: 1

    intro
    usage
    middlewares
    organizing_controllers
    services
    providers
    testing
    cookbook/index
    internals
    contributing
    providers/index
    web_servers
    changelog


================================================
FILE: doc/internals.rst
================================================
Internals
=========

This chapter will tell you how Silex works internally.

Silex
-----

Application
~~~~~~~~~~~

The application is the main interface to Silex. It implements Symfony's
`HttpKernelInterface
<http://api.symfony.com/master/Symfony/Component/HttpKernel/HttpKernelInterface.html>`_,
so you can pass a `Request
<http://api.symfony.com/master/Symfony/Component/HttpFoundation/Request.html>`_
to the ``handle`` method and it will return a `Response
<http://api.symfony.com/master/Symfony/Component/HttpFoundation/Response.html>`_.

It extends the ``Pimple`` service container, allowing for flexibility on the
outside as well as the inside. You could replace any service, and you are also
able to read them.

The application makes strong use of the `EventDispatcher
<http://api.symfony.com/master/Symfony/Component/EventDispatcher/EventDispatcher
.html>`_ to hook into the Symfony `HttpKernel
<http://api.symfony.com/master/Symfony/Component/HttpKernel/HttpKernel.html>`_
events. This allows fetching the ``Request``, converting string responses into
``Response`` objects and handling Exceptions. We also use it to dispatch some
custom events like before/after middlewares and errors.

Controller
~~~~~~~~~~

The Symfony `Route
<http://api.symfony.com/master/Symfony/Component/Routing/Route.html>`_ is
actually quite powerful. Routes can be named, which allows for URL generation.
They can also have requirements for the variable parts. In order to allow
setting these through a nice interface, the ``match`` method (which is used by
``get``, ``post``, etc.) returns an instance of the ``Controller``, which
wraps a route.

ControllerCollection
~~~~~~~~~~~~~~~~~~~~

One of the goals of exposing the `RouteCollection
<http://api.symfony.com/master/Symfony/Component/Routing/RouteCollection.html>`_
was to make it mutable, so providers could add stuff to it. The challenge here
is the fact that routes know nothing about their name. The name only has
meaning in context of the ``RouteCollection`` and cannot be changed.

To solve this challenge we came up with a staging area for routes. The
``ControllerCollection`` holds the controllers until ``flush`` is called, at
which point the routes are added to the ``RouteCollection``. Also, the
controllers are then frozen. This means that they can no longer be modified
and will throw an Exception if you try to do so.

Unfortunately no good way for flushing implicitly could be found, which is why
flushing is now always explicit. The Application will flush, but if you want
to read the ``ControllerCollection`` before the request takes place, you will
have to call flush yourself.

The ``Application`` provides a shortcut ``flush`` method for flushing the
``ControllerCollection``.

.. tip::

    Instead of creating an instance of ``RouteCollection`` yourself, use the
    ``$app['controllers_factory']`` factory instead.

Symfony
-------

Following Symfony components are used by Silex:

* **HttpFoundation**: For ``Request`` and ``Response``.

* **HttpKernel**: Because we need a heart.

* **Routing**: For matching defined routes.

* **EventDispatcher**: For hooking into the HttpKernel.

For more information, `check out the Symfony website <http://symfony.com/>`_.


================================================
FILE: doc/intro.rst
================================================
Introduction
============

Silex is a PHP microframework. It is built on the shoulders of `Symfony`_ and
`Pimple`_ and also inspired by `Sinatra`_.

Silex aims to be:

* *Concise*: Silex exposes an intuitive and concise API.

* *Extensible*: Silex has an extension system based around the Pimple
  service-container that makes it easy to tie in third party libraries.

* *Testable*: Silex uses Symfony's HttpKernel which abstracts request and
  response. This makes it very easy to test apps and the framework itself. It
  also respects the HTTP specification and encourages its proper use.

In a nutshell, you define controllers and map them to routes, all in one step.

Usage
-----

.. code-block:: php

    <?php

    // web/index.php
    require_once __DIR__.'/../vendor/autoload.php';

    $app = new Silex\Application();

    $app->get('/hello/{name}', function ($name) use ($app) {
        return 'Hello '.$app->escape($name);
    });

    $app->run();

All that is needed to get access to the Framework is to include the
autoloader.

Next, a route for ``/hello/{name}`` that matches for ``GET`` requests is
defined. When the route matches, the function is executed and the return value
is sent back to the client.

Finally, the app is run. Visit ``/hello/world`` to see the result. It's really
that easy!

.. _Symfony: http://symfony.com/
.. _Pimple: http://pimple.sensiolabs.org/
.. _Sinatra: http://www.sinatrarb.com/


================================================
FILE: doc/middlewares.rst
================================================
Middleware
==========

Silex allows you to run code, that changes the default Silex behavior, at
different stages during the handling of a request through *middleware*:

* *Application middleware* is triggered independently of the current handled
  request;

* *Route middleware* is triggered when its associated route is matched.

Application Middleware
----------------------

Application middleware is only run for the "master" Request.

Before Middleware
~~~~~~~~~~~~~~~~~

A *before* application middleware allows you to tweak the Request before the
controller is executed::

    $app->before(function (Request $request, Application $app) {
        // ...
    });

By default, the middleware is run after the routing and the security.

If you want your middleware to be run even if an exception is thrown early on
(on a 404 or 403 error for instance), then, you need to register it as an
early event::

    $app->before(function (Request $request, Application $app) {
        // ...
    }, Application::EARLY_EVENT);

In this case, the routing and the security won't have been executed, and so you
won't have access to the locale, the current route, or the security user.

.. note::

    The before middleware is an event registered on the Symfony *request*
    event.

After Middleware
~~~~~~~~~~~~~~~~

An *after* application middleware allows you to tweak the Response before it
is sent to the client::

    $app->after(function (Request $request, Response $response) {
        // ...
    });

.. note::

    The after middleware is an event registered on the Symfony *response*
    event.

Finish Middleware
~~~~~~~~~~~~~~~~~

A *finish* application middleware allows you to execute tasks after the
Response has been sent to the client (like sending emails or logging)::

    $app->finish(function (Request $request, Response $response) {
        // ...
        // Warning: modifications to the Request or Response will be ignored
    });

.. note::

    The finish middleware is an event registered on the Symfony *terminate*
    event.

Route Middleware
----------------

Route middleware is added to routes or route collections and it is only
triggered when the corresponding route is matched. You can also stack them::

    $app->get('/somewhere', function () {
        // ...
    })
    ->before($before1)
    ->before($before2)
    ->after($after1)
    ->after($after2)
    ;

Before Middleware
~~~~~~~~~~~~~~~~~

A *before* route middleware is fired just before the route callback, but after
the *before* application middleware::

    $before = function (Request $request, Application $app) {
        // ...
    };

    $app->get('/somewhere', function () {
        // ...
    })
    ->before($before);

After Middleware
~~~~~~~~~~~~~~~~

An *after* route middleware is fired just after the route callback, but before
the application *after* application middleware::

    $after = function (Request $request, Response $response, Application $app) {
        // ...
    };

    $app->get('/somewhere', function () {
        // ...
    })
    ->after($after);

Middleware Priority
-------------------

You can add as much middleware as you want, in which case they are triggered
in the same order as you added them.

You can explicitly control the priority of your middleware by passing an
additional argument to the registration methods::

    $app->before(function (Request $request) {
        // ...
    }, 32);

As a convenience, two constants allow you to register an event as early as
possible or as late as possible::

    $app->before(function (Request $request) {
        // ...
    }, Application::EARLY_EVENT);

    $app->before(function (Request $request) {
        // ...
    }, Application::LATE_EVENT);

Short-circuiting the Controller
-------------------------------

If a *before* middleware returns a ``Response`` object, the request handling is
short-circuited (the next middleware won't be run, nor the route
callback), and the Response is passed to the *after* middleware right away::

    $app->before(function (Request $request) {
        // redirect the user to the login screen if access to the Resource is protected
        if (...) {
            return new RedirectResponse('/login');
        }
    });

.. note::

    A ``RuntimeException`` is thrown if a before middleware does not return a
    Response or ``null``.


================================================
FILE: doc/organizing_controllers.rst
================================================
Organizing Controllers
======================

When your application starts to define too many controllers, you might want to
group them logically::

    // define controllers for a blog
    $blog = $app['controllers_factory'];
    $blog->get('/', function () {
        return 'Blog home page';
    });
    // ...

    // define controllers for a forum
    $forum = $app['controllers_factory'];
    $forum->get('/', function () {
        return 'Forum home page';
    });

    // define "global" controllers
    $app->get('/', function () {
        return 'Main home page';
    });

    $app->mount('/blog', $blog);
    $app->mount('/forum', $forum);

    // define controllers for a admin
    $app->mount('/admin', function ($admin) {
        // recursively mount
        $admin->mount('/blog', function ($user) {
            $user->get('/', function () {
                return 'Admin Blog home page';
            });
        });
    });

.. note::

    ``$app['controllers_factory']`` is a factory that returns a new instance
    of ``ControllerCollection`` when used.

``mount()`` prefixes all routes with the given prefix and merges them into the
main Application. So, ``/`` will map to the main home page, ``/blog/`` to the
blog home page, ``/forum/`` to the forum home page, and ``/admin/blog/`` to the
admin blog home page.

.. caution::

    When mounting a route collection under ``/blog``, it is not possible to
    define a route for the ``/blog`` URL. The shortest possible URL is
    ``/blog/``.

.. note::

    When calling ``get()``, ``match()``, or any other HTTP methods on the
    Application, you are in fact calling them on a default instance of
    ``ControllerCollection`` (stored in ``$app['controllers']``).

Another benefit is the ability to apply settings on a set of controllers very
easily. Building on the example from the middleware section, here is how you
would secure all controllers for the backend collection::

    $backend = $app['controllers_factory'];

    // ensure that all controllers require logged-in users
    $backend->before($mustBeLogged);

.. tip::

    For a better readability, you can split each controller collection into a
    separate file::

        // blog.php
        $blog = $app['controllers_factory'];
        $blog->get('/', function () { return 'Blog home page'; });

        return $blog;

        // app.php
        $app->mount('/blog', include 'blog.php');

    Instead of requiring a file, you can also create a :ref:`Controller
    provider <controller-providers>`.


================================================
FILE: doc/providers/asset.rst
================================================
Asset
=====

The *AssetServiceProvider* provides a way to manage URL generation and
versioning of web assets such as CSS stylesheets, JavaScript files and image
files.

Parameters
----------

* **assets.version**: Default version for assets.

* **assets.format_version** (optional): Default format for assets.

* **assets.named_packages** (optional): Named packages. Keys are the package
  names and values the configuration (supported keys are ``version``,
  ``version_format``, ``base_urls``, and ``base_path``).

Services
--------

* **assets.packages**: The asset service.

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\AssetServiceProvider(), array(
        'assets.version' => 'v1',
        'assets.version_format' => '%s?version=%s',
        'assets.named_packages' => array(
            'css' => array('version' => 'css2', 'base_path' => '/whatever-makes-sense'),
            'images' => array('base_urls' => array('https://img.example.com')),
        ),
    ));

.. note::

    Add the Symfony Asset Component as a dependency:

    .. code-block:: bash

        composer require symfony/asset

Usage
-----

The AssetServiceProvider is mostly useful with the Twig provider:

.. code-block:: jinja

    {{ asset('/css/foo.png') }}
    {{ asset('/css/foo.css', 'css') }}
    {{ asset('/img/foo.png', 'images') }}

    {{ asset_version('/css/foo.png') }}

For more information, check out the `Asset Component documentation
<https://symfony.com/doc/current/components/asset/introduction.html>`_.


================================================
FILE: doc/providers/csrf.rst
================================================
CSRF
====

The *CsrfServiceProvider* provides a service for building forms in your
application with the Symfony Form component.

Parameters
----------

* none

Services
--------

* **csrf.token_manager**: An instance of an implementation of the
  `CsrfProviderInterface
  <http://api.symfony.com/master/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.html>`_,
  defaults to a `DefaultCsrfProvider
  <http://api.symfony.com/master/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.html>`_.

Registering
-----------

.. code-block:: php

    use Silex\Provider\CsrfServiceProvider;

    $app->register(new CsrfServiceProvider());

.. note::

    Add the Symfony's `Security CSRF Component
    <http://symfony.com/doc/current/components/security/index.html>`_ as a
    dependency:

    .. code-block:: bash

        composer require symfony/security-csrf

Usage
-----

When the CSRF Service Provider is registered, all forms created via the Form
Service Provider are protected against CSRF by default.

You can also use the CSRF protection even without using the Symfony Form
component. If, for example, you're doing a DELETE action, you can check the
CSRF token::

    use Symfony\Component\Security\Csrf\CsrfToken;

    $app['csrf.token_manager']->isTokenValid(new CsrfToken('token_id', 'TOKEN'));


================================================
FILE: doc/providers/doctrine.rst
================================================
Doctrine
========

The *DoctrineServiceProvider* provides integration with the `Doctrine DBAL
<http://www.doctrine-project.org/projects/dbal>`_ for easy database access
(Doctrine ORM integration is **not** supplied).

Parameters
----------

* **db.options**: Array of Doctrine DBAL options.

  These options are available:

  * **driver**: The database driver to use, defaults to ``pdo_mysql``.
    Can be any of: ``pdo_mysql``, ``pdo_sqlite``, ``pdo_pgsql``,
    ``pdo_oci``, ``oci8``, ``ibm_db2``, ``pdo_ibm``, ``pdo_sqlsrv``.

  * **dbname**: The name of the database to connect to.

  * **host**: The host of the database to connect to. Defaults to
    localhost.

  * **user**: The user of the database to connect to. Defaults to
    root.

  * **password**: The password of the database to connect to.

  * **charset**: Only relevant for ``pdo_mysql``, and ``pdo_oci/oci8``,
    specifies the charset used when connecting to the database.

  * **path**: Only relevant for ``pdo_sqlite``, specifies the path to
    the SQLite database.

  * **port**: Only relevant for ``pdo_mysql``, ``pdo_pgsql``, and ``pdo_oci/oci8``,
    specifies the port of the database to connect to.

  These and additional options are described in detail in the `Doctrine DBAL
  configuration documentation <http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html>`_.

Services
--------

* **db**: The database connection, instance of
  ``Doctrine\DBAL\Connection``.

* **db.config**: Configuration object for Doctrine. Defaults to
  an empty ``Doctrine\DBAL\Configuration``.

* **db.event_manager**: Event Manager for Doctrine.

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\DoctrineServiceProvider(), array(
        'db.options' => array(
            'driver'   => 'pdo_sqlite',
            'path'     => __DIR__.'/app.db',
        ),
    ));

.. note::

    Add the Doctrine DBAL as a dependency:

    .. code-block:: bash

        composer require "doctrine/dbal:~2.2"

Usage
-----

The Doctrine provider provides a ``db`` service. Here is a usage
example::

    $app->get('/blog/{id}', function ($id) use ($app) {
        $sql = "SELECT * FROM posts WHERE id = ?";
        $post = $app['db']->fetchAssoc($sql, array((int) $id));

        return  "<h1>{$post['title']}</h1>".
                "<p>{$post['body']}</p>";
    });

Using multiple databases
------------------------

The Doctrine provider can allow access to multiple databases. In order to
configure the data sources, replace the **db.options** with **dbs.options**.
**dbs.options** is an array of configurations where keys are connection names
and values are options::

    $app->register(new Silex\Provider\DoctrineServiceProvider(), array(
        'dbs.options' => array (
            'mysql_read' => array(
                'driver'    => 'pdo_mysql',
                'host'      => 'mysql_read.someplace.tld',
                'dbname'    => 'my_database',
                'user'      => 'my_username',
                'password'  => 'my_password',
                'charset'   => 'utf8mb4',
            ),
            'mysql_write' => array(
                'driver'    => 'pdo_mysql',
                'host'      => 'mysql_write.someplace.tld',
                'dbname'    => 'my_database',
                'user'      => 'my_username',
                'password'  => 'my_password',
                'charset'   => 'utf8mb4',
            ),
        ),
    ));

The first registered connection is the default and can simply be accessed as
you would if there was only one connection. Given the above configuration,
these two lines are equivalent::

    $app['db']->fetchAll('SELECT * FROM table');

    $app['dbs']['mysql_read']->fetchAll('SELECT * FROM table');

Using multiple connections::

    $app->get('/blog/{id}', function ($id) use ($app) {
        $sql = "SELECT * FROM posts WHERE id = ?";
        $post = $app['dbs']['mysql_read']->fetchAssoc($sql, array((int) $id));

        $sql = "UPDATE posts SET value = ? WHERE id = ?";
        $app['dbs']['mysql_write']->executeUpdate($sql, array('newValue', (int) $id));

        return  "<h1>{$post['title']}</h1>".
                "<p>{$post['body']}</p>";
    });

For more information, consult the `Doctrine DBAL documentation
<http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/>`_.


================================================
FILE: doc/providers/form.rst
================================================
Form
====

The *FormServiceProvider* provides a service for building forms in
your application with the Symfony Form component.

Parameters
----------

* none

Services
--------

* **form.factory**: An instance of `FormFactory
  <http://api.symfony.com/master/Symfony/Component/Form/FormFactory.html>`_,
  that is used to build a form.

Registering
-----------

.. code-block:: php

    use Silex\Provider\FormServiceProvider;

    $app->register(new FormServiceProvider());

.. note::

    If you don't want to create your own form layout, it's fine: a default one
    will be used. But you will have to register the :doc:`translation provider
    <translation>` as the default form layout requires it::

        $app->register(new Silex\Provider\TranslationServiceProvider(), array(
            'translator.domains' => array(),
        ));

    If you want to use validation with forms, do not forget to register the
    :doc:`Validator provider <validator>`.

.. note::

    Add the Symfony Form Component as a dependency:

    .. code-block:: bash

        composer require symfony/form

    If you are going to use the validation extension with forms, you must also
    add a dependency to the ``symfony/config`` and ``symfony/translation``
    components:

    .. code-block:: bash

        composer require symfony/validator symfony/config symfony/translation

    If you want to use forms in your Twig templates, you can also install the
    Symfony Twig Bridge. Make sure to install, if you didn't do that already,
    the Translation component in order for the bridge to work:

    .. code-block:: bash

        composer require symfony/twig-bridge symfony/translation

Usage
-----

The FormServiceProvider provides a ``form.factory`` service. Here is a usage
example::

    use Symfony\Component\Form\Extension\Core\Type\FormType;
    use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

    $app->match('/form', function (Request $request) use ($app) {
        // some default data for when the form is displayed the first time
        $data = array(
            'name' => 'Your name',
            'email' => 'Your email',
        );

        $form = $app['form.factory']->createBuilder(FormType::class, $data)
            ->add('name')
            ->add('email')
            ->add('billing_plan', ChoiceType::class, array(
                'choices' => array(1 => 'free', 2 => 'small_business', 3 => 'corporate'),
                'expanded' => true,
            ))
            ->getForm();

        $form->handleRequest($request);

        if ($form->isValid()) {
            $data = $form->getData();

            // do something with the data

            // redirect somewhere
            return $app->redirect('...');
        }

        // display the form
        return $app['twig']->render('index.twig', array('form' => $form->createView()));
    });

And here is the ``index.twig`` form template (requires ``symfony/twig-bridge``):

.. code-block:: jinja

    <form action="#" method="post">
        {{ form_widget(form) }}

        <input type="submit" name="submit" />
    </form>

If you are using the validator provider, you can also add validation to your
form by adding constraints on the fields::

    use Symfony\Component\Form\Extension\Core\Type\FormType;
    use Symfony\Component\Form\Extension\Core\Type\TextType;
    use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
    use Symfony\Component\Validator\Constraints as Assert;

    $app->register(new Silex\Provider\ValidatorServiceProvider());
    $app->register(new Silex\Provider\TranslationServiceProvider(), array(
        'translator.domains' => array(),
    ));

    $form = $app['form.factory']->createBuilder(FormType::class)
        ->add('name', TextType::class, array(
            'constraints' => array(new Assert\NotBlank(), new Assert\Length(array('min' => 5)))
        ))
        ->add('email', TextType::class, array(
            'constraints' => new Assert\Email()
        ))
        ->add('billing_plan', ChoiceType::class, array(
            'choices' => array(1 => 'free', 2 => 'small_business', 3 => 'corporate'),
            'expanded' => true,
            'constraints' => new Assert\Choice(array(1, 2, 3)),
        ))
        ->getForm();

You can register form types by extending ``form.types``::

    $app['your.type.service'] = function ($app) {
        return new YourServiceFormType();
    };
    $app->extend('form.types', function ($types) use ($app) {
        $types[] = new YourFormType();
        $types[] = 'your.type.service';

        return $types;
    }));

You can register form extensions by extending ``form.extensions``::

    $app->extend('form.extensions', function ($extensions) use ($app) {
        $extensions[] = new YourTopFormExtension();

        return $extensions;
    });


You can register form type extensions by extending ``form.type.extensions``::

    $app['your.type.extension.service'] = function ($app) {
        return new YourServiceFormTypeExtension();
    };
    $app->extend('form.type.extensions', function ($extensions) use ($app) {
        $extensions[] = new YourFormTypeExtension();
        $extensions[] = 'your.type.extension.service';

        return $extensions;
    });

You can register form type guessers by extending ``form.type.guessers``::

    $app['your.type.guesser.service'] = function ($app) {
        return new YourServiceFormTypeGuesser();
    };
    $app->extend('form.type.guessers', function ($guessers) use ($app) {
        $guessers[] = new YourFormTypeGuesser();
        $guessers[] = 'your.type.guesser.service';

        return $guessers;
    });

.. warning::

    CSRF protection is only available and automatically enabled when the
    :doc:`CSRF Service Provider </providers/csrf>` is registered.

Traits
------

``Silex\Application\FormTrait`` adds the following shortcuts:

* **form**: Creates a FormBuilder instance.

.. code-block:: php

    $app->form($data);

For more information, consult the `Symfony Forms documentation
<http://symfony.com/doc/2.8/book/forms.html>`_.


================================================
FILE: doc/providers/http_cache.rst
================================================
HTTP Cache
==========

The *HttpCacheServiceProvider* provides support for the Symfony Reverse
Proxy.

Parameters
----------

* **http_cache.cache_dir**: The cache directory to store the HTTP cache data.

* **http_cache.options** (optional): An array of options for the `HttpCache
  <http://api.symfony.com/master/Symfony/Component/HttpKernel/HttpCache/HttpCache.html>`_
  constructor.

Services
--------

* **http_cache**: An instance of `HttpCache
  <http://api.symfony.com/master/Symfony/Component/HttpKernel/HttpCache/HttpCache.html>`_.

* **http_cache.esi**: An instance of `Esi
  <http://api.symfony.com/master/Symfony/Component/HttpKernel/HttpCache/Esi.html>`_,
  that implements the ESI capabilities to Request and Response instances.

* **http_cache.store**: An instance of `Store
  <http://api.symfony.com/master/Symfony/Component/HttpKernel/HttpCache/Store.html>`_,
  that implements all the logic for storing cache metadata (Request and Response
  headers).

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\HttpCacheServiceProvider(), array(
        'http_cache.cache_dir' => __DIR__.'/cache/',
    ));

Usage
-----

Silex already supports any reverse proxy like Varnish out of the box by
setting Response HTTP cache headers::

    use Symfony\Component\HttpFoundation\Response;

    $app->get('/', function() {
        return new Response('Foo', 200, array(
            'Cache-Control' => 's-maxage=5',
        ));
    });

.. tip::

    If you want Silex to trust the ``X-Forwarded-For*`` headers from your
    reverse proxy at address $ip, you will need to whitelist it as documented
    in `Trusting Proxies
    <http://symfony.com/doc/current/components/http_foundation/trusting_proxies.html>`_.

    If you would be running Varnish in front of your application on the same machine::

        use Symfony\Component\HttpFoundation\Request;
        
        Request::setTrustedProxies(array('127.0.0.1', '::1'));
        $app->run();

This provider allows you to use the Symfony reverse proxy natively with
Silex applications by using the ``http_cache`` service. The Symfony reverse proxy
acts much like any other proxy would, so you will want to whitelist it::

    use Symfony\Component\HttpFoundation\Request;
        
    Request::setTrustedProxies(array('127.0.0.1'));
    $app['http_cache']->run();

The provider also provides ESI support::

    $app->get('/', function() {
        $response = new Response(<<<EOF
    <html>
        <body>
            Hello
            <esi:include src="/included" />
        </body>
    </html>

    EOF
        , 200, array(
            'Surrogate-Control' => 'content="ESI/1.0"',
        ));

        $response->setTtl(20);

        return $response;
    });

    $app->get('/included', function() {
        $response = new Response('Foo');
        $response->setTtl(5);

        return $response;
    });

    $app['http_cache']->run();

If your application doesn't use ESI, you can disable it to slightly improve the
overall performance::

    $app->register(new Silex\Provider\HttpCacheServiceProvider(), array(
       'http_cache.cache_dir' => __DIR__.'/cache/',
       'http_cache.esi'       => null,
    ));

.. tip::

    To help you debug caching issues, set your application ``debug`` to true.
    Symfony automatically adds a ``X-Symfony-Cache`` header to each response
    with useful information about cache hits and misses.

    If you are *not* using the Symfony Session provider, you might want to set
    the PHP ``session.cache_limiter`` setting to an empty value to avoid the
    default PHP behavior.

    Finally, check that your Web server does not override your caching strategy.

For more information, consult the `Symfony HTTP Cache documentation
<http://symfony.com/doc/current/book/http_cache.html>`_.


================================================
FILE: doc/providers/http_fragment.rst
================================================
HTTP Fragment
=============

The *HttpFragmentServiceProvider* provides support for the Symfony fragment
sub-framework, which allows you to embed fragments of HTML in a template.

Parameters
----------

* **fragment.path**: The path to use for the URL generated for ESI and
  HInclude URLs (``/_fragment`` by default).

* **uri_signer.secret**: The secret to use for the URI signer service (used
  for the HInclude renderer).

* **fragment.renderers.hinclude.global_template**: The content or Twig
  template to use for the default content when using the HInclude renderer.

Services
--------

* **fragment.handler**: An instance of `FragmentHandler
  <http://api.symfony.com/master/Symfony/Component/HttpKernel/Fragment/FragmentHandler.html>`_.

* **fragment.renderers**: An array of fragment renderers (by default, the
  inline, ESI, and HInclude renderers are pre-configured).

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\HttpFragmentServiceProvider());

Usage
-----

.. note::

    This section assumes that you are using Twig for your templates.

Instead of building a page out of a single request/controller/template, the
fragment framework allows you to build a page from several
controllers/sub-requests/sub-templates by using **fragments**.

Including "sub-pages" in the main page can be done with the Twig ``render()``
function:

.. code-block:: jinja

    The main page content.

    {{ render('/foo') }}

    The main page content resumes here.

The ``render()`` call is replaced by the content of the ``/foo`` URL
(internally, a sub-request is handled by Silex to render the sub-page).

Instead of making internal sub-requests, you can also use the ESI (the
sub-request is handled by a reverse proxy) or the HInclude strategies (the
sub-request is handled by a web browser):

.. code-block:: jinja

    {{ render(url('route_name')) }}

    {{ render_esi(url('route_name')) }}

    {{ render_hinclude(url('route_name')) }}


================================================
FILE: doc/providers/index.rst
================================================
Built-in Service Providers
==========================

.. toctree::
    :maxdepth: 1

    twig
    asset
    monolog
    session
    swiftmailer
    locale
    translation
    validator
    form
    csrf
    http_cache
    http_fragment
    security
    remember_me
    serializer
    service_controller
    var_dumper
    doctrine


================================================
FILE: doc/providers/locale.rst
================================================
Locale
======

The *LocaleServiceProvider* manages the locale of an application.

Parameters
----------

* **locale**: The locale of the user. When set before any request handling, it
  defines the default locale (``en`` by default). When a request is being
  handled, it is automatically set according to the ``_locale`` request
  attribute of the current route.

Services
--------

* n/a

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\LocaleServiceProvider());


================================================
FILE: doc/providers/monolog.rst
================================================
Monolog
=======

The *MonologServiceProvider* provides a default logging mechanism through
Jordi Boggiano's `Monolog <https://github.com/Seldaek/monolog>`_ library.

It will log requests and errors and allow you to add logging to your
application. This allows you to debug and monitor the behaviour,
even in production.

Parameters
----------

* **monolog.logfile**: File where logs are written to.
* **monolog.bubble**: (optional) Whether the messages that are handled can bubble up the stack or not.
* **monolog.permission**: (optional) File permissions default (null), nothing change.

* **monolog.level** (optional): Level of logging, defaults
  to ``DEBUG``. Must be one of ``Logger::DEBUG``, ``Logger::INFO``,
  ``Logger::WARNING``, ``Logger::ERROR``. ``DEBUG`` will log
  everything, ``INFO`` will log everything except ``DEBUG``,
  etc.

  In addition to the ``Logger::`` constants, it is also possible to supply the
  level in string form, for example: ``"DEBUG"``, ``"INFO"``, ``"WARNING"``,
  ``"ERROR"``.

* **monolog.name** (optional): Name of the monolog channel,
  defaults to ``myapp``.

* **monolog.exception.logger_filter** (optional): An anonymous function that
  filters which exceptions should be logged.

* **monolog.use_error_handler** (optional): Whether errors and uncaught exceptions
  should be handled by the Monolog ``ErrorHandler`` class and added to the log.
  By default the error handler is enabled unless the application ``debug`` parameter
  is set to true.

  Please note that enabling the error handler may silence some errors,
  ignoring the PHP ``display_errors`` configuration setting.

Services
--------

* **monolog**: The monolog logger instance.

  Example usage::

    $app['monolog']->addDebug('Testing the Monolog logging.');

* **monolog.listener**: An event listener to log requests, responses and errors.

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\MonologServiceProvider(), array(
        'monolog.logfile' => __DIR__.'/development.log',
    ));

.. note::

    Add Monolog as a dependency:

    .. code-block:: bash

        composer require monolog/monolog

Usage
-----

The MonologServiceProvider provides a ``monolog`` service. You can use it to
add log entries for any logging level through ``addDebug()``, ``addInfo()``,
``addWarning()`` and ``addError()``::

    use Symfony\Component\HttpFoundation\Response;

    $app->post('/user', function () use ($app) {
        // ...

        $app['monolog']->addInfo(sprintf("User '%s' registered.", $username));

        return new Response('', 201);
    });

Customization
-------------

You can configure Monolog (like adding or changing the handlers) before using
it by extending the ``monolog`` service::

    $app->extend('monolog', function($monolog, $app) {
        $monolog->pushHandler(...);

        return $monolog;
    });

By default, all requests, responses and errors are logged by an event listener
registered as a service called `monolog.listener`. You can replace or remove
this service if you want to modify or disable the logged information.

Traits
------

``Silex\Application\MonologTrait`` adds the following shortcuts:

* **log**: Logs a message.

.. code-block:: php

    $app->log(sprintf("User '%s' registered.", $username));

For more information, check out the `Monolog documentation
<https://github.com/Seldaek/monolog>`_.


================================================
FILE: doc/providers/remember_me.rst
================================================
Remember Me
===========

The *RememberMeServiceProvider* adds "Remember-Me" authentication to the
*SecurityServiceProvider*.

Parameters
----------

n/a

Services
--------

n/a

.. note::

    The service provider defines many other services that are used internally
    but rarely need to be customized.

Registering
-----------

Before registering this service provider, you must register the
*SecurityServiceProvider*::

    $app->register(new Silex\Provider\SecurityServiceProvider());
    $app->register(new Silex\Provider\RememberMeServiceProvider());

    $app['security.firewalls'] = array(
        'my-firewall' => array(
            'pattern'     => '^/secure$',
            'form'        => true,
            'logout'      => true,
            'remember_me' => array(
                'key'                => 'Choose_A_Unique_Random_Key',
                'always_remember_me' => true,
                /* Other options */
            ),
            'users' => array( /* ... */ ),
        ),
    );

Options
-------

* **key**: A secret key to generate tokens (you should generate a random
  string).

* **name**: Cookie name (default: ``REMEMBERME``).

* **lifetime**: Cookie lifetime (default: ``31536000`` ~ 1 year).

* **path**: Cookie path (default: ``/``).

* **domain**: Cookie domain (default: ``null`` = request domain).

* **secure**: Cookie is secure (default: ``false``).

* **httponly**: Cookie is HTTP only (default: ``true``).

* **always_remember_me**: Enable remember me (default: ``false``).

* **remember_me_parameter**: Name of the request parameter enabling remember_me
  on login. To add the checkbox to the login form. You can find more
  information in the `Symfony cookbook
  <http://symfony.com/doc/current/cookbook/security/remember_me.html>`_
  (default: ``_remember_me``).


================================================
FILE: doc/providers/security.rst
================================================
Security
========

The *SecurityServiceProvider* manages authentication and authorization for
your applications.

Parameters
----------

* **security.hide_user_not_found** (optional): Defines whether to hide user not
  found exception or not. Defaults to ``true``.

* **security.encoder.bcrypt.cost** (optional): Defines BCrypt password encoder cost. Defaults to 13.

Services
--------

* **security.token_storage**: Gives access to the user token.

* **security.authorization_checker**: Allows to check authorizations for the
  users.

* **security.authentication_manager**: An instance of
  `AuthenticationProviderManager
  <http://api.symfony.com/master/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.html>`_,
  responsible for authentication.

* **security.access_manager**: An instance of `AccessDecisionManager
  <http://api.symfony.com/master/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.html>`_,
  responsible for authorization.

* **security.session_strategy**: Define the session strategy used for
  authentication (default to a migration strategy).

* **security.user_checker**: Checks user flags after authentication.

* **security.last_error**: Returns the last authentication errors when given a
  Request object.

* **security.encoder_factory**: Defines the encoding strategies for user
  passwords (uses ``security.default_encoder``).

* **security.default_encoder**: The encoder to use by default for all users (BCrypt).

* **security.encoder.digest**: Digest password encoder.

* **security.encoder.bcrypt**: BCrypt password encoder.

* **security.encoder.pbkdf2**: Pbkdf2 password encoder.

* **user**: Returns the current user

.. note::

    The service provider defines many other services that are used internally
    but rarely need to be customized.

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\SecurityServiceProvider(), array(
        'security.firewalls' => // see below
    ));

.. note::

    Add the Symfony Security Component as a dependency:

    .. code-block:: bash

        composer require symfony/security

.. caution::

    If you're using a form to authenticate users, you need to enable
    ``SessionServiceProvider``.

.. caution::

    The security features are only available after the Application has been
    booted. So, if you want to use it outside of the handling of a request,
    don't forget to call ``boot()`` first::

        $app->boot();

Usage
-----

The Symfony Security component is powerful. To learn more about it, read the
`Symfony Security documentation
<http://symfony.com/doc/2.8/book/security.html>`_.

.. tip::

    When a security configuration does not behave as expected, enable logging
    (with the Monolog extension for instance) as the Security Component logs a
    lot of interesting information about what it does and why.

Below is a list of recipes that cover some common use cases.

Accessing the current User
~~~~~~~~~~~~~~~~~~~~~~~~~~

The current user information is stored in a token that is accessible via the
``security`` service::

    $token = $app['security.token_storage']->getToken();

If there is no information about the user, the token is ``null``. If the user
is known, you can get it with a call to ``getUser()``::

    if (null !== $token) {
        $user = $token->getUser();
    }

The user can be a string, an object with a ``__toString()`` method, or an
instance of `UserInterface
<http://api.symfony.com/master/Symfony/Component/Security/Core/User/UserInterface.html>`_.

Securing a Path with HTTP Authentication
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following configuration uses HTTP basic authentication to secure URLs
under ``/admin/``::

    $app['security.firewalls'] = array(
        'admin' => array(
            'pattern' => '^/admin',
            'http' => true,
            'users' => array(
                // raw password is foo
                'admin' => array('ROLE_ADMIN', '$2y$10$3i9/lVd8UOFIJ6PAMFt8gu3/r5g0qeCJvoSlLCsvMTythye19F77a'),
            ),
        ),
    );

The ``pattern`` is a regular expression on the URL path; the ``http`` setting
tells the security layer to use HTTP basic authentication and the ``users``
entry defines valid users.

If you want to restrict the firewall by more than the URL pattern (like the
HTTP method, the client IP, the hostname, or any Request attributes), use an
instance of a `RequestMatcher
<http://api.symfony.com/master/Symfony/Component/HttpFoundation/RequestMatcher.html>`_
for the ``pattern`` option::

    use Symfony/Component/HttpFoundation/RequestMatcher;

    $app['security.firewalls'] = array(
        'admin' => array(
            'pattern' => new RequestMatcher('^/admin', 'example.com', 'POST'),
            // ...
        ),
    );

Each user is defined with the following information:

* The role or an array of roles for the user (roles are strings beginning with
  ``ROLE_`` and ending with anything you want);

* The user encoded password.

.. caution::

    All users must at least have one role associated with them.

The default configuration of the extension enforces encoded passwords. To
generate a valid encoded password from a raw password, use the
``security.encoder_factory`` service::

    // find the encoder for a UserInterface instance
    $encoder = $app['security.encoder_factory']->getEncoder($user);

    // compute the encoded password for foo
    $password = $encoder->encodePassword('foo', $user->getSalt());

When the user is authenticated, the user stored in the token is an instance of
`User
<http://api.symfony.com/master/Symfony/Component/Security/Core/User/User.html>`_

.. caution::

    If you are using php-cgi under Apache, you need to add this configuration
    to make things work correctly:

    .. code-block:: apache

        RewriteEngine On
        RewriteCond %{HTTP:Authorization} ^(.+)$
        RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^(.*)$ app.php [QSA,L]

Securing a Path with a Form
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Using a form to authenticate users is very similar to the above configuration.
Instead of using the ``http`` setting, use the ``form`` one and define these
two parameters:

* **login_path**: The login path where the user is redirected when they are
  accessing a secured area without being authenticated so that they can enter
  their credentials;

* **check_path**: The check URL used by Symfony to validate the credentials of
  the user.

Here is how to secure all URLs under ``/admin/`` with a form::

    $app['security.firewalls'] = array(
        'admin' => array(
            'pattern' => '^/admin/',
            'form' => array('login_path' => '/login', 'check_path' => '/admin/login_check'),
            'users' => array(
                'admin' => array('ROLE_ADMIN', '$2y$10$3i9/lVd8UOFIJ6PAMFt8gu3/r5g0qeCJvoSlLCsvMTythye19F77a'),
            ),
        ),
    );

Always keep in mind the following two golden rules:

* The ``login_path`` path must always be defined **outside** the secured area
  (or if it is in the secured area, the ``anonymous`` authentication mechanism
  must be enabled -- see below);

* The ``check_path`` path must always be defined **inside** the secured area.

For the login form to work, create a controller like the following::

    use Symfony\Component\HttpFoundation\Request;

    $app->get('/login', function(Request $request) use ($app) {
        return $app['twig']->render('login.html', array(
            'error'         => $app['security.last_error']($request),
            'last_username' => $app['session']->get('_security.last_username'),
        ));
    });

The ``error`` and ``last_username`` variables contain the last authentication
error and the last username entered by the user in case of an authentication
error.

Create the associated template:

.. code-block:: jinja

    <form action="{{ path('admin_login_check') }}" method="post">
        {{ error }}
        <input type="text" name="_username" value="{{ last_username }}" />
        <input type="password" name="_password" value="" />
        <input type="submit" />
    </form>

.. note::

    The ``admin_login_check`` route is automatically defined by Silex and its
    name is derived from the ``check_path`` value (all ``/`` are replaced with
    ``_`` and the leading ``/`` is stripped).

Defining more than one Firewall
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You are not limited to define one firewall per project.

Configuring several firewalls is useful when you want to secure different
parts of your website with different authentication strategies or for
different users (like using an HTTP basic authentication for the website API
and a form to secure your website administration area).

It's also useful when you want to secure all URLs except the login form::

    $app['security.firewalls'] = array(
        'login' => array(
            'pattern' => '^/login$',
        ),
        'secured' => array(
            'pattern' => '^.*$',
            'form' => array('login_path' => '/login', 'check_path' => '/login_check'),
            'users' => array(
                'admin' => array('ROLE_ADMIN', '$2y$10$3i9/lVd8UOFIJ6PAMFt8gu3/r5g0qeCJvoSlLCsvMTythye19F77a'),
            ),
        ),
    );

The order of the firewall configurations is significant as the first one to
match wins. The above configuration first ensures that the ``/login`` URL is
not secured (no authentication settings), and then it secures all other URLs.

.. tip::

    You can toggle all registered authentication mechanisms for a particular
    area on and off with the ``security`` flag::

        $app['security.firewalls'] = array(
            'api' => array(
                'pattern' => '^/api',
                'security' => $app['debug'] ? false : true,
                'wsse' => true,

                // ...
            ),
        );

Adding a Logout
~~~~~~~~~~~~~~~

When using a form for authentication, you can let users log out if you add the
``logout`` setting, where ``logout_path`` must match the main firewall
pattern::

    $app['security.firewalls'] = array(
        'secured' => array(
            'pattern' => '^/admin/',
            'form' => array('login_path' => '/login', 'check_path' => '/admin/login_check'),
            'logout' => array('logout_path' => '/admin/logout', 'invalidate_session' => true),

            // ...
        ),
    );

A route is automatically generated, based on the configured path (all ``/``
are replaced with ``_`` and the leading ``/`` is stripped):

.. code-block:: jinja

    <a href="{{ path('admin_logout') }}">Logout</a>

Allowing Anonymous Users
~~~~~~~~~~~~~~~~~~~~~~~~

When securing only some parts of your website, the user information are not
available in non-secured areas. To make the user accessible in such areas,
enabled the ``anonymous`` authentication mechanism::

    $app['security.firewalls'] = array(
        'unsecured' => array(
            'anonymous' => true,

            // ...
        ),
    );

When enabling the anonymous setting, a user will always be accessible from the
security context; if the user is not authenticated, it returns the ``anon.``
string.

Checking User Roles
~~~~~~~~~~~~~~~~~~~

To check if a user is granted some role, use the ``isGranted()`` method on the
security context::

    if ($app['security.authorization_checker']->isGranted('ROLE_ADMIN')) {
        // ...
    }

You can check roles in Twig templates too:

.. code-block:: jinja

    {% if is_granted('ROLE_ADMIN') %}
        <a href="/secured?_switch_user=fabien">Switch to Fabien</a>
    {% endif %}

You can check if a user is "fully authenticated" (not an anonymous user for
instance) with the special ``IS_AUTHENTICATED_FULLY`` role:

.. code-block:: jinja

    {% if is_granted('IS_AUTHENTICATED_FULLY') %}
        <a href="{{ path('logout') }}">Logout</a>
    {% else %}
        <a href="{{ path('login') }}">Login</a>
    {% endif %}

Of course you will need to define a ``login`` route for this to work.

.. tip::

    Don't use the ``getRoles()`` method to check user roles.

.. caution::

    ``isGranted()`` throws an exception when no authentication information is
    available (which is the case on non-secured area).

Impersonating a User
~~~~~~~~~~~~~~~~~~~~

If you want to be able to switch to another user (without knowing the user
credentials), enable the ``switch_user`` authentication strategy::

    $app['security.firewalls'] = array(
        'unsecured' => array(
            'switch_user' => array('parameter' => '_switch_user', 'role' => 'ROLE_ALLOWED_TO_SWITCH'),

            // ...
        ),
    );

Switching to another user is now a matter of adding the ``_switch_user`` query
parameter to any URL when logged in as a user who has the
``ROLE_ALLOWED_TO_SWITCH`` role:

.. code-block:: jinja

    {% if is_granted('ROLE_ALLOWED_TO_SWITCH') %}
        <a href="?_switch_user=fabien">Switch to user Fabien</a>
    {% endif %}

You can check that you are impersonating a user by checking the special
``ROLE_PREVIOUS_ADMIN``. This is useful for instance to allow the user to
switch back to their primary account:

.. code-block:: jinja

    {% if is_granted('ROLE_PREVIOUS_ADMIN') %}
        You are an admin but you've switched to another user,
        <a href="?_switch_user=_exit"> exit</a> the switch.
    {% endif %}

Defining a Role Hierarchy
~~~~~~~~~~~~~~~~~~~~~~~~~

Defining a role hierarchy allows to automatically grant users some additional
roles::

    $app['security.role_hierarchy'] = array(
        'ROLE_ADMIN' => array('ROLE_USER', 'ROLE_ALLOWED_TO_SWITCH'),
    );

With this configuration, all users with the ``ROLE_ADMIN`` role also
automatically have the ``ROLE_USER`` and ``ROLE_ALLOWED_TO_SWITCH`` roles.

Defining Access Rules
~~~~~~~~~~~~~~~~~~~~~

Roles are a great way to adapt the behavior of your website depending on
groups of users, but they can also be used to further secure some areas by
defining access rules::

    $app['security.access_rules'] = array(
        array('^/admin', 'ROLE_ADMIN', 'https'),
        array('^.*$', 'ROLE_USER'),
    );

With the above configuration, users must have the ``ROLE_ADMIN`` to access the
``/admin`` section of the website, and ``ROLE_USER`` for everything else.
Furthermore, the admin section can only be accessible via HTTPS (if that's not
the case, the user will be automatically redirected).

.. note::

    The first argument can also be a `RequestMatcher
    <http://api.symfony.com/master/Symfony/Component/HttpFoundation/RequestMatcher.html>`_
    instance.

Defining a custom User Provider
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Using an array of users is simple and useful when securing an admin section of
a personal website, but you can override this default mechanism with you own.

The ``users`` setting can be defined as a service that returns an instance of
`UserProviderInterface
<http://api.symfony.com/master/Symfony/Component/Security/Core/User/UserProviderInterface.html>`_::

    'users' => function () use ($app) {
        return new UserProvider($app['db']);
    },

Here is a simple example of a user provider, where Doctrine DBAL is used to
store the users::

    use Symfony\Component\Security\Core\User\UserProviderInterface;
    use Symfony\Component\Security\Core\User\UserInterface;
    use Symfony\Component\Security\Core\User\User;
    use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
    use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
    use Doctrine\DBAL\Connection;

    class UserProvider implements UserProviderInterface
    {
        private $conn;

        public function __construct(Connection $conn)
        {
            $this->conn = $conn;
        }

        public function loadUserByUsername($username)
        {
            $stmt = $this->conn->executeQuery('SELECT * FROM users WHERE username = ?', array(strtolower($username)));

            if (!$user = $stmt->fetch()) {
                throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
            }

            return new User($user['username'], $user['password'], explode(',', $user['roles']), true, true, true, true);
        }

        public function refreshUser(UserInterface $user)
        {
            if (!$user instanceof User) {
                throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
            }

            return $this->loadUserByUsername($user->getUsername());
        }

        public function supportsClass($class)
        {
            return $class === 'Symfony\Component\Security\Core\User\User';
        }
    }

In this example, instances of the default ``User`` class are created for the
users, but you can define your own class; the only requirement is that the
class must implement `UserInterface
<http://api.symfony.com/master/Symfony/Component/Security/Core/User/UserInterface.html>`_

And here is the code that you can use to create the database schema and some
sample users::

    use Doctrine\DBAL\Schema\Table;

    $schema = $app['db']->getSchemaManager();
    if (!$schema->tablesExist('users')) {
        $users = new Table('users');
        $users->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => true));
        $users->setPrimaryKey(array('id'));
        $users->addColumn('username', 'string', array('length' => 32));
        $users->addUniqueIndex(array('username'));
        $users->addColumn('password', 'string', array('length' => 255));
        $users->addColumn('roles', 'string', array('length' => 255));

        $schema->createTable($users);

        $app['db']->insert('users', array(
          'username' => 'fabien',
          'password' => '$2y$10$3i9/lVd8UOFIJ6PAMFt8gu3/r5g0qeCJvoSlLCsvMTythye19F77a',
          'roles' => 'ROLE_USER'
        ));

        $app['db']->insert('users', array(
          'username' => 'admin',
          'password' => '$2y$10$3i9/lVd8UOFIJ6PAMFt8gu3/r5g0qeCJvoSlLCsvMTythye19F77a',
          'roles' => 'ROLE_ADMIN'
        ));
    }

.. tip::

    If you are using the Doctrine ORM, the Symfony bridge for Doctrine
    provides a user provider class that is able to load users from your
    entities.

Defining a custom Encoder
~~~~~~~~~~~~~~~~~~~~~~~~~

By default, Silex uses the ``BCrypt`` algorithm to encode passwords.
Additionally, the password is encoded multiple times.
You can change these defaults by overriding ``security.default_encoder``
service to return one of the predefined encoders:

* **security.encoder.digest**: Digest password encoder.

* **security.encoder.bcrypt**: BCrypt password encoder.

* **security.encoder.pbkdf2**: Pbkdf2 password encoder.

.. code-block:: php

    $app['security.default_encoder'] = function ($app) {
        return $app['security.encoder.pbkdf2'];
    };

Or you can define you own, fully customizable encoder::

    use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;

    $app['security.default_encoder'] = function ($app) {
        // Plain text (e.g. for debugging)
        return new PlaintextPasswordEncoder();
    };

.. tip::

    You can change the default BCrypt encoding cost by overriding ``security.encoder.bcrypt.cost``

Defining a custom Authentication Provider
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The Symfony Security component provides a lot of ready-to-use authentication
providers (form, HTTP, X509, remember me, ...), but you can add new ones
easily. To register a new authentication provider, create a service named
``security.authentication_listener.factory.XXX`` where ``XXX`` is the name you want to
use in your configuration::

    $app['security.authentication_listener.factory.wsse'] = $app->protect(function ($name, $options) use ($app) {
        // define the authentication provider object
        $app['security.authentication_provider.'.$name.'.wsse'] = function () use ($app) {
            return new WsseProvider($app['security.user_provider.default'], __DIR__.'/security_cache');
        };

        // define the authentication listener object
        $app['security.authentication_listener.'.$name.'.wsse'] = function () use ($app) {
            return new WsseListener($app['security.token_storage'], $app['security.authentication_manager']);
        };

        return array(
            // the authentication provider id
            'security.authentication_provider.'.$name.'.wsse',
            // the authentication listener id
            'security.authentication_listener.'.$name.'.wsse',
            // the entry point id
            null,
            // the position of the listener in the stack
            'pre_auth'
        );
    });

You can now use it in your configuration like any other built-in
authentication provider::

    $app->register(new Silex\Provider\SecurityServiceProvider(), array(
        'security.firewalls' => array(
            'default' => array(
                'wsse' => true,

                // ...
            ),
        ),
    ));

Instead of ``true``, you can also define an array of options that customize
the behavior of your authentication factory; it will be passed as the second
argument of your authentication factory (see above).

This example uses the authentication provider classes as described in the
Symfony `cookbook`_.


.. note::

    The Guard component simplifies the creation of custom authentication
    providers. :doc:`How to Create a Custom Authentication System with Guard
    </cookbook/guard_authentication>`

Stateless Authentication
~~~~~~~~~~~~~~~~~~~~~~~~

By default, a session cookie is created to persist the security context of
the user. However, if you use certificates, HTTP authentication, WSSE and so
on, the credentials are sent for each request. In that case, you can turn off
persistence by activating the ``stateless`` authentication flag::

    $app['security.firewalls'] = array(
        'default' => array(
            'stateless' => true,
            'wsse' => true,

            // ...
        ),
    );

Traits
------

``Silex\Application\SecurityTrait`` adds the following shortcuts:

* **encodePassword**: Encode a given password.

.. code-block:: php

    $user = $app->user();

    $encoded = $app->encodePassword($user, 'foo');

``Silex\Route\SecurityTrait`` adds the following methods to the controllers:

* **secure**: Secures a controller for the given roles.

.. code-block:: php

    $app->get('/', function () {
        // do something but only for admins
    })->secure('ROLE_ADMIN');

.. caution::

    The ``Silex\Route\SecurityTrait`` must be used with a user defined
    ``Route`` class, not the application.

    .. code-block:: php

        use Silex\Route;

        class MyRoute extends Route
        {
            use Route\SecurityTrait;
        }

    .. code-block:: php

        $app['route_class'] = 'MyRoute';


.. _cookbook: http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html


================================================
FILE: doc/providers/serializer.rst
================================================
Serializer
==========

The *SerializerServiceProvider* provides a service for serializing objects.

Parameters
----------

None.

Services
--------

* **serializer**: An instance of `Symfony\\Component\\Serializer\\Serializer
  <http://api.symfony.com/master/Symfony/Component/Serializer/Serializer.html>`_.

* **serializer.encoders**: `Symfony\\Component\\Serializer\\Encoder\\JsonEncoder
  <http://api.symfony.com/master/Symfony/Component/Serializer/Encoder/JsonEncoder.html>`_
  and `Symfony\\Component\\Serializer\\Encoder\\XmlEncoder
  <http://api.symfony.com/master/Symfony/Component/Serializer/Encoder/XmlEncoder.html>`_.

* **serializer.normalizers**: `Symfony\\Component\\Serializer\\Normalizer\\CustomNormalizer
  <http://api.symfony.com/master/Symfony/Component/Serializer/Normalizer/CustomNormalizer.html>`_
  and `Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer
  <http://api.symfony.com/master/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.html>`_.

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\SerializerServiceProvider());
    
.. note::

    Add the Symfony's `Serializer Component
    <http://symfony.com/doc/current/components/serializer.html>`_ as a
    dependency:

    .. code-block:: bash

        composer require symfony/serializer

Usage
-----

The ``SerializerServiceProvider`` provider provides a ``serializer`` service::

    use Silex\Application;
    use Silex\Provider\SerializerServiceProvider;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;

    $app = new Application();

    $app->register(new SerializerServiceProvider());

    // only accept content types supported by the serializer via the assert method.
    $app->get("/pages/{id}.{_format}", function (Request $request, $id) use ($app) {
        // assume a page_repository service exists that returns Page objects. The
        // object returned has getters and setters exposing the state.
        $page = $app['page_repository']->find($id);
        $format = $request->getRequestFormat();

        if (!$page instanceof Page) {
            $app->abort("No page found for id: $id");
        }

        return new Response($app['serializer']->serialize($page, $format), 200, array(
            "Content-Type" => $request->getMimeType($format)
        ));
    })->assert("_format", "xml|json")
      ->assert("id", "\d+");


================================================
FILE: doc/providers/service_controller.rst
================================================
Service Controllers
===================

As your Silex application grows, you may wish to begin organizing your
controllers in a more formal fashion. Silex can use controller classes out of
the box, but with a bit of work, your controllers can be created as services,
giving you the full power of dependency injection and lazy loading.

.. ::todo Link above to controller classes cookbook

Why would I want to do this?
----------------------------

- Dependency Injection over Service Location

  Using this method, you can inject the actual dependencies required by your
  controller and gain total inversion of control, while still maintaining the
  lazy loading of your controllers and its dependencies. Because your
  dependencies are clearly defined, they are easily mocked, allowing you to test
  your controllers in isolation.

- Framework Independence

  Using this method, your controllers start to become more independent of the
  framework you are using. Carefully crafted, your controllers will become
  reusable with multiple frameworks. By keeping careful control of your
  dependencies, your controllers could easily become compatible with Silex,
  Symfony (full stack) and Drupal, to name just a few.

Parameters
----------

There are currently no parameters for the ``ServiceControllerServiceProvider``.

Services
--------

There are no extra services provided, the ``ServiceControllerServiceProvider``
simply extends the existing **resolver** service.

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\ServiceControllerServiceProvider());

Usage
-----

In this slightly contrived example of a blog API, we're going to change the
``/posts.json`` route to use a controller, that is defined as a service.

.. code-block:: php

    use Silex\Application;
    use Demo\Repository\PostRepository;

    $app = new Application();

    $app['posts.repository'] = function() {
        return new PostRepository;
    };

    $app->get('/posts.json', function() use ($app) {
        return $app->json($app['posts.repository']->findAll());
    });

Rewriting your controller as a service is pretty simple, create a Plain Ol' PHP
Object with your ``PostRepository`` as a dependency, along with an
``indexJsonAction`` method to handle the request. Although not shown in the
example below, you can use type hinting and parameter naming to get the
parameters you need, just like with standard Silex routes.

If you are a TDD/BDD fan (and you should be), you may notice that this
controller has well defined responsibilities and dependencies, and is easily
tested/specced. You may also notice that the only external dependency is on
``Symfony\Component\HttpFoundation\JsonResponse``, meaning this controller could
easily be used in a Symfony (full stack) application, or potentially with other
applications or frameworks that know how to handle a `Symfony/HttpFoundation
<http://symfony.com/doc/master/components/http_foundation/introduction.html>`_
``Response`` object.

.. code-block:: php

    namespace Demo\Controller;

    use Demo\Repository\PostRepository;
    use Symfony\Component\HttpFoundation\JsonResponse;

    class PostController
    {
        protected $repo;

        public function __construct(PostRepository $repo)
        {
            $this->repo = $repo;
        }

        public function indexJsonAction()
        {
            return new JsonResponse($this->repo->findAll());
        }
    }

And lastly, define your controller as a service in the application, along with
your route. The syntax in the route definition is the name of the service,
followed by a single colon (:), followed by the method name.

.. code-block:: php

    $app['posts.controller'] = function() use ($app) {
        return new PostController($app['posts.repository']);
    };

    $app->get('/posts.json', "posts.controller:indexJsonAction");

In addition to using classes for service controllers, you can define any
callable as a service in the application to be used for a route.

.. code-block:: php

    namespace Demo\Controller;

    use Demo\Repository\PostRepository;
    use Symfony\Component\HttpFoundation\JsonResponse;

    function postIndexJson(PostRepository $repo) {
        return function() use ($repo) {
            return new JsonResponse($repo->findAll());
        };
    }

And when defining your route, the code would look like the following:

.. code-block:: php

    $app['posts.controller'] = function($app) {
        return Demo\Controller\postIndexJson($app['posts.repository']);
    };

    $app->get('/posts.json', 'posts.controller');


================================================
FILE: doc/providers/session.rst
================================================
Session
=======

The *SessionServiceProvider* provides a service for storing data persistently
between requests.

Parameters
----------

* **session.storage.save_path** (optional): The path for the
  ``NativeFileSessionHandler``, defaults to the value of
  ``sys_get_temp_dir()``.

* **session.storage.options**: An array of options that is passed to the
  constructor of the ``session.storage`` service.

  In case of the default `NativeSessionStorage
  <http://api.symfony.com/master/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.html>`_,
  the most useful options are:

  * **name**: The cookie name (_SESS by default)
  * **id**: The session id (null by default)
  * **cookie_lifetime**: Cookie lifetime
  * **cookie_path**: Cookie path
  * **cookie_domain**: Cookie domain
  * **cookie_secure**: Cookie secure (HTTPS)
  * **cookie_httponly**: Whether the cookie is http only

  However, all of these are optional. Default Sessions life time is 1800
  seconds (30 minutes). To override this, set the ``lifetime`` option.

  For a full list of available options, read the `PHP
  <http://php.net/session.configuration>`_ official documentation.

* **session.test**: Whether to simulate sessions or not (useful when writing
  functional tests).

Services
--------

* **session**: An instance of Symfony's `Session
  <http://api.symfony.com/master/Symfony/Component/HttpFoundation/Session/Session.html>`_.

* **session.storage**: A service that is used for persistence of the session
  data.

* **session.storage.handler**: A service that is used by the
  ``session.storage`` for data access. Defaults to a `NativeFileSessionHandler
  <http://api.symfony.com/master/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.html>`_
  storage handler.

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\SessionServiceProvider());

Usage
-----

The Session provider provides a ``session`` service. Here is an example that
authenticates a user and creates a session for them::

    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;

    $app->get('/login', function (Request $request) use ($app) {
        $username = $request->server->get('PHP_AUTH_USER', false);
        $password = $request->server->get('PHP_AUTH_PW');

        if ('igor' === $username && 'password' === $password) {
            $app['session']->set('user', array('username' => $username));
            return $app->redirect('/account');
        }

        $response = new Response();
        $response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', 'site_login'));
        $response->setStatusCode(401, 'Please sign in.');
        return $response;
    });

    $app->get('/account', function () use ($app) {
        if (null === $user = $app['session']->get('user')) {
            return $app->redirect('/login');
        }

        return "Welcome {$user['username']}!";
    });


Custom Session Configurations
-----------------------------

If your system is using a custom session configuration (such as a redis handler
from a PHP extension) then you need to disable the NativeFileSessionHandler by
setting ``session.storage.handler`` to null. You will have to configure the
``session.save_path`` ini setting yourself in that case.

.. code-block:: php

    $app['session.storage.handler'] = null;



================================================
FILE: doc/providers/swiftmailer.rst
================================================
Swiftmailer
===========

The *SwiftmailerServiceProvider* provides a service for sending email through
the `Swift Mailer <http://swiftmailer.org>`_ library.

You can use the ``mailer`` service to send messages easily. By default, it
will attempt to send emails through SMTP.

Parameters
----------

* **swiftmailer.use_spool**: A boolean to specify whether or not to use the
  memory spool, defaults to true.

* **swiftmailer.options**: An array of options for the default SMTP-based
  configuration.

  The following options can be set:

  * **host**: SMTP hostname, defaults to 'localhost'.
  * **port**: SMTP port, defaults to 25.
  * **username**: SMTP username, defaults to an empty string.
  * **password**: SMTP password, defaults to an empty string.
  * **encryption**: SMTP encryption, defaults to null. Valid values are 'tls', 'ssl', or null (indicating no encryption).
  * **auth_mode**: SMTP authentication mode, defaults to null. Valid values are 'plain', 'login', 'cram-md5', or null.

  Example usage::

    $app['swiftmailer.options'] = array(
        'host' => 'host',
        'port' => '25',
        'username' => 'username',
        'password' => 'password',
        'encryption' => null,
        'auth_mode' => null
    );

* **swiftmailer.sender_address**: If set, all messages will be delivered with
  this address as the "return path" address.

* **swiftmailer.delivery_addresses**: If not empty, all email messages will be
  sent to those addresses instead of being sent to their actual recipients. This
  is often useful when developing.

* **swiftmailer.delivery_whitelist**: Used in combination with
  ``delivery_addresses``. If set, emails matching any of these patterns will be
  delivered like normal, as well as being sent to ``delivery_addresses``.

Services
--------

* **mailer**: The mailer instance.

  Example usage::

    $message = \Swift_Message::newInstance();

    // ...

    $app['mailer']->send($message);

* **swiftmailer.transport**: The transport used for e-mail
  delivery. Defaults to a ``Swift_Transport_EsmtpTransport``.

* **swiftmailer.transport.buffer**: StreamBuffer used by
  the transport.

* **swiftmailer.transport.authhandler**: Authentication
  handler used by the transport. Will try the following
  by default: CRAM-MD5, login, plaintext.

* **swiftmailer.transport.eventdispatcher**: Internal event
  dispatcher used by Swiftmailer.

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\SwiftmailerServiceProvider());

.. note::

    Add SwiftMailer as a dependency:

    .. code-block:: bash

        composer require swiftmailer/swiftmailer

Usage
-----

The Swiftmailer provider provides a ``mailer`` service::

    use Symfony\Component\HttpFoundation\Request;

    $app->post('/feedback', function (Request $request) use ($app) {
        $message = \Swift_Message::newInstance()
            ->setSubject('[YourSite] Feedback')
            ->setFrom(array('noreply@yoursite.com'))
            ->setTo(array('feedback@yoursite.com'))
            ->setBody($request->get('message'));

        $app['mailer']->send($message);

        return new Response('Thank you for your feedback!', 201);
    });

Usage in commands
~~~~~~~~~~~~~~~~~

By default, the Swiftmailer provider sends the emails using the ``KernelEvents::TERMINATE``
event, which is fired after the response has been sent. However, as this event
isn't fired for console commands, your emails won't be sent.

For that reason, if you send emails using a command console, it is recommended
that you disable the use of the memory spool (before accessing ``$app['mailer']``)::

    $app['swiftmailer.use_spool'] = false;

Alternatively, you can just make sure to flush the message spool by hand before
ending the command execution. To do so, use the following code::

    $app['swiftmailer.spooltransport']
        ->getSpool()
        ->flushQueue($app['swiftmailer.transport'])
    ;

Traits
------

``Silex\Application\SwiftmailerTrait`` adds the following shortcuts:

* **mail**: Sends an email.

.. code-block:: php

    $app->mail(\Swift_Message::newInstance()
        ->setSubject('[YourSite] Feedback')
        ->setFrom(array('noreply@yoursite.com'))
        ->setTo(array('feedback@yoursite.com'))
        ->setBody($request->get('message')));

For more information, check out the `Swift Mailer documentation
<http://swiftmailer.org>`_.


================================================
FILE: doc/providers/translation.rst
================================================
Translation
===========

The *TranslationServiceProvider* provides a service for translating your
application into different languages.

Parameters
----------

* **translator.domains** (optional): A mapping of domains/locales/messages.
  This parameter contains the translation data for all languages and domains.

* **locale** (optional): The locale for the translator. You will most likely
  want to set this based on some request parameter. Defaults to ``en``.

* **locale_fallbacks** (optional): Fallback locales for the translator. It will
  be used when the current locale has no messages set. Defaults to ``en``.

Services
--------

* **translator**: An instance of `Translator
  <http://api.symfony.com/master/Symfony/Component/Translation/Translator.html>`_,
  that is used for translation.

* **translator.loader**: An instance of an implementation of the translation
  `LoaderInterface
  <http://api.symfony.com/master/Symfony/Component/Translation/Loader/LoaderInterface.html>`_,
  defaults to an `ArrayLoader
  <http://api.symfony.com/master/Symfony/Component/Translation/Loader/ArrayLoader.html>`_.

* **translator.message_selector**: An instance of `MessageSelector
  <http://api.symfony.com/master/Symfony/Component/Translation/MessageSelector.html>`_.

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\LocaleServiceProvider());
    $app->register(new Silex\Provider\TranslationServiceProvider(), array(
        'locale_fallbacks' => array('en'),
    ));

.. note::

    Add the Symfony Translation Component as a dependency:

    .. code-block:: bash

        composer require symfony/translation

Usage
-----

The Translation provider provides a ``translator`` service and makes use of
the ``translator.domains`` parameter::

    $app['translator.domains'] = array(
        'messages' => array(
            'en' => array(
                'hello'     => 'Hello %name%',
                'goodbye'   => 'Goodbye %name%',
            ),
            'de' => array(
                'hello'     => 'Hallo %name%',
                'goodbye'   => 'Tschüss %name%',
            ),
            'fr' => array(
                'hello'     => 'Bonjour %name%',
                'goodbye'   => 'Au revoir %name%',
            ),
        ),
        'validators' => array(
            'fr' => array(
                'This value should be a valid number.' => 'Cette valeur doit être un nombre.',
            ),
        ),
    );

    $app->get('/{_locale}/{message}/{name}', function ($message, $name) use ($app) {
        return $app['translator']->trans($message, array('%name%' => $name));
    });

The above example will result in following routes:

* ``/en/hello/igor`` will return ``Hello igor``.

* ``/de/hello/igor`` will return ``Hallo igor``.

* ``/fr/hello/igor`` will return ``Bonjour igor``.

* ``/it/hello/igor`` will return ``Hello igor`` (because of the fallback).

Using Resources
---------------

When translations are stored in a file, you can load them as follows::

    $app = new Application();
    
    $app->register(new TranslationServiceProvider());
    $app->extend('translator.resources', function ($resources, $app) {
        $resources = array_merge($resources, array(
            array('array', array('This value should be a valid number.' => 'Cette valeur doit être un nombre.'), 'fr', 'validators'),
        ));

        return $resources;
    });

Traits
------

``Silex\Application\TranslationTrait`` adds the following shortcuts:

* **trans**: Translates the given message.

* **transChoice**: Translates the given choice message by choosing a
  translation according to a number.

.. code-block:: php

    $app->trans('Hello World');

    $app->transChoice('Hello World');

Recipes
-------

YAML-based language files
~~~~~~~~~~~~~~~~~~~~~~~~~

Having your translations in PHP files can be inconvenient. This recipe will
show you how to load translations from external YAML files.

First, add the Symfony ``Config`` and ``Yaml`` components as dependencies:

.. code-block:: bash

    composer require symfony/config symfony/yaml

Next, you have to create the language mappings in YAML files. A naming you can
use is ``locales/en.yml``. Just do the mapping in this file as follows:

.. code-block:: yaml

    hello: Hello %name%
    goodbye: Goodbye %name%

Then, register the ``YamlFileLoader`` on the ``translator`` and add all your
translation files::

    use Symfony\Component\Translation\Loader\YamlFileLoader;

    $app->extend('translator', function($translator, $app) {
        $translator->addLoader('yaml', new YamlFileLoader());

        $translator->addResource('yaml', __DIR__.'/locales/en.yml', 'en');
        $translator->addResource('yaml', __DIR__.'/locales/de.yml', 'de');
        $translator->addResource('yaml', __DIR__.'/locales/fr.yml', 'fr');

        return $translator;
    });

XLIFF-based language files
~~~~~~~~~~~~~~~~~~~~~~~~~~

Just as you would do with YAML translation files, you first need to add the
Symfony ``Config`` component as a dependency (see above for details).

Then, similarly, create XLIFF files in your locales directory and add them to
the translator::

    $translator->addResource('xliff', __DIR__.'/locales/en.xlf', 'en');
    $translator->addResource('xliff', __DIR__.'/locales/de.xlf', 'de');
    $translator->addResource('xliff', __DIR__.'/locales/fr.xlf', 'fr');

.. note::

    The XLIFF loader is already pre-configured by the extension.

Accessing translations in Twig templates
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Once loaded, the translation service provider is available from within Twig
templates when using the Twig bridge provided by Symfony (see
:doc:`TwigServiceProvider </providers/twig>`):

.. code-block:: jinja

    {{ 'translation_key'|trans }}
    {{ 'translation_key'|transchoice }}
    {% trans %}translation_key{% endtrans %}


================================================
FILE: doc/providers/twig.rst
================================================
Twig
====

The *TwigServiceProvider* provides integration with the `Twig
<http://twig.sensiolabs.org/>`_ template engine.

Parameters
----------

* **twig.path** (optional): Path to the directory containing twig template
  files (it can also be an array of paths).

* **twig.templates** (optional): An associative array of template names to
  template contents. Use this if you want to define your templates inline.

* **twig.options** (optional): An associative array of twig
  options. Check out the `twig documentation <http://twig.sensiolabs.org/doc/api.html#environment-options>`_
  for more information.

* **twig.form.templates** (optional): An array of templates used to render
  forms (only available when the ``FormServiceProvider`` is enabled). The
  default theme is ``form_div_layout.html.twig``, but you can use the other
  built-in themes: ``form_table_layout.html.twig``,
  ``bootstrap_3_layout.html.twig``, and
  ``bootstrap_3_horizontal_layout.html.twig``.

Services
--------

* **twig**: The ``Twig_Environment`` instance. The main way of
  interacting with Twig.

* **twig.loader**: The loader for Twig templates which uses the ``twig.path``
  and the ``twig.templates`` options. You can also replace the loader
  completely.

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\TwigServiceProvider(), array(
        'twig.path' => __DIR__.'/views',
    ));

.. note::

    Add Twig as a dependency:

    .. code-block:: bash

        composer require twig/twig

Usage
-----

The Twig provider provides a ``twig`` service that can render templates::

    $app->get('/hello/{name}', function ($name) use ($app) {
        return $app['twig']->render('hello.twig', array(
            'name' => $name,
        ));
    });

Symfony Components Integration
------------------------------

Symfony provides a Twig bridge that provides additional integration between
some Symfony components and Twig. Add it as a dependency:

.. code-block:: bash

    composer require symfony/twig-bridge

When present, the ``TwigServiceProvider`` will provide you with the following
additional capabilities.

* Access to the ``path()`` and ``url()`` functions. You can find more
  information in the `Symfony Routing documentation
  <http://symfony.com/doc/current/book/routing.html#generating-urls-from-a-template>`_:

  .. code-block:: jinja
  
      {{ path('homepage') }}
      {{ url('homepage') }} {# generates the absolute url http://example.org/ #}
      {{ path('hello', {name: 'Fabien'}) }}
      {{ url('hello', {name: 'Fabien'}) }} {# generates the absolute url http://example.org/hello/Fabien #}

* Access to the ``absolute_url()`` and ``relative_path()`` Twig functions.

Translations Support
~~~~~~~~~~~~~~~~~~~~

If you are using the ``TranslationServiceProvider``, you will get the
``trans()`` and ``transchoice()`` functions for translation in Twig templates.
You can find more information in the `Symfony Translation documentation
<http://symfony.com/doc/current/book/translation.html#twig-templates>`_.

Form Support
~~~~~~~~~~~~

If you are using the ``FormServiceProvider``, you will get a set of helpers for
working with forms in templates. You can find more information in the `Symfony
Forms reference
<http://symfony.com/doc/current/reference/forms/twig_reference.html>`_.

Security Support
~~~~~~~~~~~~~~~~

If you are using the ``SecurityServiceProvider``, you will have access to the
``is_granted()`` function in templates. You can find more information in the
`Symfony Security documentation
<http://symfony.com/doc/current/book/security.html#access-control-in-templates>`_.

Global Variable
~~~~~~~~~~~~~~~

When the Twig bridge is available, the ``global`` variable refers to an
instance of `AppVariable <http://api.symfony.com/master/Symfony/Bridge/Twig/AppVariable.html>`_.
It gives access to the following methods:

.. code-block:: jinja

    {# The current Request #}
    {{ global.request }}

    {# The current User (when security is enabled) #}
    {{ global.user }}

    {# The current Session #}
    {{ global.session }}

    {# The debug flag #}
    {{ global.debug }}

Rendering a Controller
~~~~~~~~~~~~~~~~~~~~~~

A ``render`` function is also registered to help you render another controller
from a template (available when the :doc:`HttpFragment Service Provider
</providers/http_fragment>` is registered):

.. code-block:: jinja

    {{ render(url('sidebar')) }}

    {# or you can reference a controller directly without defining a route for it #}
    {{ render(controller(controller)) }}

.. note::

    You must prepend the ``app.request.baseUrl`` to render calls to ensure
    that the render works when deployed into a sub-directory of the docroot.

.. note::

    Read the Twig `reference`_ for Symfony document to learn more about the
    various Twig functions.

Traits
------

``Silex\Application\TwigTrait`` adds the following shortcuts:

* **render**: Renders a view with the given parameters and returns a Response
  object.

.. code-block:: php

    return $app->render('index.html', ['name' => 'Fabien']);

    $response = new Response();
    $response->setTtl(10);

    return $app->render('index.html', ['name' => 'Fabien'], $response);

.. code-block:: php

    // stream a view
    use Symfony\Component\HttpFoundation\StreamedResponse;

    return $app->render('index.html', ['name' => 'Fabien'], new StreamedResponse());

Customization
-------------

You can configure the Twig environment before using it by extending the
``twig`` service::

    $app->extend('twig', function($twig, $app) {
        $twig->addGlobal('pi', 3.14);
        $twig->addFilter('levenshtein', new \Twig_Filter_Function('levenshtein'));

        return $twig;
    });

For more information, check out the `official Twig documentation
<http://twig.sensiolabs.org>`_.

.. _reference: https://symfony.com/doc/current/reference/twig_reference.html#controller


================================================
FILE: doc/providers/validator.rst
================================================
Validator
=========

The *ValidatorServiceProvider* provides a service for validating data. It is
most useful when used with the *FormServiceProvider*, but can also be used
standalone.

Parameters
----------

* **validator.validator_service_ids**: An array of service names representing
  validators.

Services
--------

* **validator**: An instance of `Validator
  <http://api.symfony.com/master/Symfony/Component/Validator/ValidatorInterface.html>`_.

* **validator.mapping.class_metadata_factory**: Factory for metadata loaders,
  which can read validation constraint information from classes. Defaults to
  StaticMethodLoader--ClassMetadataFactory.

  This means you can define a static ``loadValidatorMetadata`` method on your
  data class, which takes a ClassMetadata argument. Then you can set
  constraints on this ClassMetadata instance.

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\ValidatorServiceProvider());

.. note::

    Add the Symfony Validator Component as a dependency:

    .. code-block:: bash

        composer require symfony/validator

Usage
-----

The Validator provider provides a ``validator`` service.

Validating Values
~~~~~~~~~~~~~~~~~

You can validate values directly using the ``validate`` validator
method::

    use Symfony\Component\Validator\Constraints as Assert;

    $app->get('/validate/{email}', function ($email) use ($app) {
        $errors = $app['validator']->validate($email, new Assert\Email());

        if (count($errors) > 0) {
            return (string) $errors;
        } else {
            return 'The email is valid';
        }
    });

Validating Associative Arrays
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Validating associative arrays is like validating simple values, with a
collection of constraints::

    use Symfony\Component\Validator\Constraints as Assert;

    $book = array(
        'title' => 'My Book',
        'author' => array(
            'first_name' => 'Fabien',
            'last_name'  => 'Potencier',
        ),
    );

    $constraint = new Assert\Collection(array(
        'title' => new Assert\Length(array('min' => 10)),
        'author' => new Assert\Collection(array(
            'first_name' => array(new Assert\NotBlank(), new Assert\Length(array('min' => 10))),
            'last_name'  => new Assert\Length(array('min' => 10)),
        )),
    ));
    $errors = $app['validator']->validate($book, $constraint);

    if (count($errors) > 0) {
        foreach ($errors as $error) {
            echo $error->getPropertyPath().' '.$error->getMessage()."\n";
        }
    } else {
        echo 'The book is valid';
    }

Validating Objects
~~~~~~~~~~~~~~~~~~

If you want to add validations to a class, you can define the constraint for
the class properties and getters, and then call the ``validate`` method::

    use Symfony\Component\Validator\Constraints as Assert;

    class Book
    {
        public $title;
        public $author;
    }

    class Author
    {
        public $first_name;
        public $last_name;
    }

    $author = new Author();
    $author->first_name = 'Fabien';
    $author->last_name = 'Potencier';

    $book = new Book();
    $book->title = 'My Book';
    $book->author = $author;

    $metadata = $app['validator.mapping.class_metadata_factory']->getMetadataFor('Author');
    $metadata->addPropertyConstraint('first_name', new Assert\NotBlank());
    $metadata->addPropertyConstraint('first_name', new Assert\Length(array('min' => 10)));
    $metadata->addPropertyConstraint('last_name', new Assert\Length(array('min' => 10)));

    $metadata = $app['validator.mapping.class_metadata_factory']->getMetadataFor('Book');
    $metadata->addPropertyConstraint('title', new Assert\Length(array('min' => 10)));
    $metadata->addPropertyConstraint('author', new Assert\Valid());

    $errors = $app['validator']->validate($book);

    if (count($errors) > 0) {
        foreach ($errors as $error) {
            echo $error->getPropertyPath().' '.$error->getMessage()."\n";
        }
    } else {
        echo 'The author is valid';
    }

You can also declare the class constraint by adding a static
``loadValidatorMetadata`` method to your classes::

    use Symfony\Component\Validator\Mapping\ClassMetadata;
    use Symfony\Component\Validator\Constraints as Assert;

    class Book
    {
        public $title;
        public $author;

        static public function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addPropertyConstraint('title', new Assert\Length(array('min' => 10)));
            $metadata->addPropertyConstraint('author', new Assert\Valid());
        }
    }

    class Author
    {
        public $first_name;
        public $last_name;

        static public function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addPropertyConstraint('first_name', new Assert\NotBlank());
            $metadata->addPropertyConstraint('first_name', new Assert\Length(array('min' => 10)));
            $metadata->addPropertyConstraint('last_name', new Assert\Length(array('min' => 10)));
        }
    }

    $app->get('/validate/{email}', function ($email) use ($app) {
        $author = new Author();
        $author->first_name = 'Fabien';
        $author->last_name = 'Potencier';

        $book = new Book();
        $book->title = 'My Book';
        $book->author = $author;

        $errors = $app['validator']->validate($book);

        if (count($errors) > 0) {
            foreach ($errors as $error) {
                echo $error->getPropertyPath().' '.$error->getMessage()."\n";
            }
        } else {
            echo 'The author is valid';
        }
    });

.. note::

    Use ``addGetterConstraint()`` to add constraints on getter methods and
    ``addConstraint()`` to add constraints on the class itself.

Translation
~~~~~~~~~~~

To be able to translate the error messages, you can use the translator
provider and register the messages under the ``validators`` domain::

    $app['translator.domains'] = array(
        'validators' => array(
            'fr' => array(
                'This value should be a valid number.' => 'Cette valeur doit être un nombre.',
            ),
        ),
    );

For more information, consult the `Symfony Validation documentation
<http://symfony.com/doc/master/book/validation.html>`_.


================================================
FILE: doc/providers/var_dumper.rst
================================================
Var Dumper
==========

The *VarDumperServiceProvider* provides a mechanism that allows exploring then
dumping any PHP variable.

Parameters
----------

* **var_dumper.dump_destination**: A stream URL where dumps should be written
  to (defaults to ``null``).

Services
--------

* n/a

Registering
-----------

.. code-block:: php

    $app->register(new Silex\Provider\VarDumperServiceProvider());

.. note::

    Add the Symfony VarDumper Component as a dependency:

    .. code-block:: bash

        composer require symfony/var-dumper

Usage
-----

Adding the VarDumper component as a Composer dependency gives you access to the
``dump()`` PHP function anywhere in your code.

If you are using Twig, it also provides a ``dump()`` Twig function and a
``dump`` Twig tag.

The VarDumperServiceProvider is also useful when used with the Silex
WebProfiler as the dumps are made available in the web debug toolbar and in the
web profiler.


================================================
FILE: doc/providers.rst
================================================
Providers
=========

Providers allow the developer to reuse parts of an application into another
one. Silex provides two types of providers defined by two interfaces:
``ServiceProviderInterface`` for services and ``ControllerProviderInterface``
for controllers.

Service Providers
-----------------

Loading providers
~~~~~~~~~~~~~~~~~

In order to load and use a service provider, you must register it on the
application::

    $app = new Silex\Application();

    $app->register(new Acme\DatabaseServiceProvider());

You can also provide some parameters as a second argument. These will be set
**after** the provider is registered, but **before** it is booted::

    $app->register(new Acme\DatabaseServiceProvider(), array(
        'database.dsn'      => 'mysql:host=localhost;dbname=myapp',
        'database.user'     => 'root',
        'database.password' => 'secret_root_password',
    ));

Conventions
~~~~~~~~~~~

You need to watch out in what order you do certain things when interacting
with providers. Just keep these rules in mind:

* Overriding existing services must occur **after** the provider is
  registered.

  *Reason: If the service already exists, the provider will overwrite it.*

* You can set parameters any time **after** the provider is registered, but
  **before** the service is accessed.

  *Reason: Providers can set default values for parameters. Just like with
  services, the provider will overwrite existing values.*

Included providers
~~~~~~~~~~~~~~~~~~

There are a few providers that you get out of the box. All of these are within
the ``Silex\Provider`` namespace:

* :doc:`DoctrineServiceProvider <providers/doctrine>`
* :doc:`FormServiceProvider <providers/form>`
* :doc:`HttpCacheServiceProvider <providers/http_cache>`
* :doc:`MonologServiceProvider <providers/monolog>`
* :doc:`RememberMeServiceProvider <providers/remember_me>`
* :doc:`SecurityServiceProvider <providers/security>`
* :doc:`SerializerServiceProvider <providers/serializer>`
* :doc:`ServiceControllerServiceProvider <providers/service_controller>`
* :doc:`SessionServiceProvider <providers/session>`
* :doc:`SwiftmailerServiceProvider <providers/swiftmailer>`
* :doc:`TranslationServiceProvider <providers/translation>`
* :doc:`TwigServiceProvider <providers/twig>`
* :doc:`ValidatorServiceProvider <providers/validator>`

.. note::

    The Silex core team maintains a `WebProfiler
    <https://github.com/silexphp/Silex-WebProfiler>`_ provider that helps debug
    code in the development environment thanks to the Symfony web debug toolbar
    and the Symfony profiler.

Third party providers
~~~~~~~~~~~~~~~~~~~~~

Some service providers are developed by the community. Those third-party
providers are listed on `Silex' repository wiki
<https://github.com/silexphp/Silex/wiki/Third-Party-ServiceProviders>`_.

You are encouraged to share yours.

Creating a provider
~~~~~~~~~~~~~~~~~~~

Providers must implement the ``Pimple\ServiceProviderInterface``::

    interface ServiceProviderInterface
    {
        public function register(Container $container);
    }

This is very straight forward, just create a new class that implements the
register method. In the ``register()`` method, you can define services on the
application which then may make use of other services and parameters. 

.. tip::

    The ``Pimple\ServiceProviderInterface`` belongs to the Pimple package, so
    take care to only use the API of ``Pimple\Container`` within your
    ``register`` method. Not only is this a good practice due to the way Pimple
    and Silex work, but may allow your provider to be used outside of Silex.

Optionally, your service provider can implement the
``Silex\Api\BootableProviderInterface``. A bootable provider must
implement the ``boot()`` method, with which you can configure the application, just
before it handles a request::

    interface BootableProviderInterface
    {
        function boot(Application $app);
    }

Another optional interface, is the ``Silex\Api\EventListenerProviderInterface``.
This interface contains the ``subscribe()`` method, which allows your provider to
subscribe event listener with Silex's EventDispatcher, just before it handles a
request::

    interface EventListenerProviderInterface
    {
        function subscribe(Container $app, EventDispatcherInterface $dispatcher);
    }

Here is an example of such a provider::

    namespace Acme;

    use Pimple\Container;
    use Pimple\ServiceProviderInterface;
    use Silex\Application;
    use Silex\Api\BootableProviderInterface;
    use Silex\Api\EventListenerProviderInterface;
    use Symfony\Component\HttpKernel\KernelEvents;
    use Symfony\Component\HttpKernel\Event\FilterResponseEvent;

    class HelloServiceProvider implements ServiceProviderInterface, BootableProviderInterface, EventListenerProviderInterface
    {
        public function register(Container $app)
        {
            $app['hello'] = $app->protect(function ($name) use ($app) {
                $default = $app['hello.default_name'] ? $app['hello.default_name'] : '';
                $name = $name ?: $default;

                return 'Hello '.$app->escape($name);
            });
        }

        public function boot(Application $app)
        {
            // do something 
        }

        public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
        {
            $dispatcher->addListener(KernelEvents::REQUEST, function(FilterResponseEvent $event) use ($app) {
                // do something 
            });
        }
    }

This class provides a ``hello`` service which is a protected closure. It takes
a ``name`` argument and will return ``hello.default_name`` if no name is
given. If the default is also missing, it will use an empty string.

You can now use this provider as follows::

    use Symfony\Component\HttpFoundation\Request;

    $app = new Silex\Application();

    $app->register(new Acme\HelloServiceProvider(), array(
        'hello.default_name' => 'Igor',
    ));

    $app->get('/hello', function (Request $request) use ($app) {
        $name = $request->get('name');

        return $app['hello']($name);
    });

In this example we are getting the ``name`` parameter from the query string,
so the request path would have to be ``/hello?name=Fabien``.

.. _controller-providers:

Controller Providers
--------------------

Loading providers
~~~~~~~~~~~~~~~~~

In order to load and use a controller provider, you must "mount" its
controllers under a path::

    $app = new Silex\Application();

    $app->mount('/blog', new Acme\BlogControllerProvider());

All controllers defined by the provider will now be available under the
``/blog`` path.

Creating a provider
~~~~~~~~~~~~~~~~~~~

Providers must implement the ``Silex\Api\ControllerProviderInterface``::

    interface ControllerProviderInterface
    {
        public function connect(Application $app);
    }

Here is an example of such a provider::

    namespace Acme;

    use Silex\Application;
    use Silex\Api\ControllerProviderInterface;

    class HelloControllerProvider implements ControllerProviderInterface
    {
        public function connect(Application $app)
        {
            // creates a new controller based on the default route
            $controllers = $app['controllers_factory'];

            $controllers->get('/', function (Application $app) {
                return $app->redirect('/hello');
            });

            return $controllers;
        }
    }

The ``connect`` method must return an instance of ``ControllerCollection``.
``ControllerCollection`` is the class where all controller related methods are
defined (like ``get``, ``post``, ``match``, ...).

.. tip::

    The ``Application`` class acts in fact as a proxy for these methods.

You can use this provider as follows::

    $app = new Silex\Application();

    $app->mount('/blog', new Acme\HelloControllerProvider());

In this example, the ``/blog/`` path now references the controller defined in
the provider.

.. tip::

    You can also define a provider that implements both the service and the
    controller provider interface and package in the same class the services
    needed to make your controllers work.


================================================
FILE: doc/services.rst
================================================
Services
========

Silex is not only a framework, it is also a service container. It does this by
extending `Pimple <http://pimple.sensiolabs.org>`_ which provides a very simple
service container.

Dependency Injection
--------------------

.. note::

    You can skip this if you already know what Dependency Injection is.

Dependency Injection is a design pattern where you pass dependencies to
services instead of creating them from within the service or relying on
globals. This generally leads to code that is decoupled, re-usable, flexible
and testable.

Here is an example of a class that takes a ``User`` object and stores it as a
file in JSON format::

    class JsonUserPersister
    {
        private $basePath;

        public function __construct($basePath)
        {
            $this->basePath = $basePath;
        }

        public function persist(User $user)
        {
            $data = $user->getAttributes();
            $json = json_encode($data);
            $filename = $this->basePath.'/'.$user->id.'.json';
            file_put_contents($filename, $json, LOCK_EX);
        }
    }

In this simple example the dependency is the ``basePath`` property. It is
passed to the constructor. This means you can create several independent
instances with different base paths. Of course dependencies do not have to be
simple strings. More often they are in fact other services.

A service container is responsible for creating and storing services. It can
recursively create dependencies of the requested services and inject them. It
does so lazily, which means a service is only created when you actually need it.

Pimple
------

Pimple makes strong use of closures and implements the ArrayAccess interface.

We will start off by creating a new instance of Pimple -- and because
``Silex\Application`` extends ``Pimple\Container`` all of this applies to Silex
as well::

    $container = new Pimple\Container();

or::

    $app = new Silex\Application();

Parameters
~~~~~~~~~~

You can set parameters (which are usually strings) by setting an array key on
the container::

    $app['some_parameter'] = 'value';

The array key can be any value. By convention dots are used for namespacing::

    $app['asset.host'] = 'http://cdn.mysite.com/';

Reading parameter values is possible with the same syntax::

    echo $app['some_parameter'];

Service definitions
~~~~~~~~~~~~~~~~~~~

Defining services is no different than defining parameters. You just set an
array key on the container to be a closure. However, when you retrieve the
service, the closure is executed. This allows for lazy service creation::

    $app['some_service'] = function () {
        return new Service();
    };

And to retrieve the service, use::

    $service = $app['some_service'];

On first invocation, this will create the service; the same instance will then
be returned on any subsequent access.

Factory services
~~~~~~~~~~~~~~~~

If you want a different instance to be returned for each service access, wrap
the service definition with the ``factory()`` method::

    $app['some_service'] = $app->factory(function () {
        return new Service();
    });

Every time you call ``$app['some_service']``, a new instance of the service is
created.

Access container from closure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In many cases you will want to access the service container from within a
service definition closure. For example when fetching services the current
service depends on.

Because of this, the container is passed to the closure as an argument::

    $app['some_service'] = function ($app) {
        return new Service($app['some_other_service'], $app['some_service.config']);
    };

Here you can see an example of Dependency Injection. ``some_service`` depends
on ``some_other_service`` and takes ``some_service.config`` as configuration
options. The dependency is only created when ``some_service`` is accessed, and
it is possible to replace either of the dependencies by simply overriding
those definitions.

Going back to our initial example, here's how we could use the container
to manage its dependencies::

    $app['user.persist_path'] = '/tmp/users';
    $app['user.persister'] = function ($app) {
        return new JsonUserPersister($app['user.persist_path']);
    };


Protected closures
~~~~~~~~~~~~~~~~~~

Because the container sees closures as factories for services, it will always
execute them when reading them.

In some cases you will however want to store a closure as a parameter, so that
you can fetch it and execute it yourself -- with your own arguments.

This is why Pimple allows you to protect your closures from being executed, by
using the ``protect`` method::

    $app['closure_parameter'] = $app->protect(function ($a, $b) {
        return $a + $b;
    });

    // will not execute the closure
    $add = $app['closure_parameter'];

    // calling it now
    echo $add(2, 3);

Note that protected closures do not get access to the container.

Core services
-------------

Silex defines a range of services.

* **request_stack**: Controls the lifecycle of requests, an instance of
  `RequestStack <http://api.symfony.com/master/Symfony/Component/HttpFoundation/RequestStack.html>` _.
  It gives you access to ``GET``, ``POST`` parameters and lots more!

  Example usage::

    $id = $app['request_stack']->getCurrentRequest()->get('id');

  A request is only available when a request is being served; you can only
  access it from within a controller, an application before/after middlewares,
  or an error handler.

* **routes**: The `RouteCollection
  <http://api.symfony.com/master/Symfony/Component/Routing/RouteCollection.html>`_
  that is used internally. You can add, modify, read routes.

* **url_generator**: An instance of `UrlGenerator
  <http://api.symfony.com/master/Symfony/Component/Routing/Generator/UrlGenerator.html>`_,
  using the `RouteCollection
  <http://api.symfony.com/master/Symfony/Component/Routing/RouteCollection.html>`_
  that is provided through the ``routes`` service. It has a ``generate``
  method, which takes the route name as an argument, followed by an array of
  route parameters.

* **controllers**: The ``Silex\ControllerCollection`` that is used internally.
  Check the :doc:`Internals chapter <internals>` for more information.

* **dispatcher**: The `EventDispatcher
  <http://api.symfony.com/master/Symfony/Component/EventDispatcher/EventDispatcher.html>`_
  that is used internally. It is the core of the Symfony system and is used
  quite a bit by Silex.

* **resolver**: The `ControllerResolver
  <http://api.symfony.com/master/Symfony/Component/HttpKernel/Controller/ControllerResolver.html>`_
  that is used internally. It takes care of executing the controller with the
  right arguments.

* **kernel**: The `HttpKernel
  <http://api.symfony.com/master/Symfony/Component/HttpKernel/HttpKernel.html>`_
  that is used internally. The HttpKernel is the heart of Symfony, it takes a
  Request as input and returns a Response as output.

* **request_context**: The request context is a simplified representation of
  the request that is used by the router and the URL generator.

* **exception_handler**: The Exception handler is the default handler that is
  used when you don't register one via the ``error()`` method or if your
  handler does not return a Response. Disable it with
  ``unset($app['exception_handler'])``.

* **logger**: A `LoggerInterface <https://github.com/php-fig/log/blob/master/Psr/Log/LoggerInterface.php>`_ instance. By default, logging is
  disabled as the value is set to ``null``. To enable logging you can either use
  the :doc:`MonologServiceProvider <providers/monolog>` or define your own ``logger`` service that
  conforms to the PSR logger interface.

Core traits
-----------

* ``Silex\Application\UrlGeneratorTrait`` adds the following shortcuts:

  * **path**: Generates a path.

  * **url**: Generates an absolute URL.

  .. code-block:: php

      $app->path('homepage');
      $app->url('homepage');

Core parameters
---------------

* **request.http_port** (optional): Allows you to override the default port
  for non-HTTPS URLs. If the current request is HTTP, it will always use the
  current port.

  Defaults to 80.

  This parameter can be used when generating URLs.

* **request.https_port** (optional): Allows you to override the default port
  for HTTPS URLs. If the current request is HTTPS, it will always use the
  current port.

  Defaults to 443.

  This parameter can be used when generating URLs.

* **debug** (optional): Returns whether or not the application is running in
  debug mode.

  Defaults to false.

* **charset** (optional): The charset to use for Responses.

  Defaults to UTF-8.


================================================
FILE: doc/testing.rst
================================================
Testing
=======

Because Silex is built on top of Symfony, it is very easy to write functional
tests for your application. Functional tests are automated software tests that
ensure that your code is working correctly. They go through the user interface,
using a fake browser, and mimic the actions a user would do.

Why
---

If you are not familiar with software tests, you may be wondering why you would
need this. Every time you make a change to your application, you have to test
it. This means going through all the pages and making sure they are still
working. Functional tests save you a lot of time, because they enable you to
test your application in usually under a second by running a single command.

For more information on functional testing, unit testing, and automated
software tests in general, check out `PHPUnit
<https://github.com/sebastianbergmann/phpunit>`_ and `Bulat Shakirzyanov's talk
on Clean Code <http://www.slideshare.net/avalanche123/clean-code-5609451>`_.

PHPUnit
-------

`PHPUnit <https://github.com/sebastianbergmann/phpunit>`_ is the de-facto
standard testing framework for PHP. It was built for writing unit tests, but it
can be used for functional tests too. You write tests by creating a new class,
that extends the ``PHPUnit_Framework_TestCase``. Your test cases are methods
prefixed with ``test``::

    class ContactFormTest extends \PHPUnit_Framework_TestCase
    {
        public function testInitialPage()
        {
            ...
        }
    }

In your test cases, you do assertions on the state of what you are testing. In
this case we are testing a contact form, so we would want to assert that the
page loaded correctly and contains our form::

        public function testInitialPage()
        {
            $statusCode = ...
            $pageContent = ...

            $this->assertEquals(200, $statusCode);
            $this->assertContains('Contact us', $pageContent);
            $this->assertContains('<form', $pageContent);
        }

Here you see some of the available assertions. There is a full list available
in the `Writing Tests for PHPUnit
<https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html>`_
section of the PHPUnit documentation.

WebTestCase
-----------

Symfony provides a WebTestCase class that can be used to write functional
tests. The Silex version of this class is ``Silex\WebTestCase``, and you can
use it by making your test extend it::

    use Silex\WebTestCase;

    class ContactFormTest extends WebTestCase
    {
        ...
    }

.. caution::

    If you need to override the ``setUp()`` method, don't forget to call the
    parent (``parent::setUp()``) to call the Silex default setup.

.. note::

    If you want to use the Symfony ``WebTestCase`` class you will need to
    explicitly install its dependencies for your project:

    .. code-block:: bash

        composer require --dev symfony/browser-kit symfony/css-selector

For your WebTestCase, you will have to implement a ``createApplication``
method, which returns your application instance::

        public function createApplication()
        {
            // app.php must return an Application instance
            return require __DIR__.'/path/to/app.php';
        }

Make sure you do **not** use ``require_once`` here, as this method will be
executed before every test.

.. tip::

    By default, the application behaves in the same way as when using it from a
    browser. But when an error occurs, it is sometimes easier to get raw
    exceptions instead of HTML pages. It is rather simple if you tweak the
    application configuration in the ``createApplication()`` method like
    follows::

        public function createApplication()
        {
            $app = require __DIR__.'/path/to/app.php';
            $app['debug'] = true;
            unset($app['exception_handler']);

            return $app;
        }

.. tip::

    If your application use sessions, set ``session.test`` to ``true`` to
    simulate sessions::

        public function createApplication()
        {
            // ...

            $app['session.test'] = true;

            // ...
        }

The WebTestCase provides a ``createClient`` method. A client acts as a browser,
and allows you to interact with your application. Here's how it works::

        public function testInitialPage()
        {
            $client = $this->createClient();
            $crawler = $client->request('GET', '/');

            $this->assertTrue($client->getResponse()->isOk());
            $this->assertCount(1, $crawler->filter('h1:contains("Contact us")'));
            $this->assertCount(1, $crawler->filter('form'));
            ...
        }

There are several things going on here. You have both a ``Client`` and a
``Crawler``.

You can also access the application through ``$this->app``.

Client
~~~~~~

The client represents a browser. It holds your browsing history, cookies and
more. The ``request`` method allows you to make a request to a page on your
application.

.. note::

    You can find some documentation for it in `the client section of the
    testing chapter of the Symfony documentation
    <http://symfony.com/doc/current/book/testing.html#the-test-client>`_.

Crawler
~~~~~~~

The crawler allows you to inspect the content of a page. You can filter it
using CSS expressions and lots more.

.. note::

    You can find some documentation for it in `the crawler section of the testing
    chapter of the Symfony documentation
    <http://symfony.com/doc/current/book/testing.html#the-test-client>`_.

Configuration
-------------

The suggested way to configure PHPUnit is to create a ``phpunit.xml.dist``
file, a ``tests`` folder and your tests in
``tests/YourApp/Tests/YourTest.php``. The ``phpunit.xml.dist`` file should
look like this:

.. code-block:: xml

    <?xml version="1.0" encoding="UTF-8"?>
    <phpunit bootstrap="./vendor/autoload.php"
             backupGlobals="false"
             backupStaticAttributes="false"
             colors="true"
             convertErrorsToExceptions="true"
             convertNoticesToExceptions="true"
             convertWarningsToExceptions="true"
             processIsolation="false"
             stopOnFailure="false"
             syntaxCheck="false"
    >
        <testsuites>
            <testsuite name="YourApp Test Suite">
                <directory>./tests/</directory>
            </testsuite>
        </testsuites>
    </phpunit>

Your ``tests/YourApp/Tests/YourTest.php`` should look like this::

    namespace YourApp\Tests;

    use Silex\WebTestCase;

    class YourTest extends WebTestCase
    {
        public function createApplication()
        {
            return require __DIR__.'/../../../app.php';
        }

        public function testFooBar()
        {
            ...
        }
    }

Now, when running ``phpunit`` on the command line, tests should run.


================================================
FILE: doc/usage.rst
================================================
Usage
=====

Installation
------------

If you want to get started fast, `download`_ Silex as an archive and extract
it, you should have the following directory structure:

.. code-block:: text

    ├── composer.json
    ├── composer.lock
    ├── vendor
    │   └── ...
    └── web
        └── index.php

If you want more flexibility, use Composer_ instead:

.. code-block:: bash

    composer require silex/silex:~2.0

Web Server
----------

All examples in the documentation rely on a well-configured web server; read
the :doc:`webserver documentation<web_servers>` to check yours.

Bootstrap
---------

To bootstrap Silex, all you need to do is require the ``vendor/autoload.php``
file and create an instance of ``Silex\Application``. After your controller
definitions, call the ``run`` method on your application::

    // web/index.php
    require_once __DIR__.'/../vendor/autoload.php';

    $app = new Silex\Application();

    // ... definitions

    $app->run();

.. tip::

    When developing a website, you might want to turn on the debug mode to
    ease debugging::

        $app['debug'] = true;

.. tip::

    If your application is hosted behind a reverse proxy at address ``$ip``,
    and you want Silex to trust the ``X-Forwarded-For*`` headers, you will
    need to run your application like this::

        use Symfony\Component\HttpFoundation\Request;

        Request::setTrustedProxies(array($ip));
        $app->run();

Routing
-------

In Silex you define a route and the controller that is called when that
route is matched. A route pattern consists of:

* *Pattern*: The route pattern defines a path that points to a resource. The
  pattern can include variable parts and you are able to set RegExp
  requirements for them.

* *Method*: One of the following HTTP methods: ``GET``, ``POST``, ``PUT``,
  ``DELETE``, ``PATCH``, or ``OPTIONS``. This describes the interaction with
  the resource.

The controller is defined using a closure like this::

    function () {
        // ... do something
    }

The return value of the closure becomes the content of the page.

Example GET Route
~~~~~~~~~~~~~~~~~

Here is an example definition of a ``GET`` route::

    $blogPosts = array(
        1 => array(
            'date'      => '2011-03-29',
            'author'    => 'igorw',
            'title'     => 'Using Silex',
            'body'      => '...',
        ),
    );

    $app->get('/blog', function () use ($blogPosts) {
        $output = '';
        foreach ($blogPosts as $post) {
            $output .= $post['title'];
            $output .= '<br />';
        }

        return $output;
    });

Visiting ``/blog`` will return a list of blog post titles. The ``use``
statement means something different in this context. It tells the closure to
import the ``$blogPosts`` variable from the outer scope. This allows you to use
it from within the closure.

Dynamic Routing
~~~~~~~~~~~~~~~

Now, you can create another controller for viewing individual blog posts::

    $app->get('/blog/{id}', function (Silex\Application $app, $id) use ($blogPosts) {
        if (!isset($blogPosts[$id])) {
            $app->abort(404, "Post $id does not exist.");
        }

        $post = $blogPosts[$id];

        return  "<h1>{$post['title']}</h1>".
                "<p>{$post['body']}</p>";
    });

This route definition has a variable ``{id}`` part which is passed to the
closure.

The current ``Application`` is automatically injected by Silex to the Closure
thanks to the type hinting.

When the post does not exist, you are using ``abort()`` to stop the request
early. It actually throws an exception, which you will see how to handle later
on.

Example POST Route
~~~~~~~~~~~~~~~~~~

POST routes signify the creation of a resource. An example for this is a
feedback form. You will use the ``mail`` function to send an e-mail::

    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;

    $app->post('/feedback', function (Request $request) {
        $message = $request->get('message');
        mail('feedback@yoursite.com', '[YourSite] Feedback', $message);

        return new Response('Thank you for your feedback!', 201);
    });

It is pretty straightforward.

.. note::

    There is a :doc:`SwiftmailerServiceProvider <providers/swiftmailer>`
    included that you can use instead of ``mail()``.

The current ``request`` is automatically injected by Silex to the Closure
thanks to the type hinting. It is an instance of
Request_, so you can fetch variables using the request ``get`` method.

Instead of returning a string you are returning an instance of Response_.
This allows setting an HTTP status code, in this case it is set to
``201 Created``.

.. note::

    Silex always uses a ``Response`` internally, it converts strings to
    responses with status code ``200``.

Other methods
~~~~~~~~~~~~~

You can create controllers for most HTTP methods. Just call one of these
methods on your application: ``get``, ``post``, ``put``, ``delete``, ``patch``, ``options``::

    $app->put('/blog/{id}', function ($id) {
        // ...
    });

    $app->delete('/blog/{id}', function ($id) {
        // ...
    });

    $app->patch('/blog/{id}', function ($id) {
        // ...
    });

.. tip::

    Forms in most web browsers do not directly support the use of other HTTP
    methods. To use methods other than GET and POST you can utilize a special
    form field with a name of ``_method``. The form's ``method`` attribute must
    be set to POST when using this field:

    .. code-block:: html

        <form action="/my/target/route/" method="post">
            <!-- ... -->
            <input type="hidden" id="_method" name="_method" value="PUT" />
        </form>

    You need to explicitly enable this method override::

        use Symfony\Component\HttpFoundation\Request;

        Request::enableHttpMethodParameterOverride();
        $app->run();

You can also call ``match``, which will match all methods. This can be
restricted via the ``method`` method::

    $app->match('/blog', function () {
        // ...
    });

    $app->match('/blog', function () {
        // ...
    })
    ->method('PATCH');

    $app->match('/blog', function () {
        // ...
    })
    ->method('PUT|POST');

.. note::

    The order in which the routes are defined is significant. The first
    matching route will be used, so place more generic routes at the bottom.

Route Variables
~~~~~~~~~~~~~~~

As it has been shown before you can define variable parts in a route like
this::

    $app->get('/blog/{id}', function ($id) {
        // ...
    });

It is also possible to have more than one variable part, just make sure the
closure arguments match the names of the variable parts::

    $app->get('/blog/{postId}/{commentId}', function ($postId, $commentId) {
        // ...
    });

While it's not recommended, you could also do this (note the switched
arguments)::

    $app->get('/blog/{postId}/{commentId}', function ($commentId, $postId) {
        // ...
    });

You can also ask for the current Request and Application objects::

    $app->get('/blog/{id}', function (Application $app, Request $request, $id) {
        // ...
    });

.. note::

    Note for the Application and Request objects, Silex does the injection
    based on the type hinting and not on the variable name::

        $app->get('/blog/{id}', function (Application $foo, Request $bar, $id) {
            // ...
        });

Route Variable Converters
~~~~~~~~~~~~~~~~~~~~~~~~~

Before injecting the route variables into the controller, you can apply some
converters::

    $app->get('/user/{id}', function ($id) {
        // ...
    })->convert('id', function ($id) { return (int) $id; });

This is useful when you want to convert route variables to objects as it
allows to reuse the conversion code across different controllers::

    $userProvider = function ($id) {
        return new User($id);
    };

    $app->get('/user/{user}', function (User $user) {
        // ...
    })->convert('user', $userProvider);

    $app->get('/user/{user}/edit', function (User $user) {
        // ...
    })->convert('user', $userProvider);

The converter callback also receives the ``Request`` as its second argument::

    $callback = function ($post, Request $request) {
        return new Post($request->attributes->get('slug'));
    };

    $app->get('/blog/{id}/{slug}', function (Post $post) {
        // ...
    })->convert('post', $callback);

A converter can also be defined as a service. For example, here is a user
converter based on Doctrine ObjectManager::

    use Doctrine\Common\Persistence\ObjectManager;
    use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

    class UserConverter
    {
        private $om;

        public function __construct(ObjectManager $om)
        {
            $this->om = $om;
        }

        public function convert($id)
        {
            if (null === $user = $this->om->find('User', (int) $id)) {
                throw new NotFoundHttpException(sprintf('User %d does not exist', $id));
            }

            return $user;
        }
    }

The service will now be registered in the application, and the
``convert()`` method will be used as converter (using the syntax
``service_name:method_name``)::

    $app['converter.user'] = function () {
        return new UserConverter();
    };

    $app->get('/user/{user}', function (User $user) {
        // ...
    })->convert('user', 'converter.user:convert');

Requirements
~~~~~~~~~~~~

In some cases you may want to only match certain expressions. You can define
requirements using regular expressions by calling ``assert`` on the
``Controller`` object, which is returned by the routing methods.

The following will make sure the ``id`` argument is a positive integer, since
``\d+`` matches any amount of digits::

    $app->get('/blog/{id}', function ($id) {
        // ...
    })
    ->assert('id', '\d+');

You can also chain these calls::

    $app->get('/blog/{postId}/{commentId}', function ($postId, $commentId) {
        // ...
    })
    ->assert('postId', '\d+')
    ->assert('commentId', '\d+');

Conditions
~~~~~~~~~~

Besides restricting route matching based on the HTTP method or parameter
requirements, you can set conditions on any part of the request by calling
``when`` on the ``Controller`` object, which is returned by the routing
methods::

    $app->get('/blog/{id}', function ($id) {
        // ...
    })
    ->when("request.headers.get('User-Agent') matches '/firefox/i'");

The ``when`` argument is a Symfony Expression_ , which means that you need to
add ``symfony/expression-language`` as a dependency of your project.

Default Values
~~~~~~~~~~~~~~

You can define a default value for any route variable by calling ``value`` on
the ``Controller`` object::

    $app->get('/{pageName}', function ($pageName) {
        // ...
    })
    ->value('pageName', 'index');

This will allow matching ``/``, in which case the ``pageName`` variable will
have the value ``index``.

Named Routes
~~~~~~~~~~~~

Some providers can make use of named routes. By default Silex will generate an
internal route name for you but you can give an explicit route name by calling
``bind``::

    $app->get('/', function () {
        // ...
    })
    ->bind('homepage');

    $app->get('/blog/{id}', function ($id) {
        // ...
    })
    ->bind('blog_post');

Controllers as Classes
~~~~~~~~~~~~~~~~~~~~~~

Instead of anonymous functions, you can also define your controllers as
methods. By using the ``ControllerClass::methodName`` syntax, you can tell
Silex to lazily create the controller object for you::

    $app->get('/', 'Acme\\Foo::bar');

    use Silex\Application;
    use Symfony\Component\HttpFoundation\Request;

    namespace Acme
    {
        class Foo
        {
            public function bar(Request $request, Application $app)
            {
                // ...
            }
        }
    }

This will load the ``Acme\Foo`` class on demand, create an instance and call
the ``bar`` method to get the response. You can use ``Request`` and
``Silex\Application`` type hints to get ``$request`` and ``$app`` injected.

It is also possible to :doc:`define your controllers as services
<providers/service_controller>`.

Global Configuration
--------------------

If a controller setting must be applied to **all** controllers (a converter, a
middleware, a requirement, or a default value), configure it on
``$app['controllers']``, which holds all application controllers::

    $app['controllers']
        ->value('id', '1')
        ->assert('id', '\d+')
        ->requireHttps()
        ->method('get')
        ->convert('id', function () { /* ... */ })
        ->before(function () { /* ... */ })
        ->when('request.isSecure() == true')
    ;

These settings are applied to already registered controllers and they become
the defaults for new controllers.

.. note::

    The global configuration does not apply to controller providers you might
    mount as they have their own global configuration (read the
    :doc:`dedicated chapter<organizing_controllers>` for more information).

Error Handlers
--------------

When an exception is thrown, error handlers allow you to display a custom
error page to the user. They can also be used to do additional things, such as
logging.

To register an error handler, pass a closure to the ``error`` method which
takes an ``Exception`` argument and returns a response::

    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\HttpFoundation\Request;

    $app->error(function (\Exception $e, Request $request, $code) {
        return new Response('We are sorry, but something went terribly wrong.');
    });

You can also check for specific errors by using the ``$code`` argument, and
handle them differently::

    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\HttpFoundation\Request;

    $app->error(function (\Exception $e, Request $request, $code) {
        switch ($code) {
            case 404:
                $message = 'The requested page could not be found.';
                break;
            default:
                $message = 'We are sorry, but something went terribly wrong.';
        }

        return new Response($message);
    });

You can restrict an error handler to only handle some Exception classes by
setting a more specific type hint for the Closure argument::

    use Symfony\Component\HttpFoundation\Request;

    $app->error(function (\LogicException $e, Request $request, $code) {
        // this handler will only handle \LogicException exceptions
        // and exceptions that extend \LogicException
    });

.. note::

    As Silex ensures that the Response status code is set to the most
    appropriate one depending on the exception, setting the status on the
    response won't work. If you want to overwrite the status code, set the
    ``X-Status-Code`` header::

        return new Response('Error', 404 /* ignored */, array('X-Status-Code' => 200));

If you want to use a separate error handler for logging, make sure you register
it with a higher priority than response error handlers, because once a response
is returned, the following handlers are ignored.

.. note::

    Silex ships with a provider for Monolog_ which handles logging of errors.
    Check out the *Providers* :doc:`chapter <providers/monolog>` for details.

.. tip::

    Silex comes with a default error handler that displays a detailed error
    message with the stack trace when **debug** is true, and a simple error
    message otherwise. Error handlers registered via the ``error()`` method
    always take precedence but you can keep the nice error messages when debug
    is turned on like this::

        use Symfony\Component\HttpFoundation\Response;
        use Symfony\Component\HttpFoundation\Request;

        $app->error(function (\Exception $e, Request $request, $code) use ($app) {
            if ($app['debug']) {
                return;
            }

            // ... logic to handle the error and return a Response
        });

The error handlers are also called when you use ``abort`` to abort a request
early::

    $app->get('/blog/{id}', function (Silex\Application $app, $id) use ($blogPosts) {
        if (!isset($blogPosts[$id])) {
            $app->abort(404, "Post $id does not exist.");
        }

        return new Response(...);
    });

You can convert errors to ``Exceptions``, check out the cookbook :doc:`chapter <cookbook/error_handler>` for details.

View Handlers
-------------

View Handlers allow you to intercept a controller result that is not a
``Response`` and transform it before it gets returned to the kernel.

To register a view handler, pass a callable (or string that can be resolved to a
callable) to the ``view()`` method. The callable should accept some sort of result
from the controller::

    $app->view(function (array $controllerResult) use ($app) {
        return $app->json($controllerResult);
    });

View Handlers also receive the ``Request`` as their second argument,
making them a good candidate for basic content negotiation::

    $app->view(function (array $controllerResult, Request $request) use ($app) {
        $acceptHeader = $request->headers->get('Accept');
        $bestFormat = $app['negotiator']->getBestFormat($acceptHeader, array('json', 'xml'));

        if ('json' === $bestFormat) {
            return new JsonResponse($controllerResult);
        }

        if ('xml' === $bestFormat) {
            return $app['serializer.xml']->renderResponse($controllerResult);
        }

        return $controllerResult;
    });

View Handlers will be examined in the order they are added to the application
and Silex will use type hints to determine if a view handler should be used for
the current result, continuously using the return value of the last view handler
as the input for the next.

.. note::

    You must ensure that Silex receives a ``Response`` or a string as the result of
    the last view handler (or controller) to be run.

Redirects
---------

You can redirect to another page by returning a ``RedirectResponse`` response,
which you can create by calling the ``redirect`` method::

    $app->get('/', function () use ($app) {
        return $app->redirect('/hello');
    });

This will redirect from ``/`` to ``/hello``.

Forwards
--------

When you want to delegate the rendering to another controller, without a
round-trip to the browser (as for a redirect), use an internal sub-request::

    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpKernel\HttpKernelInterface;

    $app->get('/', function () use ($app) {
        // forward to /hello
        $subRequest = Request::create('/hello', 'GET');

        return $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
    });

.. tip::

    You can also generate the URI via the built-in URL generator::

        $request = Request::create($app['url_generator']->generate('hello'), 'GET');

There's some more things that you need to keep in mind though. In most cases you
will want to forward some parts of the current master request to the sub-request.
That includes: Cookies, server information, session.
Read more on :doc:`how to make sub-requests <cookbook/sub_requests>`.

JSON
----

If you want to return JSON data, you can use the ``json`` helper method.
Simply pass it your data, status code and headers, and it will create a JSON
response for you::

    $app->get('/users/{id}', function ($id) use ($app) {
        $user = getUser($id);

        if (!$user) {
            $error = array('message' => 'The user was not found.');

            return $app->json($error, 404);
        }

        return $app->json($user);
    });

Streaming
---------

It's possible to stream a response, which is important in cases when you don't
want to buffer the data being sent::

    $app->get('/images/{file}', function ($file) use ($app) {
        if (!file_exists(__DIR__.'/images/'.$file)) {
            return $app->abort(404, 'The image was not found.');
        }

        $stream = function () use ($file) {
            readfile($file);
        };

        return $app->stream($stream, 200, array('Content-Type' => 'image/png'));
    });

If you need to send chunks, make sure you call ``ob_flush`` and ``flush``
after every chunk::

    $stream = function () {
        $fh = fopen('http://www.example.com/', 'rb');
        while (!feof($fh)) {
            echo fread($fh, 1024);
            ob_flush();
            flush();
        }
        fclose($fh);
    };

Sending a file
--------------

If you want to return a file, you can use the ``sendFile`` helper method.
It eases returning files that would otherwise not be publicly available. Simply
pass it your file path, status code, headers and the content disposition and it
will create a ``BinaryFileResponse`` response for you::

    $app->get('/files/{path}', function ($path) use ($app) {
        if (!file_exists('/base/path/' . $path)) {
            $app->abort(404);
        }

        return $app->sendFile('/base/path/' . $path);
    });

To further customize the response before returning it, check the API doc for
`Symfony\Component\HttpFoundation\BinaryFileResponse
<http://api.symfony.com/master/Symfony/Component/HttpFoundation/BinaryFileResponse.html>`_::

    return $app
        ->sendFile('/base/path/' . $path)
        ->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, 'pic.jpg')
    ;

Traits
------

Silex comes with PHP traits that define shortcut methods.

Almost all built-in service providers have some corresponding PHP traits. To
use them, define your own Application class and include the traits you want::

    use Silex\Application;

    class MyApplication extends Application
    {
        use Application\TwigTrait;
        use Application\SecurityTrait;
        use Application\FormTrait;
        use Application\UrlGeneratorTrait;
        use Application\SwiftmailerTrait;
        use Application\MonologTrait;
        use Application\TranslationTrait;
    }

You can also define your own Route class and use some traits::

    use Silex\Route;

    class MyRoute extends Route
    {
        use Route\SecurityTrait;
    }

To use your newly defined route, override the ``$app['route_class']``
setting::

    $app['route_class'] = 'MyRoute';

Read each provider chapter to learn more about the added methods.

Security
--------

Make sure to protect your application against attacks.

Escaping
~~~~~~~~

When outputting any user input, make sure to escape it correctly to prevent
Cross-Site-Scripting attacks.

* **Escaping HTML**: PHP provides the ``htmlspecialchars`` function for this.
  Silex provides a shortcut ``escape`` method::

      use Symfony\Component\HttpFoundation\Request;

      $app->get('/name', function (Request $request, Silex\Application $app) {
          $name = $request->get('name');

          return "You provided the name {$app->escape($name)}.";
      });

  If you use the Twig template engine, you should use its escaping or even
  auto-escaping mechanisms. Check out the *Providers* :doc:`chapter <providers/twig>` for details.

* **Escaping JSON**: If you want to provide data in JSON format you should
  use the Silex ``json`` function::

      use Symfony\Component\HttpFoundation\Request;

      $app->get('/name.json', function (Request $request, Silex\Application $app) {
          $name = $request->get('name');

          return $app->json(array('name' => $name));
      });

.. _download: http://silex.sensiolabs.org/download
.. _Composer: http://getcomposer.org/
.. _Request: http://api.symfony.com/master/Symfony/Component/HttpFoundation/Request.html
.. _Response: http://api.symfony.com/master/Symfony/Component/HttpFoundation/Response.html
.. _Monolog: https://github.com/Seldaek/monolog
.. _Expression: https://symfony.com/doc/current/book/routing.html#completely-customized-route-matching-with-conditions


================================================
FILE: doc/web_servers.rst
================================================
Webserver Configuration
=======================

Apache
------

If you are using Apache, make sure ``mod_rewrite`` is enabled and use the
following ``.htaccess`` file:

.. code-block:: apache

    <IfModule mod_rewrite.c>
        Options -MultiViews

        RewriteEngine On
        #RewriteBase /path/to/app
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^ index.php [QSA,L]
    </IfModule>

.. note::

    If your site is not at the webroot level you will have to uncomment the
    ``RewriteBase`` statement and adjust the path to point to your directory,
    relative from the webroot.

Alternatively, if you use Apache 2.2.16 or higher, you can use the
`FallbackResource directive`_ to make your .htaccess even easier:

.. code-block:: apache

    FallbackResource index.php

.. note::

    If your site is not at the webroot level you will have to adjust the path to
    point to your directory, relative from the webroot.

nginx
-----

The **minimum configuration** to get your application running under Nginx is:

.. code-block:: nginx

    server {
        server_name domain.tld www.domain.tld;
        root /var/www/project/web;
    
        location / {
            # try to serve file directly, fallback to front controller
            try_files $uri /index.php$is_args$args;
        }
    
        # If you have 2 front controllers for dev|prod use the following line instead
        # location ~ ^/(index|index_dev)\.php(/|$) {
        location ~ ^/index\.php(/|$) {
            # the ubuntu default
            fastcgi_pass   unix:/var/run/php/phpX.X-fpm.sock;
            # for running on centos
            #fastcgi_pass   unix:/var/run/php-fpm/www.sock;
    
            fastcgi_split_path_info ^(.+\.php)(/.*)$;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param HTTPS off;
        
            # Prevents URIs that include the front controller. This will 404:
            # http://domain.tld/index.php/some-path
            # Enable the internal directive to disable URIs like this
            # internal;
        }

        #return 404 for all php files as we do have a front controller
        location ~ \.php$ {
            return 404;
        }
    
        error_log /var/log/nginx/project_error.log;
        access_log /var/log/nginx/project_access.log;
    }

IIS
---

If you are using the Internet Information Services from Windows, you can use
this sample ``web.config`` file:

.. code-block:: xml

    <?xml version="1.0"?>
    <configuration>
        <system.webServer>
            <defaultDocument>
                <files>
                    <clear />
                    <add value="index.php" />
                </files>
            </defaultDocument>
            <rewrite>
                <rules>
                    <rule name="Silex Front Controller" stopProcessing="true">
                        <match url="^(.*)$" ignoreCase="false" />
                        <conditions logicalGrouping="MatchAll">
                            <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
                        </conditions>
                        <action type="Rewrite" url="index.php" appendQueryString="true" />
                    </rule>
                </rules>
            </rewrite>
        </system.webServer>
    </configuration>

Lighttpd
--------

If you are using lighttpd, use this sample ``simple-vhost`` as a starting
point:

.. code-block:: lighttpd

    server.document-root = "/path/to/app"

    url.rewrite-once = (
        # configure some static files
        "^/assets/.+" => "$0",
        "^/favicon\.ico$" => "$0",

        "^(/[^\?]*)(\?.*)?" => "/index.php$1$2"
    )

.. _FallbackResource directive: http://www.adayinthelifeof.nl/2012/01/21/apaches-fallbackresource-your-new-htaccess-command/

PHP
---

PHP ships with a built-in webserver for development. This server allows you to
run silex without any configuration. However, in order to serve static files,
you'll have to make sure your front controller returns false in that case::

    // web/index.php

    $filename = __DIR__.preg_replace('#(\?.*)$#', '', $_SERVER['REQUEST_URI']);
    if (php_sapi_name() === 'cli-server' && is_file($filename)) {
        return false;
    }

    $app = require __DIR__.'/../src/app.php';
    $app->run();


Assuming your front controller is at ``web/index.php``, you can start the
server from the command-line with this command:

.. code-block:: text

    $ php -S localhost:8080 -t web web/index.php

Now the application should be running at ``http://localhost:8080``.

.. note::

    This server is for development only. It is **not** recommended to use it
    in production.


================================================
FILE: phpunit.xml.dist
================================================
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Silex Test Suite">
            <directory>./tests/Silex/</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory>./src</directory>
        </whitelist>
    </filter>
</phpunit>


================================================
FILE: src/Silex/Api/BootableProviderInterface.php
================================================
<?php

/*
 * This file is part of the Silex framework.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Silex\Ap
Download .txt
gitextract_b59cn358/

├── .gitignore
├── .travis.yml
├── LICENSE
├── README.rst
├── bin/
│   ├── build
│   └── skeleton/
│       ├── fat_composer.json
│       ├── index.php
│       └── slim_composer.json
├── composer.json
├── doc/
│   ├── changelog.rst
│   ├── conf.py
│   ├── contributing.rst
│   ├── cookbook/
│   │   ├── error_handler.rst
│   │   ├── form_no_csrf.rst
│   │   ├── guard_authentication.rst
│   │   ├── index.rst
│   │   ├── json_request_body.rst
│   │   ├── multiple_loggers.rst
│   │   ├── session_storage.rst
│   │   ├── sub_requests.rst
│   │   └── validator_yaml.rst
│   ├── index.rst
│   ├── internals.rst
│   ├── intro.rst
│   ├── middlewares.rst
│   ├── organizing_controllers.rst
│   ├── providers/
│   │   ├── asset.rst
│   │   ├── csrf.rst
│   │   ├── doctrine.rst
│   │   ├── form.rst
│   │   ├── http_cache.rst
│   │   ├── http_fragment.rst
│   │   ├── index.rst
│   │   ├── locale.rst
│   │   ├── monolog.rst
│   │   ├── remember_me.rst
│   │   ├── security.rst
│   │   ├── serializer.rst
│   │   ├── service_controller.rst
│   │   ├── session.rst
│   │   ├── swiftmailer.rst
│   │   ├── translation.rst
│   │   ├── twig.rst
│   │   ├── validator.rst
│   │   └── var_dumper.rst
│   ├── providers.rst
│   ├── services.rst
│   ├── testing.rst
│   ├── usage.rst
│   └── web_servers.rst
├── phpunit.xml.dist
├── src/
│   └── Silex/
│       ├── Api/
│       │   ├── BootableProviderInterface.php
│       │   ├── ControllerProviderInterface.php
│       │   ├── EventListenerProviderInterface.php
│       │   ├── LICENSE
│       │   └── composer.json
│       ├── AppArgumentValueResolver.php
│       ├── Application/
│       │   ├── FormTrait.php
│       │   ├── MonologTrait.php
│       │   ├── SecurityTrait.php
│       │   ├── SwiftmailerTrait.php
│       │   ├── TranslationTrait.php
│       │   ├── TwigTrait.php
│       │   └── UrlGeneratorTrait.php
│       ├── Application.php
│       ├── CallbackResolver.php
│       ├── Controller.php
│       ├── ControllerCollection.php
│       ├── ControllerResolver.php
│       ├── EventListener/
│       │   ├── ConverterListener.php
│       │   ├── LogListener.php
│       │   ├── MiddlewareListener.php
│       │   └── StringToResponseListener.php
│       ├── Exception/
│       │   └── ControllerFrozenException.php
│       ├── ExceptionHandler.php
│       ├── ExceptionListenerWrapper.php
│       ├── Provider/
│       │   ├── AssetServiceProvider.php
│       │   ├── CsrfServiceProvider.php
│       │   ├── DoctrineServiceProvider.php
│       │   ├── ExceptionHandlerServiceProvider.php
│       │   ├── Form/
│       │   │   └── SilexFormExtension.php
│       │   ├── FormServiceProvider.php
│       │   ├── HttpCache/
│       │   │   └── HttpCache.php
│       │   ├── HttpCacheServiceProvider.php
│       │   ├── HttpFragmentServiceProvider.php
│       │   ├── HttpKernelServiceProvider.php
│       │   ├── LICENSE
│       │   ├── Locale/
│       │   │   └── LocaleListener.php
│       │   ├── LocaleServiceProvider.php
│       │   ├── MonologServiceProvider.php
│       │   ├── RememberMeServiceProvider.php
│       │   ├── Routing/
│       │   │   ├── LazyRequestMatcher.php
│       │   │   └── RedirectableUrlMatcher.php
│       │   ├── RoutingServiceProvider.php
│       │   ├── SecurityServiceProvider.php
│       │   ├── SerializerServiceProvider.php
│       │   ├── ServiceControllerServiceProvider.php
│       │   ├── Session/
│       │   │   ├── SessionListener.php
│       │   │   └── TestSessionListener.php
│       │   ├── SessionServiceProvider.php
│       │   ├── SwiftmailerServiceProvider.php
│       │   ├── TranslationServiceProvider.php
│       │   ├── TwigServiceProvider.php
│       │   ├── Validator/
│       │   │   └── ConstraintValidatorFactory.php
│       │   ├── ValidatorServiceProvider.php
│       │   ├── VarDumperServiceProvider.php
│       │   └── composer.json
│       ├── Route/
│       │   └── SecurityTrait.php
│       ├── Route.php
│       ├── ServiceControllerResolver.php
│       ├── ViewListenerWrapper.php
│       └── WebTestCase.php
└── tests/
    └── Silex/
        └── Tests/
            ├── Application/
            │   ├── FormApplication.php
            │   ├── FormTraitTest.php
            │   ├── MonologApplication.php
            │   ├── MonologTraitTest.php
            │   ├── SecurityApplication.php
            │   ├── SecurityTraitTest.php
            │   ├── SwiftmailerApplication.php
            │   ├── SwiftmailerTraitTest.php
            │   ├── TranslationApplication.php
            │   ├── TranslationTraitTest.php
            │   ├── TwigApplication.php
            │   ├── TwigTraitTest.php
            │   ├── UrlGeneratorApplication.php
            │   └── UrlGeneratorTraitTest.php
            ├── ApplicationTest.php
            ├── CallbackResolverTest.php
            ├── CallbackServicesTest.php
            ├── ControllerCollectionTest.php
            ├── ControllerResolverTest.php
            ├── ControllerTest.php
            ├── EventListener/
            │   └── LogListenerTest.php
            ├── ExceptionHandlerTest.php
            ├── Fixtures/
            │   └── Php7Controller.php
            ├── FunctionalTest.php
            ├── JsonTest.php
            ├── LazyDispatcherTest.php
            ├── LazyRequestMatcherTest.php
            ├── LocaleTest.php
            ├── MiddlewareTest.php
            ├── Provider/
            │   ├── AssetServiceProviderTest.php
            │   ├── DoctrineServiceProviderTest.php
            │   ├── FormServiceProviderTest/
            │   │   └── DisableCsrfExtension.php
            │   ├── FormServiceProviderTest.php
            │   ├── HttpCacheServiceProviderTest.php
            │   ├── HttpFragmentServiceProviderTest.php
            │   ├── MonologServiceProviderTest.php
            │   ├── RememberMeServiceProviderTest.php
            │   ├── RoutingServiceProviderTest.php
            │   ├── SecurityServiceProviderTest/
            │   │   └── TokenAuthenticator.php
            │   ├── SecurityServiceProviderTest.php
            │   ├── SerializerServiceProviderTest.php
            │   ├── SessionServiceProviderTest.php
            │   ├── SpoolStub.php
            │   ├── SwiftmailerServiceProviderTest.php
            │   ├── TranslationServiceProviderTest.php
            │   ├── TwigServiceProviderTest.php
            │   ├── ValidatorServiceProviderTest/
            │   │   └── Constraint/
            │   │       ├── Custom.php
            │   │       └── CustomValidator.php
            │   └── ValidatorServiceProviderTest.php
            ├── Route/
            │   ├── SecurityRoute.php
            │   └── SecurityTraitTest.php
            ├── RouterTest.php
            ├── ServiceControllerResolverRouterTest.php
            ├── ServiceControllerResolverTest.php
            ├── StreamTest.php
            └── WebTestCaseTest.php
Download .txt
SYMBOL INDEX (628 symbols across 113 files)

FILE: src/Silex/Api/BootableProviderInterface.php
  type BootableProviderInterface (line 21) | interface BootableProviderInterface
    method boot (line 32) | public function boot(Application $app);

FILE: src/Silex/Api/ControllerProviderInterface.php
  type ControllerProviderInterface (line 22) | interface ControllerProviderInterface
    method connect (line 31) | public function connect(Application $app);

FILE: src/Silex/Api/EventListenerProviderInterface.php
  type EventListenerProviderInterface (line 22) | interface EventListenerProviderInterface
    method subscribe (line 24) | public function subscribe(Container $app, EventDispatcherInterface $di...

FILE: src/Silex/AppArgumentValueResolver.php
  class AppArgumentValueResolver (line 23) | class AppArgumentValueResolver implements ArgumentValueResolverInterface
    method __construct (line 27) | public function __construct(Application $app)
    method supports (line 35) | public function supports(Request $request, ArgumentMetadata $argument)
    method resolve (line 43) | public function resolve(Request $request, ArgumentMetadata $argument)

FILE: src/Silex/Application.php
  class Application (line 42) | class Application extends Container implements HttpKernelInterface, Term...
    method __construct (line 59) | public function __construct(array $values = array())
    method register (line 86) | public function register(ServiceProviderInterface $provider, array $va...
    method boot (line 101) | public function boot()
    method match (line 130) | public function match($pattern, $to = null)
    method get (line 143) | public function get($pattern, $to = null)
    method post (line 156) | public function post($pattern, $to = null)
    method put (line 169) | public function put($pattern, $to = null)
    method delete (line 182) | public function delete($pattern, $to = null)
    method options (line 195) | public function options($pattern, $to = null)
    method patch (line 208) | public function patch($pattern, $to = null)
    method on (line 221) | public function on($eventName, $callback, $priority = 0)
    method before (line 245) | public function before($callback, $priority = 0)
    method after (line 271) | public function after($callback, $priority = 0)
    method finish (line 298) | public function finish($callback, $priority = 0)
    method abort (line 314) | public function abort($statusCode, $message = '', array $headers = arr...
    method error (line 336) | public function error($callback, $priority = -8)
    method view (line 353) | public function view($callback, $priority = 0)
    method flush (line 361) | public function flush()
    method redirect (line 374) | public function redirect($url, $status = 302)
    method stream (line 388) | public function stream($callback = null, $status = 200, array $headers...
    method escape (line 403) | public function escape($text, $flags = ENT_COMPAT, $charset = null, $d...
    method json (line 417) | public function json($data = array(), $status = 200, array $headers = ...
    method sendFile (line 432) | public function sendFile($file, $status = 200, array $headers = array(...
    method mount (line 447) | public function mount($prefix, $controllers)
    method run (line 471) | public function run(Request $request = null)
    method handle (line 488) | public function handle(Request $request, $type = HttpKernelInterface::...
    method terminate (line 502) | public function terminate(Request $request, Response $response)

FILE: src/Silex/Application/FormTrait.php
  type FormTrait (line 25) | trait FormTrait
    method form (line 36) | public function form($data = null, array $options = array(), $type = n...
    method namedForm (line 51) | public function namedForm($name, $data = null, array $options = array(...

FILE: src/Silex/Application/MonologTrait.php
  type MonologTrait (line 21) | trait MonologTrait
    method log (line 32) | public function log($message, array $context = array(), $level = Logge...

FILE: src/Silex/Application/SecurityTrait.php
  type SecurityTrait (line 22) | trait SecurityTrait
    method encodePassword (line 34) | public function encodePassword(UserInterface $user, $password)
    method isGranted (line 49) | public function isGranted($attributes, $object = null)

FILE: src/Silex/Application/SwiftmailerTrait.php
  type SwiftmailerTrait (line 19) | trait SwiftmailerTrait
    method mail (line 29) | public function mail(\Swift_Message $message, &$failedRecipients = null)

FILE: src/Silex/Application/TranslationTrait.php
  type TranslationTrait (line 19) | trait TranslationTrait
    method trans (line 31) | public function trans($id, array $parameters = array(), $domain = 'mes...
    method transChoice (line 47) | public function transChoice($id, $number, array $parameters = array(),...

FILE: src/Silex/Application/TwigTrait.php
  type TwigTrait (line 22) | trait TwigTrait
    method render (line 35) | public function render($view, array $parameters = array(), Response $r...
    method renderView (line 61) | public function renderView($view, array $parameters = array())

FILE: src/Silex/Application/UrlGeneratorTrait.php
  type UrlGeneratorTrait (line 21) | trait UrlGeneratorTrait
    method path (line 31) | public function path($route, $parameters = array())
    method url (line 44) | public function url($route, $parameters = array())

FILE: src/Silex/CallbackResolver.php
  class CallbackResolver (line 16) | class CallbackResolver
    method __construct (line 22) | public function __construct(Container $app)
    method isValid (line 34) | public function isValid($name)
    method convertCallback (line 48) | public function convertCallback($name)
    method resolveCallback (line 74) | public function resolveCallback($name)

FILE: src/Silex/Controller.php
  class Controller (line 34) | class Controller
    method __construct (line 45) | public function __construct(Route $route)
    method getRoute (line 55) | public function getRoute()
    method getRouteName (line 65) | public function getRouteName()
    method bind (line 77) | public function bind($routeName)
    method __call (line 88) | public function __call($method, $arguments)
    method freeze (line 104) | public function freeze()
    method generateRouteName (line 109) | public function generateRouteName($prefix)

FILE: src/Silex/ControllerCollection.php
  class ControllerCollection (line 40) | class ControllerCollection
    method __construct (line 49) | public function __construct(Route $defaultRoute, RouteCollection $rout...
    method mount (line 67) | public function mount($prefix, $controllers)
    method match (line 92) | public function match($pattern, $to = null)
    method get (line 110) | public function get($pattern, $to = null)
    method post (line 123) | public function post($pattern, $to = null)
    method put (line 136) | public function put($pattern, $to = null)
    method delete (line 149) | public function delete($pattern, $to = null)
    method options (line 162) | public function options($pattern, $to = null)
    method patch (line 175) | public function patch($pattern, $to = null)
    method __call (line 180) | public function __call($method, $arguments)
    method flush (line 200) | public function flush()
    method doFlush (line 211) | private function doFlush($prefix, RouteCollection $routes)

FILE: src/Silex/ControllerResolver.php
  class ControllerResolver (line 25) | class ControllerResolver extends BaseControllerResolver
    method __construct (line 35) | public function __construct(Application $app, LoggerInterface $logger ...
    method doGetArguments (line 42) | protected function doGetArguments(Request $request, $controller, array...

FILE: src/Silex/EventListener/ConverterListener.php
  class ConverterListener (line 25) | class ConverterListener implements EventSubscriberInterface
    method __construct (line 36) | public function __construct(RouteCollection $routes, CallbackResolver ...
    method onKernelController (line 47) | public function onKernelController(FilterControllerEvent $event)
    method getSubscribedEvents (line 60) | public static function getSubscribedEvents()

FILE: src/Silex/EventListener/LogListener.php
  class LogListener (line 29) | class LogListener implements EventSubscriberInterface
    method __construct (line 34) | public function __construct(LoggerInterface $logger, $exceptionLogFilt...
    method onKernelRequest (line 55) | public function onKernelRequest(GetResponseEvent $event)
    method onKernelResponse (line 69) | public function onKernelResponse(FilterResponseEvent $event)
    method onKernelException (line 83) | public function onKernelException(GetResponseForExceptionEvent $event)
    method logRequest (line 93) | protected function logRequest(Request $request)
    method logResponse (line 103) | protected function logResponse(Response $response)
    method logException (line 117) | protected function logException(\Exception $e)
    method getSubscribedEvents (line 122) | public static function getSubscribedEvents()

FILE: src/Silex/EventListener/MiddlewareListener.php
  class MiddlewareListener (line 26) | class MiddlewareListener implements EventSubscriberInterface
    method __construct (line 35) | public function __construct(Application $app)
    method onKernelRequest (line 45) | public function onKernelRequest(GetResponseEvent $event)
    method onKernelResponse (line 70) | public function onKernelResponse(FilterResponseEvent $event)
    method getSubscribedEvents (line 88) | public static function getSubscribedEvents()

FILE: src/Silex/EventListener/StringToResponseListener.php
  class StringToResponseListener (line 24) | class StringToResponseListener implements EventSubscriberInterface
    method onKernelView (line 31) | public function onKernelView(GetResponseForControllerResultEvent $event)
    method getSubscribedEvents (line 45) | public static function getSubscribedEvents()

FILE: src/Silex/Exception/ControllerFrozenException.php
  class ControllerFrozenException (line 19) | class ControllerFrozenException extends \RuntimeException

FILE: src/Silex/ExceptionHandler.php
  class ExceptionHandler (line 26) | class ExceptionHandler implements EventSubscriberInterface
    method __construct (line 30) | public function __construct($debug)
    method onSilexError (line 35) | public function onSilexError(GetResponseForExceptionEvent $event)
    method getSubscribedEvents (line 52) | public static function getSubscribedEvents()

FILE: src/Silex/ExceptionListenerWrapper.php
  class ExceptionListenerWrapper (line 25) | class ExceptionListenerWrapper
    method __construct (line 36) | public function __construct(Application $app, $callback)
    method __invoke (line 42) | public function __invoke(GetResponseForExceptionEvent $event)
    method shouldRun (line 58) | protected function shouldRun(\Exception $exception)
    method ensureResponse (line 80) | protected function ensureResponse($response, GetResponseForExceptionEv...

FILE: src/Silex/Provider/AssetServiceProvider.php
  class AssetServiceProvider (line 29) | class AssetServiceProvider implements ServiceProviderInterface
    method register (line 31) | public function register(Container $app)

FILE: src/Silex/Provider/CsrfServiceProvider.php
  class CsrfServiceProvider (line 26) | class CsrfServiceProvider implements ServiceProviderInterface
    method register (line 28) | public function register(Container $app)

FILE: src/Silex/Provider/DoctrineServiceProvider.php
  class DoctrineServiceProvider (line 26) | class DoctrineServiceProvider implements ServiceProviderInterface
    method register (line 28) | public function register(Container $app)

FILE: src/Silex/Provider/ExceptionHandlerServiceProvider.php
  class ExceptionHandlerServiceProvider (line 11) | class ExceptionHandlerServiceProvider implements ServiceProviderInterfac...
    method register (line 16) | public function register(Container $app)
    method subscribe (line 26) | public function subscribe(Container $app, EventDispatcherInterface $di...

FILE: src/Silex/Provider/Form/SilexFormExtension.php
  class SilexFormExtension (line 19) | class SilexFormExtension implements FormExtensionInterface
    method __construct (line 28) | public function __construct(Container $app, array $types, array $typeE...
    method getType (line 36) | public function getType($name)
    method hasType (line 48) | public function hasType($name)
    method getTypeExtensions (line 53) | public function getTypeExtensions($name)
    method hasTypeExtensions (line 58) | public function hasTypeExtensions($name)
    method getTypeGuesser (line 63) | public function getTypeGuesser()
    method setTypes (line 83) | private function setTypes(array $types)
    method setTypeExtensions (line 98) | private function setTypeExtensions(array $typeExtensions)
    method setGuessers (line 112) | private function setGuessers(array $guessers)

FILE: src/Silex/Provider/FormServiceProvider.php
  class FormServiceProvider (line 27) | class FormServiceProvider implements ServiceProviderInterface
    method register (line 29) | public function register(Container $app)

FILE: src/Silex/Provider/HttpCache/HttpCache.php
  class HttpCache (line 22) | class HttpCache extends BaseHttpCache
    method run (line 29) | public function run(Request $request = null)

FILE: src/Silex/Provider/HttpCacheServiceProvider.php
  class HttpCacheServiceProvider (line 28) | class HttpCacheServiceProvider implements ServiceProviderInterface, Even...
    method register (line 30) | public function register(Container $app)
    method subscribe (line 57) | public function subscribe(Container $app, EventDispatcherInterface $di...

FILE: src/Silex/Provider/HttpFragmentServiceProvider.php
  class HttpFragmentServiceProvider (line 31) | class HttpFragmentServiceProvider implements ServiceProviderInterface, E...
    method register (line 33) | public function register(Container $app)
    method subscribe (line 82) | public function subscribe(Container $app, EventDispatcherInterface $di...

FILE: src/Silex/Provider/HttpKernelServiceProvider.php
  class HttpKernelServiceProvider (line 28) | class HttpKernelServiceProvider implements ServiceProviderInterface, Eve...
    method register (line 33) | public function register(Container $app)
    method subscribe (line 88) | public function subscribe(Container $app, EventDispatcherInterface $di...

FILE: src/Silex/Provider/Locale/LocaleListener.php
  class LocaleListener (line 29) | class LocaleListener implements EventSubscriberInterface
    method __construct (line 36) | public function __construct(Container $app, $defaultLocale = 'en', Req...
    method onKernelRequest (line 44) | public function onKernelRequest(GetResponseEvent $event)
    method onKernelFinishRequest (line 55) | public function onKernelFinishRequest(FinishRequestEvent $event)
    method setLocale (line 62) | private function setLocale(Request $request)
    method setRouterContext (line 69) | private function setRouterContext(Request $request)
    method getSubscribedEvents (line 76) | public static function getSubscribedEvents()

FILE: src/Silex/Provider/LocaleServiceProvider.php
  class LocaleServiceProvider (line 25) | class LocaleServiceProvider implements ServiceProviderInterface, EventLi...
    method register (line 27) | public function register(Container $app)
    method subscribe (line 36) | public function subscribe(Container $app, EventDispatcherInterface $di...

FILE: src/Silex/Provider/MonologServiceProvider.php
  class MonologServiceProvider (line 31) | class MonologServiceProvider implements ServiceProviderInterface, Bootab...
    method register (line 33) | public function register(Container $app)
    method boot (line 114) | public function boot(Application $app)
    method translateLevel (line 125) | public static function translateLevel($name)

FILE: src/Silex/Provider/RememberMeServiceProvider.php
  class RememberMeServiceProvider (line 28) | class RememberMeServiceProvider implements ServiceProviderInterface, Eve...
    method register (line 30) | public function register(Container $app)
    method subscribe (line 103) | public function subscribe(Container $app, EventDispatcherInterface $di...

FILE: src/Silex/Provider/Routing/LazyRequestMatcher.php
  class LazyRequestMatcher (line 24) | class LazyRequestMatcher implements RequestMatcherInterface
    method __construct (line 28) | public function __construct(\Closure $factory)
    method getRequestMatcher (line 38) | public function getRequestMatcher()
    method matchRequest (line 51) | public function matchRequest(Request $request)

FILE: src/Silex/Provider/Routing/RedirectableUrlMatcher.php
  class RedirectableUrlMatcher (line 22) | class RedirectableUrlMatcher extends BaseRedirectableUrlMatcher
    method redirect (line 27) | public function redirect($path, $route, $scheme = null)

FILE: src/Silex/Provider/RoutingServiceProvider.php
  class RoutingServiceProvider (line 31) | class RoutingServiceProvider implements ServiceProviderInterface, EventL...
    method register (line 33) | public function register(Container $app)
    method subscribe (line 83) | public function subscribe(Container $app, EventDispatcherInterface $di...

FILE: src/Silex/Provider/SecurityServiceProvider.php
  class SecurityServiceProvider (line 71) | class SecurityServiceProvider implements ServiceProviderInterface, Event...
    method register (line 75) | public function register(Container $app)
    method subscribe (line 658) | public function subscribe(Container $app, EventDispatcherInterface $di...
    method connect (line 663) | public function connect(Application $app)
    method boot (line 675) | public function boot(Application $app)
    method addFakeRoute (line 680) | public function addFakeRoute($method, $pattern, $name)

FILE: src/Silex/Provider/SerializerServiceProvider.php
  class SerializerServiceProvider (line 28) | class SerializerServiceProvider implements ServiceProviderInterface
    method register (line 36) | public function register(Container $app)

FILE: src/Silex/Provider/ServiceControllerServiceProvider.php
  class ServiceControllerServiceProvider (line 18) | class ServiceControllerServiceProvider implements ServiceProviderInterface
    method register (line 20) | public function register(Container $app)

FILE: src/Silex/Provider/Session/SessionListener.php
  class SessionListener (line 22) | class SessionListener extends BaseSessionListener
    method __construct (line 26) | public function __construct(Container $app)
    method getSession (line 31) | protected function getSession()

FILE: src/Silex/Provider/Session/TestSessionListener.php
  class TestSessionListener (line 22) | class TestSessionListener extends BaseTestSessionListener
    method __construct (line 26) | public function __construct(Container $app)
    method getSession (line 31) | protected function getSession()

FILE: src/Silex/Provider/SessionServiceProvider.php
  class SessionServiceProvider (line 30) | class SessionServiceProvider implements ServiceProviderInterface, EventL...
    method register (line 32) | public function register(Container $app)
    method subscribe (line 78) | public function subscribe(Container $app, EventDispatcherInterface $di...

FILE: src/Silex/Provider/SwiftmailerServiceProvider.php
  class SwiftmailerServiceProvider (line 27) | class SwiftmailerServiceProvider implements ServiceProviderInterface, Ev...
    method register (line 29) | public function register(Container $app)
    method subscribe (line 109) | public function subscribe(Container $app, EventDispatcherInterface $di...

FILE: src/Silex/Provider/TranslationServiceProvider.php
  class TranslationServiceProvider (line 29) | class TranslationServiceProvider implements ServiceProviderInterface, Ev...
    method register (line 31) | public function register(Container $app)
    method subscribe (line 92) | public function subscribe(Container $app, EventDispatcherInterface $di...

FILE: src/Silex/Provider/TwigServiceProvider.php
  class TwigServiceProvider (line 33) | class TwigServiceProvider implements ServiceProviderInterface
    method register (line 35) | public function register(Container $app)

FILE: src/Silex/Provider/Validator/ConstraintValidatorFactory.php
  class ConstraintValidatorFactory (line 24) | class ConstraintValidatorFactory extends BaseConstraintValidatorFactory
    method __construct (line 42) | public function __construct(Container $container, array $serviceNames ...
    method getInstance (line 53) | public function getInstance(Constraint $constraint)

FILE: src/Silex/Provider/ValidatorServiceProvider.php
  class ValidatorServiceProvider (line 27) | class ValidatorServiceProvider implements ServiceProviderInterface
    method register (line 29) | public function register(Container $app)

FILE: src/Silex/Provider/VarDumperServiceProvider.php
  class VarDumperServiceProvider (line 27) | class VarDumperServiceProvider implements ServiceProviderInterface, Boot...
    method register (line 29) | public function register(Container $app)
    method boot (line 42) | public function boot(Application $app)

FILE: src/Silex/Route.php
  class Route (line 21) | class Route extends BaseRoute
    method __construct (line 38) | public function __construct($path = '/', array $defaults = array(), ar...
    method run (line 51) | public function run($to)
    method assert (line 66) | public function assert($variable, $regexp)
    method value (line 81) | public function value($variable, $default)
    method convert (line 96) | public function convert($variable, $callback)
    method method (line 112) | public function method($method)
    method host (line 126) | public function host($host)
    method requireHttp (line 138) | public function requireHttp()
    method requireHttps (line 150) | public function requireHttps()
    method before (line 164) | public function before($callback)
    method after (line 180) | public function after($callback)
    method when (line 196) | public function when($condition)

FILE: src/Silex/Route/SecurityTrait.php
  type SecurityTrait (line 21) | trait SecurityTrait
    method secure (line 23) | public function secure($roles)

FILE: src/Silex/ServiceControllerResolver.php
  class ServiceControllerResolver (line 22) | class ServiceControllerResolver implements ControllerResolverInterface
    method __construct (line 33) | public function __construct(ControllerResolverInterface $controllerRes...
    method getController (line 42) | public function getController(Request $request)
    method getArguments (line 56) | public function getArguments(Request $request, $controller)

FILE: src/Silex/ViewListenerWrapper.php
  class ViewListenerWrapper (line 22) | class ViewListenerWrapper
    method __construct (line 33) | public function __construct(Application $app, $callback)
    method __invoke (line 39) | public function __invoke(GetResponseForControllerResultEvent $event)
    method shouldRun (line 57) | private function shouldRun($callback, $controllerResult)

FILE: src/Silex/WebTestCase.php
  class WebTestCase (line 22) | abstract class WebTestCase extends \PHPUnit_Framework_TestCase
    method setUp (line 37) | protected function setUp()
    method createApplication (line 47) | abstract public function createApplication();
    method createClient (line 56) | public function createClient(array $server = array())

FILE: tests/Silex/Tests/Application/FormApplication.php
  class FormApplication (line 16) | class FormApplication extends Application

FILE: tests/Silex/Tests/Application/FormTraitTest.php
  class FormTraitTest (line 21) | class FormTraitTest extends \PHPUnit_Framework_TestCase
    method testForm (line 23) | public function testForm()
    method createApplication (line 28) | public function createApplication()

FILE: tests/Silex/Tests/Application/MonologApplication.php
  class MonologApplication (line 16) | class MonologApplication extends Application

FILE: tests/Silex/Tests/Application/MonologTraitTest.php
  class MonologTraitTest (line 23) | class MonologTraitTest extends \PHPUnit_Framework_TestCase
    method testLog (line 25) | public function testLog()
    method createApplication (line 35) | public function createApplication()

FILE: tests/Silex/Tests/Application/SecurityApplication.php
  class SecurityApplication (line 16) | class SecurityApplication extends Application

FILE: tests/Silex/Tests/Application/SecurityTraitTest.php
  class SecurityTraitTest (line 23) | class SecurityTraitTest extends \PHPUnit_Framework_TestCase
    method testEncodePassword (line 25) | public function testEncodePassword()
    method testIsGrantedWithoutTokenThrowsException (line 43) | public function testIsGrantedWithoutTokenThrowsException()
    method testIsGranted (line 51) | public function testIsGranted()
    method createApplication (line 76) | public function createApplication($users = array())

FILE: tests/Silex/Tests/Application/SwiftmailerApplication.php
  class SwiftmailerApplication (line 16) | class SwiftmailerApplication extends Application

FILE: tests/Silex/Tests/Application/SwiftmailerTraitTest.php
  class SwiftmailerTraitTest (line 21) | class SwiftmailerTraitTest extends \PHPUnit_Framework_TestCase
    method testMail (line 23) | public function testMail()
    method createApplication (line 37) | public function createApplication()

FILE: tests/Silex/Tests/Application/TranslationApplication.php
  class TranslationApplication (line 16) | class TranslationApplication extends Application

FILE: tests/Silex/Tests/Application/TranslationTraitTest.php
  class TranslationTraitTest (line 21) | class TranslationTraitTest extends \PHPUnit_Framework_TestCase
    method testTrans (line 23) | public function testTrans()
    method testTransChoice (line 31) | public function testTransChoice()
    method createApplication (line 39) | public function createApplication()

FILE: tests/Silex/Tests/Application/TwigApplication.php
  class TwigApplication (line 16) | class TwigApplication extends Application

FILE: tests/Silex/Tests/Application/TwigTraitTest.php
  class TwigTraitTest (line 23) | class TwigTraitTest extends \PHPUnit_Framework_TestCase
    method testRender (line 25) | public function testRender()
    method testRenderKeepResponse (line 37) | public function testRenderKeepResponse()
    method testRenderForStream (line 48) | public function testRenderForStream()
    method testRenderView (line 63) | public function testRenderView()
    method createApplication (line 73) | public function createApplication()

FILE: tests/Silex/Tests/Application/UrlGeneratorApplication.php
  class UrlGeneratorApplication (line 16) | class UrlGeneratorApplication extends Application

FILE: tests/Silex/Tests/Application/UrlGeneratorTraitTest.php
  class UrlGeneratorTraitTest (line 21) | class UrlGeneratorTraitTest extends \PHPUnit_Framework_TestCase
    method testUrl (line 23) | public function testUrl()
    method testPath (line 31) | public function testPath()

FILE: tests/Silex/Tests/ApplicationTest.php
  class ApplicationTest (line 31) | class ApplicationTest extends \PHPUnit_Framework_TestCase
    method testMatchReturnValue (line 33) | public function testMatchReturnValue()
    method testConstructorInjection (line 56) | public function testConstructorInjection()
    method testGetRequest (line 69) | public function testGetRequest()
    method testGetRoutesWithNoRoutes (line 81) | public function testGetRoutesWithNoRoutes()
    method testGetRoutesWithRoutes (line 90) | public function testGetRoutesWithRoutes()
    method testOnCoreController (line 109) | public function testOnCoreController()
    method testOn (line 128) | public function testOn()
    method testAbort (line 142) | public function testAbort()
    method testEscape (line 157) | public function testEscape($expected, $text)
    method escapeProvider (line 164) | public function escapeProvider()
    method testControllersAsMethods (line 175) | public function testControllersAsMethods()
    method testApplicationTypeHintWorks (line 185) | public function testApplicationTypeHintWorks()
    method testPhp7TypeHintWorks (line 198) | public function testPhp7TypeHintWorks()
    method testHttpSpec (line 208) | public function testHttpSpec()
    method testRoutesMiddlewares (line 227) | public function testRoutesMiddlewares()
    method testRoutesBeforeMiddlewaresWithResponseObject (line 280) | public function testRoutesBeforeMiddlewaresWithResponseObject()
    method testRoutesAfterMiddlewaresWithResponseObject (line 297) | public function testRoutesAfterMiddlewaresWithResponseObject()
    method testRoutesBeforeMiddlewaresWithRedirectResponseObject (line 314) | public function testRoutesBeforeMiddlewaresWithRedirectResponseObject()
    method testRoutesBeforeMiddlewaresTriggeredAfterSilexBeforeFilters (line 332) | public function testRoutesBeforeMiddlewaresTriggeredAfterSilexBeforeFi...
    method testRoutesAfterMiddlewaresTriggeredBeforeSilexAfterFilters (line 355) | public function testRoutesAfterMiddlewaresTriggeredBeforeSilexAfterFil...
    method testFinishFilter (line 378) | public function testFinishFilter()
    method testNonResponseAndNonNullReturnFromRouteBeforeMiddlewareShouldThrowRuntimeException (line 408) | public function testNonResponseAndNonNullReturnFromRouteBeforeMiddlewa...
    method testNonResponseAndNonNullReturnFromRouteAfterMiddlewareShouldThrowRuntimeException (line 427) | public function testNonResponseAndNonNullReturnFromRouteAfterMiddlewar...
    method testSubRequest (line 443) | public function testSubRequest()
    method testRegisterShouldReturnSelf (line 456) | public function testRegisterShouldReturnSelf()
    method testMountShouldReturnSelf (line 464) | public function testMountShouldReturnSelf()
    method testMountPreservesOrder (line 473) | public function testMountPreservesOrder()
    method testMountNullException (line 491) | public function testMountNullException()
    method testMountWrongConnectReturnValueException (line 501) | public function testMountWrongConnectReturnValueException()
    method testMountCallable (line 507) | public function testMountCallable()
    method testSendFile (line 519) | public function testSendFile()
    method testGetRouteCollectionWithRouteWithoutController (line 532) | public function testGetRouteCollectionWithRouteWithoutController()
    method testBeforeFilterOnMountedControllerGroupIsolatedToGroup (line 540) | public function testBeforeFilterOnMountedControllerGroupIsolatedToGroup()
    method testViewListenerWithPrimitive (line 552) | public function testViewListenerWithPrimitive()
    method testViewListenerWithArrayTypeHint (line 565) | public function testViewListenerWithArrayTypeHint()
    method testViewListenerWithObjectTypeHint (line 578) | public function testViewListenerWithObjectTypeHint()
    method testViewListenerWithCallableTypeHint (line 591) | public function testViewListenerWithCallableTypeHint()
    method testViewListenersCanBeChained (line 604) | public function testViewListenersCanBeChained()
    method testViewListenersAreIgnoredIfNotSuitable (line 622) | public function testViewListenersAreIgnoredIfNotSuitable()
    method testViewListenersResponsesAreNotUsedIfNull (line 640) | public function testViewListenersResponsesAreNotUsedIfNull()
    method testDefaultRoutesFactory (line 658) | public function testDefaultRoutesFactory()
    method testOverriddenRoutesFactory (line 664) | public function testOverriddenRoutesFactory()
  class FooController (line 674) | class FooController
    method barAction (line 676) | public function barAction(Application $app, $name)
    method barSpecialAction (line 681) | public function barSpecialAction(SpecialApplication $app, $name)
  class IncorrectControllerCollection (line 687) | class IncorrectControllerCollection implements ControllerProviderInterface
    method connect (line 689) | public function connect(Application $app)
  class RouteCollectionSubClass (line 695) | class RouteCollectionSubClass extends RouteCollection
  class SpecialApplication (line 699) | class SpecialApplication extends Application

FILE: tests/Silex/Tests/CallbackResolverTest.php
  class CallbackResolverTest (line 17) | class CallbackResolverTest extends \PHPUnit_Framework_Testcase
    method setup (line 22) | public function setup()
    method testShouldResolveCallback (line 28) | public function testShouldResolveCallback()
    method testNonStringsAreNotValid (line 48) | public function testNonStringsAreNotValid($name)
    method nonStringsAreNotValidProvider (line 53) | public function nonStringsAreNotValidProvider()
    method testShouldThrowAnExceptionIfServiceIsNotCallable (line 67) | public function testShouldThrowAnExceptionIfServiceIsNotCallable($name)
    method shouldThrowAnExceptionIfServiceIsNotCallableProvider (line 74) | public function shouldThrowAnExceptionIfServiceIsNotCallableProvider()

FILE: tests/Silex/Tests/CallbackServicesTest.php
  class CallbackServicesTest (line 23) | class CallbackServicesTest extends \PHPUnit_Framework_TestCase
    method testCallbacksAsServices (line 27) | public function testCallbacksAsServices()
    method controller (line 65) | public function controller(Application $app)
    method before (line 70) | public function before()
    method after (line 75) | public function after()
    method beforeApp (line 80) | public function beforeApp()
    method afterApp (line 85) | public function afterApp()
    method finishApp (line 90) | public function finishApp()
    method error (line 95) | public function error()
    method convert (line 100) | public function convert()
    method onRequest (line 105) | public function onRequest()

FILE: tests/Silex/Tests/ControllerCollectionTest.php
  class ControllerCollectionTest (line 26) | class ControllerCollectionTest extends \PHPUnit_Framework_TestCase
    method testGetRouteCollectionWithNoRoutes (line 28) | public function testGetRouteCollectionWithNoRoutes()
    method testGetRouteCollectionWithRoutes (line 35) | public function testGetRouteCollectionWithRoutes()
    method testControllerFreezing (line 45) | public function testControllerFreezing()
    method testConflictingRouteNames (line 67) | public function testConflictingRouteNames()
    method testUniqueGeneratedRouteNames (line 81) | public function testUniqueGeneratedRouteNames()
    method testUniqueGeneratedRouteNamesAmongMounts (line 95) | public function testUniqueGeneratedRouteNamesAmongMounts()
    method testUniqueGeneratedRouteNamesAmongNestedMounts (line 111) | public function testUniqueGeneratedRouteNamesAmongNestedMounts()
    method testMountCallable (line 130) | public function testMountCallable()
    method testMountCallableProperClone (line 143) | public function testMountCallableProperClone()
    method testMountControllersFactory (line 159) | public function testMountControllersFactory()
    method testMountCallableException (line 175) | public function testMountCallableException()
    method testAssert (line 181) | public function testAssert()
    method testValue (line 193) | public function testValue()
    method testConvert (line 205) | public function testConvert()
    method testRequireHttp (line 215) | public function testRequireHttp()
    method testBefore (line 228) | public function testBefore()
    method testAfter (line 238) | public function testAfter()
    method testWhen (line 248) | public function testWhen()
    method testRouteExtension (line 256) | public function testRouteExtension()
    method testRouteMethodDoesNotExist (line 269) | public function testRouteMethodDoesNotExist()
    method testNestedCollectionRouteCallbacks (line 277) | public function testNestedCollectionRouteCallbacks()
    method testRoutesFactoryOmitted (line 295) | public function testRoutesFactoryOmitted()
    method testRoutesFactoryInConstructor (line 302) | public function testRoutesFactoryInConstructor()
  class MyRoute1 (line 315) | class MyRoute1 extends Route
    method foo (line 319) | public function foo($value)
  class RouteCollectionSubClass2 (line 325) | class RouteCollectionSubClass2 extends RouteCollection

FILE: tests/Silex/Tests/ControllerResolverTest.php
  class ControllerResolverTest (line 23) | class ControllerResolverTest extends \PHPUnit_Framework_TestCase
    method testGetArguments (line 28) | public function testGetArguments()

FILE: tests/Silex/Tests/ControllerTest.php
  class ControllerTest (line 22) | class ControllerTest extends \PHPUnit_Framework_TestCase
    method testBind (line 24) | public function testBind()
    method testBindOnFrozenControllerShouldThrowException (line 36) | public function testBindOnFrozenControllerShouldThrowException()
    method testAssert (line 44) | public function testAssert()
    method testValue (line 53) | public function testValue()
    method testConvert (line 62) | public function testConvert()
    method testRun (line 71) | public function testRun()
    method testDefaultRouteNameGeneration (line 83) | public function testDefaultRouteNameGeneration(Route $route, $prefix, ...
    method provideRouteAndExpectedRouteName (line 91) | public function provideRouteAndExpectedRouteName()
    method testRouteExtension (line 102) | public function testRouteExtension()
    method testRouteMethodDoesNotExist (line 115) | public function testRouteMethodDoesNotExist()
  class MyRoute (line 124) | class MyRoute extends Route
    method foo (line 128) | public function foo($value)

FILE: tests/Silex/Tests/EventListener/LogListenerTest.php
  class LogListenerTest (line 31) | class LogListenerTest extends \PHPUnit_Framework_TestCase
    method testRequestListener (line 33) | public function testRequestListener()
    method testResponseListener (line 52) | public function testResponseListener()
    method testExceptionListener (line 71) | public function testExceptionListener()

FILE: tests/Silex/Tests/ExceptionHandlerTest.php
  class ExceptionHandlerTest (line 24) | class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
    method testExceptionHandlerExceptionNoDebug (line 26) | public function testExceptionHandlerExceptionNoDebug()
    method testExceptionHandlerExceptionDebug (line 41) | public function testExceptionHandlerExceptionDebug()
    method testExceptionHandlerNotFoundNoDebug (line 57) | public function testExceptionHandlerNotFoundNoDebug()
    method testExceptionHandlerNotFoundDebug (line 68) | public function testExceptionHandlerNotFoundDebug()
    method testExceptionHandlerMethodNotAllowedNoDebug (line 79) | public function testExceptionHandlerMethodNotAllowedNoDebug()
    method testExceptionHandlerMethodNotAllowedDebug (line 93) | public function testExceptionHandlerMethodNotAllowedDebug()
    method testNoExceptionHandler (line 107) | public function testNoExceptionHandler()
    method testOneExceptionHandler (line 125) | public function testOneExceptionHandler()
    method testMultipleExceptionHandlers (line 154) | public function testMultipleExceptionHandlers()
    method testNoResponseExceptionHandler (line 189) | public function testNoResponseExceptionHandler()
    method testStringResponseExceptionHandler (line 217) | public function testStringResponseExceptionHandler()
    method testExceptionHandlerException (line 233) | public function testExceptionHandlerException()
    method testRemoveExceptionHandlerAfterDispatcherAccess (line 254) | public function testRemoveExceptionHandlerAfterDispatcherAccess()
    method testExceptionHandlerWithDefaultException (line 277) | public function testExceptionHandlerWithDefaultException()
    method testExceptionHandlerWithStandardException (line 296) | public function testExceptionHandlerWithStandardException()
    method testExceptionHandlerWithSpecifiedException (line 322) | public function testExceptionHandlerWithSpecifiedException()
    method testExceptionHandlerWithSpecifiedExceptionInReverseOrder (line 348) | public function testExceptionHandlerWithSpecifiedExceptionInReverseOrd...
    method testExceptionHandlerWithArrayStyleCallback (line 376) | public function testExceptionHandlerWithArrayStyleCallback()
    method checkRouteResponse (line 393) | protected function checkRouteResponse($app, $path, $expectedContent, $...
    method exceptionHandler (line 402) | public function exceptionHandler()

FILE: tests/Silex/Tests/Fixtures/Php7Controller.php
  class Php7Controller (line 16) | class Php7Controller
    method typehintedAction (line 18) | public function typehintedAction(Application $application, string $name)

FILE: tests/Silex/Tests/FunctionalTest.php
  class FunctionalTest (line 25) | class FunctionalTest extends \PHPUnit_Framework_TestCase
    method testBind (line 27) | public function testBind()
    method testMount (line 47) | public function testMount()

FILE: tests/Silex/Tests/JsonTest.php
  class JsonTest (line 21) | class JsonTest extends \PHPUnit_Framework_TestCase
    method testJsonReturnsJsonResponse (line 23) | public function testJsonReturnsJsonResponse()
    method testJsonUsesData (line 33) | public function testJsonUsesData()
    method testJsonUsesStatus (line 41) | public function testJsonUsesStatus()
    method testJsonUsesHeaders (line 49) | public function testJsonUsesHeaders()

FILE: tests/Silex/Tests/LazyDispatcherTest.php
  class LazyDispatcherTest (line 17) | class LazyDispatcherTest extends \PHPUnit_Framework_TestCase
    method beforeMiddlewareShouldNotCreateDispatcherEarly (line 20) | public function beforeMiddlewareShouldNotCreateDispatcherEarly()
    method eventHelpersShouldDirectlyAddListenersAfterBoot (line 42) | public function eventHelpersShouldDirectlyAddListenersAfterBoot()

FILE: tests/Silex/Tests/LazyRequestMatcherTest.php
  class LazyRequestMatcherTest (line 22) | class LazyRequestMatcherTest extends \PHPUnit_Framework_TestCase
    method testUserMatcherIsCreatedLazily (line 27) | public function testUserMatcherIsCreatedLazily()
    method testThatCanInjectRequestMatcherOnly (line 48) | public function testThatCanInjectRequestMatcherOnly()
    method testMatchIsProxy (line 61) | public function testMatchIsProxy()

FILE: tests/Silex/Tests/LocaleTest.php
  class LocaleTest (line 24) | class LocaleTest extends \PHPUnit_Framework_TestCase
    method testLocale (line 26) | public function testLocale()
    method testLocaleInSubRequests (line 48) | public function testLocaleInSubRequests()
    method testLocaleWithBefore (line 70) | public function testLocaleWithBefore()

FILE: tests/Silex/Tests/MiddlewareTest.php
  class MiddlewareTest (line 23) | class MiddlewareTest extends \PHPUnit_Framework_TestCase
    method testBeforeAndAfterFilter (line 25) | public function testBeforeAndAfterFilter()
    method testAfterFilterWithResponseObject (line 53) | public function testAfterFilterWithResponseObject()
    method testMultipleFilters (line 75) | public function testMultipleFilters()
    method testFiltersShouldFireOnException (line 113) | public function testFiltersShouldFireOnException()
    method testFiltersShouldFireOnHttpException (line 141) | public function testFiltersShouldFireOnHttpException()
    method testBeforeFilterPreventsBeforeMiddlewaresToBeExecuted (line 165) | public function testBeforeFilterPreventsBeforeMiddlewaresToBeExecuted()
    method testBeforeFilterExceptionsWhenHandlingAnException (line 180) | public function testBeforeFilterExceptionsWhenHandlingAnException()
    method testRequestShouldBePopulatedOnBefore (line 190) | public function testRequestShouldBePopulatedOnBefore()
    method testBeforeFilterAccessesRequestAndCanReturnResponse (line 209) | public function testBeforeFilterAccessesRequestAndCanReturnResponse()
    method testAfterFilterAccessRequestResponse (line 223) | public function testAfterFilterAccessRequestResponse()
    method testAfterFilterCanReturnResponse (line 237) | public function testAfterFilterCanReturnResponse()
    method testRouteAndApplicationMiddlewareParameterInjection (line 251) | public function testRouteAndApplicationMiddlewareParameterInjection()

FILE: tests/Silex/Tests/Provider/AssetServiceProviderTest.php
  class AssetServiceProviderTest (line 17) | class AssetServiceProviderTest extends \PHPUnit_Framework_TestCase
    method testGenerateAssetUrl (line 19) | public function testGenerateAssetUrl()

FILE: tests/Silex/Tests/Provider/DoctrineServiceProviderTest.php
  class DoctrineServiceProviderTest (line 23) | class DoctrineServiceProviderTest extends \PHPUnit_Framework_TestCase
    method testOptionsInitializer (line 25) | public function testOptionsInitializer()
    method testSingleConnection (line 33) | public function testSingleConnection()
    method testMultipleConnections (line 54) | public function testMultipleConnections()
    method testLoggerLoading (line 83) | public function testLoggerLoading()
    method testLoggerNotLoaded (line 101) | public function testLoggerNotLoaded()

FILE: tests/Silex/Tests/Provider/FormServiceProviderTest.php
  class FormServiceProviderTest (line 28) | class FormServiceProviderTest extends \PHPUnit_Framework_TestCase
    method testFormFactoryServiceIsFormFactory (line 30) | public function testFormFactoryServiceIsFormFactory()
    method testFormServiceProviderWillLoadTypes (line 37) | public function testFormServiceProviderWillLoadTypes()
    method testFormServiceProviderWillLoadTypesServices (line 56) | public function testFormServiceProviderWillLoadTypesServices()
    method testNonExistentTypeService (line 83) | public function testNonExistentTypeService()
    method testFormServiceProviderWillLoadTypeExtensions (line 101) | public function testFormServiceProviderWillLoadTypeExtensions()
    method testFormServiceProviderWillLoadTypeExtensionsServices (line 120) | public function testFormServiceProviderWillLoadTypeExtensionsServices()
    method testNonExistentTypeExtensionService (line 147) | public function testNonExistentTypeExtensionService()
    method testFormServiceProviderWillLoadTypeGuessers (line 165) | public function testFormServiceProviderWillLoadTypeGuessers()
    method testFormServiceProviderWillLoadTypeGuessersServices (line 180) | public function testFormServiceProviderWillLoadTypeGuessersServices()
    method testNonExistentTypeGuesserService (line 202) | public function testNonExistentTypeGuesserService()
    method testFormServiceProviderWillUseTranslatorIfAvailable (line 217) | public function testFormServiceProviderWillUseTranslatorIfAvailable()
    method testFormServiceProviderWillNotAddNonexistentTranslationFiles (line 253) | public function testFormServiceProviderWillNotAddNonexistentTranslatio...
    method testFormCsrf (line 275) | public function testFormCsrf()
    method testUserExtensionCanConfigureDefaultExtensions (line 288) | public function testUserExtensionCanConfigureDefaultExtensions()
  class DummyFormType (line 308) | class DummyFormType extends AbstractType
    method getName (line 318) | public function getName()
  class DummyFormType (line 313) | class DummyFormType extends AbstractType
    method getName (line 318) | public function getName()
  class DummyFormTypeExtension (line 326) | class DummyFormTypeExtension extends AbstractTypeExtension
    method getExtendedType (line 328) | public function getExtendedType()
    method configureOptions (line 333) | public function configureOptions(OptionsResolver $resolver)
    method getExtendedType (line 341) | public function getExtendedType()
    method setDefaultOptions (line 346) | public function setDefaultOptions(OptionsResolverInterface $resolver)
  class DummyFormTypeExtension (line 339) | class DummyFormTypeExtension extends AbstractTypeExtension
    method getExtendedType (line 328) | public function getExtendedType()
    method configureOptions (line 333) | public function configureOptions(OptionsResolver $resolver)
    method getExtendedType (line 341) | public function getExtendedType()
    method setDefaultOptions (line 346) | public function setDefaultOptions(OptionsResolverInterface $resolver)

FILE: tests/Silex/Tests/Provider/FormServiceProviderTest/DisableCsrfExtension.php
  class DisableCsrfExtension (line 9) | class DisableCsrfExtension extends AbstractTypeExtension
    method configureOptions (line 11) | public function configureOptions(OptionsResolver $resolver)
    method getExtendedType (line 18) | public function getExtendedType()

FILE: tests/Silex/Tests/Provider/HttpCacheServiceProviderTest.php
  class HttpCacheServiceProviderTest (line 24) | class HttpCacheServiceProviderTest extends \PHPUnit_Framework_TestCase
    method testRegister (line 26) | public function testRegister()
    method testRunCallsShutdown (line 42) | public function testRunCallsShutdown($app)
    method testDebugDefaultsToThatOfApp (line 60) | public function testDebugDefaultsToThatOfApp()
  class UnsendableResponse (line 74) | class UnsendableResponse extends Response
    method send (line 76) | public function send()

FILE: tests/Silex/Tests/Provider/HttpFragmentServiceProviderTest.php
  class HttpFragmentServiceProviderTest (line 20) | class HttpFragmentServiceProviderTest extends \PHPUnit_Framework_TestCase
    method testRenderFunction (line 22) | public function testRenderFunction()

FILE: tests/Silex/Tests/Provider/MonologServiceProviderTest.php
  class MonologServiceProviderTest (line 28) | class MonologServiceProviderTest extends \PHPUnit_Framework_TestCase
    method setUp (line 32) | protected function setUp()
    method tearDown (line 38) | protected function tearDown()
    method testRequestLogging (line 43) | public function testRequestLogging()
    method testManualLogging (line 68) | public function testManualLogging()
    method testOverrideFormatter (line 84) | public function testOverrideFormatter()
    method testErrorLogging (line 96) | public function testErrorLogging()
    method testRedirectLogging (line 132) | public function testRedirectLogging()
    method testErrorLoggingGivesWayToSecurityExceptionHandling (line 148) | public function testErrorLoggingGivesWayToSecurityExceptionHandling()
    method testStringErrorLevel (line 173) | public function testStringErrorLevel()
    method testNonExistentStringErrorLevel (line 185) | public function testNonExistentStringErrorLevel()
    method testDisableListener (line 193) | public function testDisableListener()
    method assertMatchingRecord (line 203) | protected function assertMatchingRecord($pattern, $level, $handler)
    method getApplication (line 216) | protected function getApplication()

FILE: tests/Silex/Tests/Provider/RememberMeServiceProviderTest.php
  class RememberMeServiceProviderTest (line 27) | class RememberMeServiceProviderTest extends WebTestCase
    method testRememberMeAuthentication (line 29) | public function testRememberMeAuthentication()
    method createApplication (line 60) | public function createApplication($authenticationMethod = 'form')
  class InteractiveLoginTriggered (line 99) | class InteractiveLoginTriggered
    method onInteractiveLogin (line 103) | public function onInteractiveLogin()

FILE: tests/Silex/Tests/Provider/RoutingServiceProviderTest.php
  class RoutingServiceProviderTest (line 25) | class RoutingServiceProviderTest extends \PHPUnit_Framework_TestCase
    method testRegister (line 27) | public function testRegister()
    method testUrlGeneration (line 42) | public function testUrlGeneration()
    method testAbsoluteUrlGeneration (line 59) | public function testAbsoluteUrlGeneration()
    method testUrlGenerationWithHttp (line 76) | public function testUrlGenerationWithHttp()
    method testUrlGenerationWithHttps (line 94) | public function testUrlGenerationWithHttps()
    method testControllersFactory (line 112) | public function testControllersFactory()

FILE: tests/Silex/Tests/Provider/SecurityServiceProviderTest.php
  class SecurityServiceProviderTest (line 28) | class SecurityServiceProviderTest extends WebTestCase
    method testWrongAuthenticationType (line 33) | public function testWrongAuthenticationType()
    method testFormAuthentication (line 48) | public function testFormAuthentication()
    method testHttpAuthentication (line 96) | public function testHttpAuthentication()
    method testGuardAuthentication (line 123) | public function testGuardAuthentication()
    method testUserPasswordValidatorIsRegistered (line 145) | public function testUserPasswordValidatorIsRegistered()
    method testExposedExceptions (line 167) | public function testExposedExceptions()
    method testFakeRoutesAreSerializable (line 186) | public function testFakeRoutesAreSerializable()
    method testUser (line 204) | public function testUser()
    method testUserWithNoToken (line 230) | public function testUserWithNoToken()
    method testUserWithInvalidUser (line 248) | public function testUserWithInvalidUser()
    method testAccessRulePathArray (line 268) | public function testAccessRulePathArray()
    method createApplication (line 293) | public function createApplication($authenticationMethod = 'form')
    method addFormAuthentication (line 305) | private function addFormAuthentication($app)
    method addHttpAuthentication (line 363) | private function addHttpAuthentication($app)
    method addGuardAuthentication (line 407) | private function addGuardAuthentication($app)

FILE: tests/Silex/Tests/Provider/SecurityServiceProviderTest/TokenAuthenticator.php
  class TokenAuthenticator (line 25) | class TokenAuthenticator extends AbstractGuardAuthenticator
    method getCredentials (line 27) | public function getCredentials(Request $request)
    method getUser (line 41) | public function getUser($credentials, UserProviderInterface $userProvi...
    method checkCredentials (line 46) | public function checkCredentials($credentials, UserInterface $user)
    method onAuthenticationSuccess (line 52) | public function onAuthenticationSuccess(Request $request, TokenInterfa...
    method onAuthenticationFailure (line 57) | public function onAuthenticationFailure(Request $request, Authenticati...
    method start (line 66) | public function start(Request $request, AuthenticationException $authE...
    method supportsRememberMe (line 75) | public function supportsRememberMe()

FILE: tests/Silex/Tests/Provider/SerializerServiceProviderTest.php
  class SerializerServiceProviderTest (line 22) | class SerializerServiceProviderTest extends \PHPUnit_Framework_TestCase
    method testRegister (line 24) | public function testRegister()

FILE: tests/Silex/Tests/Provider/SessionServiceProviderTest.php
  class SessionServiceProviderTest (line 26) | class SessionServiceProviderTest extends WebTestCase
    method testRegister (line 28) | public function testRegister()
    method createApplication (line 50) | public function createApplication()
    method testWithRoutesThatDoesNotUseSession (line 81) | public function testWithRoutesThatDoesNotUseSession()
    method testSessionRegister (line 109) | public function testSessionRegister()

FILE: tests/Silex/Tests/Provider/SpoolStub.php
  class SpoolStub (line 14) | class SpoolStub implements \Swift_Spool
    method getMessages (line 19) | public function getMessages()
    method start (line 24) | public function start()
    method stop (line 28) | public function stop()
    method isStarted (line 32) | public function isStarted()
    method queueMessage (line 37) | public function queueMessage(\Swift_Mime_Message $message)
    method flushQueue (line 42) | public function flushQueue(\Swift_Transport $transport, &$failedRecipi...

FILE: tests/Silex/Tests/Provider/SwiftmailerServiceProviderTest.php
  class SwiftmailerServiceProviderTest (line 18) | class SwiftmailerServiceProviderTest extends \PHPUnit_Framework_TestCase
    method testSwiftMailerServiceIsSwiftMailer (line 20) | public function testSwiftMailerServiceIsSwiftMailer()
    method testSwiftMailerIgnoresSpoolIfDisabled (line 30) | public function testSwiftMailerIgnoresSpoolIfDisabled()
    method testSwiftMailerSendsMailsOnFinish (line 46) | public function testSwiftMailerSendsMailsOnFinish()
    method testSwiftMailerAvoidsFlushesIfMailerIsUnused (line 72) | public function testSwiftMailerAvoidsFlushesIfMailerIsUnused()

FILE: tests/Silex/Tests/Provider/TranslationServiceProviderTest.php
  class TranslationServiceProviderTest (line 25) | class TranslationServiceProviderTest extends \PHPUnit_Framework_TestCase
    method getPreparedApp (line 30) | protected function getPreparedApp()
    method transChoiceProvider (line 59) | public function transChoiceProvider()
    method transProvider (line 74) | public function transProvider()
    method testTransForDefaultLanguage (line 89) | public function testTransForDefaultLanguage($key, $locale, $expected)
    method testTransChoiceForDefaultLanguage (line 101) | public function testTransChoiceForDefaultLanguage($key, $number, $loca...
    method testFallbacks (line 109) | public function testFallbacks()
    method testLocale (line 123) | public function testLocale()
    method testLocaleInSubRequests (line 143) | public function testLocaleInSubRequests()
    method testLocaleWithBefore (line 167) | public function testLocaleWithBefore()

FILE: tests/Silex/Tests/Provider/TwigServiceProviderTest.php
  class TwigServiceProviderTest (line 26) | class TwigServiceProviderTest extends \PHPUnit_Framework_TestCase
    method testRegisterAndRender (line 28) | public function testRegisterAndRender()
    method testLoaderPriority (line 45) | public function testLoaderPriority()
    method testHttpFoundationIntegration (line 59) | public function testHttpFoundationIntegration()
    method testAssetIntegration (line 74) | public function testAssetIntegration()
    method testGlobalVariable (line 87) | public function testGlobalVariable()
    method testFormFactory (line 99) | public function testFormFactory()
    method testFormWithoutCsrf (line 111) | public function testFormWithoutCsrf()

FILE: tests/Silex/Tests/Provider/ValidatorServiceProviderTest.php
  class ValidatorServiceProviderTest (line 30) | class ValidatorServiceProviderTest extends \PHPUnit_Framework_TestCase
    method testRegister (line 32) | public function testRegister()
    method testRegisterWithCustomValidators (line 41) | public function testRegisterWithCustomValidators()
    method testConstraintValidatorFactory (line 61) | public function testConstraintValidatorFactory($app)
    method testConstraintValidatorFactoryWithExpression (line 72) | public function testConstraintValidatorFactoryWithExpression($app)
    method testValidatorServiceIsAValidator (line 82) | public function testValidatorServiceIsAValidator($app)
    method testValidatorConstraint (line 91) | public function testValidatorConstraint($email, $isValid, $nbGlobalErr...
    method testValidatorWillNotAddNonexistentTranslationFiles (line 116) | public function testValidatorWillNotAddNonexistentTranslationFiles()
    method getTestValidatorConstraintProvider (line 137) | public function getTestValidatorConstraintProvider()
    method testAddResource (line 150) | public function testAddResource($registerValidatorFirst)
    method getAddResourceData (line 170) | public function getAddResourceData()
    method testAddResourceAlternate (line 175) | public function testAddResourceAlternate()

FILE: tests/Silex/Tests/Provider/ValidatorServiceProviderTest/Constraint/Custom.php
  class Custom (line 19) | class Custom extends Constraint
    method validatedBy (line 25) | public function validatedBy()

FILE: tests/Silex/Tests/Provider/ValidatorServiceProviderTest/Constraint/CustomValidator.php
  class CustomValidator (line 20) | class CustomValidator extends ConstraintValidator
    method isValid (line 22) | public function isValid($value, Constraint $constraint)
    method validate (line 28) | public function validate($value, Constraint $constraint)

FILE: tests/Silex/Tests/Route/SecurityRoute.php
  class SecurityRoute (line 16) | class SecurityRoute extends Route

FILE: tests/Silex/Tests/Route/SecurityTraitTest.php
  class SecurityTraitTest (line 23) | class SecurityTraitTest extends \PHPUnit_Framework_TestCase
    method testSecureWithNoAuthenticatedUser (line 25) | public function testSecureWithNoAuthenticatedUser()
    method testSecureWithAuthorizedRoles (line 38) | public function testSecureWithAuthorizedRoles()
    method testSecureWithUnauthorizedRoles (line 53) | public function testSecureWithUnauthorizedRoles()
    method createApplication (line 68) | private function createApplication()

FILE: tests/Silex/Tests/RouterTest.php
  class RouterTest (line 24) | class RouterTest extends \PHPUnit_Framework_TestCase
    method testMapRouting (line 26) | public function testMapRouting()
    method testStatusCode (line 47) | public function testStatusCode()
    method testRedirect (line 76) | public function testRedirect()
    method testMissingRoute (line 100) | public function testMissingRoute()
    method testMethodRouting (line 109) | public function testMethodRouting()
    method testRequestShouldBeStoredRegardlessOfRouting (line 151) | public function testRequestShouldBeStoredRegardlessOfRouting()
    method testTrailingSlashBehavior (line 170) | public function testTrailingSlashBehavior()
    method testHostSpecification (line 185) | public function testHostSpecification()
    method testRequireHttpRedirect (line 193) | public function testRequireHttpRedirect()
    method testRequireHttpsRedirect (line 207) | public function testRequireHttpsRedirect()
    method testRequireHttpsRedirectIncludesQueryString (line 221) | public function testRequireHttpsRedirectIncludesQueryString()
    method testConditionOnRoute (line 235) | public function testConditionOnRoute()
    method testClassNameControllerSyntax (line 248) | public function testClassNameControllerSyntax()
    method testClassNameControllerSyntaxWithStaticMethod (line 257) | public function testClassNameControllerSyntaxWithStaticMethod()
    method checkRouteResponse (line 266) | protected function checkRouteResponse(Application $app, $path, $expect...
  class MyController (line 274) | class MyController
    method getFoo (line 276) | public function getFoo()
    method getBar (line 281) | public static function getBar()

FILE: tests/Silex/Tests/ServiceControllerResolverRouterTest.php
  class ServiceControllerResolverRouterTest (line 21) | class ServiceControllerResolverRouterTest extends RouterTest
    method testServiceNameControllerSyntax (line 23) | public function testServiceNameControllerSyntax()
    method checkRouteResponse (line 37) | protected function checkRouteResponse(Application $app, $path, $expect...

FILE: tests/Silex/Tests/ServiceControllerResolverTest.php
  class ServiceControllerResolverTest (line 22) | class ServiceControllerResolverTest extends \PHPUnit_Framework_Testcase
    method setup (line 29) | public function setup()
    method testShouldResolveServiceController (line 42) | public function testShouldResolveServiceController()
    method testShouldUnresolvedControllerNames (line 61) | public function testShouldUnresolvedControllerNames()
    method testShouldDelegateGetArguments (line 79) | public function testShouldDelegateGetArguments()

FILE: tests/Silex/Tests/StreamTest.php
  class StreamTest (line 22) | class StreamTest extends \PHPUnit_Framework_TestCase
    method testStreamReturnsStreamingResponse (line 24) | public function testStreamReturnsStreamingResponse()
    method testStreamActuallyStreams (line 33) | public function testStreamActuallyStreams()

FILE: tests/Silex/Tests/WebTestCaseTest.php
  class WebTestCaseTest (line 23) | class WebTestCaseTest extends WebTestCase
    method createApplication (line 25) | public function createApplication()
    method testGetHello (line 47) | public function testGetHello()
    method testCrawlerFilter (line 57) | public function testCrawlerFilter()
    method testServerVariables (line 65) | public function testServerVariables()
Condensed preview — 168 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (592K chars).
[
  {
    "path": ".gitignore",
    "chars": 44,
    "preview": "/phpunit.xml\n/vendor\n/build\n/composer.lock\n\n"
  },
  {
    "path": ".travis.yml",
    "chars": 1061,
    "preview": "language: php\n\nsudo: false\n\nenv:\n    global:\n        - SYMFONY_DEPRECATIONS_HELPER=weak\n\ncache:\n    directories:\n      -"
  },
  {
    "path": "LICENSE",
    "chars": 1065,
    "preview": "Copyright (c) 2010-2016 Fabien Potencier\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "README.rst",
    "chars": 1303,
    "preview": "Silex, a simple Web Framework\n=============================\n\nSilex is a PHP micro-framework to develop websites based on"
  },
  {
    "path": "bin/build",
    "chars": 1609,
    "preview": "#!/bin/sh\n\nPHP=`which php`\nGIT=`which git`\nDIR=`$PHP -r \"echo dirname(dirname(realpath('$0')));\"`\n\nif [ ! -d \"$DIR/build"
  },
  {
    "path": "bin/skeleton/fat_composer.json",
    "chars": 737,
    "preview": "{\n    \"require\": {\n        \"silex/silex\": \"~1.1\",\n        \"symfony/browser-kit\": \"~2.3\",\n        \"symfony/console\": \"~2."
  },
  {
    "path": "bin/skeleton/index.php",
    "chars": 162,
    "preview": "<?php\n\nrequire_once __DIR__.'/../vendor/autoload.php';\n\n$app = new Silex\\Application();\n\n$app->get('/hello', function ()"
  },
  {
    "path": "bin/skeleton/slim_composer.json",
    "chars": 57,
    "preview": "{\n    \"require\": {\n        \"silex/silex\": \"~1.1\"\n    }\n}\n"
  },
  {
    "path": "composer.json",
    "chars": 2161,
    "preview": "{\n    \"name\": \"silex/silex\",\n    \"description\": \"The PHP micro-framework based on the Symfony Components\",\n    \"keywords"
  },
  {
    "path": "doc/changelog.rst",
    "chars": 11572,
    "preview": "Changelog\n=========\n\n2.0.4 (2016-XX-XX)\n------------------\n\n* n/a\n\n2.0.3 (2016-08-22)\n------------------\n\n* fixed lazy e"
  },
  {
    "path": "doc/conf.py",
    "chars": 337,
    "preview": "import sys, os\nfrom sphinx.highlighting import lexers\nfrom pygments.lexers.web import PhpLexer\n\nsys.path.append(os.path."
  },
  {
    "path": "doc/contributing.rst",
    "chars": 846,
    "preview": "Contributing\n============\n\nWe are open to contributions to the Silex code. If you find a bug or want to\ncontribute a pro"
  },
  {
    "path": "doc/cookbook/error_handler.rst",
    "chars": 1104,
    "preview": "Converting Errors to Exceptions\n===============================\n\nSilex catches exceptions that are thrown from within a "
  },
  {
    "path": "doc/cookbook/form_no_csrf.rst",
    "chars": 1561,
    "preview": "Disabling CSRF Protection on a Form using the FormExtension\n===========================================================\n"
  },
  {
    "path": "doc/cookbook/guard_authentication.rst",
    "chars": 6242,
    "preview": "How to Create a Custom Authentication System with Guard\n=======================================================\n\nWhether"
  },
  {
    "path": "doc/cookbook/index.rst",
    "chars": 985,
    "preview": "Cookbook\n========\n\nThe cookbook section contains recipes for solving specific problems.\n\n.. toctree::\n    :maxdepth: 1\n "
  },
  {
    "path": "doc/cookbook/json_request_body.rst",
    "chars": 2852,
    "preview": "Accepting a JSON Request Body\n=============================\n\nA common need when building a restful API is the ability to"
  },
  {
    "path": "doc/cookbook/multiple_loggers.rst",
    "chars": 2321,
    "preview": "Using multiple Monolog Loggers\n==============================\n\nHaving separate instances of Monolog for different parts "
  },
  {
    "path": "doc/cookbook/session_storage.rst",
    "chars": 3270,
    "preview": "Using PdoSessionStorage to store Sessions in the Database\n=========================================================\n\nBy "
  },
  {
    "path": "doc/cookbook/sub_requests.rst",
    "chars": 5154,
    "preview": "Making sub-Requests\n===================\n\nSince Silex is based on the ``HttpKernelInterface``, it allows you to simulate\n"
  },
  {
    "path": "doc/cookbook/validator_yaml.rst",
    "chars": 1050,
    "preview": "Using YAML to configure Validation\n==================================\n\nSimplicity is at the heart of Silex so there is n"
  },
  {
    "path": "doc/index.rst",
    "chars": 252,
    "preview": "The Book\n========\n\n.. toctree::\n    :maxdepth: 1\n\n    intro\n    usage\n    middlewares\n    organizing_controllers\n    ser"
  },
  {
    "path": "doc/internals.rst",
    "chars": 3228,
    "preview": "Internals\n=========\n\nThis chapter will tell you how Silex works internally.\n\nSilex\n-----\n\nApplication\n~~~~~~~~~~~\n\nThe a"
  },
  {
    "path": "doc/intro.rst",
    "chars": 1428,
    "preview": "Introduction\n============\n\nSilex is a PHP microframework. It is built on the shoulders of `Symfony`_ and\n`Pimple`_ and a"
  },
  {
    "path": "doc/middlewares.rst",
    "chars": 4359,
    "preview": "Middleware\n==========\n\nSilex allows you to run code, that changes the default Silex behavior, at\ndifferent stages during"
  },
  {
    "path": "doc/organizing_controllers.rst",
    "chars": 2535,
    "preview": "Organizing Controllers\n======================\n\nWhen your application starts to define too many controllers, you might wa"
  },
  {
    "path": "doc/providers/asset.rst",
    "chars": 1538,
    "preview": "Asset\n=====\n\nThe *AssetServiceProvider* provides a way to manage URL generation and\nversioning of web assets such as CSS"
  },
  {
    "path": "doc/providers/csrf.rst",
    "chars": 1343,
    "preview": "CSRF\n====\n\nThe *CsrfServiceProvider* provides a service for building forms in your\napplication with the Symfony Form com"
  },
  {
    "path": "doc/providers/doctrine.rst",
    "chars": 4383,
    "preview": "Doctrine\n========\n\nThe *DoctrineServiceProvider* provides integration with the `Doctrine DBAL\n<http://www.doctrine-proje"
  },
  {
    "path": "doc/providers/form.rst",
    "chars": 6080,
    "preview": "Form\n====\n\nThe *FormServiceProvider* provides a service for building forms in\nyour application with the Symfony Form com"
  },
  {
    "path": "doc/providers/http_cache.rst",
    "chars": 3822,
    "preview": "HTTP Cache\n==========\n\nThe *HttpCacheServiceProvider* provides support for the Symfony Reverse\nProxy.\n\nParameters\n------"
  },
  {
    "path": "doc/providers/http_fragment.rst",
    "chars": 1975,
    "preview": "HTTP Fragment\n=============\n\nThe *HttpFragmentServiceProvider* provides support for the Symfony fragment\nsub-framework, "
  },
  {
    "path": "doc/providers/index.rst",
    "chars": 332,
    "preview": "Built-in Service Providers\n==========================\n\n.. toctree::\n    :maxdepth: 1\n\n    twig\n    asset\n    monolog\n   "
  },
  {
    "path": "doc/providers/locale.rst",
    "chars": 501,
    "preview": "Locale\n======\n\nThe *LocaleServiceProvider* manages the locale of an application.\n\nParameters\n----------\n\n* **locale**: T"
  },
  {
    "path": "doc/providers/monolog.rst",
    "chars": 3395,
    "preview": "Monolog\n=======\n\nThe *MonologServiceProvider* provides a default logging mechanism through\nJordi Boggiano's `Monolog <ht"
  },
  {
    "path": "doc/providers/remember_me.rst",
    "chars": 1810,
    "preview": "Remember Me\n===========\n\nThe *RememberMeServiceProvider* adds \"Remember-Me\" authentication to the\n*SecurityServiceProvid"
  },
  {
    "path": "doc/providers/security.rst",
    "chars": 23110,
    "preview": "Security\n========\n\nThe *SecurityServiceProvider* manages authentication and authorization for\nyour applications.\n\nParame"
  },
  {
    "path": "doc/providers/serializer.rst",
    "chars": 2443,
    "preview": "Serializer\n==========\n\nThe *SerializerServiceProvider* provides a service for serializing objects.\n\nParameters\n---------"
  },
  {
    "path": "doc/providers/service_controller.rst",
    "chars": 4605,
    "preview": "Service Controllers\n===================\n\nAs your Silex application grows, you may wish to begin organizing your\ncontroll"
  },
  {
    "path": "doc/providers/session.rst",
    "chars": 3416,
    "preview": "Session\n=======\n\nThe *SessionServiceProvider* provides a service for storing data persistently\nbetween requests.\n\nParame"
  },
  {
    "path": "doc/providers/swiftmailer.rst",
    "chars": 4403,
    "preview": "Swiftmailer\n===========\n\nThe *SwiftmailerServiceProvider* provides a service for sending email through\nthe `Swift Mailer"
  },
  {
    "path": "doc/providers/translation.rst",
    "chars": 5877,
    "preview": "Translation\n===========\n\nThe *TranslationServiceProvider* provides a service for translating your\napplication into diffe"
  },
  {
    "path": "doc/providers/twig.rst",
    "chars": 5926,
    "preview": "Twig\n====\n\nThe *TwigServiceProvider* provides integration with the `Twig\n<http://twig.sensiolabs.org/>`_ template engine"
  },
  {
    "path": "doc/providers/validator.rst",
    "chars": 6373,
    "preview": "Validator\n=========\n\nThe *ValidatorServiceProvider* provides a service for validating data. It is\nmost useful when used "
  },
  {
    "path": "doc/providers/var_dumper.rst",
    "chars": 937,
    "preview": "Var Dumper\n==========\n\nThe *VarDumperServiceProvider* provides a mechanism that allows exploring then\ndumping any PHP va"
  },
  {
    "path": "doc/providers.rst",
    "chars": 8228,
    "preview": "Providers\n=========\n\nProviders allow the developer to reuse parts of an application into another\none. Silex provides two"
  },
  {
    "path": "doc/services.rst",
    "chars": 8735,
    "preview": "Services\n========\n\nSilex is not only a framework, it is also a service container. It does this by\nextending `Pimple <htt"
  },
  {
    "path": "doc/testing.rst",
    "chars": 6892,
    "preview": "Testing\n=======\n\nBecause Silex is built on top of Symfony, it is very easy to write functional\ntests for your applicatio"
  },
  {
    "path": "doc/usage.rst",
    "chars": 24070,
    "preview": "Usage\n=====\n\nInstallation\n------------\n\nIf you want to get started fast, `download`_ Silex as an archive and extract\nit,"
  },
  {
    "path": "doc/web_servers.rst",
    "chars": 4821,
    "preview": "Webserver Configuration\n=======================\n\nApache\n------\n\nIf you are using Apache, make sure ``mod_rewrite`` is en"
  },
  {
    "path": "phpunit.xml.dist",
    "chars": 670,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<phpunit backupGlobals=\"false\"\n         backupStaticAttributes=\"false\"\n         "
  },
  {
    "path": "src/Silex/Api/BootableProviderInterface.php",
    "chars": 733,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Api/ControllerProviderInterface.php",
    "chars": 716,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Api/EventListenerProviderInterface.php",
    "chars": 580,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Api/LICENSE",
    "chars": 1065,
    "preview": "Copyright (c) 2010-2015 Fabien Potencier\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/Silex/Api/composer.json",
    "chars": 858,
    "preview": "{\n    \"minimum-stability\": \"dev\",\n    \"name\": \"silex/api\",\n    \"description\": \"The Silex interfaces\",\n    \"keywords\": [\""
  },
  {
    "path": "src/Silex/AppArgumentValueResolver.php",
    "chars": 1163,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Application/FormTrait.php",
    "chars": 1704,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Application/MonologTrait.php",
    "chars": 811,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Application/SecurityTrait.php",
    "chars": 1539,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Application/SwiftmailerTrait.php",
    "chars": 787,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Application/TranslationTrait.php",
    "chars": 1596,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Application/TwigTrait.php",
    "chars": 1768,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Application/UrlGeneratorTrait.php",
    "chars": 1268,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Application.php",
    "chars": 16751,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/CallbackResolver.php",
    "chars": 1991,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Controller.php",
    "chars": 3068,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/ControllerCollection.php",
    "chars": 7625,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/ControllerResolver.php",
    "chars": 1462,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/EventListener/ConverterListener.php",
    "chars": 1934,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/EventListener/LogListener.php",
    "chars": 3900,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/EventListener/MiddlewareListener.php",
    "chars": 3176,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/EventListener/StringToResponseListener.php",
    "chars": 1423,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Exception/ControllerFrozenException.php",
    "chars": 443,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/ExceptionHandler.php",
    "chars": 1570,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/ExceptionListenerWrapper.php",
    "chars": 3027,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/AssetServiceProvider.php",
    "chars": 3014,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/CsrfServiceProvider.php",
    "chars": 1463,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/DoctrineServiceProvider.php",
    "chars": 3933,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/ExceptionHandlerServiceProvider.php",
    "chars": 816,
    "preview": "<?php\n\nnamespace Silex\\Provider;\n\nuse Pimple\\Container;\nuse Pimple\\ServiceProviderInterface;\nuse Silex\\Api\\EventListener"
  },
  {
    "path": "src/Silex/Provider/Form/SilexFormExtension.php",
    "chars": 3729,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/FormServiceProvider.php",
    "chars": 2757,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/HttpCache/HttpCache.php",
    "chars": 958,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/HttpCacheServiceProvider.php",
    "chars": 1848,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/HttpFragmentServiceProvider.php",
    "chars": 3044,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/HttpKernelServiceProvider.php",
    "chars": 3684,
    "preview": "<?php\n\nnamespace Silex\\Provider;\n\nuse Pimple\\Container;\nuse Pimple\\ServiceProviderInterface;\nuse Silex\\Api\\EventListener"
  },
  {
    "path": "src/Silex/Provider/LICENSE",
    "chars": 1065,
    "preview": "Copyright (c) 2010-2015 Fabien Potencier\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "src/Silex/Provider/Locale/LocaleListener.php",
    "chars": 2568,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/LocaleServiceProvider.php",
    "chars": 1116,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/MonologServiceProvider.php",
    "chars": 4625,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/RememberMeServiceProvider.php",
    "chars": 4478,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/Routing/LazyRequestMatcher.php",
    "chars": 1419,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/Routing/RedirectableUrlMatcher.php",
    "chars": 1563,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/RoutingServiceProvider.php",
    "chars": 2921,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/SecurityServiceProvider.php",
    "chars": 31024,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/SerializerServiceProvider.php",
    "chars": 1564,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/ServiceControllerServiceProvider.php",
    "chars": 660,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/Session/SessionListener.php",
    "chars": 802,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/Session/TestSessionListener.php",
    "chars": 825,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/SessionServiceProvider.php",
    "chars": 2779,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/SwiftmailerServiceProvider.php",
    "chars": 4896,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/TranslationServiceProvider.php",
    "chars": 3713,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/TwigServiceProvider.php",
    "chars": 5412,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/Validator/ConstraintValidatorFactory.php",
    "chars": 1566,
    "preview": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/ValidatorServiceProvider.php",
    "chars": 2074,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/VarDumperServiceProvider.php",
    "chars": 1676,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Provider/composer.json",
    "chars": 712,
    "preview": "{\n    \"minimum-stability\": \"dev\",\n    \"name\": \"silex/providers\",\n    \"description\": \"The Silex providers\",\n    \"keywords"
  },
  {
    "path": "src/Silex/Route/SecurityTrait.php",
    "chars": 700,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/Route.php",
    "chars": 5547,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/ServiceControllerResolver.php",
    "chars": 1747,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/ViewListenerWrapper.php",
    "chars": 2681,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "src/Silex/WebTestCase.php",
    "chars": 1529,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "tests/Silex/Tests/Application/FormApplication.php",
    "chars": 360,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/FormTraitTest.php",
    "chars": 759,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/MonologApplication.php",
    "chars": 366,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/MonologTraitTest.php",
    "chars": 1179,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/SecurityApplication.php",
    "chars": 368,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/SecurityTraitTest.php",
    "chars": 2863,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/SwiftmailerApplication.php",
    "chars": 374,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/SwiftmailerTraitTest.php",
    "chars": 1091,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/TranslationApplication.php",
    "chars": 374,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/TranslationTraitTest.php",
    "chars": 1322,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/TwigApplication.php",
    "chars": 360,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/TwigTraitTest.php",
    "chars": 2576,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/UrlGeneratorApplication.php",
    "chars": 376,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Application/UrlGeneratorTraitTest.php",
    "chars": 1298,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/ApplicationTest.php",
    "chars": 21870,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/CallbackResolverTest.php",
    "chars": 2384,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "tests/Silex/Tests/CallbackServicesTest.php",
    "chars": 2368,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/ControllerCollectionTest.php",
    "chars": 11149,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/ControllerResolverTest.php",
    "chars": 857,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/ControllerTest.php",
    "chars": 3883,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/EventListener/LogListenerTest.php",
    "chars": 3911,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/ExceptionHandlerTest.php",
    "chars": 12910,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Fixtures/Php7Controller.php",
    "chars": 478,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/FunctionalTest.php",
    "chars": 1479,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/JsonTest.php",
    "chars": 1367,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/LazyDispatcherTest.php",
    "chars": 1456,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/LazyRequestMatcherTest.php",
    "chars": 2291,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/LocaleTest.php",
    "chars": 3545,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/MiddlewareTest.php",
    "chars": 9156,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/AssetServiceProviderTest.php",
    "chars": 1219,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/DoctrineServiceProviderTest.php",
    "chars": 3908,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/FormServiceProviderTest/DisableCsrfExtension.php",
    "chars": 537,
    "preview": "<?php\n\nnamespace Silex\\Tests\\Provider\\FormServiceProviderTest;\n\nuse Symfony\\Component\\Form\\AbstractTypeExtension;\nuse Sy"
  },
  {
    "path": "tests/Silex/Tests/Provider/FormServiceProviderTest.php",
    "chars": 11563,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/HttpCacheServiceProviderTest.php",
    "chars": 1918,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/HttpFragmentServiceProviderTest.php",
    "chars": 1457,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/MonologServiceProviderTest.php",
    "chars": 6906,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/RememberMeServiceProviderTest.php",
    "chars": 3557,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/RoutingServiceProviderTest.php",
    "chars": 3407,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/SecurityServiceProviderTest/TokenAuthenticator.php",
    "chars": 2290,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/SecurityServiceProviderTest.php",
    "chars": 16021,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/SerializerServiceProviderTest.php",
    "chars": 1029,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/SessionServiceProviderTest.php",
    "chars": 3495,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/SpoolStub.php",
    "chars": 896,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/SwiftmailerServiceProviderTest.php",
    "chars": 2584,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/TranslationServiceProviderTest.php",
    "chars": 6672,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/TwigServiceProviderTest.php",
    "chars": 4050,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/ValidatorServiceProviderTest/Constraint/Custom.php",
    "chars": 611,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/ValidatorServiceProviderTest/Constraint/CustomValidator.php",
    "chars": 751,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Provider/ValidatorServiceProviderTest.php",
    "chars": 6280,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Route/SecurityRoute.php",
    "chars": 338,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/Route/SecurityTraitTest.php",
    "chars": 2404,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/RouterTest.php",
    "chars": 8028,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/ServiceControllerResolverRouterTest.php",
    "chars": 1180,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/ServiceControllerResolverTest.php",
    "chars": 2846,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the ful"
  },
  {
    "path": "tests/Silex/Tests/StreamTest.php",
    "chars": 1166,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  },
  {
    "path": "tests/Silex/Tests/WebTestCaseTest.php",
    "chars": 1880,
    "preview": "<?php\n\n/*\n * This file is part of the Silex framework.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * This source"
  }
]

About this extraction

This page contains the full source code of the fabpot/Silex GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 168 files (545.5 KB), approximately 131.2k tokens, and a symbol index with 628 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!