Skip to content

Commit

Permalink
Merge branch '2.8' into 3.0
Browse files Browse the repository at this point in the history
Conflicts:
	cookbook/form/unit_testing.rst
  • Loading branch information
wouterj committed Feb 6, 2016
2 parents e901fbc + b56880b commit 16cc4bc
Show file tree
Hide file tree
Showing 44 changed files with 476 additions and 173 deletions.
5 changes: 3 additions & 2 deletions best_practices/tests.rst
Expand Up @@ -113,12 +113,13 @@ pure JavaScript-based testing tools.
Learn More about Functional Tests
---------------------------------

Consider using `Faker`_ and `Alice`_ libraries to generate real-looking data
for your test fixtures.
Consider using the `HautelookAliceBundle`_ to generate real-looking data for
your test fixtures using `Faker`_ and `Alice`_.

.. _`Faker`: https://github.com/fzaninotto/Faker
.. _`Alice`: https://github.com/nelmio/alice
.. _`PhpUnit`: https://phpunit.de/
.. _`PhpSpec`: http://www.phpspec.net/
.. _`Mink`: http://mink.behat.org
.. _`smoke testing`: https://en.wikipedia.org/wiki/Smoke_testing_(software)
.. _`HautelookAliceBundle`: https://github.com/hautelook/AliceBundle
2 changes: 1 addition & 1 deletion book/security.rst
Expand Up @@ -511,7 +511,7 @@ else, you'll want to encode their passwords. The best algorithm to use is
));
Of course, your users' passwords now need to be encoded with this exact algorithm.
For hardcoded users, since 2.7 you can use the built-in command :
For hardcoded users, since 2.7 you can use the built-in command:

.. code-block:: bash
Expand Down
112 changes: 78 additions & 34 deletions components/dependency_injection/compilation.rst
Expand Up @@ -306,46 +306,94 @@ For more details, see :doc:`/cookbook/bundles/prepend_extension`, which
is specific to the Symfony Framework, but contains more details about this
feature.

Creating a Compiler Pass
------------------------
.. _creating-a-compiler-pass:
.. _components-di-compiler-pass:

You can also create and register your own compiler passes with the container.
To create a compiler pass it needs to implement the
:class:`Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface`
interface. The compiler pass gives you an opportunity to manipulate the
service definitions that have been compiled. This can be very powerful,
but is not something needed in everyday use.
Execute Code During Compilation
-------------------------------

The compiler pass must have the ``process`` method which is passed the container
being compiled::
You can also execute custom code during compilation by writing your own
compiler pass. By implementing
:class:`Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface`
in your extension, the added ``process()`` method will be called during
compilation::

// ...
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class CustomCompilerPass implements CompilerPassInterface
class AcmeDemoExtension implements ExtensionInterface, CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
// ...
// ... do something during the compilation
}

// ...
}

.. versionadded:: 2.8
Prior to Symfony 2.8, extensions implementing ``CompilerPassInterface``
were not automatically registered. You needed to register them as explained
in :ref:`the next section <components-di-separate-compiler-passes>`.

As ``process()`` is called *after* all extensions are loaded, it allows you to
edit service definitions of other extensions as well as retrieving information
about service definitions.

The container's parameters and definitions can be manipulated using the
methods described in the :doc:`/components/dependency_injection/definitions`.
One common thing to do in a compiler pass is to search for all services
that have a certain tag in order to process them in some way or dynamically
plug each into some other service.
methods described in :doc:`/components/dependency_injection/definitions`.

.. note::

Please note that the ``process()`` method in the extension class is
called during the optimization step. You can read
:ref:`the next section <components-di-separate-compiler-passes>` if you
need to edit the container during another step.

.. note::

As a rule, only work with services definition in a compiler pass and do not
create service instances. In practice, this means using the methods
``has()``, ``findDefinition()``, ``getDefinition()``, ``setDefinition()``,
etc. instead of ``get()``, ``set()``, etc.

.. tip::

Make sure your compiler pass does not require services to exist. Abort the
method call if some required service is not available.

Registering a Compiler Pass
---------------------------
A common use-case of compiler passes is to search for all service definitions
that have a certain tag in order to process dynamically plug each into some
other service. See the section on :ref:`service tags <components-di-compiler-pass-tags>`
for an example.

You need to register your custom pass with the container. Its process method
will then be called when the container is compiled::
.. _components-di-separate-compiler-passes:

Creating Separate Compiler Passes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sometimes, you need to do more than one thing during compliation, want to use
compiler passes without an extension or you need to execute some code at
another step in the compilation process. In these cases, you can create a new
class implementing the ``CompilerPassInterface``::

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class CustomPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
// ... do something during the compilation
}
}

You then need to register your custom pass with the container::

use Symfony\Component\DependencyInjection\ContainerBuilder;

$container = new ContainerBuilder();
$container->addCompilerPass(new CustomCompilerPass);
$container->addCompilerPass(new CustomPass());

.. note::

Expand All @@ -354,17 +402,16 @@ will then be called when the container is compiled::
more details.

Controlling the Pass Ordering
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.............................

The default compiler passes are grouped into optimization passes and removal
passes. The optimization passes run first and include tasks such as resolving
references within the definitions. The removal passes perform tasks such
as removing private aliases and unused services. You can choose where in
the order any custom passes you add are run. By default they will be run
before the optimization passes.
as removing private aliases and unused services. When registering compiler
passes using ``addCompilerPass()``, you can configure when your compiler pass
is run. By default, they are run before the optimization passes.

You can use the following constants as the second argument when registering
a pass with the container to control where it goes in the order:
You can use the following constants to determine when your pass is executed:

* ``PassConfig::TYPE_BEFORE_OPTIMIZATION``
* ``PassConfig::TYPE_OPTIMIZE``
Expand All @@ -373,14 +420,11 @@ a pass with the container to control where it goes in the order:
* ``PassConfig::TYPE_AFTER_REMOVING``

For example, to run your custom pass after the default removal passes have
been run::
been run, use::

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;

$container = new ContainerBuilder();
// ...
$container->addCompilerPass(
new CustomCompilerPass,
new CustomPass(),
PassConfig::TYPE_AFTER_REMOVING
);

Expand Down
21 changes: 15 additions & 6 deletions components/dependency_injection/tags.rst
Expand Up @@ -117,11 +117,14 @@ Notice that each was given a tag named ``acme_mailer.transport``. This is
the custom tag that you'll use in your compiler pass. The compiler pass
is what makes this tag "mean" something.

Create a ``CompilerPass``
-------------------------
.. _components-di-compiler-pass-tags:
.. _create-a-compilerpass:

Your compiler pass can now ask the container for any services with the
custom tag::
Create a Compiler Pass
----------------------

You can now use a :ref:`compiler pass <components-di-separate-compiler-passes>` to ask the
container for any services with the ``acme_mailer.transport`` tag::

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
Expand Down Expand Up @@ -154,7 +157,7 @@ custom tag::
The ``process()`` method checks for the existence of the ``acme_mailer.transport_chain``
service, then looks for all services tagged ``acme_mailer.transport``. It
adds to the definition of the ``acme_mailer.transport_chain`` service a
call to ``addTransport()`` for each "acme_mailer.transport" service it has
call to ``addTransport()`` for each ``acme_mailer.transport`` service it has
found. The first argument of each of these calls will be the mailer transport
service itself.

Expand All @@ -175,6 +178,13 @@ run when the container is compiled::
framework. See :doc:`/cookbook/service_container/compiler_passes` for
more details.

.. tip::

When implementing the ``CompilerPassInterface`` in a service extension, you
do not need to register it. See the
:ref:`components documentation <components-di-compiler-pass>` for more
information.

Adding Additional Attributes on Tags
------------------------------------

Expand Down Expand Up @@ -296,4 +306,3 @@ The double loop may be confusing. This is because a service can have more
than one tag. You tag a service twice or more with the ``acme_mailer.transport``
tag. The second foreach loop iterates over the ``acme_mailer.transport``
tags set for the current service and gives you the attributes.

38 changes: 19 additions & 19 deletions components/form/introduction.rst
Expand Up @@ -113,45 +113,45 @@ CSRF Protection
~~~~~~~~~~~~~~~

Protection against CSRF attacks is built into the Form component, but you need
to explicitly enable it or replace it with a custom solution. The following
snippet adds CSRF protection to the form factory::
to explicitly enable it or replace it with a custom solution. If you want to
use the built-in support, require the Security CSRF component by executing
``composer require symfony/security-csrf``.

The following snippet adds CSRF protection to the form factory::

use Symfony\Component\Form\Forms;
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider;
use Symfony\Component\HttpFoundation\Session\Session;

// generate a CSRF secret from somewhere
$csrfSecret = '<generated token>';
use Symfony\Component\Security\Extension\Csrf\CsrfExtension;
use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage;
use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator;
use Symfony\Component\Security\Csrf\CsrfTokenManager;

// create a Session object from the HttpFoundation component
$session = new Session();

$csrfProvider = new SessionCsrfProvider($session, $csrfSecret);
$csrfGenerator = new UriSafeTokenGenerator();
$csrfStorage = new SessionTokenStorage($session);
$csrfManager = new CsrfTokenManager($csrfGenerator, $csrfStorage);

$formFactory = Forms::createFormFactoryBuilder()
// ...
->addExtension(new CsrfExtension($csrfProvider))
->addExtension(new CsrfExtension($csrfStorage))
->getFormFactory();

To secure your application against CSRF attacks, you need to define a CSRF
secret. Generate a random string with at least 32 characters, insert it in the
above snippet and make sure that nobody except your web server can access
the secret.

Internally, this extension will automatically add a hidden field to every
form (called ``_token`` by default) whose value is automatically generated
and validated when binding the form.
form (called ``_token`` by default) whose value is automatically generated by
the CSRF generator and validated when binding the form.

.. tip::

If you're not using the HttpFoundation component, you can use
:class:`Symfony\\Component\\Form\\Extension\\Csrf\\CsrfProvider\\DefaultCsrfProvider`
:class:`Symfony\\Component\\Security\\Csrf\\TokenStorage\\NativeSessionTokenStorage`
instead, which relies on PHP's native session handling::

use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider;
use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage;

$csrfProvider = new DefaultCsrfProvider($csrfSecret);
$csrfStorage = new NativeSessionTokenStorage();
// ...

Twig Templating
~~~~~~~~~~~~~~~
Expand Down
54 changes: 25 additions & 29 deletions components/security/secure_tools.rst
@@ -1,47 +1,43 @@
Securely Generating Random Numbers
==================================
Securely Generating Random Values
=================================

The Symfony Security component comes with a collection of nice utilities
related to security. These utilities are used by Symfony, but you should
also use them if you want to solve the problem they address.

Generating a Secure random Number
Generating a Secure random String
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Whenever you need to generate a secure random number, you are highly
encouraged to use the Symfony
:class:`Symfony\\Component\\Security\\Core\\Util\\SecureRandom` class::
Whenever you need to generate a secure random string, you are highly
encouraged to use the :phpfunction:`random_bytes` function::

use Symfony\Component\Security\Core\Util\SecureRandom;
$random = random_bytes(10);

$generator = new SecureRandom();
$random = $generator->nextBytes(10);
The function returns a random string, suitable for cryptographic use, of
the number bytes passed as an argument (10 in the above example).

The
:method:`Symfony\\Component\\Security\\Core\\Util\\SecureRandom::nextBytes`
method returns a random string composed of the number of characters passed as
an argument (10 in the above example).
.. tip::

The SecureRandom class works better when OpenSSL is installed. But when it's
not available, it falls back to an internal algorithm, which needs a seed file
to work correctly. Just pass a file name to enable it::
The ``random_bytes()`` function returns a binary string which may contain
the ``\0`` character. This can cause trouble in several common scenarios,
such as storing this value in a database or including it as part of the
URL. The solution is to encode or hash the value returned by
``random_bytes()`` (to do that, you can use a simple ``base64_encode()``
PHP function).

use Symfony\Component\Security\Core\Util\SecureRandom;
Generating a Secure Random Number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

$generator = new SecureRandom('/some/path/to/store/the/seed.txt');
If you need to generate a cryptographically secure random integer, you should
use the :phpfunction:`random_int` function::

$random = $generator->nextBytes(10);
$hashedRandom = md5($random); // see tip below
$random = random_int(1, 10);

.. note::

If you're using the Symfony Framework, you can get a secure random number
generator via the ``security.secure_random`` service.

.. tip::
PHP 7 and up provide the ``random_bytes()`` and ``random_int()`` functions
natively, for older versions of PHP a polyfill is provided by the
`Symfony Polyfill Component`_ and the `paragonie/random_compat package`_.

The ``nextBytes()`` method returns a binary string which may contain the
``\0`` character. This can cause trouble in several common scenarios, such
as storing this value in a database or including it as part of the URL. The
solution is to hash the value returned by ``nextBytes()`` (to do that, you
can use a simple ``md5()`` PHP function).
.. _`Symfony Polyfill Component`: https://github.com/symfony/polyfill
.. _`paragonie/random_compat package`: https://github.com/paragonie/random_compat
2 changes: 2 additions & 0 deletions components/serializer.rst
Expand Up @@ -344,6 +344,8 @@ method on the normalizer definition::
$serializer = new Serializer(array($normalizer), array($encoder));
$serializer->serialize($person, 'json'); // Output: {"name":"foo","sportsman":false}

.. _component-serializer-converting-property-names-when-serializing-and-deserializing:

Converting Property Names when Serializing and Deserializing
------------------------------------------------------------

Expand Down
2 changes: 2 additions & 0 deletions components/translation/usage.rst
Expand Up @@ -139,6 +139,8 @@ recommended format. These files are parsed by one of the loader classes.
'symfony.great' => 'J\'aime Symfony',
);
.. _translation-real-vs-keyword-messages:

.. sidebar:: Using Real or Keyword Messages

This example illustrates the two different philosophies when creating
Expand Down

0 comments on commit 16cc4bc

Please sign in to comment.