Commit ae8f9d43 authored by Fabien Potencier's avatar Fabien Potencier

feature #947 Move master to 2.0 (fabpot, jkazimir)

This PR was merged into the 1.2.x-dev branch.

Discussion
----------

Move master to 2.0

This PR moves master to 2.0@dev. As there is a 1.2 branch, that should not be a problem for anyone ... except if you target dev-master in your composer.json, but hey, that's your choice.

Of course, it's not finished yet, but working on master is easier for everyone and future PRs.

TODO:

 - [ ] update documentation
 - [ ] update CHANGELOG

Commits
-------

5a4b265e upgraded to Pimple 2.1
322dbb5d updated route_factory service to use Pimple 2 factory method
fc8bbb62 switched to Pimple 2.0
c2421fab removed the flush call in the url generator service
5f9716d8 made the logger optional in all providers
349dcf97 moved everything related to the routing to a reusable service provider
e96f9be8 removed the request service in favor of the request_stack one
26e85436 changed charset to have a sensible default in all providers
34524a52 changed debug to have a sensible default in all providers
18b6050b fixed stupid typo...
0d10e89e fixed composer.json paths
a4b0b201 simplified composer names
6863b9a0 fixed composer.json files
67802eb2 added composer.json for Api and Provider
c341ca17 moved classes so that Silex\Provider can be used as a sub-tree split independently of eveything else
2d3a96bb changed type-hint to Pimple whenever possible
df568cb2 added BootableProviderInterface
1ba15a17 moved the provider interfaces under Silex\Api
eb5079be moved fake routes for the security service provider to a connect() method (with auto-registration)
3fdfa4be emptied the boot() method of the remember me service provider
27eb5267 moved Swiftmailer finish call to a proper listener
7bee6bfd adding a new interface for providers willing to register event listeners
613c4bfa removed obsolete comment
3b1ba69b removed conditions about the request stack as Symfony 2.4+ is required now
cd044b6f removed the deprecated Compiler class and the doc on the phar
de674e6d removed deprecated locale_fallback setting
24bce51f removed the deprecated TwigCoreExtension class
a4c7c51f fixed visibility
38c84add moved locale management to a locale service provider
88e44ea4 refactored session code to make it more reusable
9a32c0a9 bumped version to 2.0
parents d0b2b9b2 5a4b265e
#!/usr/bin/env php
<?php
require_once __DIR__.'/../vendor/autoload.php';
use Silex\Util\Compiler;
$compiler = new Compiler();
$compiler->compile();
......@@ -17,29 +17,29 @@
],
"require": {
"php": ">=5.3.3",
"pimple/pimple": "~1.0",
"symfony/event-dispatcher": ">=2.3,<2.6-dev",
"symfony/http-foundation": ">=2.3,<2.6-dev",
"symfony/http-kernel": ">=2.3,<2.6-dev",
"symfony/routing": ">=2.3,<2.6-dev"
"pimple/pimple": "~2.1@dev",
"symfony/event-dispatcher": ">=2.4,<2.6-dev",
"symfony/http-foundation": ">=2.4,<2.6-dev",
"symfony/http-kernel": ">=2.4,<2.6-dev",
"symfony/routing": ">=2.4,<2.6-dev"
},
"require-dev": {
"symfony/security": ">=2.3,<2.6-dev",
"symfony/config": ">=2.3,<2.6-dev",
"symfony/locale": ">=2.3,<2.6-dev",
"symfony/form": ">=2.3,<2.6-dev",
"symfony/browser-kit": ">=2.3,<2.6-dev",
"symfony/css-selector": ">=2.3,<2.6-dev",
"symfony/debug": ">=2.3,<2.6-dev",
"symfony/dom-crawler": ">=2.3,<2.6-dev",
"symfony/finder": ">=2.3,<2.6-dev",
"symfony/monolog-bridge": ">=2.3,<2.6-dev",
"symfony/options-resolver": ">=2.3,<2.6-dev",
"symfony/process": ">=2.3,<2.6-dev",
"symfony/serializer": ">=2.3,<2.6-dev",
"symfony/translation": ">=2.3,<2.6-dev",
"symfony/twig-bridge": ">=2.3,<2.6-dev",
"symfony/validator": ">=2.3,<2.6-dev",
"symfony/security": ">=2.4,<2.6-dev",
"symfony/config": ">=2.4,<2.6-dev",
"symfony/locale": ">=2.4,<2.6-dev",
"symfony/form": ">=2.4,<2.6-dev",
"symfony/browser-kit": ">=2.4,<2.6-dev",
"symfony/css-selector": ">=2.4,<2.6-dev",
"symfony/debug": ">=2.4,<2.6-dev",
"symfony/dom-crawler": ">=2.4,<2.6-dev",
"symfony/finder": ">=2.4,<2.6-dev",
"symfony/monolog-bridge": ">=2.4,<2.6-dev",
"symfony/options-resolver": ">=2.4,<2.6-dev",
"symfony/process": ">=2.4,<2.6-dev",
"symfony/serializer": ">=2.4,<2.6-dev",
"symfony/translation": ">=2.4,<2.6-dev",
"symfony/twig-bridge": ">=2.4,<2.6-dev",
"symfony/validator": ">=2.4,<2.6-dev",
"twig/twig": ">=1.8.0,<2.0-dev",
"doctrine/dbal": "~2.2",
"swiftmailer/swiftmailer": "5.*",
......@@ -47,17 +47,21 @@
"phpunit/phpunit": "~3.7"
},
"suggest": {
"symfony/browser-kit": ">=2.3,<2.6-dev",
"symfony/css-selector": ">=2.3,<2.6-dev",
"symfony/dom-crawler": ">=2.3,<2.6-dev",
"symfony/form": ">=2.3,<2.6-dev"
"symfony/browser-kit": ">=2.4,<2.6-dev",
"symfony/css-selector": ">=2.4,<2.6-dev",
"symfony/dom-crawler": ">=2.4,<2.6-dev",
"symfony/form": ">=2.4,<2.6-dev"
},
"replace": {
"silex/api": "self.version",
"silex/providers": "self.version"
},
"autoload": {
"psr-0": { "Silex": "src/" }
},
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
"dev-master": "2.0.x-dev"
}
}
}
Changelog
=========
2.0.0 (2013-XX-XX)
------------------
* Updated Pimple to 2.1
* 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)
1.2.0 (2014-03-29)
------------------
......
......@@ -34,11 +34,11 @@ Using it in a template is as easy as before:
If you need to implement some logic independently of the asset, define a
service instead::
$app['asset_path'] = $app->share(function () {
$app['asset_path'] = function () {
// implement whatever logic you need to determine the asset path
return 'http://assets.examples.com';
});
};
Usage is exactly the same as before:
......@@ -49,7 +49,7 @@ Usage is exactly the same as before:
If the asset location depends on the asset type or path, you will need more
abstraction; here is one way to do that with a Twig function::
$app['twig'] = $app->share($app->extend('twig', function($twig, $app) {
$app->extend('twig', function($twig, $app) {
$twig->addFunction(new \Twig_SimpleFunction('asset', function ($asset) {
// implement whatever logic you need to determine the asset path
......@@ -57,7 +57,7 @@ abstraction; here is one way to do that with a Twig function::
}));
return $twig;
}));
});
The ``asset`` function can then be used in your templates:
......
......@@ -18,9 +18,9 @@ using the bundled handler, but each with a different channel.
});
foreach (array('auth', 'payments', 'stats') as $channel) {
$app['monolog.'.$channel] = $app->share(function ($app) use ($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
......@@ -31,13 +31,13 @@ particular service separately, including your customizations.
use Monolog\Handler\StreamHandler;
$app['monolog.payments'] = $app->share(function ($app) {
$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
......@@ -62,10 +62,8 @@ the container with the channel name, defaulting to the bundled handler.
return $log;
});
$app['monolog.payments.handlers'] = $app->share(function ($app) {
$app['monolog.payments.handlers'] = function ($app) {
return array(
new StreamHandler(__DIR__.'/../payments.log', Logger::DEBUG),
);
});
};
......@@ -35,21 +35,21 @@ With a dedicated PDO service
'db_time_col' => 'session_time',
);
$app['pdo'] = $app->share(function () use ($app) {
$app['pdo'] = function () use ($app) {
return new PDO(
$app['pdo.dsn'],
$app['pdo.user'],
$app['pdo.password']
);
});
};
$app['session.storage.handler'] = $app->share(function () use ($app) {
$app['session.storage.handler'] = function () use ($app) {
return new PdoSessionHandler(
$app['pdo'],
$app['session.db_options'],
$app['session.storage.options']
);
});
};
Using the DoctrineServiceProvider
---------------------------------
......@@ -70,13 +70,13 @@ have to make another database connection, simply pass the getWrappedConnection m
'db_time_col' => 'session_time',
);
$app['session.storage.handler'] = $app->share(function () use ($app) {
$app['session.storage.handler'] = function () use ($app) {
return new PdoSessionHandler(
$app['db']->getWrappedConnection(),
$app['session.db_options'],
$app['session.storage.options']
);
});
};
Database structure
------------------
......
......@@ -17,4 +17,3 @@ Silex
providers/index
web_servers
changelog
phar
Phar File
=========
.. caution::
Using the Silex ``phar`` file is deprecated. You should use Composer
instead to install Silex and its dependencies or download one of the
archives.
Installing
----------
Installing Silex is as easy as downloading the `phar
<http://silex.sensiolabs.org/get/silex.phar>`_ and storing it somewhere on
the disk. Then, require it in your script::
<?php
require_once __DIR__.'/silex.phar';
$app = new Silex\Application();
$app->get('/hello/{name}', function ($name) use ($app) {
return 'Hello '.$app->escape($name);
});
$app->run();
Console
-------
Silex includes a lightweight console for updating to the latest version.
To find out which version of Silex you are using, invoke ``silex.phar`` on the
command-line with ``version`` as an argument:
.. code-block:: text
$ php silex.phar version
Silex version 0a243d3 2011-04-17 14:49:31 +0200
To check that your are using the latest version, run the ``check`` command:
.. code-block:: text
$ php silex.phar check
To update ``silex.phar`` to the latest version, invoke the ``update``
command:
.. code-block:: text
$ php silex.phar update
This will automatically download a new ``silex.phar`` from
``silex.sensiolabs.org`` and replace the existing one.
Pitfalls
--------
There are some things that can go wrong. Here we will try and outline the
most frequent ones.
PHP configuration
~~~~~~~~~~~~~~~~~
Certain PHP distributions have restrictive default Phar settings. Setting
the following may help.
.. code-block:: ini
detect_unicode = Off
phar.readonly = Off
phar.require_hash = Off
If you are on Suhosin you will also have to set this:
.. code-block:: ini
suhosin.executor.include.whitelist = phar
.. note::
Ubuntu's PHP ships with Suhosin, so if you are using Ubuntu, you will need
this change.
Phar-Stub bug
~~~~~~~~~~~~~
Some PHP installations have a bug that throws a ``PharException`` when trying
to include the Phar. It will also tell you that ``Silex\Application`` could not
be found. A workaround is using the following include line::
require_once 'phar://'.__DIR__.'/silex.phar/autoload.php';
The exact cause of this issue could not be determined yet.
ioncube loader bug
~~~~~~~~~~~~~~~~~~
Ioncube loader is an extension that can decode PHP encoded file.
Unfortunately, old versions (prior to version 4.0.9) are not working well
with phar archives.
You must either upgrade Ioncube loader to version 4.0.9 or newer or disable it
by commenting or removing this line in your php.ini file:
.. code-block:: ini
zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so
......@@ -80,7 +80,7 @@ You are encouraged to share yours.
Creating a provider
~~~~~~~~~~~~~~~~~~~
Providers must implement the ``Silex\ServiceProviderInterface``::
Providers must implement the ``Silex\Api\ServiceProviderInterface``::
interface ServiceProviderInterface
{
......@@ -100,7 +100,7 @@ Here is an example of such a provider::
namespace Acme;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Silex\Api\ServiceProviderInterface;
class HelloServiceProvider implements ServiceProviderInterface
{
......@@ -161,7 +161,7 @@ All controllers defined by the provider will now be available under the
Creating a provider
~~~~~~~~~~~~~~~~~~~
Providers must implement the ``Silex\ControllerProviderInterface``::
Providers must implement the ``Silex\Api\ControllerProviderInterface``::
interface ControllerProviderInterface
{
......@@ -173,7 +173,7 @@ Here is an example of such a provider::
namespace Acme;
use Silex\Application;
use Silex\ControllerProviderInterface;
use Silex\Api\ControllerProviderInterface;
class HelloControllerProvider implements ControllerProviderInterface
{
......
......@@ -168,28 +168,28 @@ form by adding constraints on the fields::
You can register form extensions by extending ``form.extensions``::
$app['form.extensions'] = $app->share($app->extend('form.extensions', function ($extensions) use ($app) {
$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['form.type.extensions'] = $app->share($app->extend('form.type.extensions', function ($extensions) use ($app) {
$app->extend('form.type.extensions', function ($extensions) use ($app) {
$extensions[] = new YourFormTypeExtension();
return $extensions;
}));
});
You can register form type guessers by extending ``form.type.guessers``::
$app['form.type.guessers'] = $app->share($app->extend('form.type.guessers', function ($guessers) use ($app) {
$app->extend('form.type.guessers', function ($guessers) use ($app) {
$guessers[] = new YourFormTypeGuesser();
return $guessers;
}));
});
Traits
------
......
LocaleServiceProvider
=====================
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());
......@@ -81,11 +81,11 @@ Customization
You can configure Monolog (like adding or changing the handlers) before using
it by extending the ``monolog`` service::
$app['monolog'] = $app->share($app->extend('monolog', function($monolog, $app) {
$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
......
......@@ -432,9 +432,9 @@ 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' => $app->share(function () use ($app) {
'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::
......@@ -532,12 +532,12 @@ service::
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
$app['security.encoder.digest'] = $app->share(function ($app) {
$app['security.encoder.digest'] = function ($app) {
// use the sha1 algorithm
// don't base64 encode the password
// use only 1 iteration
return new MessageDigestPasswordEncoder('sha1', false, 1);
});
};
Defining a custom Authentication Provider
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -550,14 +550,14 @@ 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'] = $app->share(function () use ($app) {
$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'] = $app->share(function () use ($app) {
$app['security.authentication_listener.'.$name.'.wsse'] = function () use ($app) {
return new WsseListener($app['security'], $app['security.authentication_manager']);
});
};
return array(
// the authentication provider id
......
......@@ -58,9 +58,9 @@ In this slightly contrived example of a blog API, we're going to change the
$app = new Application();
$app['posts.repository'] = $app->share(function() {
$app['posts.repository'] = function() {
return new PostRepository;
});
};
$app->get('/posts.json', function() use ($app) {
return $app->json($app['posts.repository']->findAll());
......@@ -109,8 +109,8 @@ followed by a single colon (:), followed by the method name.
.. code-block:: php
$app['posts.controller'] = $app->share(function() use ($app) {
$app['posts.controller'] = function() use ($app) {
return new PostController($app['posts.repository']);
});
};
$app->get('/posts.json', "posts.controller:indexJsonAction");
......@@ -37,6 +37,7 @@ Registering
.. code-block:: php
$app->register(new Silex\Provider\LocaleServiceProvider());
$app->register(new Silex\Provider\TranslationServiceProvider(), array(
'locale_fallbacks' => array('en'),
));
......@@ -143,7 +144,7 @@ translation files::
use Symfony\Component\Translation\Loader\YamlFileLoader;
$app['translator'] = $app->share($app->extend('translator', function($translator, $app) {
$app->extend('translator', function($translator, $app) {
$translator->addLoader('yaml', new YamlFileLoader());
$translator->addResource('yaml', __DIR__.'/locales/en.yml', 'en');
......@@ -151,7 +152,7 @@ translation files::
$translator->addResource('yaml', __DIR__.'/locales/fr.yml', 'fr');
return $translator;
}));
});
XLIFF-based language files
~~~~~~~~~~~~~~~~~~~~~~~~~~
......
......@@ -156,12 +156,12 @@ Customization
You can configure the Twig environment before using it by extending the
``twig`` service::
$app['twig'] = $app->share($app->extend('twig', function($twig, $app) {
$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>`_.
......@@ -64,6 +64,14 @@ Moreover, if you have ``twig-bridge`` in your ``composer.json``, you will have a
{{ path('hello', {name: 'Fabien'}) }}
{{ url('hello', {name: 'Fabien'}) }} {# generates the absolute url http://example.org/hello/Fabien #}
.. warning::
If you try to use the ``url_generator`` service outside the handling of a
request, you must explicitly flush routes first::
$app->flush();
$url = $app['url_generator']->generate('homepage');
Traits
------
......
......@@ -63,10 +63,10 @@ Pimple is probably the simplest service container out there. It 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`` all of this applies to Silex as
well::
``Silex\Application`` extends ``Pimple\Container`` all of this applies to Silex
as well::
$container = new Pimple();
$container = new Pimple\Container();
or::
......@@ -107,19 +107,6 @@ And to retrieve the service, use::
Every time you call ``$app['some_service']``, a new instance of the service is
created.
Shared services
~~~~~~~~~~~~~~~
You may want to use the same instance of a service across all of your code. In
order to do that you can make a *shared* service::
$app['some_service'] = $app->share(function () {
return new Service();
});
This will create the service on first invocation, and then return the existing
instance on any subsequent access.
Access container from closure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -139,17 +126,13 @@ 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.
.. note::
This also works for shared services.
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'] = $app->share(function ($app) {
$app['user.persister'] = function ($app) {
return new JsonUserPersister($app['user.persist_path']);
});
};
Protected closures
......@@ -230,13 +213,6 @@ don't want to mess with most of them.
the ``MonologServiceProvider`` or define your own ``logger`` service that
conforms to the PSR logger interface.
In versions of Silex before 1.1 this must be a
``Symfony\Component\HttpKernel\Log\LoggerInterface``.
.. note::
All of these Silex core services are shared.
Core parameters
---------------
......@@ -256,11 +232,6 @@ Core parameters
This parameter can be used by the ``UrlGeneratorProvider``.
* **locale** (optional): 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.
* **debug** (optional): Returns whether or not the application is running in
debug mode.
......
......@@ -25,7 +25,7 @@ If you want more flexibility, use Composer_ instead. Create a
{
"require": {
"silex/silex": "~1.1"
"silex/silex": "~2.0"
}
}
......@@ -375,9 +375,9 @@ converter based on Doctrine ObjectManager::
The service will now be registered in the application, and the
convert method will be used as converter::
$app['converter.user'] = $app->share(function () {
$app['converter.user'] = function () {
return new UserConverter();
});
};
$app->get('/user/{user}', function (User $user) {
// ...
......
......@@ -9,25 +9,17 @@
* file that was distributed with this source code.
*/
namespace Silex;
namespace Silex\Api;
use Silex\Application;
/**
* Interface that all Silex service providers must implement.
* Interface that must implement all Silex service providers.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface ServiceProviderInterface
interface BootableProviderInterface
{
/**
* Registers services on the given app.
*
* This method should only be used to configure services and parameters.
* It should not get services.
*
* @param Application $app An Application instance
*/
public function register(Application $app);
/**
* Bootstraps the application.
*
......
......@@ -9,7 +9,9 @@
* file that was distributed with this source code.
*/
namespace Silex;
namespace Silex\Api;
use Silex\Application;
/**
* Interface for controller providers.
......
<?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\Api;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Pimple\Container;
/**
* Interface for event listener providers.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface EventListenerProviderInterface
{
public function subscribe(Container $app, EventDispatcherInterface $dispatcher);
}
Copyright (c) 2010-2013 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.
{
"minimum-stability": "dev",
"name": "silex/api",
"description": "The Silex interfaces",
"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.3.3",
"pimple/pimple": "~1.0"
},
"suggest": {
"symfony/event-dispatcher": "For EventListenerProviderInterface",
"silex/silex": "For BootableProviderInterface and ControllerProviderInterface"
},
"autoload": {
"psr-0": { "Silex\\Api": "" }
},
"target-dir": "Silex/Api",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
}
}
......@@ -11,6 +11,8 @@
namespace Silex;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
......@@ -19,7 +21,6 @@ use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpKernel\EventListener\ResponseListener;
use Symfony\Component\HttpKernel\EventListener\RouterListener;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\Request;
......@@ -29,20 +30,22 @@ use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
use Silex\EventListener\LocaleListener;
use Silex\Api\BootableProviderInterface;
use Silex\Api\EventListenerProviderInterface;
use Silex\Api\ControllerProviderInterface;
use Silex\EventListener\MiddlewareListener;
use Silex\EventListener\ConverterListener;
use Silex\EventListener\StringToResponseListener;
use Silex\Provider\RoutingServiceProvider;
/**
* The Silex framework class.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Application extends \Pimple implements HttpKernelInterface, TerminableInterface
class Application extends Container implements HttpKernelInterface, TerminableInterface
{
const VERSION = '1.2.0';
const VERSION = '2.0.0-DEV';
const EARLY_EVENT = 512;
const LATE_EVENT = -512;
......@@ -63,38 +66,31 @@ class Application extends \Pimple implements HttpKernelInterface, TerminableInte
$app = $this;
$this['logger'] = null;
$this['routes'] = $this->share(function () {
$this['routes'] = function () {
return new RouteCollection();
});
};
$this['controllers'] = $this->share(function () use ($app) {
$this['controllers'] = function () use ($app) {
return $app['controllers_factory'];
});
};
$this['controllers_factory'] = function () use ($app) {
$this['controllers_factory'] = $this->factory(function () use ($app) {
return new ControllerCollection($app['route_factory']);
};
});
$this['route_class'] = 'Silex\\Route';
$this['route_factory'] = function () use ($app) {
$this['route_factory'] = $this->factory(function () use ($app) {
return new $app['route_class']();
};
});
$this['exception_handler'] = $this->share(function () use ($app) {
$this['exception_handler'] = function () use ($app) {
return new ExceptionHandler($app['debug']);
});
};
$this['dispatcher_class'] = 'Symfony\\Component\\EventDispatcher\\EventDispatcher';
$this['dispatcher'] = $this->share(function () use ($app) {
$this['dispatcher'] = function () use ($app) {
$dispatcher = new $app['dispatcher_class']();
$urlMatcher = new LazyUrlMatcher(function () use ($app) {
return $app['url_matcher'];
});
$dispatcher->addSubscriber(new RouterListener($urlMatcher, $app['request_context'], $app['logger'], $app['request_stack']));
$dispatcher->addSubscriber(new LocaleListener($app, $urlMatcher, $app['request_stack']));
if (isset($app['exception_handler'])) {
$dispatcher->addSubscriber($app['exception_handler']);
}
......@@ -104,50 +100,31 @@ class Application extends \Pimple implements HttpKernelInterface, TerminableInte
$dispatcher->addSubscriber(new StringToResponseListener());
return $dispatcher;
});
};
$this['callback_resolver'] = $this->share(function () use ($app) {
$this['callback_resolver'] = function () use ($app) {
return new CallbackResolver($app);
});
};
$this['resolver'] = $this->share(function () use ($app) {
$this['resolver'] = function () use ($app) {
return new ControllerResolver($app, $app['logger']);
});
};
$this['kernel'] = $this->share(function () use ($app) {
$this['kernel'] = function () use ($app) {
return new HttpKernel($app['dispatcher'], $app['resolver'], $app['request_stack']);
});
$this['request_stack'] = $this->share(function () use ($app) {
if (class_exists('Symfony\Component\HttpFoundation\RequestStack')) {
return new RequestStack();
}
});
$this['request_context'] = $this->share(function () use ($app) {
$context = new RequestContext();
$context->setHttpPort($app['request.http_port']);
$context->setHttpsPort($app['request.https_port']);
return $context;
});
$this['url_matcher'] = $this->share(function () use ($app) {
return new RedirectableUrlMatcher($app['routes'], $app['request_context']);
});
$this['request_error'] = $this->protect(function () {
throw new \RuntimeException('Accessed request service outside of request scope. Try moving that call to a before handler or controller.');
});
};
$this['request'] = $this['request_error'];
$this['request_stack'] = function () use ($app) {
return new RequestStack();
};
$this['request.http_port'] = 80;
$this['request.https_port'] = 443;
$this['debug'] = false;
$this['charset'] = 'UTF-8';
$this['locale'] = 'en';
$this['logger'] = null;
$this->register(new RoutingServiceProvider());
foreach ($values as $key => $value) {
$this[$key] = $value;
......@@ -184,11 +161,17 @@ class Application extends \Pimple implements HttpKernelInterface, TerminableInte
public function boot()
{
if (!$this->booted) {
$this->booted = true;
foreach ($this->providers as $provider) {
$provider->boot($this);
}
if ($provider instanceof EventListenerProviderInterface) {
$provider->subscribe($this, $this['dispatcher']);
}
$this->booted = true;
if ($provider instanceof BootableProviderInterface) {
$provider->boot($this);
}
}
}
}
......@@ -288,11 +271,11 @@ class Application extends \Pimple implements HttpKernelInterface, TerminableInte
return;
}
$this['dispatcher'] = $this->share($this->extend('dispatcher', function ($dispatcher, $app) use ($callback, $priority, $eventName) {
$this->extend('dispatcher', function ($dispatcher, $app) use ($callback, $priority, $eventName) {
$dispatcher->addListener($eventName, $app['callback_resolver']->resolveCallback($callback), $priority);
return $dispatcher;
}));
});
}
/**
......@@ -470,8 +453,6 @@ class Application extends \Pimple implements HttpKernelInterface, TerminableInte
* @param null|string $contentDisposition The type of Content-Disposition to set automatically with the filename
*
* @return BinaryFileResponse
*
* @throws \RuntimeException When the feature is not supported, before http-foundation v2.2
*/
public function sendFile($file, $status = 200, array $headers = array(), $contentDisposition = null)
{
......@@ -529,17 +510,9 @@ class Application extends \Pimple implements HttpKernelInterface, TerminableInte
$this->boot();
}
$current = HttpKernelInterface::SUB_REQUEST === $type ? $this['request'] : $this['request_error'];
$this['request'] = $request;
$this->flush();
$response = $this['kernel']->handle($request, $type, $catch);
$this['request'] = $current;
return $response;
return $this['kernel']->handle($request, $type, $catch);
}
/**
......
......@@ -11,13 +11,15 @@
namespace Silex;
use Pimple\Container;
class CallbackResolver
{
const SERVICE_PATTERN = "/[A-Za-z0-9\._\-]+:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/";
private $app;
public function __construct(\Pimple $app)
public function __construct(Container $app)
{
$this->app = $app;
}
......
......@@ -49,7 +49,7 @@ class ExceptionListenerWrapper
$code = $exception instanceof HttpExceptionInterface ? $exception->getStatusCode() : 500;
$response = call_user_func($this->callback, $exception, $code);
$response = call_user_func($this->callback, $exception, $event->getRequest(), $code);
$this->ensureResponse($response, $event);
}
......
......@@ -11,8 +11,8 @@
namespace Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Configuration;
use Doctrine\Common\EventManager;
......@@ -25,7 +25,7 @@ use Symfony\Bridge\Doctrine\Logger\DbalLogger;
*/
class DoctrineServiceProvider implements ServiceProviderInterface
{
public function register(Application $app)
public function register(Container $app)
{
$app['db.default_options'] = array(
'driver' => 'pdo_mysql',
......@@ -60,10 +60,10 @@ class DoctrineServiceProvider implements ServiceProviderInterface
$app['dbs.options'] = $tmp;
});
$app['dbs'] = $app->share(function ($app) {
$app['dbs'] = function ($app) {
$app['dbs.options.initializer']();
$dbs = new \Pimple();
$dbs = new Container();
foreach ($app['dbs.options'] as $name => $options) {
if ($app['dbs.default'] === $name) {
// we use shortcuts here in case the default has been overridden
......@@ -74,18 +74,18 @@ class DoctrineServiceProvider implements ServiceProviderInterface
$manager = $app['dbs.event_manager'][$name];
}
$dbs[$name] = $dbs->share(function ($dbs) use ($options, $config, $manager) {
$dbs[$name] = function ($dbs) use ($options, $config, $manager) {
return DriverManager::getConnection($options, $config, $manager);
});
};
}
return $dbs;
});
};
$app['dbs.config'] = $app->share(function ($app) {
$app['dbs.config'] = function ($app) {
$app['dbs.options.initializer']();
$configs = new \Pimple();
$configs = new Container();
foreach ($app['dbs.options'] as $name => $options) {
$configs[$name] = new Configuration();
......@@ -95,40 +95,36 @@ class DoctrineServiceProvider implements ServiceProviderInterface
}
return $configs;
});
};
$app['dbs.event_manager'] = $app->share(function ($app) {
$app['dbs.event_manager'] = function ($app) {
$app['dbs.options.initializer']();
$managers = new \Pimple();
$managers = new Container();
foreach ($app['dbs.options'] as $name => $options) {
$managers[$name] = new EventManager();
}
return $managers;
});
};
// shortcuts for the "first" DB
$app['db'] = $app->share(function ($app) {
$app['db'] = function ($app) {
$dbs = $app['dbs'];
return $dbs[$app['dbs.default']];
});
};
$app['db.config'] = $app->share(function ($app) {
$app['db.config'] = function ($app) {
$dbs = $app['dbs.config'];
return $dbs[$app['dbs.default']];
});
};
$app['db.event_manager'] = $app->share(function ($app) {
$app['db.event_manager'] = function ($app) {
$dbs = $app['dbs.event_manager'];
return $dbs[$app['dbs.default']];
});
}
public function boot(Application $app)
{
};
}
}
......@@ -11,8 +11,8 @@
namespace Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider;
......@@ -28,7 +28,7 @@ use Symfony\Component\Form\ResolvedFormTypeFactory;
*/
class FormServiceProvider implements ServiceProviderInterface
{
public function register(Application $app)
public function register(Container $app)
{
if (!class_exists('Locale') && !class_exists('Symfony\Component\Locale\Stub\StubLocale')) {
throw new \RuntimeException('You must either install the PHP intl extension or the Symfony Locale Component to use the Form extension.');
......@@ -47,23 +47,23 @@ class FormServiceProvider implements ServiceProviderInterface
$app['form.secret'] = md5(__DIR__);
$app['form.type.extensions'] = $app->share(function ($app) {
$app['form.type.extensions'] = function ($app) {
return array();
});
};
$app['form.type.guessers'] = $app->share(function ($app) {
$app['form.type.guessers'] = function ($app) {
return array();
});
};
$app['form.extension.csrf'] = $app->share(function ($app) {
$app['form.extension.csrf'] = function ($app) {
if (isset($app['translator'])) {
return new CsrfExtension($app['form.csrf_provider'], $app['translator']);
}
return new CsrfExtension($app['form.csrf_provider']);
});
};
$app['form.extensions'] = $app->share(function ($app) {
$app['form.extensions'] = function ($app) {
$extensions = array(
$app['form.extension.csrf'],
new HttpFoundationExtension(),
......@@ -79,9 +79,9 @@ class FormServiceProvider implements ServiceProviderInterface
}
return $extensions;
});
};
$app['form.factory'] = $app->share(function ($app) {
$app['form.factory'] = function ($app) {
return Forms::createFormFactoryBuilder()
->addExtensions($app['form.extensions'])
->addTypeExtensions($app['form.type.extensions'])
......@@ -89,22 +89,18 @@ class FormServiceProvider implements ServiceProviderInterface
->setResolvedTypeFactory($app['form.resolved_type_factory'])
->getFormFactory()
;
});
};
$app['form.resolved_type_factory'] = $app->share(function ($app) {
$app['form.resolved_type_factory'] = function ($app) {
return new ResolvedFormTypeFactory();
});
};
$app['form.csrf_provider'] = $app->share(function ($app) {
$app['form.csrf_provider'] = function ($app) {
if (isset($app['session'])) {
return new SessionCsrfProvider($app['session'], $app['form.secret']);
}
return new DefaultCsrfProvider($app['form.secret']);
});
}
public function boot(Application $app)
{
};
}
}
......@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Silex;
namespace Silex\Provider\HttpCache;
use Symfony\Component\HttpKernel\HttpCache\HttpCache as BaseHttpCache;
use Symfony\Component\HttpFoundation\Request;
......
......@@ -11,9 +11,11 @@
namespace Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Silex\HttpCache;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Provider\HttpCache\HttpCache;
use Silex\Api\EventListenerProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\HttpKernel\HttpCache\Store;
use Symfony\Component\HttpKernel\EventListener\EsiListener;
......@@ -23,37 +25,37 @@ use Symfony\Component\HttpKernel\EventListener\EsiListener;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class HttpCacheServiceProvider implements ServiceProviderInterface
class HttpCacheServiceProvider implements ServiceProviderInterface, EventListenerProviderInterface
{
public function register(Application $app)
public function register(Container $app)
{
$app['http_cache'] = $app->share(function ($app) {
$app['http_cache'] = function ($app) {
$app['http_cache.options'] = array_replace(
array(
'debug' => $app['debug'],
'debug' => isset($app['debug']) ? $app['debug'] : false,
), $app['http_cache.options']
);
return new HttpCache($app, $app['http_cache.store'], $app['http_cache.esi'], $app['http_cache.options']);
});
};
$app['http_cache.esi'] = $app->share(function ($app) {
$app['http_cache.esi'] = function ($app) {
return new Esi();
});
};
$app['http_cache.store'] = $app->share(function ($app) {
$app['http_cache.store'] = function ($app) {
return new Store($app['http_cache.cache_dir']);
});
};
$app['http_cache.esi_listener'] = $app->share(function ($app) {
$app['http_cache.esi_listener'] = function ($app) {
return new EsiListener($app['http_cache.esi']);
});
};
$app['http_cache.options'] = array();
}
public function boot(Application $app)
public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
{
$app['dispatcher']->addSubscriber($app['http_cache.esi_listener']);
$dispatcher->addSubscriber($app['http_cache.esi_listener']);
}
}
......@@ -11,8 +11,10 @@
namespace Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Api\EventListenerProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
use Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer;
use Symfony\Component\HttpKernel\Fragment\EsiFragmentRenderer;
......@@ -23,55 +25,49 @@ use Symfony\Component\HttpKernel\UriSigner;
/**
* HttpKernel Fragment integration for Silex.
*
* This service provider requires Symfony 2.4+.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class HttpFragmentServiceProvider implements ServiceProviderInterface
class HttpFragmentServiceProvider implements ServiceProviderInterface, EventListenerProviderInterface
{
public function register(Application $app)
public function register(Container $app)
{
if (!class_exists('Symfony\Component\HttpFoundation\RequestStack')) {
throw new \LogicException('The HTTP Fragment service provider only works with Symfony 2.4+.');
}
$app['fragment.handler'] = $app->share(function ($app) {
return new FragmentHandler($app['fragment.renderers'], $app['debug'], $app['request_stack']);
});
$app['fragment.handler'] = function ($app) {
return new FragmentHandler($app['fragment.renderers'], isset($app['debug']) ? $app['debug'] : false, $app['request_stack']);
};
$app['fragment.renderer.inline'] = $app->share(function ($app) {
$app['fragment.renderer.inline'] = function ($app) {
$renderer = new InlineFragmentRenderer($app['kernel'], $app['dispatcher']);
$renderer->setFragmentPath($app['fragment.path']);
return $renderer;
});
};
$app['fragment.renderer.hinclude'] = $app->share(function ($app) {
$renderer = new HIncludeFragmentRenderer(null, $app['uri_signer'], $app['fragment.renderer.hinclude.global_template'], $app['charset']);
$app['fragment.renderer.hinclude'] = function ($app) {
$renderer = new HIncludeFragmentRenderer(null, $app['uri_signer'], $app['fragment.renderer.hinclude.global_template'], isset($app['charset']) ? $app['charset'] : 'UTF-8');
$renderer->setFragmentPath($app['fragment.path']);
return $renderer;
});
};
$app['fragment.renderer.esi'] = $app->share(function ($app) {
$app['fragment.renderer.esi'] = function ($app) {
$renderer = new EsiFragmentRenderer($app['http_cache.esi'], $app['fragment.renderer.inline']);
$renderer->setFragmentPath($app['fragment.path']);
return $renderer;
});
};
$app['fragment.listener'] = $app->share(function ($app) {
$app['fragment.listener'] = function ($app) {
return new FragmentListener($app['uri_signer'], $app['fragment.path']);
});
};
$app['uri_signer'] = $app->share(function ($app) {
$app['uri_signer'] = function ($app) {
return new UriSigner($app['uri_signer.secret']);
});
};
$app['uri_signer.secret'] = md5(__DIR__);
$app['fragment.path'] = '/_fragment';
$app['fragment.renderer.hinclude.global_template'] = null;
$app['fragment.renderers'] = $app->share(function ($app) {
$app['fragment.renderers'] = function ($app) {
$renderers = array($app['fragment.renderer.inline'], $app['fragment.renderer.hinclude']);
if (isset($app['http_cache.esi'])) {
......@@ -79,11 +75,11 @@ class HttpFragmentServiceProvider implements ServiceProviderInterface
}
return $renderers;
});
};
}
public function boot(Application $app)
public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
{
$app['dispatcher']->addSubscriber($app['fragment.listener']);
$dispatcher->addSubscriber($app['fragment.listener']);
}
}
Copyright (c) 2010-2013 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.
......@@ -9,13 +9,13 @@
* file that was distributed with this source code.
*/
namespace Silex\EventListener;
namespace Silex\Provider\Locale;
use Pimple\Container;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\EventListener\LocaleListener as BaseLocaleListener;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RequestContextAwareInterface;
use Silex\Application;
/**
* Initializes the locale based on the current request.
......@@ -26,7 +26,7 @@ class LocaleListener extends BaseLocaleListener
{
protected $app;
public function __construct(Application $app, RequestContextAwareInterface $router = null, RequestStack $requestStack = null)
public function __construct(Container $app, RequestContextAwareInterface $router = null, RequestStack $requestStack = null)
{
parent::__construct($app['locale'], $router, $requestStack);
......
<?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\Provider;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Api\EventListenerProviderInterface;
use Silex\Provider\Locale\LocaleListener;
use Silex\Provider\Routing\LazyUrlMatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* Locale Provider.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class LocaleServiceProvider implements ServiceProviderInterface, EventListenerProviderInterface
{
public function register(Container $app)
{
$app['locale.listener'] = function ($app) {
$urlMatcher = null;
if (isset($app['url_matcher'])) {
$urlMatcher = new LazyUrlMatcher(function () use ($app) {
return $app['url_matcher'];
});
}
return new LocaleListener($app, $urlMatcher, $app['request_stack']);
};
$app['locale'] = 'en';
}
public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
{
$dispatcher->addSubscriber($app['locale.listener']);
}
}
......@@ -11,10 +11,15 @@
namespace Silex\Provider;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Silex\Api\BootableProviderInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bridge\Monolog\Handler\DebugHandler;
use Silex\EventListener\LogListener;
......@@ -23,9 +28,9 @@ use Silex\EventListener\LogListener;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class MonologServiceProvider implements ServiceProviderInterface
class MonologServiceProvider implements ServiceProviderInterface, BootableProviderInterface
{
public function register(Application $app)
public function register(Container $app)
{
$app['logger'] = function () use ($app) {
return $app['monolog'];
......@@ -41,17 +46,17 @@ class MonologServiceProvider implements ServiceProviderInterface
$app['monolog.logger.class'] = $bridge ? 'Symfony\Bridge\Monolog\Logger' : 'Monolog\Logger';
$app['monolog'] = $app->share(function ($app) {
$app['monolog'] = function ($app) {
$log = new $app['monolog.logger.class']($app['monolog.name']);
$log->pushHandler($app['monolog.handler']);
if ($app['debug'] && isset($app['monolog.handler.debug'])) {
if (isset($app['debug']) && $app['debug'] && isset($app['monolog.handler.debug'])) {
$log->pushHandler($app['monolog.handler.debug']);
}
return $log;
});
};
$app['monolog.handler'] = function () use ($app) {
$level = MonologServiceProvider::translateLevel($app['monolog.level']);
......@@ -63,9 +68,9 @@ class MonologServiceProvider implements ServiceProviderInterface
return Logger::DEBUG;
};
$app['monolog.listener'] = $app->share(function () use ($app) {
$app['monolog.listener'] = function () use ($app) {
return new LogListener($app['logger']);
});
};
$app['monolog.name'] = 'myapp';
}
......
......@@ -11,8 +11,10 @@
namespace Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Api\EventListenerProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\Authentication\Provider\RememberMeAuthenticationProvider;
use Symfony\Component\Security\Http\Firewall\RememberMeListener;
use Symfony\Component\Security\Http\RememberMe\TokenBasedRememberMeServices;
......@@ -23,13 +25,17 @@ use Symfony\Component\Security\Http\RememberMe\ResponseListener;
*
* @author Jérôme Tamarelle <jerome@tamarelle.net>
*/
class RememberMeServiceProvider implements ServiceProviderInterface
class RememberMeServiceProvider implements ServiceProviderInterface, EventListenerProviderInterface
{
public function register(Application $app)
public function register(Container $app)
{
$app['security.remember_me.response_listener'] = $app->share(function () {
$app['security.remember_me.response_listener'] = function ($app) {
if (!isset($app['security'])) {
throw new \LogicException('You must register the SecurityServiceProvider to use the RememberMeServiceProvider');
}
return new ResponseListener();
});
};
$app['security.authentication_listener.factory.remember_me'] = $app->protect(function ($name, $options) use ($app) {
if (empty($options['key'])) {
......@@ -57,7 +63,7 @@ class RememberMeServiceProvider implements ServiceProviderInterface
});
$app['security.remember_me.service._proto'] = $app->protect(function ($providerKey, $options) use ($app) {
return $app->share(function () use ($providerKey, $options, $app) {
return function () use ($providerKey, $options, $app) {
$options = array_replace(array(
'name' => 'REMEMBERME',
'lifetime' => 31536000,
......@@ -69,36 +75,32 @@ class RememberMeServiceProvider implements ServiceProviderInterface
'remember_me_parameter' => '_remember_me',
), $options);
return new TokenBasedRememberMeServices(array($app['security.user_provider.'.$providerKey]), $options['key'], $providerKey, $options, $app['logger']);
});
return new TokenBasedRememberMeServices(array($app['security.user_provider.'.$providerKey]), $options['key'], $providerKey, $options, isset($app['logger']) ? $app['logger'] : null);
};
});
$app['security.authentication_listener.remember_me._proto'] = $app->protect(function ($providerKey) use ($app) {
return $app->share(function () use ($app, $providerKey) {
return function () use ($app, $providerKey) {
$listener = new RememberMeListener(
$app['security'],
$app['security.remember_me.service.'.$providerKey],
$app['security.authentication_manager'],
$app['logger']
isset($app['logger']) ? $app['logger'] : null
);
return $listener;
});
};
});
$app['security.authentication_provider.remember_me._proto'] = $app->protect(function ($name, $options) use ($app) {
return $app->share(function () use ($app, $name, $options) {
return function () use ($app, $name, $options) {
return new RememberMeAuthenticationProvider($app['security.user_checker'], $options['key'], $name);
});
};
});
}
public function boot(Application $app)
public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
{
if (!isset($app['security'])) {
throw new \LogicException('You must register the SecurityServiceProvider to use the RememberMeServiceProvider');
}
$app['dispatcher']->addSubscriber($app['security.remember_me.response_listener']);
$dispatcher->addSubscriber($app['security.remember_me.response_listener']);
}
}
......@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Silex;
namespace Silex\Provider\Routing;
use Symfony\Component\Routing\RequestContext as SymfonyRequestContext;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
......
......@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Silex;
namespace Silex\Provider\Routing;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Matcher\RedirectableUrlMatcher as BaseRedirectableUrlMatcher;
......
<?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\Provider;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Api\EventListenerProviderInterface;
use Silex\Provider\Routing\RedirectableUrlMatcher;
use Silex\Provider\Routing\LazyUrlMatcher;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\HttpKernel\EventListener\RouterListener;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* Symfony Routing component Provider.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class RoutingServiceProvider implements ServiceProviderInterface, EventListenerProviderInterface
{
public function register(Container $app)
{
$app['url_generator'] = function ($app) {
return new UrlGenerator($app['routes'], $app['request_context']);
};
$app['url_matcher'] = function () use ($app) {
return new RedirectableUrlMatcher($app['routes'], $app['request_context']);
};
$app['request_context'] = function () use ($app) {
$context = new RequestContext();
$context->setHttpPort(isset($app['request.http_port']) ? $app['request.http_port'] : 80);
$context->setHttpsPort(isset($app['request.https_port']) ? $app['request.https_port'] : 443);
return $context;
};
$app['routing.listener'] = function () use ($app) {
$urlMatcher = new LazyUrlMatcher(function () use ($app) {
return $app['url_matcher'];
});
return new RouterListener($urlMatcher, $app['request_context'], isset($app['logger']) ? $app['logger'] : null, $app['request_stack']);
};
}
public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
{
$dispatcher->addSubscriber($app['routing.listener']);
}
}
......@@ -11,8 +11,13 @@
namespace Silex\Provider;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Silex\Api\BootableProviderInterface;
use Silex\Api\ControllerProviderInterface;
use Silex\Api\EventListenerProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RequestMatcher;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\SecurityContext;
......@@ -57,11 +62,11 @@ use Symfony\Component\Security\Http\HttpUtils;
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class SecurityServiceProvider implements ServiceProviderInterface
class SecurityServiceProvider implements ServiceProviderInterface, EventListenerProviderInterface, ControllerProviderInterface, BootableProviderInterface
{
protected $fakeRoutes;
public function register(Application $app)
public function register(Container $app)
{
// used to register routes for login_check and logout
$this->fakeRoutes = array();
......@@ -72,54 +77,57 @@ class SecurityServiceProvider implements ServiceProviderInterface
$app['security.access_rules'] = array();
$app['security.hide_user_not_found'] = true;
$app['security'] = $app->share(function ($app) {
$app['security'] = function ($app) {
return new SecurityContext($app['security.authentication_manager'], $app['security.access_manager']);
});
};
$app['security.authentication_manager'] = $app->share(function ($app) {
$app['security.authentication_manager'] = function ($app) {
$manager = new AuthenticationProviderManager($app['security.authentication_providers']);
$manager->setEventDispatcher($app['dispatcher']);
return $manager;
});
};
// by default, all users use the digest encoder
$app['security.encoder_factory'] = $app->share(function ($app) {
$app['security.encoder_factory'] = function ($app) {
return new EncoderFactory(array(
'Symfony\Component\Security\Core\User\UserInterface' => $app['security.encoder.digest'],
));
});
};
$app['security.encoder.digest'] = $app->share(function ($app) {
$app['security.encoder.digest'] = function ($app) {
return new MessageDigestPasswordEncoder();
});
};
$app['security.user_checker'] = $app->share(function ($app) {
$app['security.user_checker'] = function ($app) {
return new UserChecker();
});
};
$app['security.access_manager'] = $app->share(function ($app) {
$app['security.access_manager'] = function ($app) {
return new AccessDecisionManager($app['security.voters']);
});
};
$app['security.voters'] = $app->share(function ($app) {
$app['security.voters'] = function ($app) {
return array(
new RoleHierarchyVoter(new RoleHierarchy($app['security.role_hierarchy'])),
new AuthenticatedVoter($app['security.trust_resolver']),
);
});
};
$app['security.firewall'] = $app->share(function ($app) {
$app['security.firewall'] = function ($app) {
return new Firewall($app['security.firewall_map'], $app['dispatcher']);
});
};
$app['security.channel_listener'] = $app->share(function ($app) {
$app['security.channel_listener'] = function ($app) {
return new ChannelListener(
$app['security.access_map'],
new RetryAuthenticationEntryPoint($app['request.http_port'], $app['request.https_port']),
$app['logger']
new RetryAuthenticationEntryPoint(
isset($app['request.http_port']) ? $app['request.http_port'] : 80,
isset($app['request.https_port']) ? $app['request.https_port'] : 443
),
isset($app['logger']) ? $app['logger'] : null
);
});
};
// generate the build-in authentication factories
foreach (array('logout', 'pre_auth', 'form', 'http', 'remember_me', 'anonymous') as $type) {
......@@ -153,7 +161,7 @@ class SecurityServiceProvider implements ServiceProviderInterface
});
}
$app['security.firewall_map'] = $app->share(function ($app) {
$app['security.firewall_map'] = function ($app) {
$positions = array('logout', 'pre_auth', 'form', 'http', 'remember_me', 'anonymous');
$providers = array();
$configs = array();
......@@ -267,19 +275,19 @@ class SecurityServiceProvider implements ServiceProviderInterface
}
return $map;
});
};
$app['security.access_listener'] = $app->share(function ($app) {
$app['security.access_listener'] = function ($app) {
return new AccessListener(
$app['security'],
$app['security.access_manager'],
$app['security.access_map'],
$app['security.authentication_manager'],
$app['logger']
isset($app['logger']) ? $app['logger'] : null
);
});
};
$app['security.access_map'] = $app->share(function ($app) {
$app['security.access_map'] = function ($app) {
$map = new AccessMap();
foreach ($app['security.access_rules'] as $rule) {
......@@ -291,19 +299,19 @@ class SecurityServiceProvider implements ServiceProviderInterface
}
return $map;
});
};
$app['security.trust_resolver'] = $app->share(function ($app) {
$app['security.trust_resolver'] = function ($app) {
return new AuthenticationTrustResolver('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken', 'Symfony\Component\Security\Core\Authentication\Token\RememberMeToken');
});
};
$app['security.session_strategy'] = $app->share(function ($app) {
$app['security.session_strategy'] = function ($app) {
return new SessionAuthenticationStrategy('migrate');
});
};
$app['security.http_utils'] = $app->share(function ($app) {
$app['security.http_utils'] = function ($app) {
return new HttpUtils(isset($app['url_generator']) ? $app['url_generator'] : null, $app['url_matcher']);
});
};
$app['security.last_error'] = $app->protect(function (Request $request) {
if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
......@@ -322,30 +330,30 @@ class SecurityServiceProvider implements ServiceProviderInterface
// prototypes (used by the Firewall Map)
$app['security.context_listener._proto'] = $app->protect(function ($providerKey, $userProviders) use ($app) {
return $app->share(function () use ($app, $userProviders, $providerKey) {
return function () use ($app, $userProviders, $providerKey) {
return new ContextListener(
$app['security'],
$userProviders,
$providerKey,
$app['logger'],
isset($app['logger']) ? $app['logger'] : null,
$app['dispatcher']
);
});
};
});
$app['security.user_provider.inmemory._proto'] = $app->protect(function ($params) use ($app) {
return $app->share(function () use ($app, $params) {
return function () use ($app, $params) {
$users = array();
foreach ($params as $name => $user) {
$users[$name] = array('roles' => (array) $user[0], 'password' => $user[1]);
}
return new InMemoryUserProvider($users);
});
};
});
$app['security.exception_listener._proto'] = $app->protect(function ($entryPoint, $name) use ($app) {
return $app->share(function () use ($app, $entryPoint, $name) {
return function () use ($app, $entryPoint, $name) {
return new ExceptionListener(
$app['security'],
$app['security.trust_resolver'],
......@@ -354,13 +362,13 @@ class SecurityServiceProvider implements ServiceProviderInterface
$app[$entryPoint],
null, // errorPage
null, // AccessDeniedHandlerInterface
$app['logger']
isset($app['logger']) ? $app['logger'] : null
);
});
};
});
$app['security.authentication.success_handler._proto'] = $app->protect(function ($name, $options) use ($app) {
return $app->share(function () use ($name, $options, $app) {
return function () use ($name, $options, $app) {
$handler = new DefaultAuthenticationSuccessHandler(
$app['security.http_utils'],
$options
......@@ -368,22 +376,22 @@ class SecurityServiceProvider implements ServiceProviderInterface
$handler->setProviderKey($name);
return $handler;
});
};
});
$app['security.authentication.failure_handler._proto'] = $app->protect(function ($name, $options) use ($app) {
return $app->share(function () use ($name, $options, $app) {
return function () use ($name, $options, $app) {
return new DefaultAuthenticationFailureHandler(
$app,
$app['security.http_utils'],
$options,
$app['logger']
isset($app['logger']) ? $app['logger'] : null
);
});
};
});
$app['security.authentication_listener.form._proto'] = $app->protect(function ($name, $options) use ($app, $that) {
return $app->share(function () use ($app, $name, $options, $that) {
return function () use ($app, $name, $options, $that) {
$that->addFakeRoute(
'match',
$tmp = isset($options['check_path']) ? $options['check_path'] : '/login_check',
......@@ -409,46 +417,46 @@ class SecurityServiceProvider implements ServiceProviderInterface
$app['security.authentication.success_handler.'.$name],
$app['security.authentication.failure_handler.'.$name],
$options,
$app['logger'],
isset($app['logger']) ? $app['logger'] : null,
$app['dispatcher'],
isset($options['with_csrf']) && $options['with_csrf'] && isset($app['form.csrf_provider']) ? $app['form.csrf_provider'] : null
);
});
};
});
$app['security.authentication_listener.http._proto'] = $app->protect(function ($providerKey, $options) use ($app) {
return $app->share(function () use ($app, $providerKey, $options) {
return function () use ($app, $providerKey, $options) {
return new BasicAuthenticationListener(
$app['security'],
$app['security.authentication_manager'],
$providerKey,
$app['security.entry_point.'.$providerKey.'.http'],
$app['logger']
isset($app['logger']) ? $app['logger'] : null
);
});
};
});
$app['security.authentication_listener.anonymous._proto'] = $app->protect(function ($providerKey, $options) use ($app) {
return $app->share(function () use ($app, $providerKey, $options) {
return function () use ($app, $providerKey, $options) {
return new AnonymousAuthenticationListener(
$app['security'],
$providerKey,
$app['logger']
isset($app['logger']) ? $app['logger'] : null
);
});
};
});
$app['security.authentication.logout_handler._proto'] = $app->protect(function ($name, $options) use ($app) {
return $app->share(function () use ($name, $options, $app) {
return function () use ($name, $options, $app) {
return new DefaultLogoutSuccessHandler(
$app['security.http_utils'],
isset($options['target_url']) ? $options['target_url'] : '/'
);
});
};
});
$app['security.authentication_listener.logout._proto'] = $app->protect(function ($name, $options) use ($app, $that) {
return $app->share(function () use ($app, $name, $options, $that) {
return function () use ($app, $name, $options, $that) {
$that->addFakeRoute(
'get',
$tmp = isset($options['logout_path']) ? $options['logout_path'] : '/logout',
......@@ -470,42 +478,42 @@ class SecurityServiceProvider implements ServiceProviderInterface
$listener->addHandler(new SessionLogoutHandler());
return $listener;
});
};
});
$app['security.authentication_listener.switch_user._proto'] = $app->protect(function ($name, $options) use ($app, $that) {
return $app->share(function () use ($app, $name, $options, $that) {
return function () use ($app, $name, $options, $that) {
return new SwitchUserListener(
$app['security'],
$app['security.user_provider.'.$name],
$app['security.user_checker'],
$name,
$app['security.access_manager'],
$app['logger'],
isset($app['logger']) ? $app['logger'] : null,
isset($options['parameter']) ? $options['parameter'] : '_switch_user',
isset($options['role']) ? $options['role'] : 'ROLE_ALLOWED_TO_SWITCH',
$app['dispatcher']
);
});
};
});
$app['security.entry_point.form._proto'] = $app->protect(function ($name, array $options) use ($app) {
return $app->share(function () use ($app, $options) {
return function () use ($app, $options) {
$loginPath = isset($options['login_path']) ? $options['login_path'] : '/login';
$useForward = isset($options['use_forward']) ? $options['use_forward'] : false;
return new FormAuthenticationEntryPoint($app, $app['security.http_utils'], $loginPath, $useForward);
});
};
});
$app['security.entry_point.http._proto'] = $app->protect(function ($name, array $options) use ($app) {
return $app->share(function () use ($app, $name, $options) {
return function () use ($app, $name, $options) {
return new BasicAuthenticationEntryPoint(isset($options['real_name']) ? $options['real_name'] : 'Secured');
});
};
});
$app['security.authentication_provider.dao._proto'] = $app->protect(function ($name) use ($app) {
return $app->share(function () use ($app, $name) {
return function () use ($app, $name) {
return new DaoAuthenticationProvider(
$app['security.user_provider.'.$name],
$app['security.user_checker'],
......@@ -513,19 +521,19 @@ class SecurityServiceProvider implements ServiceProviderInterface
$app['security.encoder_factory'],
$app['security.hide_user_not_found']
);
});
};
});
$app['security.authentication_provider.anonymous._proto'] = $app->protect(function ($name) use ($app) {
return $app->share(function () use ($app, $name) {
return function () use ($app, $name) {
return new AnonymousAuthenticationProvider($name);
});
};
});
if (isset($app['validator'])) {
$app['security.validator.user_password_validator'] = $app->share(function ($app) {
$app['security.validator.user_password_validator'] = function ($app) {
return new UserPasswordValidator($app['security'], $app['security.encoder_factory']);
});
};
if (!isset($app['validator.validator_service_ids'])) {
$app['validator.validator_service_ids'] = array();
......@@ -535,15 +543,26 @@ class SecurityServiceProvider implements ServiceProviderInterface
}
}
public function boot(Application $app)
public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
{
$app['dispatcher']->addSubscriber($app['security.firewall']);
$dispatcher->addSubscriber($app['security.firewall']);
}
public function connect(Application $app)
{
$controllers = $app['controllers_factory'];
foreach ($this->fakeRoutes as $route) {
list($method, $pattern, $name) = $route;
$app->$method($pattern)->run(null)->bind($name);
$controllers->$method($pattern)->run(null)->bind($name);
}
return $controllers;
}
public function boot(Application $app)
{
$app->mount('/', $this->connect($app));
}
public function addFakeRoute($method, $pattern, $name)
......
......@@ -11,8 +11,8 @@
namespace Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
......@@ -33,31 +33,20 @@ class SerializerServiceProvider implements ServiceProviderInterface
* This method registers a serializer service. {@link http://api.symfony.com/master/Symfony/Component/Serializer/Serializer.html
* The service is provided by the Symfony Serializer component}.
*
* @param Silex\Application $app
* @param Pimple $app
*/
public function register(Application $app)
public function register(Container $app)
{
$app['serializer'] = $app->share(function () use ($app) {
$app['serializer'] = function () use ($app) {
return new Serializer($app['serializer.normalizers'], $app['serializer.encoders']);
});
};
$app['serializer.encoders'] = $app->share(function () {
$app['serializer.encoders'] = function () {
return array(new JsonEncoder(), new XmlEncoder());
});
};
$app['serializer.normalizers'] = $app->share(function () {
$app['serializer.normalizers'] = function () {
return array(new CustomNormalizer(), new GetSetMethodNormalizer());
});
}
/**
* {@inheritDoc}
*
* This provider does not execute any code when booting.
*
* @param Silex\Application $app
*/
public function boot(Application $app)
{
};
}
}
......@@ -11,21 +11,16 @@
namespace Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\ServiceControllerResolver;
class ServiceControllerServiceProvider implements ServiceProviderInterface
{
public function register(Application $app)
public function register(Container $app)
{
$app['resolver'] = $app->share($app->extend('resolver', function ($resolver, $app) {
$app->extend('resolver', function ($resolver, $app) {
return new ServiceControllerResolver($resolver, $app['callback_resolver']);
}));
}
public function boot(Application $app)
{
// noop
});
}
}
......@@ -9,29 +9,31 @@
* file that was distributed with this source code.
*/
namespace Silex\Provider;
namespace Silex\Provider\Session;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Pimple\Container;
use Symfony\Component\HttpKernel\EventListener\SessionListener as BaseSessionListener;
/**
* Symfony Routing component Provider for URL generation.
* Sets the session in the request.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class UrlGeneratorServiceProvider implements ServiceProviderInterface
class SessionListener extends BaseSessionListener
{
public function register(Application $app)
{
$app['url_generator'] = $app->share(function ($app) {
$app->flush();
private $app;
return new UrlGenerator($app['routes'], $app['request_context']);
});
public function __construct(Container $app)
{
$this->app = $app;
}
public function boot(Application $app)
protected function getSession()
{
if (!isset($this->app['session'])) {
return null;
}
return $this->app['session'];
}
}
<?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\Provider\Session;
use Pimple\Container;
use Symfony\Component\HttpKernel\EventListener\TestSessionListener as BaseTestSessionListener;
/**
* Simulates sessions for testing purpose.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class TestSessionListener extends BaseTestSessionListener
{
private $app;
public function __construct(Container $app)
{
$this->app = $app;
}
protected function getSession()
{
if (!isset($this->app['session'])) {
return null;
}
return $this->app['session'];
}
}
......@@ -11,34 +11,33 @@
namespace Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Api\EventListenerProviderInterface;
use Silex\Provider\Session\SessionListener;
use Silex\Provider\Session\TestSessionListener;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/**
* Symfony HttpFoundation component Provider for sessions.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class SessionServiceProvider implements ServiceProviderInterface
class SessionServiceProvider implements ServiceProviderInterface, EventListenerProviderInterface
{
private $app;
public function register(Application $app)
public function register(Container $app)
{
$this->app = $app;
$app['session.test'] = false;
$app['session'] = $app->share(function ($app) {
$app['session'] = function ($app) {
if (!isset($app['session.storage'])) {
if ($app['session.test']) {
$app['session.storage'] = $app['session.storage.test'];
......@@ -48,77 +47,42 @@ class SessionServiceProvider implements ServiceProviderInterface
}
return new Session($app['session.storage']);
});
};
$app['session.storage.handler'] = $app->share(function ($app) {
$app['session.storage.handler'] = function ($app) {
return new NativeFileSessionHandler($app['session.storage.save_path']);
});
};
$app['session.storage.native'] = $app->share(function ($app) {
$app['session.storage.native'] = function ($app) {
return new NativeSessionStorage(
$app['session.storage.options'],
$app['session.storage.handler']
);
});
};
$app['session.storage.test'] = $app->share(function () {
$app['session.listener'] = function ($app) {
return new SessionListener($app);
};
$app['session.storage.test'] = function () {
return new MockFileSessionStorage();
});
};
$app['session.listener.test'] = function ($app) {
return new TestSessionListener($app);
};
$app['session.storage.options'] = array();
$app['session.default_locale'] = 'en';
$app['session.storage.save_path'] = null;
}
public function onEarlyKernelRequest(GetResponseEvent $event)
{
$event->getRequest()->setSession($this->app['session']);
}
public function onKernelRequest(GetResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
// bootstrap the session
if (!isset($this->app['session'])) {
return;
}
$session = $this->app['session'];
$cookies = $event->getRequest()->cookies;
if ($cookies->has($session->getName())) {
$session->setId($cookies->get($session->getName()));
} else {
$session->migrate(false);
}
}
public function onKernelResponse(FilterResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
$session = $event->getRequest()->getSession();
if ($session && $session->isStarted()) {
$session->save();
$params = session_get_cookie_params();
$event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly']));
}
}
public function boot(Application $app)
public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
{
$app['dispatcher']->addListener(KernelEvents::REQUEST, array($this, 'onEarlyKernelRequest'), 128);
$dispatcher->addSubscriber($app['session.listener']);
if ($app['session.test']) {
$app['dispatcher']->addListener(KernelEvents::REQUEST, array($this, 'onKernelRequest'), 192);
$app['dispatcher']->addListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse'), -128);
$app['dispatcher']->addSubscriber($app['session.listener.test']);
}
}
}
......@@ -11,37 +11,41 @@
namespace Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Api\EventListenerProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
/**
* Swiftmailer Provider.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class SwiftmailerServiceProvider implements ServiceProviderInterface
class SwiftmailerServiceProvider implements ServiceProviderInterface, EventListenerProviderInterface
{
public function register(Application $app)
public function register(Container $app)
{
$app['swiftmailer.options'] = array();
$app['mailer.initialized'] = false;
$app['mailer'] = $app->share(function ($app) {
$app['mailer'] = function ($app) {
$app['mailer.initialized'] = true;
return new \Swift_Mailer($app['swiftmailer.spooltransport']);
});
};
$app['swiftmailer.spooltransport'] = $app->share(function ($app) {
$app['swiftmailer.spooltransport'] = function ($app) {
return new \Swift_SpoolTransport($app['swiftmailer.spool']);
});
};
$app['swiftmailer.spool'] = $app->share(function ($app) {
$app['swiftmailer.spool'] = function ($app) {
return new \Swift_MemorySpool();
});
};
$app['swiftmailer.transport'] = $app->share(function ($app) {
$app['swiftmailer.transport'] = function ($app) {
$transport = new \Swift_Transport_EsmtpTransport(
$app['swiftmailer.transport.buffer'],
array($app['swiftmailer.transport.authhandler']),
......@@ -65,28 +69,28 @@ class SwiftmailerServiceProvider implements ServiceProviderInterface
$transport->setAuthMode($options['auth_mode']);
return $transport;
});
};
$app['swiftmailer.transport.buffer'] = $app->share(function () {
$app['swiftmailer.transport.buffer'] = function () {
return new \Swift_Transport_StreamBuffer(new \Swift_StreamFilters_StringReplacementFilterFactory());
});
};
$app['swiftmailer.transport.authhandler'] = $app->share(function () {
$app['swiftmailer.transport.authhandler'] = function () {
return new \Swift_Transport_Esmtp_AuthHandler(array(
new \Swift_Transport_Esmtp_Auth_CramMd5Authenticator(),
new \Swift_Transport_Esmtp_Auth_LoginAuthenticator(),
new \Swift_Transport_Esmtp_Auth_PlainAuthenticator(),
));
});
};
$app['swiftmailer.transport.eventdispatcher'] = $app->share(function () {
$app['swiftmailer.transport.eventdispatcher'] = function () {
return new \Swift_Events_SimpleEventDispatcher();
});
};
}
public function boot(Application $app)
public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
{
$app->finish(function () use ($app) {
$dispatcher->addListener(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($app) {
// To speed things up (by avoiding Swift Mailer initialization), flush
// messages only if our mailer has been created (potentially used)
if ($app['mailer.initialized']) {
......
......@@ -9,13 +9,14 @@
* file that was distributed with this source code.
*/
namespace Silex;
namespace Silex\Provider\Translation;
use Pimple\Container;
use Symfony\Component\Translation\Translator as BaseTranslator;
use Symfony\Component\Translation\MessageSelector;
/**
* Translator that gets the current locale from the Silex application.
* Translator that gets the current locale from the container.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
......@@ -23,7 +24,7 @@ class Translator extends BaseTranslator
{
protected $app;
public function __construct(Application $app, MessageSelector $selector)
public function __construct(Container $app, MessageSelector $selector)
{
$this->app = $app;
......
......@@ -11,9 +11,9 @@
namespace Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Silex\Translator;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Provider\Translation\Translator;
use Symfony\Component\Translation\MessageSelector;
use Symfony\Component\Translation\Loader\ArrayLoader;
use Symfony\Component\Translation\Loader\XliffFileLoader;
......@@ -25,18 +25,15 @@ use Symfony\Component\Translation\Loader\XliffFileLoader;
*/
class TranslationServiceProvider implements ServiceProviderInterface
{
public function register(Application $app)
public function register(Container $app)
{
$app['translator'] = $app->share(function ($app) {
$translator = new Translator($app, $app['translator.message_selector']);
// Handle deprecated 'locale_fallback'
if (isset($app['locale_fallback'])) {
$app['locale_fallbacks'] = (array) $app['locale_fallback'];
$app['translator'] = function ($app) {
if (!isset($app['locale'])) {
throw new \LogicException('You must register the LocaleServiceProvider to use the TranslationServiceProvider');
}
$translator = new Translator($app, $app['translator.message_selector']);
$translator->setFallbackLocales($app['locale_fallbacks']);
$translator->addLoader('array', new ArrayLoader());
$translator->addLoader('xliff', new XliffFileLoader());
......@@ -47,17 +44,13 @@ class TranslationServiceProvider implements ServiceProviderInterface
}
return $translator;
});
};
$app['translator.message_selector'] = $app->share(function () {
$app['translator.message_selector'] = function () {
return new MessageSelector();
});
};
$app['translator.domains'] = array();
$app['locale_fallbacks'] = array('en');
}
public function boot(Application $app)
{
}
}
<?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\Provider;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Twig extension.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated deprecated since 1.2, will be removed in 1.3. Use HttpFragmentServiceProvider instead
*/
class TwigCoreExtension extends \Twig_Extension
{
public function getFunctions()
{
return array(
'render' => new \Twig_Function_Method($this, 'render', array('needs_environment' => true, 'is_safe' => array('html'))),
);
}
public function render(\Twig_Environment $twig, $uri)
{
$globals = $twig->getGlobals();
$request = $globals['app']['request'];
$subRequest = Request::create($uri, 'get', array(), $request->cookies->all(), array(), $request->server->all());
if ($request->getSession()) {
$subRequest->setSession($request->getSession());
}
$response = $globals['app']->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
if (!$response->isSuccessful()) {
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $request->getUri(), $response->getStatusCode()));
}
return $response->getContent();
}
public function getName()
{
return 'silex';
}
}
......@@ -11,8 +11,8 @@
namespace Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Symfony\Bridge\Twig\Extension\RoutingExtension;
use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Bridge\Twig\Extension\FormExtension;
......@@ -28,26 +28,26 @@ use Symfony\Bridge\Twig\Form\TwigRenderer;
*/
class TwigServiceProvider implements ServiceProviderInterface
{
public function register(Application $app)
public function register(Container $app)
{
$app['twig.options'] = array();
$app['twig.form.templates'] = array('form_div_layout.html.twig');
$app['twig.path'] = array();
$app['twig.templates'] = array();
$app['twig'] = $app->share(function ($app) {
$app['twig'] = function ($app) {
$app['twig.options'] = array_replace(
array(
'charset' => $app['charset'],
'debug' => $app['debug'],
'strict_variables' => $app['debug'],
'charset' => isset($app['charset']) ? $app['charset'] : 'UTF-8',
'debug' => isset($app['debug']) ? $app['debug'] : false,
'strict_variables' => isset($app['debug']) ? $app['debug'] : false,
), $app['twig.options']
);
$twig = new \Twig_Environment($app['twig.loader'], $app['twig.options']);
$twig->addGlobal('app', $app);
if ($app['debug']) {
if (isset($app['debug']) && $app['debug']) {
$twig->addExtension(new \Twig_Extension_Debug());
}
......@@ -68,19 +68,16 @@ class TwigServiceProvider implements ServiceProviderInterface
$app['fragment.renderer.hinclude']->setTemplating($twig);
$twig->addExtension(new HttpKernelExtension($app['fragment.handler']));
} else {
// fallback for BC, to be removed in 1.3
$twig->addExtension(new TwigCoreExtension());
}
if (isset($app['form.factory'])) {
$app['twig.form.engine'] = $app->share(function ($app) {
$app['twig.form.engine'] = function ($app) {
return new TwigRendererEngine($app['twig.form.templates']);
});
};
$app['twig.form.renderer'] = $app->share(function ($app) {
$app['twig.form.renderer'] = function ($app) {
return new TwigRenderer($app['twig.form.engine'], $app['form.csrf_provider']);
});
};
$twig->addExtension(new FormExtension($app['twig.form.renderer']));
......@@ -92,25 +89,21 @@ class TwigServiceProvider implements ServiceProviderInterface
}
return $twig;
});
};
$app['twig.loader.filesystem'] = $app->share(function ($app) {
$app['twig.loader.filesystem'] = function ($app) {
return new \Twig_Loader_Filesystem($app['twig.path']);
});
};
$app['twig.loader.array'] = $app->share(function ($app) {
$app['twig.loader.array'] = function ($app) {
return new \Twig_Loader_Array($app['twig.templates']);
});
};
$app['twig.loader'] = $app->share(function ($app) {
$app['twig.loader'] = function ($app) {
return new \Twig_Loader_Chain(array(
$app['twig.loader.array'],
$app['twig.loader.filesystem'],
));
});
}
public function boot(Application $app)
{
};
}
}
......@@ -9,8 +9,9 @@
* file that was distributed with this source code.
*/
namespace Silex;
namespace Silex\Provider\Validator;
use Pimple\Container;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
use Symfony\Component\Validator\ConstraintValidator;
......@@ -24,7 +25,7 @@ use Symfony\Component\Validator\ConstraintValidator;
class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
{
/**
* @var \Pimple
* @var Container
*/
protected $container;
......@@ -41,10 +42,10 @@ class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
/**
* Constructor
*
* @param \Pimple $container DI container
* @param array $serviceNames Validator service names
* @param Container $container DI container
* @param array $serviceNames Validator service names
*/
public function __construct(\Pimple $container, array $serviceNames = array())
public function __construct(Container $container, array $serviceNames = array())
{
$this->container = $container;
$this->serviceNames = $serviceNames;
......
......@@ -11,9 +11,9 @@
namespace Silex\Provider;
use Silex\Application;
use Silex\ServiceProviderInterface;
use Silex\ConstraintValidatorFactory;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Silex\Provider\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
......@@ -26,9 +26,9 @@ use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
*/
class ValidatorServiceProvider implements ServiceProviderInterface
{
public function register(Application $app)
public function register(Container $app)
{
$app['validator'] = $app->share(function ($app) {
$app['validator'] = function ($app) {
$r = new \ReflectionClass('Symfony\Component\Validator\Validator');
if (isset($app['translator'])) {
......@@ -42,24 +42,20 @@ class ValidatorServiceProvider implements ServiceProviderInterface
'validators',
$app['validator.object_initializers']
);
});
};
$app['validator.mapping.class_metadata_factory'] = $app->share(function ($app) {
$app['validator.mapping.class_metadata_factory'] = function ($app) {
return new ClassMetadataFactory(new StaticMethodLoader());
});
};
$app['validator.validator_factory'] = $app->share(function () use ($app) {
$app['validator.validator_factory'] = function () use ($app) {
$validators = isset($app['validator.validator_service_ids']) ? $app['validator.validator_service_ids'] : array();
return new ConstraintValidatorFactory($app, $validators);
});
};
$app['validator.object_initializers'] = $app->share(function ($app) {
$app['validator.object_initializers'] = function ($app) {
return array();
});
}
public function boot(Application $app)
{
};
}
}
{
"minimum-stability": "dev",
"name": "silex/providers",
"description": "The Silex providers",
"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.3.3",
"pimple/pimple": "~1.0",
"silex/api": "*"
},
"autoload": {
"psr-0": { "Silex\\Provider": "" }
},
"target-dir": "Silex/Provider",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
}
}
<?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\Util;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Process\Process;
/**
* The Compiler class compiles the Silex framework.
*
* This is deprecated. Use composer instead.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Compiler
{
protected $version;
/**
* Compiles the Silex source code into one single Phar file.
*
* @param string $pharFile Name of the output Phar file
*/
public function compile($pharFile = 'silex.phar')
{
if (file_exists($pharFile)) {
unlink($pharFile);
}
$process = new Process('git log --pretty="%h %ci" -n1 HEAD');
if ($process->run() > 0) {
throw new \RuntimeException('The git binary cannot be found.');
}
$this->version = trim($process->getOutput());
$phar = new \Phar($pharFile, 0, 'silex.phar');
$phar->setSignatureAlgorithm(\Phar::SHA1);
$phar->startBuffering();
$root = __DIR__.'/../../..';
$finder = new Finder();
$finder->files()
->ignoreVCS(true)
->name('*.php')
->notName('Compiler.php')
->exclude('Tests')
->in($root.'/src')
->in($root.'/vendor/pimple/pimple/lib')
->in($root.'/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher')
->in($root.'/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation')
->in($root.'/vendor/symfony/http-kernel/Symfony/Component/HttpKernel')
->in($root.'/vendor/symfony/routing/Symfony/Component/Routing')
->in($root.'/vendor/symfony/browser-kit/Symfony/Component/BrowserKit')
->in($root.'/vendor/symfony/css-selector/Symfony/Component/CssSelector')
->in($root.'/vendor/symfony/dom-crawler/Symfony/Component/DomCrawler')
;
foreach ($finder as $file) {
$this->addFile($phar, $file);
}
$this->addFile($phar, new \SplFileInfo($root.'/LICENSE'), false);
$this->addFile($phar, new \SplFileInfo($root.'/vendor/autoload.php'));
$this->addFile($phar, new \SplFileInfo($root.'/vendor/composer/ClassLoader.php'));
$this->addFile($phar, new \SplFileInfo($root.'/vendor/composer/autoload_namespaces.php'));
$this->addFile($phar, new \SplFileInfo($root.'/vendor/composer/autoload_classmap.php'));
// Stubs
$phar->setStub($this->getStub());
$phar->stopBuffering();
unset($phar);
}
protected function addFile(\Phar $phar, \SplFileInfo $file, $strip = true)
{
$path = str_replace(dirname(dirname(dirname(__DIR__))).DIRECTORY_SEPARATOR, '', $file->getRealPath());
$content = file_get_contents($file);
if ($strip) {
$content = self::stripWhitespace($content);
}
$content = preg_replace("/const VERSION = '.*?';/", "const VERSION = '".$this->version."';", $content);
$phar->addFromString($path, $content);
}
protected function getStub()
{
return <<<'EOF'
<?php
/*
* This file is part of the Silex framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
Phar::mapPhar('silex.phar');
require_once 'phar://silex.phar/vendor/autoload.php';
if ('cli' === php_sapi_name() && basename(__FILE__) === basename($_SERVER['argv'][0]) && isset($_SERVER['argv'][1])) {
switch ($_SERVER['argv'][1]) {
case 'update':
$remoteFilename = 'http://silex.sensiolabs.org/get/silex.phar';
$localFilename = __DIR__.'/silex.phar';
file_put_contents($localFilename, file_get_contents($remoteFilename));
break;
case 'check':
$latest = trim(file_get_contents('http://silex.sensiolabs.org/get/version'));
if ($latest != Silex\Application::VERSION) {
printf("A newer Silex version is available (%s).\n", $latest);
} else {
print("You are using the latest Silex version.\n");
}
break;
case 'version':
printf("Silex version %s\n", Silex\Application::VERSION);
break;
default:
printf("Unknown command '%s' (available commands: version, check, and update).\n", $_SERVER['argv'][1]);
}
exit(0);
}
__HALT_COMPILER();
EOF;
}
/**
* Removes whitespace from a PHP source string while preserving line numbers.
*
* Based on Kernel::stripComments(), but keeps line numbers intact.
*
* @param string $source A PHP string
*
* @return string The PHP string with the whitespace removed
*/
public static function stripWhitespace($source)
{
if (!function_exists('token_get_all')) {
return $source;
}
$output = '';
foreach (token_get_all($source) as $token) {
if (is_string($token)) {
$output .= $token;
} elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
$output .= str_repeat("\n", substr_count($token[1], "\n"));
} elseif (T_WHITESPACE === $token[0]) {
// reduce wide spaces
$whitespace = preg_replace('{[ \t]+}', ' ', $token[1]);
// normalize newlines to \n
$whitespace = preg_replace('{(?:\r\n|\r|\n)}', "\n", $whitespace);
// trim leading spaces
$whitespace = preg_replace('{\n +}', "\n", $whitespace);
$output .= $whitespace;
} else {
$output .= $token[1];
}
}
return $output;
}
}
......@@ -39,9 +39,9 @@ class MonologTraitTest extends \PHPUnit_Framework_TestCase
{
$app = new MonologApplication();
$app->register(new MonologServiceProvider(), array(
'monolog.handler' => $app->share(function () use ($app) {
'monolog.handler' => function () use ($app) {
return new TestHandler($app['monolog.level']);
}),
},
));
return $app;
......
......@@ -12,7 +12,7 @@
namespace Silex\Tests\Application;
use Silex\Application;
use Silex\Provider\UrlGeneratorServiceProvider;
use Silex\Provider\RoutingServiceProvider;
/**
* UrlGeneratorTrait test cases.
......@@ -25,7 +25,7 @@ class UrlGeneratorTraitTest extends \PHPUnit_Framework_TestCase
{
public function testUrl()
{
$app = $this->createApplication();
$app = new UrlGeneratorApplication();
$app['url_generator'] = $translator = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface')->disableOriginalConstructor()->getMock();
$translator->expects($this->once())->method('generate')->with('foo', array(), true);
$app->url('foo');
......@@ -33,17 +33,9 @@ class UrlGeneratorTraitTest extends \PHPUnit_Framework_TestCase
public function testPath()
{
$app = $this->createApplication();
$app = new UrlGeneratorApplication();
$app['url_generator'] = $translator = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface')->disableOriginalConstructor()->getMock();
$translator->expects($this->once())->method('generate')->with('foo', array(), false);
$app->path('foo');
}
public function createApplication()
{
$app = new UrlGeneratorApplication();
$app->register(new UrlGeneratorServiceProvider());
return $app;
}
}
......@@ -416,30 +416,6 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
$app->handle(Request::create('/'), HttpKernelInterface::MASTER_REQUEST, false);
}
/**
* @expectedException \RuntimeException
*/
public function testAccessingRequestOutsideOfScopeShouldThrowRuntimeException()
{
$app = new Application();
$request = $app['request'];
}
/**
* @expectedException \RuntimeException
*/
public function testAccessingRequestOutsideOfScopeShouldThrowRuntimeExceptionAfterHandling()
{
$app = new Application();
$app->get('/', function () {
return 'hello';
});
$app->handle(Request::create('/'), HttpKernelInterface::MASTER_REQUEST, false);
$request = $app['request'];
}
public function testSubRequest()
{
$app = new Application();
......@@ -453,31 +429,10 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('foo', $app->handle(Request::create('/'))->getContent());
}
public function testSubRequestDoesNotReplaceMainRequestAfterHandling()
{
$mainRequest = Request::create('/');
$subRequest = Request::create('/sub');
$app = new Application();
$app->get('/sub', function (Request $request) {
return new Response('foo');
});
$app->get('/', function (Request $request) use ($subRequest, $app) {
$response = $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
// request in app must be the main request here
$response->setContent($response->getContent().' '.$app['request']->getPathInfo());
return $response;
});
$this->assertEquals('foo /', $app->handle($mainRequest)->getContent());
}
public function testRegisterShouldReturnSelf()
{
$app = new Application();
$provider = $this->getMock('Silex\ServiceProviderInterface');
$provider = $this->getMock('Pimple\ServiceProviderInterface');
$this->assertSame($app, $app->register($provider));
}
......@@ -542,6 +497,18 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
$response = $app->handle(Request::create('/foo'));
$this->assertEquals(301, $response->getStatusCode());
}
public function testBeforeFilterOnMountedControllerGroupIsolatedToGroup()
{
$app = new Application();
$app->match('/', function() { return new Response('ok'); });
$mounted = $app['controllers_factory'];
$mounted->before(function() { return new Response('not ok'); });
$app->mount('/group', $mounted);
$response = $app->handle(Request::create('/'));
$this->assertEquals('ok', $response->getContent());
}
}
class FooController
......
......@@ -11,13 +11,14 @@
namespace Silex\Tests;
use Pimple\Container;
use Silex\CallbackResolver;
class CallbackResolverTest extends \PHPUnit_Framework_Testcase
{
public function setup()
{
$this->app = new \Pimple();
$this->app = new Container();
$this->resolver = new CallbackResolver($this->app);
}
......
......@@ -28,9 +28,9 @@ class CallbackServicesTest extends \PHPUnit_Framework_TestCase
{
$app = new Application();
$app['service'] = $app->share(function () {
$app['service'] = function () {
return new self();
});
};
$app->before('service:beforeApp');
$app->after('service:afterApp');
......
......@@ -22,11 +22,11 @@ class LazyDispatcherTest extends \PHPUnit_Framework_TestCase
$dispatcherCreated = false;
$app = new Application();
$app['dispatcher'] = $app->share($app->extend('dispatcher', function ($dispatcher, $app) use (&$dispatcherCreated) {
$app->extend('dispatcher', function ($dispatcher, $app) use (&$dispatcherCreated) {
$dispatcherCreated = true;
return $dispatcher;
}));
});
$app->before(function () {});
......
......@@ -11,7 +11,7 @@
namespace Silex\Tests;
use Silex\LazyUrlMatcher;
use Silex\Provider\Routing\LazyUrlMatcher;
/**
* LazyUrlMatcher test case.
......
......@@ -12,6 +12,7 @@
namespace Silex\Tests;
use Silex\Application;
use Silex\Provider\LocaleServiceProvider;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
......@@ -25,17 +26,20 @@ class LocaleTest extends \PHPUnit_Framework_TestCase
public function testLocale()
{
$app = new Application();
$app->register(new LocaleServiceProvider());
$app->get('/', function (Request $request) { return $request->getLocale(); });
$response = $app->handle(Request::create('/'));
$this->assertEquals('en', $response->getContent());
$app = new Application();
$app->register(new LocaleServiceProvider());
$app['locale'] = 'fr';
$app->get('/', function (Request $request) { return $request->getLocale(); });
$response = $app->handle(Request::create('/'));
$this->assertEquals('fr', $response->getContent());
$app = new Application();
$app->register(new LocaleServiceProvider());
$app->get('/{_locale}', function (Request $request) { return $request->getLocale(); });
$response = $app->handle(Request::create('/es'));
$this->assertEquals('es', $response->getContent());
......@@ -44,6 +48,7 @@ class LocaleTest extends \PHPUnit_Framework_TestCase
public function testLocaleInSubRequests()
{
$app = new Application();
$app->register(new LocaleServiceProvider());
$app->get('/embed/{_locale}', function (Request $request) { return $request->getLocale(); });
$app->get('/{_locale}', function (Request $request) use ($app) {
return $request->getLocale().$app->handle(Request::create('/embed/es'), HttpKernelInterface::SUB_REQUEST)->getContent().$request->getLocale();
......@@ -52,6 +57,7 @@ class LocaleTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('fresfr', $response->getContent());
$app = new Application();
$app->register(new LocaleServiceProvider());
$app->get('/embed', function (Request $request) { return $request->getLocale(); });
$app->get('/{_locale}', function (Request $request) use ($app) {
return $request->getLocale().$app->handle(Request::create('/embed'), HttpKernelInterface::SUB_REQUEST)->getContent().$request->getLocale();
......@@ -64,6 +70,7 @@ class LocaleTest extends \PHPUnit_Framework_TestCase
public function testLocaleWithBefore()
{
$app = new Application();
$app->register(new LocaleServiceProvider());
$app->before(function (Request $request) use ($app) { $request->setLocale('fr'); });
$app->get('/embed', function (Request $request) { return $request->getLocale(); });
$app->get('/', function (Request $request) use ($app) {
......
......@@ -191,8 +191,8 @@ class MiddlewareTest extends \PHPUnit_Framework_TestCase
{
$app = new Application();
$app->before(function () use ($app) {
$app['project'] = $app['request']->get('project');
$app->before(function (Request $request) use ($app) {
$app['project'] = $request->get('project');
});
$app->match('/foo/{project}', function () use ($app) {
......
......@@ -35,11 +35,11 @@ class FormServiceProviderTest extends \PHPUnit_Framework_TestCase
$app->register(new FormServiceProvider());
$app['form.type.extensions'] = $app->share($app->extend('form.type.extensions', function($extensions) {
$app->extend('form.type.extensions', function($extensions) {
$extensions[] = new DummyFormTypeExtension();
return $extensions;
}));
});
$form = $app['form.factory']->createBuilder('form', array())
->add('file', 'file', array('image_path' => 'webPath'))
......@@ -54,11 +54,11 @@ class FormServiceProviderTest extends \PHPUnit_Framework_TestCase
$app->register(new FormServiceProvider());
$app['form.type.guessers'] = $app->share($app->extend('form.type.guessers', function($guessers) {
$app->extend('form.type.guessers', function($guessers) {
$guessers[] = new FormTypeGuesserChain(array());
return $guessers;
}));
});
$this->assertInstanceOf('Symfony\Component\Form\FormFactory', $app['form.factory']);
}
......@@ -78,9 +78,9 @@ class FormServiceProviderTest extends \PHPUnit_Framework_TestCase
);
$app['locale'] = 'de';
$app['form.csrf_provider'] = $app->share(function () {
$app['form.csrf_provider'] = function () {
return new FakeCsrfProvider();
});
};
$form = $app['form.factory']->createBuilder('form', array())
->getForm();
......
......@@ -31,7 +31,7 @@ class HttpCacheServiceProviderTest extends \PHPUnit_Framework_TestCase
'http_cache.cache_dir' => sys_get_temp_dir().'/silex_http_cache_'.uniqid(),
));
$this->assertInstanceOf('Silex\HttpCache', $app['http_cache']);
$this->assertInstanceOf('Silex\Provider\HttpCache\HttpCache', $app['http_cache']);
return $app;
}
......
......@@ -185,11 +185,11 @@ class MonologServiceProviderTest extends \PHPUnit_Framework_TestCase
$app->register(new MonologServiceProvider());
$app['monolog.handler'] = $app->share(function () use ($app) {
$app['monolog.handler'] = function () use ($app) {
$level = MonologServiceProvider::translateLevel($app['monolog.level']);
return new TestHandler($level);
});
};
return $app;
}
......
......@@ -12,22 +12,20 @@
namespace Silex\Tests\Provider;
use Silex\Application;
use Silex\Provider\UrlGeneratorServiceProvider;
use Silex\Provider\RoutingServiceProvider;
use Symfony\Component\HttpFoundation\Request;
/**
* UrlGeneratorProvider test cases.
* RoutingProvider test cases.
*
* @author Igor Wiedler <igor@wiedler.ch>
*/
class UrlGeneratorServiceProviderTest extends \PHPUnit_Framework_TestCase
class RoutingServiceProviderTest extends \PHPUnit_Framework_TestCase
{
public function testRegister()
{
$app = new Application();
$app->register(new UrlGeneratorServiceProvider());
$app->get('/hello/{name}', function ($name) {})
->bind('hello');
......@@ -43,8 +41,6 @@ class UrlGeneratorServiceProviderTest extends \PHPUnit_Framework_TestCase
{
$app = new Application();
$app->register(new UrlGeneratorServiceProvider());
$app->get('/hello/{name}', function ($name) {})
->bind('hello');
......@@ -62,8 +58,6 @@ class UrlGeneratorServiceProviderTest extends \PHPUnit_Framework_TestCase
{
$app = new Application();
$app->register(new UrlGeneratorServiceProvider());
$app->get('/hello/{name}', function ($name) {})
->bind('hello');
......@@ -81,8 +75,6 @@ class UrlGeneratorServiceProviderTest extends \PHPUnit_Framework_TestCase
{
$app = new Application();
$app->register(new UrlGeneratorServiceProvider());
$app->get('/insecure', function () {})
->bind('insecure_page')
->requireHttp();
......@@ -101,8 +93,6 @@ class UrlGeneratorServiceProviderTest extends \PHPUnit_Framework_TestCase
{
$app = new Application();
$app->register(new UrlGeneratorServiceProvider());
$app->get('/secure', function () {})
->bind('secure_page')
->requireHttps();
......
......@@ -200,7 +200,9 @@ class SecurityServiceProviderTest extends WebTestCase
'default' => array(
'pattern' => '^.*$',
'anonymous' => true,
'form' => true,
'form' => array(
'require_previous_session' => false,
),
'logout' => true,
'users' => array(
// password is foo
......
......@@ -34,9 +34,9 @@ class SwiftmailerServiceProviderTest extends \PHPUnit_Framework_TestCase
$app->register(new SwiftmailerServiceProvider());
$app->boot();
$app['swiftmailer.spool'] = $app->share(function () {
$app['swiftmailer.spool'] = function () {
return new SpoolStub();
});
};
$app->get('/', function() use ($app) {
$app['mailer']->send(\Swift_Message::newInstance());
......@@ -60,9 +60,9 @@ class SwiftmailerServiceProviderTest extends \PHPUnit_Framework_TestCase
$app->register(new SwiftmailerServiceProvider());
$app->boot();
$app['swiftmailer.spool'] = $app->share(function () {
$app['swiftmailer.spool'] = function () {
return new SpoolStub();
});
};
$app->get('/', function() use ($app) { });
......
......@@ -13,6 +13,7 @@ namespace Silex\Tests\Provider;
use Silex\Application;
use Silex\Provider\TranslationServiceProvider;
use Silex\Provider\LocaleServiceProvider;
/**
* TranslationProvider test cases.
......@@ -28,6 +29,7 @@ class TranslationServiceProviderTest extends \PHPUnit_Framework_TestCase
{
$app = new Application();
$app->register(new LocaleServiceProvider());
$app->register(new TranslationServiceProvider());
$app['translator.domains'] = array(
'messages' => array(
......@@ -102,15 +104,6 @@ class TranslationServiceProviderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($expected, $result);
}
public function testBackwardCompatiblityForFallback()
{
$app = $this->getPreparedApp();
$app['locale_fallback'] = 'de';
$result = $app['translator']->trans('key1', array(), null, 'ru');
$this->assertEquals('The german translation', $result);
}
public function testFallbacks()
{
$app = $this->getPreparedApp();
......
......@@ -27,7 +27,7 @@ class TwigServiceProviderTest extends \PHPUnit_Framework_TestCase
$app = new Application();
$app->register(new TwigServiceProvider(), array(
'twig.templates' => array('hello' => 'Hello {{ name }}!'),
'twig.templates' => array('hello' => 'Hello {{ name }}!'),
));
$app->get('/hello/{name}', function ($name) use ($app) {
......@@ -39,30 +39,6 @@ class TwigServiceProviderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('Hello john!', $response->getContent());
}
public function testRenderFunction()
{
$app = new Application();
$app->register(new TwigServiceProvider(), array(
'twig.templates' => array(
'hello' => '{{ render("/foo") }}',
'foo' => 'foo',
),
));
$app->get('/hello', function () use ($app) {
return $app['twig']->render('hello');
});
$app->get('/foo', function () use ($app) {
return $app['twig']->render('foo');
});
$request = Request::create('/hello');
$response = $app->handle($request);
$this->assertEquals('foo', $response->getContent());
}
public function testLoaderPriority()
{
$app = new Application();
......@@ -71,9 +47,9 @@ class TwigServiceProviderTest extends \PHPUnit_Framework_TestCase
));
$loader = $this->getMock('\Twig_LoaderInterface');
$loader->expects($this->never())->method('getSource');
$app['twig.loader.filesystem'] = $app->share(function ($app) use ($loader) {
$app['twig.loader.filesystem'] = function ($app) use ($loader) {
return $loader;
});
};
$this->assertEquals('foo', $app['twig.loader']->getSource('foo'));
}
}
......@@ -28,8 +28,8 @@ class ValidatorServiceProviderTest extends \PHPUnit_Framework_TestCase
public function testRegister()
{
$app = new Application();
$app->register(new ValidatorServiceProvider());
$app->register(new FormServiceProvider());
return $app;
}
......@@ -38,9 +38,9 @@ class ValidatorServiceProviderTest extends \PHPUnit_Framework_TestCase
{
$app = new Application();
$app['custom.validator'] = $app->share(function() {
$app['custom.validator'] = function() {
return new CustomValidator();
});
};
$app->register(new ValidatorServiceProvider(), array(
'validator.validator_service_ids' => array(
......@@ -56,7 +56,7 @@ class ValidatorServiceProviderTest extends \PHPUnit_Framework_TestCase
*/
public function testConstraintValidatorFactory($app)
{
$this->assertInstanceOf('Silex\ConstraintValidatorFactory', $app['validator.validator_factory']);
$this->assertInstanceOf('Silex\Provider\Validator\ConstraintValidatorFactory', $app['validator.validator_factory']);
$validator = $app['validator.validator_factory']->getInstance(new Custom());
$this->assertInstanceOf('Silex\Tests\Provider\ValidatorServiceProviderTest\Constraint\CustomValidator', $validator);
......@@ -76,9 +76,6 @@ class ValidatorServiceProviderTest extends \PHPUnit_Framework_TestCase
*/
public function testValidatorConstraint($email, $isValid, $nbGlobalError, $nbEmailError, $app)
{
$app->register(new ValidatorServiceProvider());
$app->register(new FormServiceProvider());
$constraints = new Assert\Collection(array(
'email' => array(
new Assert\NotBlank(),
......
......@@ -152,12 +152,12 @@ class RouterTest extends \PHPUnit_Framework_TestCase
{
$app = new Application();
$app->get('/foo', function () use ($app) {
return new Response($app['request']->getRequestUri());
$app->get('/foo', function (Request $request) use ($app) {
return new Response($request->getRequestUri());
});
$app->error(function ($e) use ($app) {
return new Response($app['request']->getRequestUri());
$app->error(function ($e, Request $request, $code) use ($app) {
return new Response($request->getRequestUri());
});
foreach (array('/foo', '/bar') as $path) {
......
......@@ -23,6 +23,7 @@ class ServiceControllerResolverRouterTest extends RouterTest
public function testServiceNameControllerSyntax()
{
$app = new Application();
$app->register(new ServiceControllerServiceProvider());
$app['service_name'] = function () {
return new MyController();
......@@ -35,8 +36,6 @@ class ServiceControllerResolverRouterTest extends RouterTest
protected function checkRouteResponse(Application $app, $path, $expectedContent, $method = 'get', $message = null)
{
$app->register(new ServiceControllerServiceProvider());
$request = Request::create($path, $method);
$response = $app->handle($request);
$this->assertEquals($expectedContent, $response->getContent(), $message);
......
......@@ -13,6 +13,7 @@ namespace Silex\Tests;
use Silex\Application;
use Silex\WebTestCase;
use Symfony\Component\HttpFoundation\Request;
/**
* Functional test cases.
......@@ -33,9 +34,9 @@ class WebTestCaseTest extends WebTestCase
return '<h1>title</h1>';
});
$app->match('/server', function () use ($app) {
$user = $app['request']->server->get('PHP_AUTH_USER');
$pass = $app['request']->server->get('PHP_AUTH_PW');
$app->match('/server', function (Request $request) use ($app) {
$user = $request->server->get('PHP_AUTH_USER');
$pass = $request->server->get('PHP_AUTH_PW');
return "<h1>$user:$pass</h1>";
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment