From 50905ff253e5e1164b377ad5f285d1c439e7bdb7 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 7 May 2013 22:32:26 +0200 Subject: [PATCH 0001/1181] Adding lazy services documentation as of symfony/symfony#7890 --- components/dependency_injection/index.rst | 1 + .../dependency_injection/lazy_services.rst | 68 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 components/dependency_injection/lazy_services.rst diff --git a/components/dependency_injection/index.rst b/components/dependency_injection/index.rst index e1d6b0eab8d..b3960eb8e00 100644 --- a/components/dependency_injection/index.rst +++ b/components/dependency_injection/index.rst @@ -14,5 +14,6 @@ configurators parentservices advanced + lazy_services workflow diff --git a/components/dependency_injection/lazy_services.rst b/components/dependency_injection/lazy_services.rst new file mode 100644 index 00000000000..ca97b5cad24 --- /dev/null +++ b/components/dependency_injection/lazy_services.rst @@ -0,0 +1,68 @@ +.. index:: + single: Dependency Injection; Lazy Services + +Lazy Services +============= + +.. versionadded:: 2.3 + Lazy services were added in Symfony 2.3. + +Configuring lazy services +------------------------- + +In some particular cases where a very heavy service is always requested, +but not always used, you may want to mark it as ``lazy`` to delay its instantiation. + +In order to have services to lazily instantiate, you will first need to install +the `ProxyManager bridge`_:: + + php composer.phar require symfony/proxy-manager-bridge:2.3.* + +You can mark the service as ``lazy`` by manipulating its definitions: + + +.. configuration-block:: + + .. code-block:: yaml + + services: + foo: + class: Example\Foo + lazy: true + + .. code-block:: xml + + + + .. code-block:: php + + $definition = new Definition('Example\Foo'); + $definition->setLazy(true); + $container->setDefinition('foo', $definition); + +You can then require the service from the container:: + + $service = $container->get($serviceId); + +At this point the retrieved ``$service`` should be a virtual `proxy`_ with the same +signature of the class representing the service. + +.. note:: + + If you don't install the `ProxyManager bridge`_, the container will just skip + over the ``lazy`` flag and simply instantiate the service as it would normally do. + +The proxy gets initialized and the actual service is instantiated as soon as you interact +in any way with this object. + +Additional resources +-------------------- + + +You can read more about how proxies are instantiated, generated and initialized in +the `documentation of ProxyManager`_. + + +.. _`ProxyManager bridge`: https://github.com/symfony/symfony/tree/2.3/src/Symfony/Bridge/ProxyManager +.. _`proxy`: http://en.wikipedia.org/wiki/Proxy_pattern +.. _`documentation of ProxyManager`: https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-value-holder.md \ No newline at end of file From c3c3e98bab34427db516ab391bca73dbd0b04a3a Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Wed, 8 May 2013 18:35:49 +0200 Subject: [PATCH 0002/1181] [Components][Console] Fixed typos for table helper --- components/console/helpers/tablehelper.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/console/helpers/tablehelper.rst b/components/console/helpers/tablehelper.rst index 04301af5048..1145dd7b603 100644 --- a/components/console/helpers/tablehelper.rst +++ b/components/console/helpers/tablehelper.rst @@ -48,8 +48,8 @@ You can also control table rendering by setting custom rendering option values: * :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setPaddingChar` * :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setHorizontalBorderChar` * :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setVerticalBorderChar` -* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setVrossingChar` -* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setVellHeaderFormat` -* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setVellRowFormat` +* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setCrossingChar` +* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setCellHeaderFormat` +* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setCellRowFormat` * :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setBorderFormat` * :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setPadType` From 931091d8e3aa0b9d4f1393d313388d5ee1a5d47d Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 9 May 2013 20:18:51 +0200 Subject: [PATCH 0003/1181] Applying changes suggested by @WouterJ, adding lazy_services to components map --- .../dependency_injection/lazy_services.rst | 17 ++++++++--------- components/map.rst.inc | 1 + 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/components/dependency_injection/lazy_services.rst b/components/dependency_injection/lazy_services.rst index ca97b5cad24..599d503f7e6 100644 --- a/components/dependency_injection/lazy_services.rst +++ b/components/dependency_injection/lazy_services.rst @@ -14,35 +14,35 @@ In some particular cases where a very heavy service is always requested, but not always used, you may want to mark it as ``lazy`` to delay its instantiation. In order to have services to lazily instantiate, you will first need to install -the `ProxyManager bridge`_:: +the `ProxyManager bridge`_: - php composer.phar require symfony/proxy-manager-bridge:2.3.* +.. code-block:: bash + $ php composer.phar require symfony/proxy-manager-bridge:2.3.* You can mark the service as ``lazy`` by manipulating its definitions: - .. configuration-block:: .. code-block:: yaml services: foo: - class: Example\Foo + class: Acme\Foo lazy: true .. code-block:: xml - + .. code-block:: php - $definition = new Definition('Example\Foo'); + $definition = new Definition('Acme\Foo'); $definition->setLazy(true); $container->setDefinition('foo', $definition); You can then require the service from the container:: - $service = $container->get($serviceId); + $service = $container->get('foo'); At this point the retrieved ``$service`` should be a virtual `proxy`_ with the same signature of the class representing the service. @@ -55,10 +55,9 @@ signature of the class representing the service. The proxy gets initialized and the actual service is instantiated as soon as you interact in any way with this object. -Additional resources +Additional Resources -------------------- - You can read more about how proxies are instantiated, generated and initialized in the `documentation of ProxyManager`_. diff --git a/components/map.rst.inc b/components/map.rst.inc index e29df506e55..d360c65a706 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -39,6 +39,7 @@ * :doc:`/components/dependency_injection/configurators` * :doc:`/components/dependency_injection/parentservices` * :doc:`/components/dependency_injection/advanced` + * :doc:`/components/dependency_injection/lazy_services` * :doc:`/components/dependency_injection/workflow` * **DOM Crawler** From 2d9316f6d0a9808c6265881b81ecf4d15b1a45a3 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Fri, 10 May 2013 19:56:56 +0200 Subject: [PATCH 0004/1181] Added new tag --- reference/twig_reference.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/reference/twig_reference.rst b/reference/twig_reference.rst index b6960b1e729..a6cbfc1d8a4 100644 --- a/reference/twig_reference.rst +++ b/reference/twig_reference.rst @@ -134,6 +134,9 @@ Filters Tags ---- +.. versionadded:: 2.3 + The stopwatch tag was added in Symfony 2.3 + +---------------------------------------------------+--------------------------------------------------------------------+ | Tag Syntax | Usage | +===================================================+====================================================================+ @@ -150,6 +153,9 @@ Tags | ``{% trans_default_domain language %}`` | This will set the default domain for message catalogues in the | | | current template | +---------------------------------------------------+--------------------------------------------------------------------+ +| ``{% stopwatch name %}...{% endstopwatch %}`` | This will time the run time of the code inside it and put that on | +| | the timeline of the WebDeveloperBundle. | ++---------------------------------------------------+--------------------------------------------------------------------+ Tests ----- From 438c8244e04e8c9ad818d93f22699ab5c8aa0289 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Wed, 15 May 2013 13:01:26 +0200 Subject: [PATCH 0005/1181] Made the Icu component compatible with ICU 3.8 --- components/intl.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/intl.rst b/components/intl.rst index cf42b9778d5..e9c5028d4c2 100644 --- a/components/intl.rst +++ b/components/intl.rst @@ -72,7 +72,7 @@ expose them manually by adding the following lines to your autoload code:: but usually Composer does this for you automatically: * 1.0.*: when the intl extension is not available - * 1.1.*: when intl is compiled with ICU 4.0 or higher + * 1.1.*: when intl is compiled with ICU 3.8 or higher * 1.2.*: when intl is compiled with ICU 4.4 or higher These versions are important when you deploy your application to a **server with From d7ea3a540a5dc425bf1d16f4113746975404da38 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 15 May 2013 22:04:52 -0500 Subject: [PATCH 0006/1181] [#2619] Tweaks for new proxy/lazy services entry --- .../dependency_injection/lazy_services.rst | 55 ++++++++++++++----- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/components/dependency_injection/lazy_services.rst b/components/dependency_injection/lazy_services.rst index 599d503f7e6..88ad0c51f59 100644 --- a/components/dependency_injection/lazy_services.rst +++ b/components/dependency_injection/lazy_services.rst @@ -7,19 +7,41 @@ Lazy Services .. versionadded:: 2.3 Lazy services were added in Symfony 2.3. -Configuring lazy services -------------------------- +Why Lazy Services? +------------------ -In some particular cases where a very heavy service is always requested, -but not always used, you may want to mark it as ``lazy`` to delay its instantiation. +In some cases, you may want to inject a service that is a bit heavy to instantiate, +but is not always used inside your object. For example, imagine you have +a ``NewsletterManager`` and you inject a ``mailer`` service into it. Only +a few methods on your ``NewsletterManager`` actually use the ``mailer``, +but even when you don't need it, a ``mailer`` service is always instantiated +in order to construct your ``NewsletterManager``. -In order to have services to lazily instantiate, you will first need to install +Configuring lazy services is one answer to this. With a lazy service, a "proxy" +of the ``mailer`` service is actually injected. It looks and acts just like +the ``mailer``, except that the ``mailer`` isn't actually instantiated until +you interact with the proxy in some way. + +Installation +------------ + +In order to use the lazy service instantiation, you will first need to install the `ProxyManager bridge`_: .. code-block:: bash + $ php composer.phar require symfony/proxy-manager-bridge:2.3.* -You can mark the service as ``lazy`` by manipulating its definitions: +.. note:: + + If you're using the full-stack framework, this package is not included + and needs to be added to ``composer.json`` and installed (which is what + the above command does). + +Configuration +------------- + +You can mark the service as ``lazy`` by manipulating its definition: .. configuration-block:: @@ -44,24 +66,27 @@ You can then require the service from the container:: $service = $container->get('foo'); -At this point the retrieved ``$service`` should be a virtual `proxy`_ with the same -signature of the class representing the service. +At this point the retrieved ``$service`` should be a virtual `proxy`_ with +the same signature of the class representing the service. You can also inject +the service just like normal into other services. The object that's actually +injected will be the proxy. .. note:: - If you don't install the `ProxyManager bridge`_, the container will just skip - over the ``lazy`` flag and simply instantiate the service as it would normally do. + If you don't install the `ProxyManager bridge`_, the container will just + skip over the ``lazy`` flag and simply instantiate the service as it would + normally do. -The proxy gets initialized and the actual service is instantiated as soon as you interact -in any way with this object. +The proxy gets initialized and the actual service is instantiated as soon +as you interact in any way with this object. Additional Resources -------------------- -You can read more about how proxies are instantiated, generated and initialized in -the `documentation of ProxyManager`_. +You can read more about how proxies are instantiated, generated and initialized +in the `documentation of ProxyManager`_. -.. _`ProxyManager bridge`: https://github.com/symfony/symfony/tree/2.3/src/Symfony/Bridge/ProxyManager +.. _`ProxyManager bridge`: https://github.com/symfony/symfony/tree/master/src/Symfony/Bridge/ProxyManager .. _`proxy`: http://en.wikipedia.org/wiki/Proxy_pattern .. _`documentation of ProxyManager`: https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-value-holder.md \ No newline at end of file From ac3df5725ac4e8b775992ed7777ca4b75dba978a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A4rtel?= Date: Fri, 17 May 2013 16:15:11 +0300 Subject: [PATCH 0007/1181] Documented ProgressHelper's clear() method. --- components/console/helpers/progresshelper.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/components/console/helpers/progresshelper.rst b/components/console/helpers/progresshelper.rst index cadf41d947d..1c3635e93c6 100644 --- a/components/console/helpers/progresshelper.rst +++ b/components/console/helpers/progresshelper.rst @@ -10,6 +10,9 @@ Progress Helper .. versionadded:: 2.3 The ``setCurrent`` method was added in Symfony 2.3. +.. versionadded:: 2.4 + The ``clear`` method was added in Symfony 2.4. + When executing longer-running commands, it may be helpful to show progress information, which updates as your command runs: @@ -37,6 +40,12 @@ pass it a total number of units, and advance the progress as your command execut :method:`Symfony\\Component\\Console\\Helper\\ProgressHelper::setCurrent` method. +If you want to output something while the progress bar is running, +call :method:`Symfony\\Component\\Console\\Helper\\ProgressHelper::clear` first. +After you're done, call +:method:`Symfony\\Component\\Console\\Helper\\ProgressHelper::display` +to show the progress bar again. + The appearance of the progress output can be customized as well, with a number of different levels of verbosity. Each of these displays different possible items - like percentage completion, a moving progress bar, or current/total From 3ca7875b1de0b1cbd56c92bbc671899297986ea0 Mon Sep 17 00:00:00 2001 From: Juan Traverso Date: Sun, 16 Jun 2013 12:40:39 +0200 Subject: [PATCH 0008/1181] [Process] Doc for output flush methods. --- components/process.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/components/process.rst b/components/process.rst index 6c7c9205454..b0ec4d9788b 100644 --- a/components/process.rst +++ b/components/process.rst @@ -45,6 +45,15 @@ output. Alternatively, the :method:`Symfony\\Component\\Process\\Process::getInc and :method:`Symfony\\Component\\Process\\Process::getIncrementalErrorOutput` methods returns the new outputs since the last call. +.. versionadded:: 2.4 + The ``getAndFlushOutput()``, ``getAndFlushIncrementalOutput()``, ``getAndFlushErrorOutput()``, ` + ``getAndFlushIncrementalErrorOutput()``, ``flushOutput()`` and ``flushErrorOutput()`` methods were + added in Symfony 2.4. + +These methods clears the output and error output buffers. Also, ``getAndFlushOutput()``, +``getAndFlushIncrementalOutput()``, ``getAndFlushErrorOutput()`` and ``getAndFlushIncrementalErrorOutput()`` +returns the outputs as well. + Getting real-time Process Output -------------------------------- From f9f20e5523c4c600c7aa3c8bbcb187e84efe1910 Mon Sep 17 00:00:00 2001 From: Juan Traverso Date: Sun, 16 Jun 2013 13:58:42 +0200 Subject: [PATCH 0009/1181] [Process] Rewriting to avoid wrong sentences. --- components/process.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/components/process.rst b/components/process.rst index b0ec4d9788b..afc9e85c98b 100644 --- a/components/process.rst +++ b/components/process.rst @@ -46,13 +46,16 @@ and :method:`Symfony\\Component\\Process\\Process::getIncrementalErrorOutput` methods returns the new outputs since the last call. .. versionadded:: 2.4 - The ``getAndFlushOutput()``, ``getAndFlushIncrementalOutput()``, ``getAndFlushErrorOutput()``, ` + The ``getAndFlushOutput()``, ``getAndFlushIncrementalOutput()``, ``getAndFlushErrorOutput()``, ``getAndFlushIncrementalErrorOutput()``, ``flushOutput()`` and ``flushErrorOutput()`` methods were added in Symfony 2.4. -These methods clears the output and error output buffers. Also, ``getAndFlushOutput()``, -``getAndFlushIncrementalOutput()``, ``getAndFlushErrorOutput()`` and ``getAndFlushIncrementalErrorOutput()`` -returns the outputs as well. +The :method:`Symfony\\Component\\Process\\Process::flushOutput()` method flushes the contents of the output and +and :method:`Symfony\\Component\\Process\\Process::flushErrorOutput()` the content of the error output. You can get the +contents and flush the whole output or the error output by using :method:`Symfony\\Component\\Process\\Process::getAndFlushOutput()` +and :method:`Symfony\\Component\\Process\\Process::getAndFlushErrorOutput()` methods, or the outputs since the last call +by using the :method:`Symfony\\Component\\Process\\Process::getAndFlushIncrementalOutput()` and +:method:`Symfony\\Component\\Process\\Process::getAndFlushIncrementalErrorOutput()` methods. Getting real-time Process Output -------------------------------- From 1f7898045f3f1ad06dc63f32f4d921519fc5e3d7 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 29 Jun 2013 17:42:06 -0500 Subject: [PATCH 0010/1181] [#2720] Playing "catch-up" to get the master branch up to date with the new documentation standards Specifically, I'm pretending as if 2.1 had reached its end-of-life today, and am applying all the needed changes to the master branch --- book/security.rst | 4 ++-- book/stable_api.rst | 5 +++-- components/filesystem.rst | 6 ++---- components/stopwatch.rst | 2 +- cookbook/bundles/installation.rst | 9 ++------- cookbook/configuration/override_dir_structure.rst | 4 ++-- reference/constraints/Image.rst | 4 ++-- reference/forms/types/options/error_mapping.rst.inc | 3 --- reference/forms/types/options/property_path.rst.inc | 3 --- 9 files changed, 14 insertions(+), 26 deletions(-) diff --git a/book/security.rst b/book/security.rst index ee45430393e..aa1463a2da7 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1702,8 +1702,8 @@ a route so that you can use it to generate the URL: .. caution:: - As of Symfony 2.1, you *must* have a route that corresponds to your logout - path. Without this route, logging out will not work. + You *must* have a route that corresponds to your logout path. Without + this route, logging out will not work. .. configuration-block:: diff --git a/book/stable_api.rst b/book/stable_api.rst index 0d92777bdd0..8980f0274dc 100644 --- a/book/stable_api.rst +++ b/book/stable_api.rst @@ -22,7 +22,8 @@ everything not tagged explicitly is not part of the stable API. Any third party bundle should also publish its own stable API. -As of Symfony 2.0, the following components have a public tagged API: +As of the latest stable release of Symfony, the following components have +a public tagged API: * BrowserKit * ClassLoader @@ -31,7 +32,7 @@ As of Symfony 2.0, the following components have a public tagged API: * DependencyInjection * DomCrawler * EventDispatcher -* Filesystem (as of Symfony 2.1) +* Filesystem * Finder * HttpFoundation * HttpKernel diff --git a/components/filesystem.rst b/components/filesystem.rst index d8386ae69fb..9e93336b239 100644 --- a/components/filesystem.rst +++ b/components/filesystem.rst @@ -258,9 +258,7 @@ thrown. .. note:: - Prior to version 2.1, ``mkdir`` returned a boolean and did not throw - exceptions. As of 2.1, a - :class:`Symfony\\Component\\Filesystem\\Exception\\IOException` is thrown - if a directory creation fails. + An :class:`Symfony\\Component\\Filesystem\\Exception\\IOException` is + thrown if directory creation fails. .. _`Packagist`: https://packagist.org/packages/symfony/filesystem diff --git a/components/stopwatch.rst b/components/stopwatch.rst index af5f98e823b..06908f13ee0 100644 --- a/components/stopwatch.rst +++ b/components/stopwatch.rst @@ -9,7 +9,7 @@ The Stopwatch Component .. versionadded:: 2.2 The Stopwatch Component is new to Symfony 2.2. Previously, the ``Stopwatch`` - class was located in the ``HttpKernel`` component (and was new in 2.1). + class was located in the ``HttpKernel`` component. Installation ------------ diff --git a/cookbook/bundles/installation.rst b/cookbook/bundles/installation.rst index c844d067ca3..84d17cda70a 100644 --- a/cookbook/bundles/installation.rst +++ b/cookbook/bundles/installation.rst @@ -10,8 +10,8 @@ basic steps for installing a bundle are the same. Add Composer Dependencies ------------------------- -Starting from Symfony 2.1, dependencies are managed with Composer. It's -a good idea to learn some basics of Composer in `their documentation`_. +In Symfony, dependencies are managed with Composer. It's a good idea to learn +some basics of Composer in `their documentation`_. Before you can use composer to install a bundle, you should look for a `Packagist`_ package of that bundle. For example, if you search for the popular @@ -33,11 +33,6 @@ file. If it isn't, you can use the version you want. If you choose an incompatib version, Composer will throw dependency errors when you try to install. If this happens, you can try a different version. -In the case of the FOSUserBundle, the ``README`` file has a caution that version -1.2.0 must be used for Symfony 2.0 and 1.3+ for Symfony 2.1+. Packagist displays -example ``require`` statements for all existing versions of a package. The -current development version of FOSUserBundle is ``"friendsofsymfony/user-bundle": "2.0.*@dev"``. - Now you can add the bundle to your ``composer.json`` file and update the dependencies. You can do this manually: diff --git a/cookbook/configuration/override_dir_structure.rst b/cookbook/configuration/override_dir_structure.rst index 31aeb973847..6112b67edde 100644 --- a/cookbook/configuration/override_dir_structure.rst +++ b/cookbook/configuration/override_dir_structure.rst @@ -91,8 +91,8 @@ may need to modify the paths inside these files:: require_once __DIR__.'/../Symfony/app/bootstrap.php.cache'; require_once __DIR__.'/../Symfony/app/AppKernel.php'; -Since Symfony 2.1 (in which Composer is introduced), you also need to change -the ``extra.symfony-web-dir`` option in the ``composer.json`` file: +You also need to change the ``extra.symfony-web-dir`` option in the ``composer.json`` +file: .. code-block:: json diff --git a/reference/constraints/Image.rst b/reference/constraints/Image.rst index 180397330a3..7c4b094b201 100644 --- a/reference/constraints/Image.rst +++ b/reference/constraints/Image.rst @@ -5,8 +5,8 @@ The Image constraint works exactly like the :doc:`File` constraint for the bulk of the documentation on this constraint. diff --git a/reference/forms/types/options/error_mapping.rst.inc b/reference/forms/types/options/error_mapping.rst.inc index 8c03180db7c..05ad2148c34 100644 --- a/reference/forms/types/options/error_mapping.rst.inc +++ b/reference/forms/types/options/error_mapping.rst.inc @@ -1,6 +1,3 @@ -.. versionadded:: 2.1 - The ``error_mapping`` option is new to Symfony 2.1. - error_mapping ~~~~~~~~~~~~~ diff --git a/reference/forms/types/options/property_path.rst.inc b/reference/forms/types/options/property_path.rst.inc index 540d17063ea..3d75992d1cb 100644 --- a/reference/forms/types/options/property_path.rst.inc +++ b/reference/forms/types/options/property_path.rst.inc @@ -14,6 +14,3 @@ If you wish the field to be ignored when reading or writing to the object you can set the ``property_path`` option to ``false``, but using ``property_path`` for this purpose is deprecated, you should use the ``mapped`` option. - -.. versionadded:: 2.1 - Since 2.1, the ``mapped`` option has been added for this use-case. From f8974119c1310bdf6ae9e0feafc8bc0d596c3b43 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 20 Jul 2013 14:59:05 -0500 Subject: [PATCH 0011/1181] [#2797] Removing the 2.1 version notes on master (since 2.1 has been deprecated - see documentation release directions) --- reference/constraints/UniqueEntity.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/reference/constraints/UniqueEntity.rst b/reference/constraints/UniqueEntity.rst index fb50ad03c3b..19a855d9a36 100644 --- a/reference/constraints/UniqueEntity.rst +++ b/reference/constraints/UniqueEntity.rst @@ -153,9 +153,6 @@ errorPath **type**: ``string`` **default**: The name of the first `field`_ -.. versionadded:: 2.1 - The ``errorPath`` option was added in Symfony 2.1. - If the entity violates constraint the error message is bound to the first field in `fields`_. If there are more than one fields, you may want to map the error message to another field. @@ -254,9 +251,6 @@ ignoreNull **type**: ``Boolean`` **default**: ``true`` -.. versionadded:: 2.1 - The ``ignoreNull`` option was added in Symfony 2.1. - If this option is set to ``true``, then the constraint will allow multiple entities to have a ``null`` value for a field without failing validation. If set to ``false``, only one ``null`` value is allowed - if a second entity From f57b569a46b77a9cd57f8baa179da82bf67d79f7 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 20 Jul 2013 16:44:59 -0500 Subject: [PATCH 0012/1181] [#2829] Changing reference back to master - eventually we'll need an extension that helps us manage this version stuff --- cookbook/form/form_customization.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/form/form_customization.rst b/cookbook/form/form_customization.rst index f1585e0513d..02caa9cbd12 100644 --- a/cookbook/form/form_customization.rst +++ b/cookbook/form/form_customization.rst @@ -948,4 +948,4 @@ customizations directly. Look at the following example: The array passed as the second argument contains form "variables". For more details about this concept in Twig, see :ref:`twig-reference-form-variables`. -.. _`form_div_layout.html.twig`: https://github.com/symfony/symfony/blob/2.3/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +.. _`form_div_layout.html.twig`: https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig From c80e4e71df8e0a9be60ac6d5b1f19541bbb00d57 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 28 Jul 2013 19:54:43 -0500 Subject: [PATCH 0013/1181] [#2783] Removing 2.1 versionadded that came back due to a tweak on the 2.2 branch --- book/security.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/book/security.rst b/book/security.rst index 3cd4a8a1760..071ce973635 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1803,11 +1803,6 @@ a route so that you can use it to generate the URL: return $collection; -.. caution:: - - As of Symfony 2.1, you *must* have a route that corresponds to your logout - path. Without this route, logging out will not work. - Once the user has been logged out, he will be redirected to whatever path is defined by the ``target`` parameter above (e.g. the ``homepage``). For more information on configuring the logout, see the From b6d5606a9124fa18e81c82f23fe14eb6cc7c4148 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 1 Aug 2013 15:44:38 +0200 Subject: [PATCH 0014/1181] Updated rounding_mode documentation to reflect changed ROUND_ constants. --- reference/forms/types/integer.rst | 24 ++++++++++++++-------- reference/forms/types/number.rst | 34 ++++++++++++++----------------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/reference/forms/types/integer.rst b/reference/forms/types/integer.rst index b1a3d518eea..0ea2e2d1405 100644 --- a/reference/forms/types/integer.rst +++ b/reference/forms/types/integer.rst @@ -48,17 +48,25 @@ By default, if the user enters a non-integer number, it will be rounded down. There are several other rounding methods, and each is a constant on the :class:`Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\IntegerToLocalizedStringTransformer`: -* ``IntegerToLocalizedStringTransformer::ROUND_DOWN`` Rounding mode to - round towards zero. +* ``IntegerToLocalizedStringTransformer::ROUND_DOWN`` Round towards zero. -* ``IntegerToLocalizedStringTransformer::ROUND_FLOOR`` Rounding mode to - round towards negative infinity. +* ``IntegerToLocalizedStringTransformer::ROUND_FLOOR`` Round towards negative + infinity. -* ``IntegerToLocalizedStringTransformer::ROUND_UP`` Rounding mode to round - away from zero. +* ``IntegerToLocalizedStringTransformer::ROUND_UP`` Round away from zero. -* ``IntegerToLocalizedStringTransformer::ROUND_CEILING`` Rounding mode - to round towards positive infinity. +* ``IntegerToLocalizedStringTransformer::ROUND_CEILING`` Round towards + positive infinity. + +* ``IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN`` Round towards the + "nearest neighbor". If both neighbors are equidistant, round down. + +* ``IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN`` Round towards the + "nearest neighbor". If both neighbors are equidistant, round towards the + even neighbor. + +* ``IntegerToLocalizedStringTransformer::ROUND_HALF_UP`` Round towards the + "nearest neighbor". If both neighbors are equidistant, round up. .. include:: /reference/forms/types/options/grouping.rst.inc diff --git a/reference/forms/types/number.rst b/reference/forms/types/number.rst index ce40bce055c..6445efcc407 100644 --- a/reference/forms/types/number.rst +++ b/reference/forms/types/number.rst @@ -38,35 +38,31 @@ Field Options rounding_mode ~~~~~~~~~~~~~ -**type**: ``integer`` **default**: ``IntegerToLocalizedStringTransformer::ROUND_HALFUP`` +**type**: ``integer`` **default**: ``NumberToLocalizedStringTransformer::ROUND_HALFUP`` If a submitted number needs to be rounded (based on the ``precision`` option), you have several configurable options for that rounding. Each -option is a constant on the :class:`Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\IntegerToLocalizedStringTransformer`: +option is a constant on the :class:`Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\NumberToLocalizedStringTransformer`: -* ``IntegerToLocalizedStringTransformer::ROUND_DOWN`` Rounding mode to - round towards zero. +* ``NumberToLocalizedStringTransformer::ROUND_DOWN`` Round towards zero. -* ``IntegerToLocalizedStringTransformer::ROUND_FLOOR`` Rounding mode to - round towards negative infinity. +* ``NumberToLocalizedStringTransformer::ROUND_FLOOR`` Round towards negative + infinity. -* ``IntegerToLocalizedStringTransformer::ROUND_UP`` Rounding mode to round - away from zero. +* ``NumberToLocalizedStringTransformer::ROUND_UP`` Round away from zero. -* ``IntegerToLocalizedStringTransformer::ROUND_CEILING`` Rounding mode - to round towards positive infinity. +* ``NumberToLocalizedStringTransformer::ROUND_CEILING`` Round towards + positive infinity. -* ``IntegerToLocalizedStringTransformer::ROUND_HALFDOWN`` Rounding mode - to round towards "nearest neighbor" unless both neighbors are equidistant, - in which case round down. +* ``NumberToLocalizedStringTransformer::ROUND_HALF_DOWN`` Round towards the + "nearest neighbor". If both neighbors are equidistant, round down. -* ``IntegerToLocalizedStringTransformer::ROUND_HALFEVEN`` Rounding mode - to round towards the "nearest neighbor" unless both neighbors are equidistant, - in which case, round towards the even neighbor. +* ``NumberToLocalizedStringTransformer::ROUND_HALF_EVEN`` Round towards the + "nearest neighbor". If both neighbors are equidistant, round towards the + even neighbor. -* ``IntegerToLocalizedStringTransformer::ROUND_HALFUP`` Rounding mode to - round towards "nearest neighbor" unless both neighbors are equidistant, - in which case round up. +* ``NumberToLocalizedStringTransformer::ROUND_HALF_UP`` Round towards the + "nearest neighbor". If both neighbors are equidistant, round up. .. include:: /reference/forms/types/options/grouping.rst.inc From 2e25e0037c2d67872c3775ec1a515329beeb1d46 Mon Sep 17 00:00:00 2001 From: Johannes Date: Sun, 4 Aug 2013 16:08:10 +0200 Subject: [PATCH 0015/1181] adds docs for idle timeout (see symfony/symfony#8651) --- components/process.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/components/process.rst b/components/process.rst index 56ba1686513..9c459dc742d 100644 --- a/components/process.rst +++ b/components/process.rst @@ -210,6 +210,25 @@ check regularly:: .. _reference-process-signal: +Process Idle Timeout +-------------------- + +.. versionadded:: 2.4 + The ``setIdleTimeout`` method was added in Symfony 2.4. + +In contrast to the timeout of the previous paragraph, the idle timeout only +considers the time since the last output was produced by the process:: + + use Symfony\Component\Process\Process; + + $process = new Process('something-with-variable-runtime'); + $process->setTimeout(3600); + $process->setIdleTimeout(60); + $process->run(); + +In the case above, a process is considered timed out, when either the total runtime +exceeds 3600 seconds, or the process does not produce any output for 60 seconds. + Process Signals --------------- From 3fa71b83602864c10af749d698bf64cfd4b6bb9b Mon Sep 17 00:00:00 2001 From: Johannes Date: Sun, 4 Aug 2013 16:37:52 +0200 Subject: [PATCH 0016/1181] adds api link --- components/process.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/process.rst b/components/process.rst index 9c459dc742d..c10824d77dd 100644 --- a/components/process.rst +++ b/components/process.rst @@ -214,7 +214,7 @@ Process Idle Timeout -------------------- .. versionadded:: 2.4 - The ``setIdleTimeout`` method was added in Symfony 2.4. + The :method:`Symfony\\Component\\Process\\Process::setIdleTimeout` method was added in Symfony 2.4. In contrast to the timeout of the previous paragraph, the idle timeout only considers the time since the last output was produced by the process:: From 1891edd61ec713d12b114dcbd59dd442b23ee13a Mon Sep 17 00:00:00 2001 From: Luciano Mammino Date: Mon, 22 Jul 2013 01:22:53 +0200 Subject: [PATCH 0017/1181] Updated documentation for PR https://github.com/symfony/symfony/pull/8490 --- reference/constraints/Image.rst | 182 ++++++++++++++++++++++++++++++-- 1 file changed, 175 insertions(+), 7 deletions(-) diff --git a/reference/constraints/Image.rst b/reference/constraints/Image.rst index ca90c6476c7..7364f319f64 100644 --- a/reference/constraints/Image.rst +++ b/reference/constraints/Image.rst @@ -8,6 +8,11 @@ automatically setup to work for image files specifically. Additionally, as of Symfony 2.1, it has options so you can validate against the width and height of the image. +.. versionadded:: 2.4 + As of Symfony 2.4 you can also validate against the image aspect ratio ( defined + as ``width / height``) and selectively allow square, landscape and portrait + image orientations. + See the :doc:`File` constraint for the bulk of the documentation on this constraint. @@ -19,12 +24,22 @@ the documentation on this constraint. | | - `maxWidth`_ | | | - `maxHeight`_ | | | - `minHeight`_ | +| | - `maxRatio`_ | +| | - `minRatio`_ | +| | - `allowSquare`_ | +| | - `allowLandscape`_ | +| | - `allowPortrait`_ | | | - `mimeTypesMessage`_ | | | - `sizeNotDetectedMessage`_ | | | - `maxWidthMessage`_ | | | - `minWidthMessage`_ | | | - `maxHeightMessage`_ | | | - `minHeightMessage`_ | +| | - `maxRatioMessage`_ | +| | - `minRatioMessage`_ | +| | - `allowSquareMessage`_ | +| | - `allowLandscapeMessage`_ | +| | - `allowPortraitMessage`_ | | | - See :doc:`File` for inherited options | +----------------+----------------------------------------------------------------------+ | Class | :class:`Symfony\\Component\\Validator\\Constraints\\File` | @@ -82,6 +97,8 @@ it is between a certain size, add the following: .. code-block:: php-annotations // src/Acme/BlogBundle/Entity/Author.php + namespace Acme\BlogBundle\Entity; + use Symfony\Component\Validator\Constraints as Assert; class Author @@ -114,10 +131,10 @@ it is between a certain size, add the following: .. code-block:: php // src/Acme/BlogBundle/Entity/Author.php - // ... + namespace Acme/BlogBundle/Entity use Symfony\Component\Validator\Mapping\ClassMetadata; - use Symfony\Component\Validator\Constraints\Image; + use Symfony\Component\Validator\Constraints as Assert; class Author { @@ -125,7 +142,7 @@ it is between a certain size, add the following: public static function loadValidatorMetadata(ClassMetadata $metadata) { - $metadata->addPropertyConstraint('headshot', new Image(array( + $metadata->addPropertyConstraint('headshot', new Assert\Image(array( 'minWidth' => 200, 'maxWidth' => 400, 'minHeight' => 200, @@ -137,6 +154,76 @@ it is between a certain size, add the following: The ``headshot`` property is validated to guarantee that it is a real image and that it is between a certain width and height. +You may also want to guarantee the ``headshot`` image to be square. In this +case you can disable portrait and landscape orientations as shown in the +following code: + +.. configuration-block:: + + .. code-block:: yaml + + # src/Acme/BlogBundle/Resources/config/validation.yml + Acme\BlogBundle\Entity\Author + properties: + headshot: + - Image: + allowLandscape: false + allowPortrait: false + + + .. code-block:: php-annotations + + // src/Acme/BlogBundle/Entity/Author.php + namespace Acme\BlogBundle\Entity; + + use Symfony\Component\Validator\Constraints as Assert; + + class Author + { + /** + * @Assert\Image( + * allowLandscape = false + * allowPortrait = false + * ) + */ + protected $headshot; + } + + .. code-block:: xml + + + + + + + + + + + + .. code-block:: php + + // src/Acme/BlogBundle/Entity/Author.php + namespace Acme\BlogBundle\Entity; + + use Symfony\Component\Validator\Mapping\ClassMetadata; + use Symfony\Component\Validator\Constraints as Assert; + + class Author + { + // ... + + public static function loadValidatorMetadata(ClassMetadata $metadata) + { + $metadata->addPropertyConstraint('headshot', new Assert\Image(array( + 'allowLandscape' => false, + 'allowPortrait' => false, + ))); + } + } + +You can mix all the constraint options to create powerful validation rules. + Options ------- @@ -191,6 +278,43 @@ maxHeight If set, the height of the image file must be less than or equal to this value in pixels. +maxRatio +~~~~~~~~ + +**type**: ``integer`` + +If set, the aspect ratio (``width / height``) of the image file must be less than or equal to this +value. + +minRatio +~~~~~~~~ + +**type**: ``integer`` + +If set, the aspect ratio (``width / height``) of the image file must be greater than or equal to this +value. + +allowSquare +~~~~~~~~~~~ + +**type**: ``Boolean`` **default**: ``true`` + +If this option is false, the image must not be square. + +allowLandscape +~~~~~~~~~~~~~~ + +**type**: ``Boolean`` **default**: ``true`` + +If this option is false, the image must not be landscape oriented. + +allowPortrait +~~~~~~~~~~~~~ + +**type**: ``Boolean`` **default**: ``true`` + +If this option is false, the image must not be portrait oriented. + sizeNotDetectedMessage ~~~~~~~~~~~~~~~~~~~~~~ @@ -203,29 +327,73 @@ options has been set. maxWidthMessage ~~~~~~~~~~~~~~~ -**type**: ``string`` **default**: ``The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px`` +**type**: ``string`` **default**: ``The image width is too big ({{ width }}px). +Allowed maximum width is {{ max_width }}px`` The error message if the width of the image exceeds `maxWidth`_. minWidthMessage ~~~~~~~~~~~~~~~ -**type**: ``string`` **default**: ``The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px`` +**type**: ``string`` **default**: ``The image width is too small ({{ width }}px). +Minimum width expected is {{ min_width }}px`` The error message if the width of the image is less than `minWidth`_. maxHeightMessage ~~~~~~~~~~~~~~~~ -**type**: ``string`` **default**: ``The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px`` +**type**: ``string`` **default**: ``The image height is too big ({{ height }}px). +Allowed maximum height is {{ max_height }}px`` The error message if the height of the image exceeds `maxHeight`_. minHeightMessage ~~~~~~~~~~~~~~~~ -**type**: ``string`` **default**: ``The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px`` +**type**: ``string`` **default**: ``The image height is too small ({{ height }}px). +Minimum height expected is {{ min_height }}px`` The error message if the height of the image is less than `minHeight`_. +maxRatioMessage +~~~~~~~~~~~~~~~ + +**type**: ``string`` **default**: ``The image ratio is too big ({{ ratio }}). +Allowed maximum ratio is {{ max_ratio }}`` + +The error message if the aspect ratio of the image exceeds `maxRatio`_. + +minRatioMessage +~~~~~~~~~~~~~~~ + +**type**: ``string`` **default**: ``The image ratio is too small ({{ ratio }}). +Minimum ratio expected is {{ min_ratio }}`` + +The error message if the aspect ratio of the image is less than `minRatio`_. + +allowSquareMessage +~~~~~~~~~~~~~~~~~~ + +**type**: ``string`` **default**: ``The image is square ({{ width }}x{{ height }}px). +Square images are not allowed`` + +The error message if the image is square and you set `allowSquare`_ to ``false``. + +allowLandscapeMessage +~~~~~~~~~~~~~~~~~~~~~ + +**type**: ``string`` **default**: ``The image is landscape oriented ({{ width }}x{{ height }}px). +Landscape oriented images are not allowed`` + +The error message if the image is landscape oriented and you set `allowLandscape`_ to ``false``. + +allowPortraitMessage +~~~~~~~~~~~~~~~~~~~~ + +**type**: ``string`` **default**: ``The image is portrait oriented ({{ width }}x{{ height }}px). +Portrait oriented images are not allowed`` + +The error message if the image is portrait oriented and you set `allowPoirtrait`_ to ``false``. + .. _`IANA website`: http://www.iana.org/assignments/media-types/image/index.html From 8b0611ab3e615edbfc6bd7c011549f5c7e737ea4 Mon Sep 17 00:00:00 2001 From: Juan Traverso Date: Fri, 9 Aug 2013 16:59:47 +0200 Subject: [PATCH 0018/1181] [Process] Update docs for modifications. --- components/process.rst | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/components/process.rst b/components/process.rst index afc9e85c98b..f05e6c70ca4 100644 --- a/components/process.rst +++ b/components/process.rst @@ -46,16 +46,10 @@ and :method:`Symfony\\Component\\Process\\Process::getIncrementalErrorOutput` methods returns the new outputs since the last call. .. versionadded:: 2.4 - The ``getAndFlushOutput()``, ``getAndFlushIncrementalOutput()``, ``getAndFlushErrorOutput()``, - ``getAndFlushIncrementalErrorOutput()``, ``flushOutput()`` and ``flushErrorOutput()`` methods were - added in Symfony 2.4. + The ``flushOutput()`` and ``flushErrorOutput()`` methods were added in Symfony 2.4. The :method:`Symfony\\Component\\Process\\Process::flushOutput()` method flushes the contents of the output and -and :method:`Symfony\\Component\\Process\\Process::flushErrorOutput()` the content of the error output. You can get the -contents and flush the whole output or the error output by using :method:`Symfony\\Component\\Process\\Process::getAndFlushOutput()` -and :method:`Symfony\\Component\\Process\\Process::getAndFlushErrorOutput()` methods, or the outputs since the last call -by using the :method:`Symfony\\Component\\Process\\Process::getAndFlushIncrementalOutput()` and -:method:`Symfony\\Component\\Process\\Process::getAndFlushIncrementalErrorOutput()` methods. +and :method:`Symfony\\Component\\Process\\Process::flushErrorOutput()` the content of the error output. Getting real-time Process Output -------------------------------- From 8e6f084a9a980fbd4f9a26328601653eb334a10b Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 10 Aug 2013 04:30:18 -0700 Subject: [PATCH 0019/1181] [#2840] Minor tweaks to new orientation Image validation constraints --- reference/constraints/Image.rst | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/reference/constraints/Image.rst b/reference/constraints/Image.rst index e376d875485..b303641f16c 100644 --- a/reference/constraints/Image.rst +++ b/reference/constraints/Image.rst @@ -9,9 +9,9 @@ Additionally it has options so you can validate against the width and height of the image. .. versionadded:: 2.4 - As of Symfony 2.4 you can also validate against the image aspect ratio ( defined - as ``width / height``) and selectively allow square, landscape and portrait - image orientations. + As of Symfony 2.4 you can also validate against the image aspect ratio + (defined as ``width / height``) and selectively allow square, landscape + and portrait image orientations. See the :doc:`File` constraint for the bulk of the documentation on this constraint. @@ -284,39 +284,41 @@ value in pixels. maxRatio ~~~~~~~~ -**type**: ``integer`` +**type**: ``float`` -If set, the aspect ratio (``width / height``) of the image file must be less than or equal to this -value. +If set, the aspect ratio (``width / height``) of the image file must be less +than or equal to this value. minRatio ~~~~~~~~ -**type**: ``integer`` +**type**: ``float`` -If set, the aspect ratio (``width / height``) of the image file must be greater than or equal to this -value. +If set, the aspect ratio (``width / height``) of the image file must be greater +than or equal to this value. allowSquare ~~~~~~~~~~~ **type**: ``Boolean`` **default**: ``true`` -If this option is false, the image must not be square. +If this option is false, the image cannot be a square. If you want to force +a square image, then set leave this option as its default ``true`` value +and set `allowLandscape`_ and `allowPortrait`_ both to ``false``. allowLandscape ~~~~~~~~~~~~~~ **type**: ``Boolean`` **default**: ``true`` -If this option is false, the image must not be landscape oriented. +If this option is false, the image cannot be landscape oriented. allowPortrait ~~~~~~~~~~~~~ **type**: ``Boolean`` **default**: ``true`` -If this option is false, the image must not be portrait oriented. +If this option is false, the image cannot be portrait oriented. sizeNotDetectedMessage ~~~~~~~~~~~~~~~~~~~~~~ @@ -324,7 +326,7 @@ sizeNotDetectedMessage **type**: ``string`` **default**: ``The size of the image could not be detected`` If the system is unable to determine the size of the image, this error will -be displayed. This will only occur when at least one of the four size constraint +be displayed. This will only occur when at least one of the size constraint options has been set. maxWidthMessage @@ -397,6 +399,6 @@ allowPortraitMessage **type**: ``string`` **default**: ``The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed`` -The error message if the image is portrait oriented and you set `allowPoirtrait`_ to ``false``. +The error message if the image is portrait oriented and you set `allowPortrait`_ to ``false``. .. _`IANA website`: http://www.iana.org/assignments/media-types/image/index.html From 03aaa5c195da6003faf3135d61a5c0c87ee5ad9e Mon Sep 17 00:00:00 2001 From: Jeroen van den Enden Date: Sun, 11 Aug 2013 14:12:13 +0200 Subject: [PATCH 0020/1181] Document possibility to use ContainerAwareTrait In addition to https://github.com/symfony/symfony/pull/8488 --- book/controller.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/book/controller.rst b/book/controller.rst index c8e01927de2..5955938a626 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -378,8 +378,11 @@ itself. Extending the base class is *optional* in Symfony; it contains useful shortcuts but nothing mandatory. You can also extend - :class:`Symfony\\Component\\DependencyInjection\\ContainerAware`. The service - container object will then be accessible via the ``container`` property. + :class:`Symfony\\Component\\DependencyInjection\\ContainerAware`or use the + :class:`Symfony\\Component\\DependencyInjection\\ContainerAwareTrait` (>= PHP 5.4). + Both provide an implementation to the + :class:`Symfony\\Component\\DependencyInjection\\ContainerAwareInterface`, making the + service container object accessible via the ``container`` property. .. note:: From 3d27f535b139d1abde92fea5ab3aec16731f675e Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 17 Aug 2013 12:23:10 -0400 Subject: [PATCH 0021/1181] [#2630] Tweaks for new stopwatch tag - updating version, syntax for using it, and wrong bundle name --- reference/twig_reference.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/reference/twig_reference.rst b/reference/twig_reference.rst index a6cbfc1d8a4..c7abf7cb716 100644 --- a/reference/twig_reference.rst +++ b/reference/twig_reference.rst @@ -134,8 +134,8 @@ Filters Tags ---- -.. versionadded:: 2.3 - The stopwatch tag was added in Symfony 2.3 +.. versionadded:: 2.4 + The stopwatch tag was added in Symfony 2.4. +---------------------------------------------------+--------------------------------------------------------------------+ | Tag Syntax | Usage | @@ -153,8 +153,8 @@ Tags | ``{% trans_default_domain language %}`` | This will set the default domain for message catalogues in the | | | current template | +---------------------------------------------------+--------------------------------------------------------------------+ -| ``{% stopwatch name %}...{% endstopwatch %}`` | This will time the run time of the code inside it and put that on | -| | the timeline of the WebDeveloperBundle. | +| ``{% stopwatch 'name' %}...{% endstopwatch %}`` | This will time the run time of the code inside it and put that on | +| | the timeline of the WebProfilerBundle. | +---------------------------------------------------+--------------------------------------------------------------------+ Tests From c6e50b769ad5a4c4ddbc0492fa25c9e243b7ff54 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 17 Aug 2013 13:20:35 -0400 Subject: [PATCH 0022/1181] Removing several "2.1" references, which is consistent with our release process: "Remove all versionadded directives - and any other notes related to features changing or being new - for the version (e.g. 2.1) from the master branch. The result is that the next release (which is the first that comes entirely after the end of maintenance of this branch), will have no mentions of the old version (e.g. 2.1)." This should have been done when 2.1 reached end of maintenance, but the release process wasn't formed at that time. Also, the release of 2.3 and the end of maintenance for 2.1 were unique because they basically happened at the same time. For our purposes, we assume that 2.3 was released before the 2.1 end of life, which means that the 2.1 references are removed for 2.4 (master), not for 2.3. --- book/forms.rst | 5 ----- book/security.rst | 10 ++++------ book/translation.rst | 5 ----- components/config/definition.rst | 7 ++----- components/event_dispatcher/immutable_dispatcher.rst | 3 --- components/process.rst | 3 --- cookbook/configuration/pdo_session_storage.rst | 7 ------- reference/constraints/Regex.rst | 3 --- reference/dic_tags.rst | 6 ------ 9 files changed, 6 insertions(+), 43 deletions(-) diff --git a/book/forms.rst b/book/forms.rst index b23e895b1b6..70f0fc934ab 100644 --- a/book/forms.rst +++ b/book/forms.rst @@ -1792,11 +1792,6 @@ The answer is to setup the constraints yourself, and attach them to the individu fields. The overall approach is covered a bit more in the :ref:`validation chapter`, but here's a short example: -.. versionadded:: 2.1 - The ``constraints`` option, which accepts a single constraint or an array - of constraints (before 2.1, the option was called ``validation_constraint``, - and only accepted a single constraint) is new to Symfony 2.1. - .. code-block:: php use Symfony\Component\Validator\Constraints\Length; diff --git a/book/security.rst b/book/security.rst index 071ce973635..1cd411ac422 100644 --- a/book/security.rst +++ b/book/security.rst @@ -418,12 +418,8 @@ submission (i.e. ``/login_check``): You will *not* need to implement a controller for the ``/login_check`` URL as the firewall will automatically catch and process any form submitted - to this URL. - -.. versionadded:: 2.1 - As of Symfony 2.1, you *must* have routes configured for your ``login_path``, - ``check_path`` ``logout`` keys. These keys can be route names (as shown - in this example) or URLs that have routes configured for them. + to this URL. However, you *must* have a route (as shown here) for this + URL, as well as one for your logout path (see :ref:`book-security-logging-out`). Notice that the name of the ``login`` route matches the ``login_path`` config value, as that's where the security system will redirect users that need @@ -1700,6 +1696,8 @@ In the above configuration, users with ``ROLE_ADMIN`` role will also have the ``ROLE_USER`` role. The ``ROLE_SUPER_ADMIN`` role has ``ROLE_ADMIN``, ``ROLE_ALLOWED_TO_SWITCH`` and ``ROLE_USER`` (inherited from ``ROLE_ADMIN``). +.. _book-security-logging-out: + Logging Out ----------- diff --git a/book/translation.rst b/book/translation.rst index 360c17b602b..d9a3b1ddfe0 100644 --- a/book/translation.rst +++ b/book/translation.rst @@ -557,11 +557,6 @@ by defining a ``default_locale`` for the framework: 'default_locale' => 'en', )); -.. versionadded:: 2.1 - The ``default_locale`` parameter was defined under the session key - originally, however, as of 2.1 this has been moved. This is because the - locale is now set on the request instead of the session. - .. _book-translation-locale-url: The Locale and the URL diff --git a/components/config/definition.rst b/components/config/definition.rst index d43aea02052..cb901ceb169 100644 --- a/components/config/definition.rst +++ b/components/config/definition.rst @@ -100,8 +100,8 @@ node definition. Node type are available for: * scalar * boolean * integer (new in 2.2) -* float (new in 2.2) -* enum (new in 2.1) +* float +* enum * array * variable (no validation) @@ -136,9 +136,6 @@ allowing to validate the value:: Enum nodes ~~~~~~~~~~ -.. versionadded:: 2.1 - The enum node is new in Symfony 2.1 - Enum nodes provide a constraint to match the given input against a set of values:: diff --git a/components/event_dispatcher/immutable_dispatcher.rst b/components/event_dispatcher/immutable_dispatcher.rst index c5d17eb6f00..5b01136e558 100644 --- a/components/event_dispatcher/immutable_dispatcher.rst +++ b/components/event_dispatcher/immutable_dispatcher.rst @@ -4,9 +4,6 @@ The Immutable Event Dispatcher ============================== -.. versionadded:: 2.1 - This feature was added in Symfony 2.1. - The :class:`Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher` is a locked or frozen event dispatcher. The dispatcher cannot register new listeners or subscribers. diff --git a/components/process.rst b/components/process.rst index c10824d77dd..a13e901329a 100644 --- a/components/process.rst +++ b/components/process.rst @@ -64,9 +64,6 @@ anonymous function to the } }); -.. versionadded:: 2.1 - The non-blocking feature was added in 2.1. - Running Processes Asynchronously -------------------------------- diff --git a/cookbook/configuration/pdo_session_storage.rst b/cookbook/configuration/pdo_session_storage.rst index 758b7b0fb92..a6b1886682b 100644 --- a/cookbook/configuration/pdo_session_storage.rst +++ b/cookbook/configuration/pdo_session_storage.rst @@ -14,13 +14,6 @@ Symfony2 has a built-in solution for database session storage called To use it, you just need to change some parameters in ``config.yml`` (or the configuration format of your choice): -.. versionadded:: 2.1 - In Symfony2.1 the class and namespace are slightly modified. You can now - find the session storage classes in the `Session\\Storage` namespace: - ``Symfony\Component\HttpFoundation\Session\Storage``. Also - note that in Symfony2.1 you should configure ``handler_id`` not ``storage_id`` like in Symfony2.0. - Below, you'll notice that ``%session.storage.options%`` is not used anymore. - .. configuration-block:: .. code-block:: yaml diff --git a/reference/constraints/Regex.rst b/reference/constraints/Regex.rst index 2bdf0a8a87c..784600743e4 100644 --- a/reference/constraints/Regex.rst +++ b/reference/constraints/Regex.rst @@ -177,9 +177,6 @@ string *does* match this pattern. htmlPattern ~~~~~~~~~~~ -.. versionadded:: 2.1 - The ``htmlPattern`` option was added in Symfony 2.1 - **type**: ``string|Boolean`` **default**: null This option specifies the pattern to use in the HTML5 ``pattern`` attribute. diff --git a/reference/dic_tags.rst b/reference/dic_tags.rst index ca23140ddcb..fe284080688 100644 --- a/reference/dic_tags.rst +++ b/reference/dic_tags.rst @@ -964,9 +964,6 @@ translation.extractor **Purpose**: To register a custom service that extracts messages from a file -.. versionadded:: 2.1 - The ability to add message extractors is new in Symfony 2.1. - When executing the ``translation:update`` command, it uses extractors to extract translation messages from a file. By default, the Symfony2 framework has a :class:`Symfony\\Bridge\\Twig\\Translation\\TwigExtractor` and a @@ -1035,9 +1032,6 @@ translation.dumper **Purpose**: To register a custom service that dumps messages to a file -.. versionadded:: 2.1 - The ability to add message dumpers is new in Symfony 2.1. - After an `Extractor `_ has extracted all messages from the templates, the dumpers are executed to dump the messages to a translation file in a specific format. From a801c09bf18ac6ee67161230aa4e7361ad63824c Mon Sep 17 00:00:00 2001 From: endroid Date: Tue, 27 Aug 2013 18:53:36 -0400 Subject: [PATCH 0023/1181] Improve documentation of ContentAwareTrait --- book/controller.rst | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) mode change 100644 => 100755 book/controller.rst diff --git a/book/controller.rst b/book/controller.rst old mode 100644 new mode 100755 index 5955938a626..0c1ea72abb9 --- a/book/controller.rst +++ b/book/controller.rst @@ -378,11 +378,17 @@ itself. Extending the base class is *optional* in Symfony; it contains useful shortcuts but nothing mandatory. You can also extend - :class:`Symfony\\Component\\DependencyInjection\\ContainerAware`or use the - :class:`Symfony\\Component\\DependencyInjection\\ContainerAwareTrait` (>= PHP 5.4). - Both provide an implementation to the - :class:`Symfony\\Component\\DependencyInjection\\ContainerAwareInterface`, making the - service container object accessible via the ``container`` property. + :class:`Symfony\\Component\\DependencyInjection\\ContainerAware`. The service + container object will then be accessible via the ``container`` property. + +.. tip:: + + If your host uses PHP 5.4 or higher, you can also use the + class:`Symfony\\Component\\DependencyInjection\\ContainerAwareTrait` trait to + make the container accessible via the ``container`` property. + +.. versionadded:: 2.4 + The ``ContainerAwareTrait`` is new in Symfony 2.4 .. note:: From 066fcd5cac6293869c581058385add43891d1989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=A4rtner?= Date: Sun, 1 Sep 2013 15:49:13 +0200 Subject: [PATCH 0024/1181] Added docs for the changes proposed in symfony/symfony#8908 --- components/filesystem.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/filesystem.rst b/components/filesystem.rst index df97db82ca6..9b9ffef2eb1 100644 --- a/components/filesystem.rst +++ b/components/filesystem.rst @@ -28,7 +28,7 @@ endpoint for filesystem operations:: try { $fs->mkdir('/tmp/random/dir/' . mt_rand()); } catch (IOException $e) { - echo "An error occurred while creating your directory"; + echo "An error occurred while creating your directory at ".$e.getPath(); } .. note:: @@ -251,7 +251,7 @@ Error Handling -------------- Whenever something wrong happens, an exception implementing -:class:`Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface` is +:class:`Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface` and :class:`Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface` is thrown. .. note:: From 7afa87fbea5bba2b1799b1d2b93a0af3e20c31b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=A4rtner?= Date: Sun, 1 Sep 2013 16:55:44 +0200 Subject: [PATCH 0025/1181] Update filesystem.rst --- components/filesystem.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/filesystem.rst b/components/filesystem.rst index 9b9ffef2eb1..60344f6212e 100644 --- a/components/filesystem.rst +++ b/components/filesystem.rst @@ -251,8 +251,8 @@ Error Handling -------------- Whenever something wrong happens, an exception implementing -:class:`Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface` and :class:`Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface` is -thrown. +:class:`Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface` and +:class:`Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface` is thrown. .. note:: From feb346d14c16b11d54136d4025b6ddeb335e8cc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=A4rtner?= Date: Sun, 1 Sep 2013 21:59:54 +0200 Subject: [PATCH 0026/1181] Update filesystem.rst --- components/filesystem.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/filesystem.rst b/components/filesystem.rst index 60344f6212e..21c1afc1291 100644 --- a/components/filesystem.rst +++ b/components/filesystem.rst @@ -28,7 +28,7 @@ endpoint for filesystem operations:: try { $fs->mkdir('/tmp/random/dir/' . mt_rand()); } catch (IOException $e) { - echo "An error occurred while creating your directory at ".$e.getPath(); + echo "An error occurred while creating your directory at ".$e->getPath(); } .. note:: From d03f39dc184ccb152cff120f1526606b8ba1a62d Mon Sep 17 00:00:00 2001 From: daniele Date: Fri, 6 Sep 2013 11:04:13 +0200 Subject: [PATCH 0027/1181] Added configuration to enable profiler in test --- book/testing.rst | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/book/testing.rst b/book/testing.rst index 5ec4ebaf683..65104368a11 100644 --- a/book/testing.rst +++ b/book/testing.rst @@ -473,6 +473,52 @@ To get the Profiler for the last request, do the following:: For specific details on using the profiler inside a test, see the :doc:`/cookbook/testing/profiling` cookbook entry. +To avoid collecting data in each test you can set the ``collect`` parameter +in the configuration: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config_test.yml + + # ... + framework: + profiler: + enabled: true + collect: false + + .. code-block:: xml + + + + + + + + + + + + + .. code-block:: php + + // app/config/config.php + + // ... + $container->loadFromExtension('framework', array( + 'profiler' => array( + 'enabled' => true, + 'collect' => false, + ), + )); + +In this way only tests that call ``enableProfiler()`` will collect data. + Redirecting ~~~~~~~~~~~ From d9050a56d6a2574b0be48c6a907dff647fb22f03 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 8 Sep 2013 08:30:32 +0200 Subject: [PATCH 0028/1181] added documentation for the new request_stack service --- book/service_container.rst | 38 +++++++++++++++++++++------ cookbook/service_container/scopes.rst | 16 +++++------ 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/book/service_container.rst b/book/service_container.rst index c8e64bc7c4f..d24b77d95d6 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -270,14 +270,6 @@ looks up the value of each parameter and uses it in the service definition. http://symfony.com/?foo=%%s&bar=%%d -.. caution:: - - You may receive a - :class:`Symfony\\Component\\DependencyInjection\\Exception\\ScopeWideningInjectionException` - when passing the ``request`` service as an argument. To understand this - problem better and learn how to solve it, refer to the cookbook article - :doc:`/cookbook/service_container/scopes`. - The purpose of parameters is to feed information into services. Of course there was nothing wrong with defining the service without using any parameters. Parameters, however, have several advantages: @@ -762,6 +754,36 @@ Injecting the dependency by the setter method just needs a change of syntax: and "setter injection". The Symfony2 service container also supports "property injection". +Injecting the Request +~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 2.4 + The ``request_stack`` service was introduced in version 2.4. + +Almost all Symfony2 built-in services behave in the same way: a single +instance is created by the container which it returns whenever you get it or +when it is injected into another service. There is one exception in a standard +Symfony2 application: the ``request`` service. + +If you try to inject the ``request`` into a service, you will probably receive +a +:class:`Symfony\\Component\\DependencyInjection\\Exception\\ScopeWideningInjectionException` +exception. That's because the ``request`` can **change** during the life-time +of a container (when a sub-request is created for instance). + +As of Symfony 2.4, instead of injecting the ``request`` service, you should +inject the ``request_stack`` service instead and access the Request by calling +the ``getCurrentRequest()`` method. For earlier versions, or if you want to +understand this problem better, refer to the cookbook article +:doc:`/cookbook/service_container/scopes`. + +.. tip:: + + If you define a controller as a service then you can get the ``Request`` + object without injecting the container by having it passed in as an + argument of your action method. See + :ref:`book-controller-request-argument` for details. + Making References Optional -------------------------- diff --git a/cookbook/service_container/scopes.rst b/cookbook/service_container/scopes.rst index 8f5e8af0cfe..68a301a1101 100644 --- a/cookbook/service_container/scopes.rst +++ b/cookbook/service_container/scopes.rst @@ -6,8 +6,13 @@ How to work with Scopes This entry is all about scopes, a somewhat advanced topic related to the :doc:`/book/service_container`. If you've ever gotten an error mentioning -"scopes" when creating services, or need to create a service that depends -on the ``request`` service, then this entry is for you. +"scopes" when creating services, then this entry is for you. + +.. note:: + + If you are trying to inject the ``request`` service, the simple solution + is to inject the ``request_stack`` service instead and access the current + Request by calling the ``getCurrentRequest()`` method. Understanding Scopes -------------------- @@ -337,10 +342,3 @@ The service config for this class would look something like this: Injecting the whole container into a service is generally not a good idea (only inject what you need). - -.. tip:: - - If you define a controller as a service then you can get the ``Request`` - object without injecting the container by having it passed in as an - argument of your action method. See - :ref:`book-controller-request-argument` for details. From 3780933fb43bc357d94e196e3011b3599d3d87bc Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 10 Sep 2013 21:51:03 +0200 Subject: [PATCH 0029/1181] Documented Stopwatch Helper --- cookbook/templating/PHP.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cookbook/templating/PHP.rst b/cookbook/templating/PHP.rst index a3454abbb29..759e124e0d2 100644 --- a/cookbook/templating/PHP.rst +++ b/cookbook/templating/PHP.rst @@ -310,6 +310,21 @@ portable. Thanks to this helper, you can move the application root directory anywhere under your web root directory without changing anything in your template's code. +Profiling Templates +~~~~~~~~~~~~~~~~~~~ + +Using the ``stopwatch`` helper, you are able to time parts of your template +and display it on the timeline of the WebProfilerBundle:: + + start('foo') ?> + ... things that gets timed + stop('foo') ?> + +.. tip:: + + If you use the same name more than once in your template, the times are + grouped on the same line in the timeline. + Output Escaping --------------- From b84f52c28d969b5143521261d818105824eaea5e Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 11 Sep 2013 21:40:59 -0500 Subject: [PATCH 0030/1181] [#2956] A few more changes to the scopes chapter to update the new way of working with the request service --- cookbook/service_container/scopes.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cookbook/service_container/scopes.rst b/cookbook/service_container/scopes.rst index 68a301a1101..f305a97837d 100644 --- a/cookbook/service_container/scopes.rst +++ b/cookbook/service_container/scopes.rst @@ -79,12 +79,14 @@ when compiling the container. Read the sidebar below for more details. Using a Service from a narrower Scope ------------------------------------- -If your service has a dependency on a scoped service (like the ``request``), -you have three ways to deal with it: +The most common problem with "scope" is when your service has a dependency +on the ``request`` service. The *easiest* way to solve this is to instead +inject the ``request_stack`` service and access the current Request by calling +the ``getCurrentRequest()`` method. -* Use setter injection if the dependency is "synchronized"; this is the - recommended way and the best solution for the ``request`` instance as it is - synchronized with the ``request`` scope (see +This solution is great, but there are also others: + +* Use setter injection if the dependency is "synchronized"; (see :ref:`using-synchronized-service`). * Put your service in the same scope as the dependency (or a narrower one). If @@ -108,7 +110,7 @@ Using a synchronized Service Injecting the container or setting your service to a narrower scope have drawbacks. For synchronized services (like the ``request``), using setter -injection is the best option as it has no drawbacks and everything works +injection is a nice option as it has no drawbacks and everything works without any special code in your service or in your definition:: // src/Acme/HelloBundle/Mail/Mailer.php From 67901ff4a4c4dbdedc6e4f11479759efdc4ed10a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 12 Sep 2013 19:49:24 +0200 Subject: [PATCH 0031/1181] document the getEncodings() method of the Request class --- components/http_foundation/introduction.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index f15372da975..0f64bc3f59f 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -240,7 +240,13 @@ by using the following methods: returns the list of accepted languages ordered by descending quality; * :method:`Symfony\\Component\\HttpFoundation\\Request::getCharsets`: - returns the list of accepted charsets ordered by descending quality. + returns the list of accepted charsets ordered by descending quality; + +* :method:`Symfony\\Component\\HttpFoundation\\Request::getEncodings`: + returns the list of accepted encodings in preferable order. + + .. versionadded:: 2.4 + The ``getEncodings()`` method was added in Symfony 2.4. .. versionadded:: 2.2 The :class:`Symfony\\Component\\HttpFoundation\\AcceptHeader` class is new in Symfony 2.2. From 3210251af21fc96b0f23129c69517f5ff362531d Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 18 Sep 2013 09:09:39 -0500 Subject: [PATCH 0032/1181] [#2891] Shortening note about ContainerAwareTrait --- book/controller.rst | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/book/controller.rst b/book/controller.rst index 74979301a6d..6904bd10248 100755 --- a/book/controller.rst +++ b/book/controller.rst @@ -392,17 +392,13 @@ itself. Extending the base class is *optional* in Symfony; it contains useful shortcuts but nothing mandatory. You can also extend - :class:`Symfony\\Component\\DependencyInjection\\ContainerAware`. The service - container object will then be accessible via the ``container`` property. - -.. tip:: - - If your host uses PHP 5.4 or higher, you can also use the - class:`Symfony\\Component\\DependencyInjection\\ContainerAwareTrait` trait to - make the container accessible via the ``container`` property. + :class:`Symfony\\Component\\DependencyInjection\\ContainerAware` or use + the class:`Symfony\\Component\\DependencyInjection\\ContainerAwareTrait` trait + (if you have PHP 5.4). The service container object will then be accessible + via the ``container`` property. .. versionadded:: 2.4 - The ``ContainerAwareTrait`` is new in Symfony 2.4 + The ``ContainerAwareTrait`` is new in Symfony 2.4. .. note:: From 887f0d2b682f58b5205c23de1f434b4ea652180f Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 26 Sep 2013 13:06:36 +0200 Subject: [PATCH 0033/1181] Updated the documentation for the simplified Callback constraint --- reference/constraints/Callback.rst | 253 +++++++++++++++++------------ 1 file changed, 147 insertions(+), 106 deletions(-) diff --git a/reference/constraints/Callback.rst b/reference/constraints/Callback.rst index a367ac9f5d5..93a279068b5 100644 --- a/reference/constraints/Callback.rst +++ b/reference/constraints/Callback.rst @@ -1,7 +1,12 @@ Callback ======== -The purpose of the Callback assertion is to let you create completely custom +.. versionadded:: 2.4 + The ``Callback`` constraint was simplified in Symfony 2.4. For usage + examples with older Symfony versions, see the corresponding versions of this + documentation page. + +The purpose of the Callback constraint is to create completely custom validation rules and to assign any validation errors to specific fields on your object. If you're using validation with forms, this means that you can make these custom errors display next to a specific field, instead of simply @@ -20,15 +25,15 @@ can do anything, including creating and assigning validation errors. +----------------+------------------------------------------------------------------------+ | Applies to | :ref:`class` | +----------------+------------------------------------------------------------------------+ -| Options | - `methods`_ | +| Options | - `callback`_ | +----------------+------------------------------------------------------------------------+ | Class | :class:`Symfony\\Component\\Validator\\Constraints\\Callback` | +----------------+------------------------------------------------------------------------+ | Validator | :class:`Symfony\\Component\\Validator\\Constraints\\CallbackValidator` | +----------------+------------------------------------------------------------------------+ -Setup ------ +Configuration +------------- .. configuration-block:: @@ -37,8 +42,7 @@ Setup # src/Acme/BlogBundle/Resources/config/validation.yml Acme\BlogBundle\Entity\Author: constraints: - - Callback: - methods: [isAuthorValid] + - Callback: validate .. code-block:: php-annotations @@ -46,12 +50,17 @@ Setup namespace Acme\BlogBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; + use Symfony\Component\Validator\ExecutionContextInterface; - /** - * @Assert\Callback(methods={"isAuthorValid"}) - */ class Author { + /** + * @Assert\Callback + */ + public function validate(ExecutionContextInterface $context) + { + // ... + } } .. code-block:: xml @@ -63,11 +72,7 @@ Setup xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd"> - - - + validate @@ -83,9 +88,7 @@ Setup { public static function loadValidatorMetadata(ClassMetadata $metadata) { - $metadata->addConstraint(new Assert\Callback(array( - 'methods' => array('isAuthorValid'), - ))); + $metadata->addConstraint(new Assert\Callback('validate')); } } @@ -98,133 +101,171 @@ those errors should be attributed:: // ... use Symfony\Component\Validator\ExecutionContextInterface; - + class Author { // ... private $firstName; - - public function isAuthorValid(ExecutionContextInterface $context) + + public function validate(ExecutionContextInterface $context) { // somehow you have an array of "fake names" - $fakeNames = array(); - + $fakeNames = array(/* ... */); + // check if the name is actually a fake name if (in_array($this->getFirstName(), $fakeNames)) { - $context->addViolationAt('firstname', 'This name sounds totally fake!', array(), null); + $context->addViolationAt('firstName', 'This name sounds totally fake!', array(), null); } } } -Options -------- +Static Callbacks +---------------- -methods -~~~~~~~ +You can also use the constraint with static methods. Since static methods don't +have access to the object instance, they receive the object as first argument:: -**type**: ``array`` **default**: ``array()`` [:ref:`default option`] + public static function validate($object, ExecutionContextInterface $context) + { + // somehow you have an array of "fake names" + $fakeNames = array(/* ... */); -This is an array of the methods that should be executed during the validation -process. Each method can be one of the following formats: + // check if the name is actually a fake name + if (in_array($object->getFirstName(), $fakeNames)) { + $context->addViolationAt('firstName', 'This name sounds totally fake!', array(), null); + } + } -1) **String method name** +External Callbacks and Closures +------------------------------- - If the name of a method is a simple string (e.g. ``isAuthorValid``), that - method will be called on the same object that's being validated and the - ``ExecutionContextInterface`` will be the only argument (see the above example). +If you want to execute a static callback method that is not located in the class +of the validated object, you can configure the constraint to invoke an array +callable as supported by PHP's :phpfunction:`call_user_func` function. Suppose +your validation function is `Vendor\Package\Validator::validate()`:: -2) **Static array callback** + namespace Vendor\Package; - Each method can also be specified as a standard array callback: + use Symfony\Component\Validator\ExecutionContextInterface; - .. configuration-block:: + class Validator + { + public function validate($object, ExecutionContextInterface $context) + { + // ... + } + } - .. code-block:: yaml +You can then use the following configuration to invoke this validator:: - # src/Acme/BlogBundle/Resources/config/validation.yml - Acme\BlogBundle\Entity\Author: - constraints: - - Callback: - methods: - - [Acme\BlogBundle\MyStaticValidatorClass, isAuthorValid] +.. configuration-block:: - .. code-block:: php-annotations + .. code-block:: yaml - // src/Acme/BlogBundle/Entity/Author.php - use Symfony\Component\Validator\Constraints as Assert; + # src/Acme/BlogBundle/Resources/config/validation.yml + Acme\BlogBundle\Entity\Author: + constraints: + - Callback: [Vendor\Package\Validator, validate] - /** - * @Assert\Callback(methods={ - * { "Acme\BlogBundle\MyStaticValidatorClass", "isAuthorValid"} - * }) - */ - class Author - { - } + .. code-block:: php-annotations - .. code-block:: xml + // src/Acme/BlogBundle/Entity/Author.php + namespace Acme\BlogBundle\Entity; - - - + use Symfony\Component\Validator\Constraints as Assert; + use Symfony\Component\Validator\ExecutionContextInterface; - - - - - - + /** + * @Assert\Callback({"Vendor\Package\Validator", "validate"}) + */ + class Author + { + } - .. code-block:: php + .. code-block:: xml - // src/Acme/BlogBundle/Entity/Author.php + + + + + + + Vendor\Package\Validator + validate + + + - use Symfony\Component\Validator\Mapping\ClassMetadata; - use Symfony\Component\Validator\Constraints\Callback; + .. code-block:: php - class Author + // src/Acme/BlogBundle/Entity/Author.php + namespace Acme\BlogBundle\Entity; + + use Symfony\Component\Validator\Mapping\ClassMetadata; + use Symfony\Component\Validator\Constraints as Assert; + + class Author + { + public static function loadValidatorMetadata(ClassMetadata $metadata) { - public $name; - - public static function loadValidatorMetadata(ClassMetadata $metadata) - { - $metadata->addConstraint(new Callback(array( - 'methods' => array( - array('Acme\BlogBundle\MyStaticValidatorClass', 'isAuthorValid'), - ), - ))); - } + $metadata->addConstraint(new Assert\Callback(array( + 'Vendor\Package\Validator', + 'validate' + ))); } + } - In this case, the static method ``isAuthorValid`` will be called on the - ``Acme\BlogBundle\MyStaticValidatorClass`` class. It's passed both the original - object being validated (e.g. ``Author``) as well as the ``ExecutionContextInterface``:: +.. note:: - namespace Acme\BlogBundle; - - use Symfony\Component\Validator\ExecutionContextInterface; - use Acme\BlogBundle\Entity\Author; - - class MyStaticValidatorClass + The Callback constraint does *not* support global callback functions or + It is *not* possible to specify a global function or a :term:`service` + method as callback. To validate using a service, you should + :doc:`create a custom validation constraint` + and add that new constraint to your class. + +When configuring the constraint via PHP, you can also pass a closure to the +constructor of the Callback constraint:: + + // src/Acme/BlogBundle/Entity/Author.php + namespace Acme\BlogBundle\Entity; + + use Symfony\Component\Validator\Mapping\ClassMetadata; + use Symfony\Component\Validator\Constraints as Assert; + + class Author + { + public static function loadValidatorMetadata(ClassMetadata $metadata) { - public static function isAuthorValid(Author $author, ExecutionContextInterface $context) - { + $callback = function ($object, ExecutionContextInterface $context) { // ... - } + }; + + $metadata->addConstraint(new Assert\Callback($callback)); } + } + +Options +------- + +callback +~~~~~~~~ + +**type**: ``string``, ``array`` or ``Closure`` [:ref:`default option`] + +The callback option accepts three different formats for specifying the +callback method: + +* A **string** containing the name of a concrete or static method. + +* An array callable with the format ``array('', '')``. + +* A closure. - .. tip:: +Concrete callbacks receive an :class:`Symfony\\Component\\Validator\\ExecutionContextInterface` +instance as only argument. - If you specify your ``Callback`` constraint via PHP, then you also have - the option to make your callback either a PHP closure or a non-static - callback. It is *not* currently possible, however, to specify a :term:`service` - as a constraint. To validate using a service, you should - :doc:`create a custom validation constraint` - and add that new constraint to your class. +Static or closure callbacks receive the validated object as first argument +and the :class:`Symfony\\Component\\Validator\\ExecutionContextInterface` +instance as second argument. From 893a7806c1c93c89f8435c414a7148cd2966d0e6 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 26 Sep 2013 14:33:14 -0500 Subject: [PATCH 0034/1181] [#3009] Updating information for 2.4 with the new checkPasswordLength method --- components/security/authentication.rst | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/components/security/authentication.rst b/components/security/authentication.rst index 016dde98c46..0f7c63d523b 100644 --- a/components/security/authentication.rst +++ b/components/security/authentication.rst @@ -198,10 +198,8 @@ own, it just needs to follow these rules: #. The class must implement :class:`Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface`; -#. The first line in ``encodePassword`` and ``isPasswordValid`` must check - to make sure the password is not too long (e.g. 4096). This is for security - (see `CVE-2013-5750`_), and you can copy the `BasePasswordEncoder::checkPasswordLength`_ - implementation from Symfony 2.4. +#. ``$this->checkPasswordLength($raw);`` must be the first code executed in + ``encodePassword()`` and ``isPasswordValid()`` (see `CVE-2013-5750`_). Using Password Encoders ~~~~~~~~~~~~~~~~~~~~~~~ @@ -227,5 +225,4 @@ which should be used to encode this user's password:: $password, $user->getSalt()); -.. _`CVE-2013-5750`: http://symfony.com/blog/cve-2013-5750-security-issue-in-fosuserbundle-login-form -.. _`BasePasswordEncoder::checkPasswordLength`: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.php \ No newline at end of file +.. _`CVE-2013-5750`: http://symfony.com/blog/cve-2013-5750-security-issue-in-fosuserbundle-login-form \ No newline at end of file From 574d7a826a15aaa83e96eb492437767016bb2551 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 28 Sep 2013 17:56:23 -0500 Subject: [PATCH 0035/1181] [#2913] Removing versionadded 2.1 messages from the master branch --- components/class_loader/cache_class_loader.rst | 6 ------ components/class_loader/class_loader.rst | 3 --- components/class_loader/debug_class_loader.rst | 3 --- 3 files changed, 12 deletions(-) diff --git a/components/class_loader/cache_class_loader.rst b/components/class_loader/cache_class_loader.rst index dbce3ce1929..01a393de216 100644 --- a/components/class_loader/cache_class_loader.rst +++ b/components/class_loader/cache_class_loader.rst @@ -26,9 +26,6 @@ for a class. ApcClassLoader -------------- -.. versionadded:: 2.1 - The ``ApcClassLoader`` class was added in Symfony 2.1. - ``ApcClassLoader`` wraps an existing class loader and caches calls to its ``findFile()`` method using `APC`_:: @@ -49,9 +46,6 @@ ApcClassLoader XcacheClassLoader ----------------- -.. versionadded:: 2.1 - The ``XcacheClassLoader`` class was added in Symfony 2.1. - ``XcacheClassLoader`` uses `XCache`_ to cache a class loader. Registering it is straightforward:: diff --git a/components/class_loader/class_loader.rst b/components/class_loader/class_loader.rst index c5f2d65b70d..44de944443e 100644 --- a/components/class_loader/class_loader.rst +++ b/components/class_loader/class_loader.rst @@ -4,9 +4,6 @@ The PSR-0 Class Loader ====================== -.. versionadded:: 2.1 - The ``ClassLoader`` class was added in Symfony 2.1. - If your classes and third-party libraries follow the `PSR-0`_ standard, you can use the :class:`Symfony\\Component\\ClassLoader\\ClassLoader` class to load all of your project's classes. diff --git a/components/class_loader/debug_class_loader.rst b/components/class_loader/debug_class_loader.rst index 2af2e158401..7533f715b07 100644 --- a/components/class_loader/debug_class_loader.rst +++ b/components/class_loader/debug_class_loader.rst @@ -4,9 +4,6 @@ Debugging a Class Loader ======================== -.. versionadded:: 2.1 - The ``DebugClassLoader`` class was added in Symfony 2.1. - The :class:`Symfony\\Component\\ClassLoader\\DebugClassLoader` attempts to throw more helpful exceptions when a class isn't found by the registered autoloaders. All autoloaders that implement a ``findFile()`` method are replaced From a8666062621a3638abf156e17f86420a1fc7ca4e Mon Sep 17 00:00:00 2001 From: Adrien Brault Date: Fri, 27 Sep 2013 15:53:12 -0700 Subject: [PATCH 0036/1181] Add a cookbook entry on how to limit session metadata writes --- cookbook/map.rst.inc | 1 + cookbook/session/index.rst | 3 +- cookbook/session/limit_metadata_writes.rst | 68 ++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 cookbook/session/limit_metadata_writes.rst diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index c4196b0b035..d98207e594d 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -148,6 +148,7 @@ * :doc:`/cookbook/session/locale_sticky_session` * :doc:`/cookbook/session/sessions_directory` * :doc:`/cookbook/session/php_bridge` + * :doc:`/cookbook/session/limit_metadata_writes` * **symfony1** diff --git a/cookbook/session/index.rst b/cookbook/session/index.rst index 536ad02c3d8..dede3362434 100644 --- a/cookbook/session/index.rst +++ b/cookbook/session/index.rst @@ -7,4 +7,5 @@ Sessions proxy_examples locale_sticky_session sessions_directory - php_bridge \ No newline at end of file + php_bridge + limit_metadata_writes diff --git a/cookbook/session/limit_metadata_writes.rst b/cookbook/session/limit_metadata_writes.rst new file mode 100644 index 00000000000..b2d0208d21c --- /dev/null +++ b/cookbook/session/limit_metadata_writes.rst @@ -0,0 +1,68 @@ +.. index:: + single: Limit Metadata Writes; Session + +Limit session metadata writes +============================= + +.. versionadded:: 2.4 + The ability to limit session metadata writes was added in Symfony 2.4. + +The default behaviour of PHP session is to persist the session regardless of +whether the session data has changed or not. In Symfony, each time the session +is accessed metadata is recorded (session created/last used) which can be used +to determine session age and idle time. + +If for performance reasons you wish to limit the frequency at which the session +persists, this feature can adjust the granularity of the metadata updates and +persist the session less often while still maintaining relatively accurate +metadata. If other session data is changed, the session will always persist. + +You can tell Symfony not to update the metadata "session last updated" time +until a certain amount of time has passed, by setting +``framework.session.metadata_update_threshold`` to a value in seconds greater +than zero: + +.. configuration-block:: + + .. code-block:: yaml + + framework: + session: + metadata_update_threshold: 120 + + .. code-block:: xml + + + + + + + + + + + .. code-block:: php + + $container->loadFromExtension('framework', array( + 'session' => array( + 'metadata_update_threshold' => 120, + ), + )); + +.. info:: + + PHP default's behavior is to save the session whether it has been changed or + not. When using ``framework.session.metadata_update_threshold`` Symfony + will wrap the session handler (configured at + ``framework.session.handler_id``) into the WriteCheckSessionHandler, that + will prevent any session write if the session was not modified. + +.. caution:: + + Be aware that if the session is not written at every request, it may be + garbage collected sooner than usual. This means that your users may be + logged out sooner than expected. From 0e9f02a96b5955cc477a101aa595686390800290 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 30 Sep 2013 22:45:55 +0200 Subject: [PATCH 0037/1181] added documentation about Request::setFactory() --- components/http_foundation/introduction.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index f15372da975..ba37c78aa25 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -269,6 +269,26 @@ request information. Have a look at :class:`the Request API` for more information about them. +Overriding the Request +~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 2.4 + The :method:`Symfony\\Component\\HttpFoundation\\Request::setFactory` + class was added in Symfony 2.4. + +The Request class should not be overridden as it is a data object that +represents an HTTP message. But when moving from a legacy system, adding +methods or changing some default behavior might help. In that case, register a +PHP callable that is able to create an instance of your Request class:: + + use Symfony\Component\HttpFoundation\Request; + + Request::setFactory(function (array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { + return SpecialRequest::create($query, $request, $attributes, $cookies, $files, $server, $content); + }); + + $request = Request::createFromGlobals(); + .. _component-http-foundation-response: Response From 16799b4db8717fcccfbb3ad0ec83085a57d4946d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 2 Oct 2013 09:37:56 +0200 Subject: [PATCH 0038/1181] added the compact layout information --- components/console/helpers/tablehelper.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/console/helpers/tablehelper.rst b/components/console/helpers/tablehelper.rst index 1145dd7b603..4bc3323ebe6 100644 --- a/components/console/helpers/tablehelper.rst +++ b/components/console/helpers/tablehelper.rst @@ -32,12 +32,17 @@ table rendering: using named layouts or by customizing rendering options. Customize Table Layout using Named Layouts ------------------------------------------ -The Table helper ships with two preconfigured table layouts: +.. versionadded:: 2.4 + The ``TableHelper::LAYOUT_COMPACT`` layout was added in Symfony 2.4. + +The Table helper ships with three preconfigured table layouts: * ``TableHelper::LAYOUT_DEFAULT`` * ``TableHelper::LAYOUT_BORDERLESS`` +* ``TableHelper::LAYOUT_COMPACT`` + Layout can be set using :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setLayout` method. Customize Table Layout using Rendering Options From 7e0cb8bb05e993b4b983bd82bbebef56261e7479 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 2 Oct 2013 17:27:58 -0400 Subject: [PATCH 0039/1181] [#2947] Adding versionadded details --- components/filesystem.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/components/filesystem.rst b/components/filesystem.rst index 21c1afc1291..d59827885bc 100644 --- a/components/filesystem.rst +++ b/components/filesystem.rst @@ -21,16 +21,21 @@ The :class:`Symfony\\Component\\Filesystem\\Filesystem` class is the unique endpoint for filesystem operations:: use Symfony\Component\Filesystem\Filesystem; - use Symfony\Component\Filesystem\Exception\IOException; + use Symfony\Component\Filesystem\Exception\IOExceptionInterface; $fs = new Filesystem(); try { $fs->mkdir('/tmp/random/dir/' . mt_rand()); - } catch (IOException $e) { + } catch (IOExceptionInterface $e) { echo "An error occurred while creating your directory at ".$e->getPath(); } +.. versionadded:: + + The ``IOExceptionInterface`` and its ``getPath`` method are new in Symfony + 2.4. Prior to 2.4, you would catch the ``IOException`` class. + .. note:: Methods :method:`Symfony\\Component\\Filesystem\\Filesystem::mkdir`, @@ -251,7 +256,7 @@ Error Handling -------------- Whenever something wrong happens, an exception implementing -:class:`Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface` and +:class:`Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface` or :class:`Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface` is thrown. .. note:: From 2be6510ec8af216976901e0f05ab3bfef4e10963 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 2 Oct 2013 17:31:28 -0400 Subject: [PATCH 0040/1181] [#2960] Minor changes thanks to @xabbuh --- cookbook/templating/PHP.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook/templating/PHP.rst b/cookbook/templating/PHP.rst index 759e124e0d2..3db2f9b23fb 100644 --- a/cookbook/templating/PHP.rst +++ b/cookbook/templating/PHP.rst @@ -313,11 +313,11 @@ template's code. Profiling Templates ~~~~~~~~~~~~~~~~~~~ -Using the ``stopwatch`` helper, you are able to time parts of your template +By using the ``stopwatch`` helper, you are able to time parts of your template and display it on the timeline of the WebProfilerBundle:: start('foo') ?> - ... things that gets timed + ... things that get timed stop('foo') ?> .. tip:: From 88f051a137b18292eb1797ff5345fd5e0ed2c9db Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 2 Oct 2013 17:43:47 -0400 Subject: [PATCH 0041/1181] [#2728] Minor tweaks to docs on Process flush methods --- components/process.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/components/process.rst b/components/process.rst index 0add196b0ca..87c6942eb1c 100644 --- a/components/process.rst +++ b/components/process.rst @@ -48,8 +48,10 @@ methods returns the new outputs since the last call. .. versionadded:: 2.4 The ``flushOutput()`` and ``flushErrorOutput()`` methods were added in Symfony 2.4. -The :method:`Symfony\\Component\\Process\\Process::flushOutput()` method flushes the contents of the output and -and :method:`Symfony\\Component\\Process\\Process::flushErrorOutput()` the content of the error output. +The :method:`Symfony\\Component\\Process\\Process::flushOutput` method flushes +the contents of the output and +:method:`Symfony\\Component\\Process\\Process::flushErrorOutput` flushes +the content of the error output. Getting real-time Process Output -------------------------------- From 66f16729cd2e7e60c9ec2a593b956182ead3bab7 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 2 Oct 2013 17:53:55 -0400 Subject: [PATCH 0042/1181] [#2971] Minor language tweak to be consistent with the other areas The language used by @xabbuh is actually straight from the PHPDoc, which is cool, but I don't love the wording there, and having some variety in wording might help clarification. --- components/http_foundation/introduction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index 0f64bc3f59f..f1d3b1df79a 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -243,7 +243,7 @@ by using the following methods: returns the list of accepted charsets ordered by descending quality; * :method:`Symfony\\Component\\HttpFoundation\\Request::getEncodings`: - returns the list of accepted encodings in preferable order. + returns the list of accepted charsets ordered by descending quality; .. versionadded:: 2.4 The ``getEncodings()`` method was added in Symfony 2.4. From e52ac5cb02d2af23c2dc483fdb2e11ba2f9ecc88 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 4 Oct 2013 19:32:16 +0200 Subject: [PATCH 0043/1181] fix versionadded directive --- components/filesystem.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/filesystem.rst b/components/filesystem.rst index d59827885bc..9a50e256e2b 100644 --- a/components/filesystem.rst +++ b/components/filesystem.rst @@ -31,8 +31,7 @@ endpoint for filesystem operations:: echo "An error occurred while creating your directory at ".$e->getPath(); } -.. versionadded:: - +.. versionadded:: 2.4 The ``IOExceptionInterface`` and its ``getPath`` method are new in Symfony 2.4. Prior to 2.4, you would catch the ``IOException`` class. From 4732a76f571f1dd3903b4e825843a21bf22fe87b Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 5 Oct 2013 13:04:55 -0400 Subject: [PATCH 0044/1181] [#2728] Fixing typo thanks to @xabbuh --- components/process.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/process.rst b/components/process.rst index 87c6942eb1c..981ec69e493 100644 --- a/components/process.rst +++ b/components/process.rst @@ -51,7 +51,7 @@ methods returns the new outputs since the last call. The :method:`Symfony\\Component\\Process\\Process::flushOutput` method flushes the contents of the output and :method:`Symfony\\Component\\Process\\Process::flushErrorOutput` flushes -the content of the error output. +the contents of the error output. Getting real-time Process Output -------------------------------- From 1d94f348c5fcb333dc2c4588e29e6d5a284e4a9e Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 6 Oct 2013 11:23:11 -0400 Subject: [PATCH 0045/1181] [#3021] Minor tweaks thanks to @WouterJ and @GromNaN --- components/http_foundation/introduction.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index 8079be2a954..09c9f2ccc76 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -280,12 +280,12 @@ Overriding the Request .. versionadded:: 2.4 The :method:`Symfony\\Component\\HttpFoundation\\Request::setFactory` - class was added in Symfony 2.4. + method was added in Symfony 2.4. The Request class should not be overridden as it is a data object that represents an HTTP message. But when moving from a legacy system, adding methods or changing some default behavior might help. In that case, register a -PHP callable that is able to create an instance of your Request class:: +PHP callable that is able to create an instance of your ``Request`` class:: use Symfony\Component\HttpFoundation\Request; From cab5c89e5c608cd239a382b57c063f998da209ec Mon Sep 17 00:00:00 2001 From: Wouter J Date: Sun, 6 Oct 2013 20:04:50 +0200 Subject: [PATCH 0046/1181] Creates Expression Language chapter --- components/expression_language/index.rst | 7 +++++++ components/index.rst | 1 + components/map.rst.inc | 2 ++ 3 files changed, 10 insertions(+) create mode 100644 components/expression_language/index.rst diff --git a/components/expression_language/index.rst b/components/expression_language/index.rst new file mode 100644 index 00000000000..adddcd4fc6d --- /dev/null +++ b/components/expression_language/index.rst @@ -0,0 +1,7 @@ +Expression Language +=================== + +.. toctree:: + :maxdepth: 2 + + introduction diff --git a/components/index.rst b/components/index.rst index e5dffc58cd6..3cf769b6282 100644 --- a/components/index.rst +++ b/components/index.rst @@ -13,6 +13,7 @@ The Components dom_crawler dependency_injection/index event_dispatcher/index + expression_language/index filesystem finder form/index diff --git a/components/map.rst.inc b/components/map.rst.inc index a915310cde1..e1512b04ec2 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -57,6 +57,8 @@ * :doc:`/components/event_dispatcher/generic_event` * :doc:`/components/event_dispatcher/immutable_dispatcher` +* :doc:`/components/expression_language/index` + * **Filesystem** * :doc:`/components/filesystem` From 27822ffabb5eb94b9b8673a4064365b32003a1d8 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Sun, 6 Oct 2013 20:08:43 +0200 Subject: [PATCH 0047/1181] Bootstraps intro --- .../expression_language/introduction.rst | 23 +++++++++++++++++++ components/map.rst.inc | 2 ++ 2 files changed, 25 insertions(+) create mode 100644 components/expression_language/introduction.rst diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst new file mode 100644 index 00000000000..230a82ba1c0 --- /dev/null +++ b/components/expression_language/introduction.rst @@ -0,0 +1,23 @@ +.. index:: + single: Expressions + Single: Components; Expression Language + +The ExpressionLanguage Component +================================= + + The ExpressionLanguage component provides an engine that can compile and + evaluate expressions. An expression is a one-liner that returns a value + (mostly, but not limited to, Booleans). + +.. versionadded:: 2.4 + The ExpressionLanguage Component was new in Symfony 2.4. + +Installation +------------ + +You can install the component in 2 different ways: + +* Use the official Git repository (https://github.com/symfony/ExpressionLanguage); +* :doc:`Install it via Composer ` (``symfony/expression-language`` on `Packagist`_). + +.. _Packagist: https://packagist.org/packages/symfony/expression-language diff --git a/components/map.rst.inc b/components/map.rst.inc index e1512b04ec2..d55e3c4e721 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -59,6 +59,8 @@ * :doc:`/components/expression_language/index` + * :doc:`/components/expression_language/introduction` + * **Filesystem** * :doc:`/components/filesystem` From efe349e3ae0e9a285ba50384da4ac1a427f9e79c Mon Sep 17 00:00:00 2001 From: xabbuh Date: Sun, 6 Oct 2013 20:40:54 +0200 Subject: [PATCH 0048/1181] use literal for class name --- components/http_foundation/introduction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index 09c9f2ccc76..f7cb342037e 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -282,7 +282,7 @@ Overriding the Request The :method:`Symfony\\Component\\HttpFoundation\\Request::setFactory` method was added in Symfony 2.4. -The Request class should not be overridden as it is a data object that +The ``Request`` class should not be overridden as it is a data object that represents an HTTP message. But when moving from a legacy system, adding methods or changing some default behavior might help. In that case, register a PHP callable that is able to create an instance of your ``Request`` class:: From 6631f70836fbffdad407eef9e3e5289761756ed7 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Sun, 6 Oct 2013 21:58:04 +0200 Subject: [PATCH 0049/1181] Added operators --- .../expression_language/introduction.rst | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst index 230a82ba1c0..3c3039cccaa 100644 --- a/components/expression_language/introduction.rst +++ b/components/expression_language/introduction.rst @@ -20,4 +20,115 @@ You can install the component in 2 different ways: * Use the official Git repository (https://github.com/symfony/ExpressionLanguage); * :doc:`Install it via Composer ` (``symfony/expression-language`` on `Packagist`_). +Usage +----- + +The ExpressionLanguage component can compile and evaluate expressions. +Expressions are one-liners which most of the time return a boolean, you can +compare them to the expression in an ``if`` statement. A simple example of an +expression is ``1 + 2``. You can also use more complicated expressions, such +as ``someArray[3].someMethod('bar')``. + +The component provide 2 ways to work with expressions: + +* **compile**: the expression is compiled to PHP, so it can be cached and + evaluated; +* **evaluation**: the expression is evaluated without being compiled to PHP. + +The main class of the component is +:class:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage`:: + + use Symfony\Component\ExpressionLanguage\ExpressionLanguage; + + $language = new ExpressionLanguage(); + + echo $language->evaluate('1 + 2'); // displays 3 + + echo $language->compile('1 + 2'); // displays (1 + 2) + +Supported Literals +~~~~~~~~~~~~~~~~~~ + +The component supports: + +* **strings** - single and double quotes (e.g. ``'hello'``) +* **numbers** - e.g. ``103`` +* **arrays** - using twig notation (e.g. ``[1, 2]``) +* **hashes** - using twig notation (e.g. ``{ foo: 'bar' }``) +* **booleans** - ``true`` and ``false`` +* **null** - ``null`` + +Supported Operators +~~~~~~~~~~~~~~~~~~~ + +The component comes with a lot of operators: + +Arithmetic Operators +.................... + +* ``+`` (addition) +* ``-`` (subtraction) +* ``*`` (multiplication) +* ``/`` (division) +* ``%`` (modulus) +* ``**`` (pow) + +Assignment Operators +.................... + +* ``=`` + +Bitwise Operators +................. + +* ``&`` (and) +* ``|`` (or) +* ``^`` (xor) + +Comparison Operators +.................... + +* ``==`` (equal) +* ``===`` (identical) +* ``!=`` (not equal) +* ``!==`` (not identical) +* ``<`` (less than) +* ``>`` (greater than) +* ``<=`` (less than or equal to) +* ``>=`` (greater than or equal to) +* ``=~`` (regex match) +* ``!~`` (regex does not match) + +.. sidebar:: Regex Operator + + The Regex Operators (``=~`` and ``!~``) are coming from Perl. This + operator matches if the regular expression on the right side of the + operator matches the string on the left. For instance, + ``'foobar' =~ '/foo/'`` evaluates to true. + ``!~`` is the opposite and matches if the regular expression does *not* + match the string. + +Logical Operators +................. + +* ``not`` or ``!`` +* ``and`` or ``&&`` +* ``or`` or ``||`` + +String Operators +................ + +* ``~`` (concatenation) + +Array Operators +............... + +* ``in`` (contain) +* ``not in`` (does not contain) + +Numeric Operators +................. + +* ``..`` (range) + .. _Packagist: https://packagist.org/packages/symfony/expression-language From 4ff9faeab25fa64ae540181b8b24df450a903f7d Mon Sep 17 00:00:00 2001 From: Wouter J Date: Sun, 6 Oct 2013 22:01:38 +0200 Subject: [PATCH 0050/1181] Added another operator --- components/expression_language/introduction.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst index 3c3039cccaa..475b15cb42f 100644 --- a/components/expression_language/introduction.rst +++ b/components/expression_language/introduction.rst @@ -131,4 +131,11 @@ Numeric Operators * ``..`` (range) +Ternary Operators +................. + +* ``foo ? 'yes' : 'no'`` +* ``foo ?: 'no'`` (equal to ``foo ? foo : 'no'``) +* ``foo ? 'yes'`` (equal to ``foo ? 'yes' : ''``) + .. _Packagist: https://packagist.org/packages/symfony/expression-language From f98fa24c22e1abf385b09bad7fd6eb6c43fcf4dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Fri, 4 Oct 2013 15:04:11 +0200 Subject: [PATCH 0051/1181] Register Commands in the Service Container --- cookbook/console/console_command.rst | 46 ++++++++++++++++++++++++++++ reference/dic_tags.rst | 14 +++++++++ 2 files changed, 60 insertions(+) diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index 83033761feb..da6ff969200 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -62,6 +62,52 @@ This command will now automatically be available to run: $ app/console demo:greet Fabien +.. _cookbook-console-dic: + +Register Commands in the Service Container +------------------------------------------ + +.. versionadded:: 2.4 + Support for registering commands in the service container was added in + version 2.4. + +You can register commands in the service container using the ``console.command`` +tag: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + services: + acme_hello.command.my_command: + class: Acme\HelloBundle\Command\MyCommand + tags: + - { name: console.command } + + .. code-block:: xml + + + + + + + + + + + .. code-block:: php + + // app/config/config.php + + $container + ->register('acme_hello.command.my_command', 'Acme\HelloBundle\Command\MyCommand') + ->addTag('console.command') + ; + Getting Services from the Service Container ------------------------------------------- diff --git a/reference/dic_tags.rst b/reference/dic_tags.rst index 727ef309f2d..731cfd84454 100644 --- a/reference/dic_tags.rst +++ b/reference/dic_tags.rst @@ -29,6 +29,8 @@ may also be tags in other bundles you use that aren't listed here. +-----------------------------------+---------------------------------------------------------------------------+ | `assetic.templating.twig`_ | Remove this service if twig templating is disabled | +-----------------------------------+---------------------------------------------------------------------------+ +| `console.command`_ | Add a command | ++-----------------------------------+---------------------------------------------------------------------------+ | `data_collector`_ | Create a class that collects custom data for the profiler | +-----------------------------------+---------------------------------------------------------------------------+ | `doctrine.event_listener`_ | Add a Doctrine event listener | @@ -241,6 +243,18 @@ assetic.templating.twig The tagged service will be removed from the container if ``framework.templating.engines`` config section does not contain twig. +console.command +--------------- + +.. versionadded:: 2.4 + Support for registering commands in the service container was added in + version 2.4. + +**Purpose**: Add a command to the application + +For details on registering your own commands in the service container, read +:ref:`the cookbook article`. + data_collector -------------- From b94e3f7f5d522d4a20ea5e5e2b0911a8fa45c4d5 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 8 Oct 2013 08:45:49 -0400 Subject: [PATCH 0052/1181] [#3012] Tweaks to Callback changes - most thanks to the careful eye of @xabbuh --- reference/constraints/Callback.rst | 41 ++++++++++++++++++------------ 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/reference/constraints/Callback.rst b/reference/constraints/Callback.rst index f9024f37ef9..83b68d69401 100644 --- a/reference/constraints/Callback.rst +++ b/reference/constraints/Callback.rst @@ -114,7 +114,12 @@ those errors should be attributed:: // check if the name is actually a fake name if (in_array($this->getFirstName(), $fakeNames)) { - $context->addViolationAt('firstName', 'This name sounds totally fake!', array(), null); + $context->addViolationAt( + 'firstName', + 'This name sounds totally fake!', + array(), + null + ); } } } @@ -123,7 +128,7 @@ Static Callbacks ---------------- You can also use the constraint with static methods. Since static methods don't -have access to the object instance, they receive the object as first argument:: +have access to the object instance, they receive the object as the first argument:: public static function validate($object, ExecutionContextInterface $context) { @@ -132,7 +137,12 @@ have access to the object instance, they receive the object as first argument:: // check if the name is actually a fake name if (in_array($object->getFirstName(), $fakeNames)) { - $context->addViolationAt('firstName', 'This name sounds totally fake!', array(), null); + $context->addViolationAt( + 'firstName', + 'This name sounds totally fake!', + array(), + null + ); } } @@ -142,7 +152,7 @@ External Callbacks and Closures If you want to execute a static callback method that is not located in the class of the validated object, you can configure the constraint to invoke an array callable as supported by PHP's :phpfunction:`call_user_func` function. Suppose -your validation function is `Vendor\Package\Validator::validate()`:: +your validation function is ``Vendor\Package\Validator::validate()``:: namespace Vendor\Package; @@ -156,7 +166,7 @@ your validation function is `Vendor\Package\Validator::validate()`:: } } -You can then use the following configuration to invoke this validator:: +You can then use the following configuration to invoke this validator: .. configuration-block:: @@ -173,7 +183,6 @@ You can then use the following configuration to invoke this validator:: namespace Acme\BlogBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; - use Symfony\Component\Validator\ExecutionContextInterface; /** * @Assert\Callback({"Vendor\Package\Validator", "validate"}) @@ -212,17 +221,17 @@ You can then use the following configuration to invoke this validator:: { $metadata->addConstraint(new Assert\Callback(array( 'Vendor\Package\Validator', - 'validate' + 'validate', ))); } } .. note:: - The Callback constraint does *not* support global callback functions or - It is *not* possible to specify a global function or a :term:`service` - method as callback. To validate using a service, you should - :doc:`create a custom validation constraint` + The Callback constraint does *not* support global callback functions nor + is it possible to specify a global function or a :term:`service` method + as callback. To validate using a service, you should + :doc:`create a custom validation constraint ` and add that new constraint to your class. When configuring the constraint via PHP, you can also pass a closure to the @@ -252,20 +261,20 @@ Options callback ~~~~~~~~ -**type**: ``string``, ``array`` or ``Closure`` [:ref:`default option`] +**type**: ``string``, ``array`` or ``Closure`` [:ref:`default option `] The callback option accepts three different formats for specifying the callback method: -* A **string** containing the name of a concrete or static method. +* A **string** containing the name of a concrete or static method; -* An array callable with the format ``array('', '')``. +* An array callable with the format ``array('', '')``; * A closure. Concrete callbacks receive an :class:`Symfony\\Component\\Validator\\ExecutionContextInterface` instance as only argument. -Static or closure callbacks receive the validated object as first argument +Static or closure callbacks receive the validated object as the first argument and the :class:`Symfony\\Component\\Validator\\ExecutionContextInterface` -instance as second argument. +instance as the second argument. From 3efd179c43b47e5ee5d15cabf222c850b620c565 Mon Sep 17 00:00:00 2001 From: Eric GELOEN Date: Fri, 4 Oct 2013 00:26:21 +0200 Subject: [PATCH 0053/1181] [Form] Add a 'submitted' attribute to the form view --- reference/forms/twig_reference.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/reference/forms/twig_reference.rst b/reference/forms/twig_reference.rst index 20156e5a8f8..42d2150bcc1 100644 --- a/reference/forms/twig_reference.rst +++ b/reference/forms/twig_reference.rst @@ -295,6 +295,9 @@ object: get('name')->vars['label'] ?> +.. versionadded:: 2.4 + The ``submitted`` variable was added in Symfony 2.4. + +-----------------+-----------------------------------------------------------------------------------------+ | Variable | Usage | +=================+=========================================================================================+ @@ -310,6 +313,8 @@ object: | | since this only returns "global" errors: some individual fields may have errors | | | Instead, use the ``valid`` option | +-----------------+-----------------------------------------------------------------------------------------+ +| ``submitted`` | Returns ``true`` or ``false`` depending on whether the whole form is submitted | ++-----------------+-----------------------------------------------------------------------------------------+ | ``valid`` | Returns ``true`` or ``false`` depending on whether the whole form is valid | +-----------------+-----------------------------------------------------------------------------------------+ | ``value`` | The value that will be used when rendering (commonly the ``value`` HTML attribute) | From ca83f6a50cd9aac697184b07b98a64e2faf3785b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Tue, 8 Oct 2013 16:30:03 +0200 Subject: [PATCH 0054/1181] Documents Output::*Verbose methods --- components/console/introduction.rst | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/components/console/introduction.rst b/components/console/introduction.rst index 451b6f18722..7d579576fd3 100755 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -196,6 +196,31 @@ level. For example:: $output->writeln(...); } +.. versionadded:: 2.4 + The :method:`Symfony\\Component\Console\\Output\\Output::isQuiet`, + :method:`Symfony\\Component\Console\\Output\\Output::isVerbose`, + :method:`Symfony\\Component\Console\\Output\\Output::isVeryVerbose` and + :method:`Symfony\\Component\Console\\Output\\Output::isDebug` + methods were introduced in version 2.4 + +.. code-block:: php + + if ($output->isQuiet()) { + // ... + } + + if ($output->isVerbose()) { + // ... + } + + if ($output->isVeryVerbose()) { + // ... + } + + if ($output->isDebug()) { + // ... + } + When the quiet level is used, all output is suppressed as the default :method:`Symfony\Component\Console\Output::write ` method returns without actually printing. From bdd37ba279c930d6d8e0720eb738a91b45185d00 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 10 Oct 2013 10:30:00 -0400 Subject: [PATCH 0055/1181] [#3017] Very minor tweaks --- cookbook/session/limit_metadata_writes.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cookbook/session/limit_metadata_writes.rst b/cookbook/session/limit_metadata_writes.rst index b2d0208d21c..78d3923c69b 100644 --- a/cookbook/session/limit_metadata_writes.rst +++ b/cookbook/session/limit_metadata_writes.rst @@ -1,15 +1,15 @@ .. index:: single: Limit Metadata Writes; Session -Limit session metadata writes +Limit Session Metadata Writes ============================= .. versionadded:: 2.4 The ability to limit session metadata writes was added in Symfony 2.4. -The default behaviour of PHP session is to persist the session regardless of +The default behavior of PHP session is to persist the session regardless of whether the session data has changed or not. In Symfony, each time the session -is accessed metadata is recorded (session created/last used) which can be used +is accessed, metadata is recorded (session created/last used) which can be used to determine session age and idle time. If for performance reasons you wish to limit the frequency at which the session @@ -53,12 +53,12 @@ than zero: ), )); -.. info:: +.. note:: PHP default's behavior is to save the session whether it has been changed or not. When using ``framework.session.metadata_update_threshold`` Symfony will wrap the session handler (configured at - ``framework.session.handler_id``) into the WriteCheckSessionHandler, that + ``framework.session.handler_id``) into the WriteCheckSessionHandler. This will prevent any session write if the session was not modified. .. caution:: From ce45928a592268e2cb9e89bf0e782b4962ed3d4d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 10 Oct 2013 18:04:21 +0200 Subject: [PATCH 0056/1181] make target name unique that is used as a reference --- reference/constraints/Callback.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/reference/constraints/Callback.rst b/reference/constraints/Callback.rst index 83b68d69401..e59754f450a 100644 --- a/reference/constraints/Callback.rst +++ b/reference/constraints/Callback.rst @@ -25,7 +25,7 @@ can do anything, including creating and assigning validation errors. +----------------+------------------------------------------------------------------------+ | Applies to | :ref:`class ` | +----------------+------------------------------------------------------------------------+ -| Options | - `callback`_ | +| Options | - :ref:`callback ` | +----------------+------------------------------------------------------------------------+ | Class | :class:`Symfony\\Component\\Validator\\Constraints\\Callback` | +----------------+------------------------------------------------------------------------+ @@ -258,6 +258,8 @@ constructor of the Callback constraint:: Options ------- +.. _callback-option: + callback ~~~~~~~~ From 0925090d11de169e05d4d22a6da6e061d7a01226 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 14 Oct 2013 17:22:50 -0500 Subject: [PATCH 0057/1181] [#3031] Adding some details as to why you may or may not want to register a command a service --- cookbook/console/console_command.rst | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index da6ff969200..3ff3759d4eb 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -71,8 +71,9 @@ Register Commands in the Service Container Support for registering commands in the service container was added in version 2.4. -You can register commands in the service container using the ``console.command`` -tag: +Instead of putting your command in the ``Command`` directory and having Symfony +auto-discover it for you, you can register commands in the service container +using the ``console.command`` tag: .. configuration-block:: @@ -108,6 +109,12 @@ tag: ->addTag('console.command') ; +.. tip:: + + Registering your command as a service gives you more control over its + location and the services that are injected into it. But, there are no + functional advantages, so you don't need register your command as a service. + Getting Services from the Service Container ------------------------------------------- From a53c8ad93e80740df3d380b3344e062a33cdae1a Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 15 Oct 2013 09:50:26 -0500 Subject: [PATCH 0058/1181] [#3048] Adding intro paragraph about the semantic verbosity methods --- components/console/introduction.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/console/introduction.rst b/components/console/introduction.rst index 7d579576fd3..12fcbe525ab 100755 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -203,7 +203,8 @@ level. For example:: :method:`Symfony\\Component\Console\\Output\\Output::isDebug` methods were introduced in version 2.4 -.. code-block:: php +There are also more semantic methods you can use to test for each of the +verbosity levels:: if ($output->isQuiet()) { // ... From 72b690fe39cb06aeba4f383461cd8003591c6d1a Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 15 Oct 2013 10:04:53 -0500 Subject: [PATCH 0059/1181] [#3031] Fixing typo thanks to @xabbuh --- cookbook/console/console_command.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index c30d9edeb49..303a9ee45ed 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -113,7 +113,7 @@ using the ``console.command`` tag: Registering your command as a service gives you more control over its location and the services that are injected into it. But, there are no - functional advantages, so you don't need register your command as a service. + functional advantages, so you don't need to register your command as a service. Getting Services from the Service Container ------------------------------------------- From b944124de02eaa2650804d64eb83cbcd1ab59c2e Mon Sep 17 00:00:00 2001 From: Pierre-Yves LEBECQ Date: Sun, 20 Oct 2013 13:11:59 +0200 Subject: [PATCH 0060/1181] Added documentation about disabling internal validation of DomCrawler forms. --- book/testing.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/book/testing.rst b/book/testing.rst index 3de9cba48d6..729bb51804b 100644 --- a/book/testing.rst +++ b/book/testing.rst @@ -671,6 +671,22 @@ their type:: // Upload a file $form['photo']->upload('/path/to/lucas.jpg'); +.. versionadded:: 2.4 + The :method:`Symfony\\Component\\DomCrawler\\Form::disableValidation` + method was added in Symfony 2.4. + +By default, choice fields (select, radio) have internal validation activated +to prevent you from setting invalid values. If you want to be able to set +invalid values, you can use the ``disableValidation()`` method on either +the whole form or specific field(s):: + + // Disable validation for a specific field + $form['country']->disableValidation()->select('Invalid value'); + + // Disable validation for the whole form + $form->disableValidation(); + $form['country']->select('Invalid value'); + .. tip:: You can get the values that will be submitted by calling the ``getValues()`` From b02bc8cd003211a25cbfdaa6bc3947399c5ce71d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 22 Oct 2013 17:34:33 +0200 Subject: [PATCH 0061/1181] add note about not passing the command argument with Symfony 2.4 --- cookbook/console/console_command.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index 303a9ee45ed..fa7db6f1673 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -159,7 +159,6 @@ instead of $commandTester = new CommandTester($command); $commandTester->execute( array( - 'command' => $command->getName(), 'name' => 'Fabien', '--yell' => true, ) @@ -171,6 +170,11 @@ instead of } } +.. versionadded:: 2.4 + Since Symfony 2.4, the ``CommandTester`` automatically detects the name of + the command to execute. Thus, you don't need to pass it via the ``command`` + argument anymore. + .. note:: In the specific case above, the ``name`` parameter and the ``--yell`` option @@ -200,7 +204,6 @@ you can extend your test from $commandTester = new CommandTester($command); $commandTester->execute( array( - 'command' => $command->getName(), 'name' => 'Fabien', '--yell' => true, ) From 8fe9fd606fdf4b0b20bf55606b9b7472b3965c83 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Sat, 26 Oct 2013 12:32:53 +0200 Subject: [PATCH 0062/1181] Fixed comments and splitted in intro and syntax --- components/expression_language/index.rst | 1 + .../expression_language/introduction.rst | 100 ++---------------- components/expression_language/syntax.rst | 98 +++++++++++++++++ components/map.rst.inc | 1 + 4 files changed, 107 insertions(+), 93 deletions(-) create mode 100644 components/expression_language/syntax.rst diff --git a/components/expression_language/index.rst b/components/expression_language/index.rst index adddcd4fc6d..e6eb657b4be 100644 --- a/components/expression_language/index.rst +++ b/components/expression_language/index.rst @@ -5,3 +5,4 @@ Expression Language :maxdepth: 2 introduction + syntax diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst index 475b15cb42f..a7f474c732a 100644 --- a/components/expression_language/introduction.rst +++ b/components/expression_language/introduction.rst @@ -10,14 +10,14 @@ The ExpressionLanguage Component (mostly, but not limited to, Booleans). .. versionadded:: 2.4 - The ExpressionLanguage Component was new in Symfony 2.4. + The ExpressionLanguage component was new in Symfony 2.4. Installation ------------ You can install the component in 2 different ways: -* Use the official Git repository (https://github.com/symfony/ExpressionLanguage); +* Use the official Git repository (https://github.com/symfony/expression-language); * :doc:`Install it via Composer ` (``symfony/expression-language`` on `Packagist`_). Usage @@ -29,7 +29,7 @@ compare them to the expression in an ``if`` statement. A simple example of an expression is ``1 + 2``. You can also use more complicated expressions, such as ``someArray[3].someMethod('bar')``. -The component provide 2 ways to work with expressions: +The component provides 2 ways to work with expressions: * **compile**: the expression is compiled to PHP, so it can be cached and evaluated; @@ -46,96 +46,10 @@ The main class of the component is echo $language->compile('1 + 2'); // displays (1 + 2) -Supported Literals -~~~~~~~~~~~~~~~~~~ +Expression Syntax +----------------- -The component supports: - -* **strings** - single and double quotes (e.g. ``'hello'``) -* **numbers** - e.g. ``103`` -* **arrays** - using twig notation (e.g. ``[1, 2]``) -* **hashes** - using twig notation (e.g. ``{ foo: 'bar' }``) -* **booleans** - ``true`` and ``false`` -* **null** - ``null`` - -Supported Operators -~~~~~~~~~~~~~~~~~~~ - -The component comes with a lot of operators: - -Arithmetic Operators -.................... - -* ``+`` (addition) -* ``-`` (subtraction) -* ``*`` (multiplication) -* ``/`` (division) -* ``%`` (modulus) -* ``**`` (pow) - -Assignment Operators -.................... - -* ``=`` - -Bitwise Operators -................. - -* ``&`` (and) -* ``|`` (or) -* ``^`` (xor) - -Comparison Operators -.................... - -* ``==`` (equal) -* ``===`` (identical) -* ``!=`` (not equal) -* ``!==`` (not identical) -* ``<`` (less than) -* ``>`` (greater than) -* ``<=`` (less than or equal to) -* ``>=`` (greater than or equal to) -* ``=~`` (regex match) -* ``!~`` (regex does not match) - -.. sidebar:: Regex Operator - - The Regex Operators (``=~`` and ``!~``) are coming from Perl. This - operator matches if the regular expression on the right side of the - operator matches the string on the left. For instance, - ``'foobar' =~ '/foo/'`` evaluates to true. - ``!~`` is the opposite and matches if the regular expression does *not* - match the string. - -Logical Operators -................. - -* ``not`` or ``!`` -* ``and`` or ``&&`` -* ``or`` or ``||`` - -String Operators -................ - -* ``~`` (concatenation) - -Array Operators -............... - -* ``in`` (contain) -* ``not in`` (does not contain) - -Numeric Operators -................. - -* ``..`` (range) - -Ternary Operators -................. - -* ``foo ? 'yes' : 'no'`` -* ``foo ?: 'no'`` (equal to ``foo ? foo : 'no'``) -* ``foo ? 'yes'`` (equal to ``foo ? 'yes' : ''``) +See ":doc:`/components/expression_language/syntax`" to learn the syntax of the +ExpressionLanguage component. .. _Packagist: https://packagist.org/packages/symfony/expression-language diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst new file mode 100644 index 00000000000..7c3a59fccb9 --- /dev/null +++ b/components/expression_language/syntax.rst @@ -0,0 +1,98 @@ +.. index:: + single: Syntax; ExpressionLanguage + +The Expression Syntax +===================== + +The ExpressionLanguage component uses a specific syntax which is based on the +expression syntax of Twig. In this document, you can find all supported +syntaxes. + +Supported Literals +~~~~~~~~~~~~~~~~~~ + +The component supports: + +* **strings** - single and double quotes (e.g. ``'hello'``) +* **numbers** - e.g. ``103`` +* **arrays** - using twig notation (e.g. ``[1, 2]``) +* **hashes** - using twig notation (e.g. ``{ foo: 'bar' }``) +* **booleans** - ``true`` and ``false`` +* **null** - ``null`` + +Supported Operators +~~~~~~~~~~~~~~~~~~~ + +The component comes with a lot of operators: + +Arithmetic Operators +.................... + +* ``+`` (addition) +* ``-`` (subtraction) +* ``*`` (multiplication) +* ``/`` (division) +* ``%`` (modulus) +* ``**`` (pow) + +Assignment Operators +.................... + +* ``=`` + +Bitwise Operators +................. + +* ``&`` (and) +* ``|`` (or) +* ``^`` (xor) + +Comparison Operators +.................... + +* ``==`` (equal) +* ``===`` (identical) +* ``!=`` (not equal) +* ``!==`` (not identical) +* ``<`` (less than) +* ``>`` (greater than) +* ``<=`` (less than or equal to) +* ``>=`` (greater than or equal to) +* ``matches`` (regex match) + +.. tip:: + + To test if a string does *not* match a regex, use the logical ``not`` + operator in combination with the ``matches`` operator:: + + $language->evaluate('not "foo" matches "/bar/"'); // returns true + +Logical Operators +................. + +* ``not`` or ``!`` +* ``and`` or ``&&`` +* ``or`` or ``||`` + +String Operators +................ + +* ``~`` (concatenation) + +Array Operators +............... + +* ``in`` (contain) +* ``not in`` (does not contain) + +Numeric Operators +................. + +* ``..`` (range) + +Ternary Operators +................. + +* ``foo ? 'yes' : 'no'`` +* ``foo ?: 'no'`` (equal to ``foo ? foo : 'no'``) +* ``foo ? 'yes'`` (equal to ``foo ? 'yes' : ''``) diff --git a/components/map.rst.inc b/components/map.rst.inc index d55e3c4e721..fb1055a6555 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -60,6 +60,7 @@ * :doc:`/components/expression_language/index` * :doc:`/components/expression_language/introduction` + * :doc:`/components/expression_language/syntax` * **Filesystem** From 31fb5b84c75b8178cbf6f9b8a9de9985fe4f78f1 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Mon, 28 Oct 2013 10:38:19 +0100 Subject: [PATCH 0063/1181] update framework csrf configuration https://github.com/symfony/symfony/pull/9252 --- reference/configuration/framework.rst | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/reference/configuration/framework.rst b/reference/configuration/framework.rst index 05d707e370d..01752fbe950 100644 --- a/reference/configuration/framework.rst +++ b/reference/configuration/framework.rst @@ -20,11 +20,14 @@ Configuration * `ide`_ * `test`_ * `trusted_proxies`_ -* `form`_ - * enabled * `csrf_protection`_ * enabled - * field_name + * field_name (deprecated) +* `form`_ + * enabled + * csrf_protection + * enabled + * field_name * `session`_ * `name`_ * `cookie_lifetime`_ @@ -452,12 +455,16 @@ Full Default Configuration test: ~ default_locale: en + csrf_protection: + enabled: false + field_name: _token # Deprecated since 2.4, to be removed in 3.0. Use form.csrf_protection.field_name instead + # form configuration form: enabled: false - csrf_protection: - enabled: false - field_name: _token + csrf_protection: + enabled: true + field_name: ~ # esi configuration esi: From 2a5049340ab0524edaf5e50b9e70eb8f56346e8c Mon Sep 17 00:00:00 2001 From: Luis Cordova Date: Mon, 28 Oct 2013 16:50:34 -0500 Subject: [PATCH 0064/1181] switch argument to key to be more precise --- cookbook/console/console_command.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index fa7db6f1673..18efda43a3e 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -4,7 +4,7 @@ How to create a Console Command =============================== -The Console page of the Components section (:doc:`/components/console/introduction`) covers +The Console page of the Components section (:doc:`/components/console/introductcion`) covers how to create a Console command. This cookbook article covers the differences when creating Console commands within the Symfony2 framework. @@ -173,7 +173,7 @@ instead of .. versionadded:: 2.4 Since Symfony 2.4, the ``CommandTester`` automatically detects the name of the command to execute. Thus, you don't need to pass it via the ``command`` - argument anymore. + key anymore. .. note:: From fda51eee9a34107eba3eee45d4a922803e0df5b8 Mon Sep 17 00:00:00 2001 From: Luis Cordova Date: Mon, 28 Oct 2013 16:51:58 -0500 Subject: [PATCH 0065/1181] fix introducing typo --- cookbook/console/console_command.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index 18efda43a3e..7571b49543b 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -4,7 +4,7 @@ How to create a Console Command =============================== -The Console page of the Components section (:doc:`/components/console/introductcion`) covers +The Console page of the Components section (:doc:`/components/console/introduction`) covers how to create a Console command. This cookbook article covers the differences when creating Console commands within the Symfony2 framework. From ae03fdb5cc28e9ffe9a089fe539d1354ae977b00 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Fri, 1 Nov 2013 22:15:08 -0500 Subject: [PATCH 0066/1181] [#3075] Moving new Form::disableValidation DomCrawler details into the component The idea is to keep the book chapter to more main-stream details and put longer details into the component docs --- book/testing.rst | 17 +++-------------- components/dom_crawler.rst | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/book/testing.rst b/book/testing.rst index 729bb51804b..4deb4229075 100644 --- a/book/testing.rst +++ b/book/testing.rst @@ -671,21 +671,10 @@ their type:: // Upload a file $form['photo']->upload('/path/to/lucas.jpg'); -.. versionadded:: 2.4 - The :method:`Symfony\\Component\\DomCrawler\\Form::disableValidation` - method was added in Symfony 2.4. - -By default, choice fields (select, radio) have internal validation activated -to prevent you from setting invalid values. If you want to be able to set -invalid values, you can use the ``disableValidation()`` method on either -the whole form or specific field(s):: - - // Disable validation for a specific field - $form['country']->disableValidation()->select('Invalid value'); +.. tip:: - // Disable validation for the whole form - $form->disableValidation(); - $form['country']->select('Invalid value'); + If you purposefully want to select "invalid" select/radio values, see + :ref:`components-dom-crawler-invalid`. .. tip:: diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index d1ae7a66e3f..ba9b9a09ade 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -340,6 +340,9 @@ and uploading files:: // even fake a file upload $form['registration[photo]']->upload('/path/to/lucas.jpg'); +Using the Form Data +................... + What's the point of doing all of this? If you're testing internally, you can grab the information off of your form as if it had just been submitted by using the PHP values:: @@ -375,5 +378,26 @@ directly:: // submit that form $crawler = $client->submit($form); +.. _components-dom-crawler-invalid: + +Selecting Invalid Choice Values +............................... + +.. versionadded:: 2.4 + The :method:`Symfony\\Component\\DomCrawler\\Form::disableValidation` + method was added in Symfony 2.4. + +By default, choice fields (select, radio) have internal validation activated +to prevent you from setting invalid values. If you want to be able to set +invalid values, you can use the ``disableValidation()`` method on either +the whole form or specific field(s):: + + // Disable validation for a specific field + $form['country']->disableValidation()->select('Invalid value'); + + // Disable validation for the whole form + $form->disableValidation(); + $form['country']->select('Invalid value'); + .. _`Goutte`: https://github.com/fabpot/goutte .. _Packagist: https://packagist.org/packages/symfony/dom-crawler From 10fe8a4d16be777c12ad84eaaa7429011d60dbdc Mon Sep 17 00:00:00 2001 From: Wouter J Date: Sat, 2 Nov 2013 11:35:59 +0100 Subject: [PATCH 0067/1181] Removed 2.2 references as it reached eom --- book/forms.rst | 6 +++--- book/routing.rst | 14 -------------- book/security.rst | 7 ------- book/templating.rst | 12 ------------ components/config/definition.rst | 8 +------- components/console/helpers/dialoghelper.rst | 13 ------------- components/console/helpers/progresshelper.rst | 3 --- components/dependency_injection/compilation.rst | 3 --- components/finder.rst | 6 ------ components/http_foundation/introduction.rst | 7 ------- components/process.rst | 3 --- components/property_access/introduction.rst | 4 ---- components/routing/hostname_pattern.rst | 3 --- components/routing/introduction.rst | 7 ------- components/stopwatch.rst | 4 ---- cookbook/console/sending_emails.rst | 9 +++------ cookbook/form/dynamic_form_modification.rst | 8 -------- cookbook/templating/namespaced_paths.rst | 5 +---- cookbook/templating/render_without_controller.rst | 6 +----- reference/configuration/framework.rst | 5 ----- reference/configuration/security.rst | 6 ------ reference/constraints/CardScheme.rst | 3 --- reference/constraints/Luhn.rst | 3 --- reference/constraints/UserPassword.rst | 8 -------- reference/dic_tags.rst | 2 +- reference/twig_reference.rst | 4 ---- 26 files changed, 10 insertions(+), 149 deletions(-) diff --git a/book/forms.rst b/book/forms.rst index f5621c51a5b..a835cd2cb16 100644 --- a/book/forms.rst +++ b/book/forms.rst @@ -1873,7 +1873,7 @@ Learn more from the Cookbook .. _`Symfony2 Form Component`: https://github.com/symfony/Form .. _`DateTime`: http://php.net/manual/en/class.datetime.php -.. _`Twig Bridge`: https://github.com/symfony/symfony/tree/2.2/src/Symfony/Bridge/Twig -.. _`form_div_layout.html.twig`: https://github.com/symfony/symfony/blob/2.2/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +.. _`Twig Bridge`: https://github.com/symfony/symfony/tree/master/src/Symfony/Bridge/Twig +.. _`form_div_layout.html.twig`: https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig .. _`Cross-site request forgery`: http://en.wikipedia.org/wiki/Cross-site_request_forgery -.. _`view on GitHub`: https://github.com/symfony/symfony/tree/2.2/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form +.. _`view on GitHub`: https://github.com/symfony/symfony/tree/master/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form diff --git a/book/routing.rst b/book/routing.rst index 68a9e4c7ce6..fc594aaeaff 100644 --- a/book/routing.rst +++ b/book/routing.rst @@ -68,10 +68,6 @@ The route is simple: return $collection; -.. versionadded:: 2.2 - The ``path`` option is new in Symfony2.2, ``pattern`` is used in older - versions. - The path defined by the ``blog_show`` route acts like ``/blog/*`` where the wildcard is given the name ``slug``. For the URL ``/blog/my-blog-post``, the ``slug`` variable gets a value of ``my-blog-post``, which is available @@ -694,10 +690,6 @@ be accomplished with the following route configuration: return $collection; -.. versionadded:: 2.2 - The ``methods`` option is added in Symfony2.2. Use the ``_method`` - requirement in older versions. - Despite the fact that these two routes have identical paths (``/contact``), the first route will match only GET requests and the second route will match only POST requests. This means that you can display the form and submit the @@ -710,9 +702,6 @@ form via the same URL, while using distinct controllers for the two actions. Adding a Host ~~~~~~~~~~~~~ -.. versionadded:: 2.2 - Host matching support was added in Symfony 2.2 - You can also match on the HTTP *host* of the incoming request. For more information, see :doc:`/components/routing/hostname_pattern` in the Routing component documentation. @@ -1070,9 +1059,6 @@ from the new routing resource. Adding a Host regex to Imported Routes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. versionadded:: 2.2 - Host matching support was added in Symfony 2.2 - You can set the host regex on imported routes. For more information, see :ref:`component-routing-host-imported`. diff --git a/book/security.rst b/book/security.rst index e21e32cc438..6a82b4ecfd1 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1385,10 +1385,6 @@ it as base64. In other words, the password has been greatly obfuscated so that the hashed password can't be decoded (i.e. you can't determine the password from the hashed password). -.. versionadded:: 2.2 - As of Symfony 2.2 you can also use the :ref:`PBKDF2 ` - and :ref:`BCrypt ` password encoders. - Determining the Hashed Password ............................... @@ -2023,9 +2019,6 @@ cookie will be ever created by Symfony2): Utilities --------- -.. versionadded:: 2.2 - The ``StringUtils`` and ``SecureRandom`` classes were added in Symfony 2.2 - 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. diff --git a/book/templating.rst b/book/templating.rst index 2e01d869196..d6e75fa0f75 100644 --- a/book/templating.rst +++ b/book/templating.rst @@ -375,11 +375,6 @@ When working with template inheritance, here are some tips to keep in mind: Template Naming and Locations ----------------------------- -.. versionadded:: 2.2 - Namespaced path support was added in 2.2, allowing for template names - like ``@AcmeDemo/layout.html.twig``. See :doc:`/cookbook/templating/namespaced_paths` - for more details. - By default, templates can live in two different locations: * ``app/Resources/views/``: The applications ``views`` directory can contain @@ -572,10 +567,6 @@ you set `with_context`_ to false). maps (i.e. an array with named keys). If you needed to pass in multiple elements, it would look like this: ``{'foo': foo, 'bar': bar}``. -.. versionadded:: 2.2 - The `include() function`_ is a new Twig feature that's available in Symfony - 2.2. Prior, the `{% include %} tag`_ tag was used. - .. index:: single: Templating; Embedding action @@ -782,9 +773,6 @@ in your application configuration: ), )); -.. versionadded:: 2.2 - Default templates per render function was added in Symfony 2.2 - You can define default templates per ``render`` function (which will override any global default template that is defined): diff --git a/components/config/definition.rst b/components/config/definition.rst index 0bd25d19a03..9a5f22d7125 100644 --- a/components/config/definition.rst +++ b/components/config/definition.rst @@ -99,7 +99,7 @@ node definition. Node type are available for: * scalar * boolean -* integer (new in 2.2) +* integer * float * enum * array @@ -111,9 +111,6 @@ and are created with ``node($name, $type)`` or their associated shortcut Numeric node constraints ~~~~~~~~~~~~~~~~~~~~~~~~ -.. versionadded:: 2.2 - The numeric (float and integer) nodes are new in 2.2 - Numeric nodes (float and integer) provide two extra constraints - :method:`Symfony\\Component\\Config\\Definition\\Builder::min` and :method:`Symfony\\Component\\Config\\Definition\\Builder::max` - @@ -287,9 +284,6 @@ has a certain value: Optional Sections ----------------- -.. versionadded:: 2.2 - The ``canBeEnabled`` and ``canBeDisabled`` methods are new in Symfony 2.2 - If you have entire sections which are optional and can be enabled/disabled, you can take advantage of the shortcut :method:`Symfony\\Component\\Config\\Definition\\Builder\\ArrayNodeDefinition::canBeEnabled` and diff --git a/components/console/helpers/dialoghelper.rst b/components/console/helpers/dialoghelper.rst index 1d1215236f1..584a080164d 100644 --- a/components/console/helpers/dialoghelper.rst +++ b/components/console/helpers/dialoghelper.rst @@ -56,9 +56,6 @@ the default value (``AcmeDemoBundle`` here) is returned. Autocompletion ~~~~~~~~~~~~~~ -.. versionadded:: 2.2 - Autocompletion for questions was added in Symfony 2.2. - You can also specify an array of potential answers for a given question. These will be autocompleted as the user types:: @@ -74,9 +71,6 @@ will be autocompleted as the user types:: Hiding the User's Response ~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. versionadded:: 2.2 - The ``askHiddenResponse`` method was added in Symfony 2.2. - You can also ask a question and hide the response. This is particularly convenient for passwords:: @@ -144,9 +138,6 @@ be able to proceed if her input is valid. Hiding the User's Response ~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. versionadded:: 2.2 - The ``askHiddenResponseAndValidate`` method was added in Symfony 2.2. - You can also ask and validate a hidden response:: $dialog = $this->getHelperSet()->get('dialog'); @@ -171,10 +162,6 @@ some reason, pass true as the fifth argument. Let the user choose from a list of Answers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. versionadded:: 2.2 - The :method:`Symfony\\Component\\Console\\Helper\\DialogHelper::select` method - was added in Symfony 2.2. - If you have a predefined set of answers the user can choose from, you could use the ``ask`` method described above or, to make sure the user provided a correct answer, the ``askAndValidate`` method. Both have diff --git a/components/console/helpers/progresshelper.rst b/components/console/helpers/progresshelper.rst index ccd5d381afd..9ee76b694cb 100644 --- a/components/console/helpers/progresshelper.rst +++ b/components/console/helpers/progresshelper.rst @@ -4,9 +4,6 @@ Progress Helper =============== -.. versionadded:: 2.2 - The ``progress`` helper was added in Symfony 2.2. - .. versionadded:: 2.3 The ``setCurrent`` method was added in Symfony 2.3. diff --git a/components/dependency_injection/compilation.rst b/components/dependency_injection/compilation.rst index af1fd1444f5..07c8a737c6a 100644 --- a/components/dependency_injection/compilation.rst +++ b/components/dependency_injection/compilation.rst @@ -276,9 +276,6 @@ but also load a secondary one only if a certain parameter is set:: Prepending Configuration passed to the Extension ------------------------------------------------ -.. versionadded:: 2.2 - The ability to prepend the configuration of a bundle is new in Symfony 2.2. - An Extension can prepend the configuration of any Bundle before the ``load()`` method is called by implementing :class:`Symfony\\Component\\DependencyInjection\\Extension\\PrependExtensionInterface`:: diff --git a/components/finder.rst b/components/finder.rst index c63d624e6c6..2f985ba0af9 100644 --- a/components/finder.rst +++ b/components/finder.rst @@ -82,9 +82,6 @@ Search in several locations by chaining calls to $finder->files()->in(__DIR__)->in('/elsewhere'); -.. versionadded:: 2.2 - Wildcard support was added in version 2.2. - Use wildcard characters to search in the directories matching a pattern:: $finder->in('src/Symfony/*/*/Resources'); @@ -206,9 +203,6 @@ The ``notContains()`` method excludes files containing given pattern:: Path ~~~~ -.. versionadded:: 2.2 - The ``path()`` and ``notPath()`` methods were added in version 2.2. - Restrict files and directories by path with the :method:`Symfony\\Component\\Finder\\Finder::path` method:: diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index f7cb342037e..f7880d15e5f 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -248,9 +248,6 @@ by using the following methods: .. versionadded:: 2.4 The ``getEncodings()`` method was added in Symfony 2.4. -.. versionadded:: 2.2 - The :class:`Symfony\\Component\\HttpFoundation\\AcceptHeader` class is new in Symfony 2.2. - If you need to get full access to parsed data from ``Accept``, ``Accept-Language``, ``Accept-Charset`` or ``Accept-Encoding``, you can use :class:`Symfony\\Component\\HttpFoundation\\AcceptHeader` utility class:: @@ -462,10 +459,6 @@ abstracts the hard work behind a simple API:: $response->headers->set('Content-Disposition', $d); -.. versionadded:: 2.2 - The :class:`Symfony\\Component\\HttpFoundation\\BinaryFileResponse` - class was added in Symfony 2.2. - Alternatively, if you are serving a static file, you can use a :class:`Symfony\\Component\\HttpFoundation\\BinaryFileResponse`:: diff --git a/components/process.rst b/components/process.rst index 981ec69e493..a9d21d1187f 100644 --- a/components/process.rst +++ b/components/process.rst @@ -36,9 +36,6 @@ a command in a sub-process:: The component takes care of the subtle differences between the different platforms when executing the command. -.. versionadded:: 2.2 - The ``getIncrementalOutput()`` and ``getIncrementalErrorOutput()`` methods were added in Symfony 2.2. - The ``getOutput()`` method always return the whole content of the standard output of the command and ``getErrorOutput()`` the content of the error output. Alternatively, the :method:`Symfony\\Component\\Process\\Process::getIncrementalOutput` diff --git a/components/property_access/introduction.rst b/components/property_access/introduction.rst index 767097f8dfd..3c316726142 100644 --- a/components/property_access/introduction.rst +++ b/components/property_access/introduction.rst @@ -8,10 +8,6 @@ The PropertyAccess Component The PropertyAccess component provides function to read and write from/to an object or array using a simple string notation. -.. versionadded:: 2.2 - The PropertyAccess Component is new to Symfony 2.2. Previously, the - ``PropertyPath`` class was located in the ``Form`` component. - Installation ------------ diff --git a/components/routing/hostname_pattern.rst b/components/routing/hostname_pattern.rst index dfe5df8a445..fd872bb65a8 100644 --- a/components/routing/hostname_pattern.rst +++ b/components/routing/hostname_pattern.rst @@ -4,9 +4,6 @@ How to match a route based on the Host ====================================== -.. versionadded:: 2.2 - Host matching support was added in Symfony 2.2 - You can also match on the HTTP *host* of the incoming request. .. configuration-block:: diff --git a/components/routing/introduction.rst b/components/routing/introduction.rst index 12a032eb9d4..dc4ddcdd85d 100644 --- a/components/routing/introduction.rst +++ b/components/routing/introduction.rst @@ -93,9 +93,6 @@ are the least commonly needed. 7. An array of methods. These enforce a certain HTTP request method (``HEAD``, ``GET``, ``POST``, ...). -.. versionadded:: 2.2 - Host matching support was added in Symfony 2.2 - Take the following route, which combines several of these ideas:: $route = new Route( @@ -160,10 +157,6 @@ the :method:`Symfony\\Component\\Routing\\RouteCollection::addPrefix` method:: $rootCollection->addCollection($subCollection); -.. versionadded:: 2.2 - The ``addPrefix`` method is added in Symfony2.2. This was part of the - ``addCollection`` method in older versions. - Set the Request Parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/components/stopwatch.rst b/components/stopwatch.rst index c7347a4ad5c..6b0004441c0 100644 --- a/components/stopwatch.rst +++ b/components/stopwatch.rst @@ -7,10 +7,6 @@ The Stopwatch Component Stopwatch component provides a way to profile code. -.. versionadded:: 2.2 - The Stopwatch Component is new to Symfony 2.2. Previously, the ``Stopwatch`` - class was located in the ``HttpKernel`` component. - Installation ------------ diff --git a/cookbook/console/sending_emails.rst b/cookbook/console/sending_emails.rst index 2d72da3cfd4..e7dbcbca03d 100644 --- a/cookbook/console/sending_emails.rst +++ b/cookbook/console/sending_emails.rst @@ -17,16 +17,13 @@ what URL it should use when generating URLs. There are two ways of configuring the request context: at the application level and per Command. -Configuring the Request Context globally +Configuring the Request Context Globally ---------------------------------------- -.. versionadded: 2.2 - The ``base_url`` parameter is available since Symfony 2.2 - To configure the Request Context - which is used by the URL Generator - you can redefine the parameters it uses as default values to change the default host -(localhost) and scheme (http). Starting with Symfony 2.2 you can also configure -the base path if Symfony is not running in the root directory. +(localhost) and scheme (http). You can also configure the base path if Symfony +is not running in the root directory. Note that this does not impact URLs generated via normal web requests, since those will override the defaults. diff --git a/cookbook/form/dynamic_form_modification.rst b/cookbook/form/dynamic_form_modification.rst index e358d39bb96..a53998ef168 100644 --- a/cookbook/form/dynamic_form_modification.rst +++ b/cookbook/form/dynamic_form_modification.rst @@ -114,10 +114,6 @@ The goal is to create a "name" field *only* if the underlying Product object is new (e.g. hasn't been persisted to the database). Based on that, the subscriber might look like the following: -.. versionadded:: 2.2 - The ability to pass a string into :method:`FormInterface::add ` - was added in Symfony 2.2. - .. code-block:: php // src/Acme/DemoBundle/Form/EventListener/AddNameFieldSubscriber.php @@ -469,10 +465,6 @@ On a form, we can usually listen to the following events: The events ``PRE_SUBMIT``, ``SUBMIT`` and ``POST_SUBMIT`` were added in Symfony 2.3. Before, they were named ``PRE_BIND``, ``BIND`` and ``POST_BIND``. -.. versionadded:: 2.2.6 - The behavior of the ``POST_SUBMIT`` event changed slightly in 2.2.6, which the - below example uses. - The key is to add a ``POST_SUBMIT`` listener to the field that your new field depends on. If you add a ``POST_SUBMIT`` listener to a form child (e.g. ``sport``), and add new children to the parent form, the Form component will detect the diff --git a/cookbook/templating/namespaced_paths.rst b/cookbook/templating/namespaced_paths.rst index 8e33b38ef66..ff41d10e7c0 100644 --- a/cookbook/templating/namespaced_paths.rst +++ b/cookbook/templating/namespaced_paths.rst @@ -4,9 +4,6 @@ How to use and Register namespaced Twig Paths ============================================= -.. versionadded:: 2.2 - Namespaced path support was added in 2.2. - Usually, when you refer to a template, you'll use the ``MyBundle:Subdir:filename.html.twig`` format (see :ref:`template-naming-locations`). @@ -80,4 +77,4 @@ called ``sidebar.twig`` in that directory, you can use it easily: .. code-block:: jinja - {% include '@foo_bar/side.bar.twig` %} \ No newline at end of file + {% include '@foo_bar/side.bar.twig` %} diff --git a/cookbook/templating/render_without_controller.rst b/cookbook/templating/render_without_controller.rst index f2a44f7e4e1..a00c9089f1a 100644 --- a/cookbook/templating/render_without_controller.rst +++ b/cookbook/templating/render_without_controller.rst @@ -77,10 +77,6 @@ this is probably only useful if you'd like to cache this page partial (see Caching the static Template --------------------------- -.. versionadded:: 2.2 - The ability to cache templates rendered via ``FrameworkBundle:Template:template`` - is new in Symfony 2.2. - Since templates that are rendered in this way are typically static, it might make sense to cache them. Fortunately, this is easy! By configuring a few other variables in your route, you can control exactly how your page is cached: @@ -134,4 +130,4 @@ object created in the controller. For more information on caching, see There is also a ``private`` variable (not shown here). By default, the Response will be made public, as long as ``maxAge`` or ``sharedMaxAge`` are passed. -If set to ``true``, the Response will be marked as private. \ No newline at end of file +If set to ``true``, the Response will be marked as private. diff --git a/reference/configuration/framework.rst b/reference/configuration/framework.rst index 05d707e370d..2e91dd07e2c 100644 --- a/reference/configuration/framework.rst +++ b/reference/configuration/framework.rst @@ -405,11 +405,6 @@ would be ``/images/logo.png?version=5``. profiler ~~~~~~~~ -.. versionadded:: 2.2 - The ``enabled`` option was added in Symfony 2.2. Previously, the profiler - could only be disabled by omitting the ``framework.profiler`` configuration - entirely. - .. _profiler.enabled: enabled diff --git a/reference/configuration/security.rst b/reference/configuration/security.rst index dce75e06451..fd33ffc94aa 100644 --- a/reference/configuration/security.rst +++ b/reference/configuration/security.rst @@ -284,9 +284,6 @@ Redirecting after Login Using the PBKDF2 encoder: Security and Speed -------------------------------------------- -.. versionadded:: 2.2 - The PBKDF2 password encoder was added in Symfony 2.2. - The `PBKDF2`_ encoder provides a high level of Cryptographic security, as recommended by the National Institute of Standards and Technology (NIST). @@ -309,9 +306,6 @@ Using the BCrypt Password Encoder To use this encoder, you either need to use PHP Version 5.5 or install the `ircmaxell/password-compat`_ library via Composer. -.. versionadded:: 2.2 - The BCrypt password encoder was added in Symfony 2.2. - .. configuration-block:: .. code-block:: yaml diff --git a/reference/constraints/CardScheme.rst b/reference/constraints/CardScheme.rst index 172ddbfdf70..7e9309c1ea7 100644 --- a/reference/constraints/CardScheme.rst +++ b/reference/constraints/CardScheme.rst @@ -1,9 +1,6 @@ CardScheme ========== -.. versionadded:: 2.2 - The CardScheme validation is new in Symfony 2.2. - This constraint ensures that a credit card number is valid for a given credit card company. It can be used to validate the number before trying to initiate a payment through a payment gateway. diff --git a/reference/constraints/Luhn.rst b/reference/constraints/Luhn.rst index 58697e94184..0907456266b 100644 --- a/reference/constraints/Luhn.rst +++ b/reference/constraints/Luhn.rst @@ -1,9 +1,6 @@ Luhn ==== -.. versionadded:: 2.2 - The Luhn validation is new in Symfony 2.2. - This constraint is used to ensure that a credit card number passes the `Luhn algorithm`_. It is useful as a first step to validating a credit card: before communicating with a payment gateway. diff --git a/reference/constraints/UserPassword.rst b/reference/constraints/UserPassword.rst index e5e1baea42d..fdd9371b40c 100644 --- a/reference/constraints/UserPassword.rst +++ b/reference/constraints/UserPassword.rst @@ -1,14 +1,6 @@ UserPassword ============ -.. note:: - - Since Symfony 2.2, the ``UserPassword*`` classes in the - ``Symfony\\Component\\Security\\Core\\Validator\\Constraint`` namespace are - deprecated and will be removed in Symfony 2.3. Please use the - ``UserPassword*`` classes in the - ``Symfony\\Component\\Security\\Core\\Validator\\Constraints`` namespace instead. - This validates that an input value is equal to the current authenticated user's password. This is useful in a form where a user can change his password, but needs to enter his old password for security. diff --git a/reference/dic_tags.rst b/reference/dic_tags.rst index f81362c8dbc..35ed24521e6 100644 --- a/reference/dic_tags.rst +++ b/reference/dic_tags.rst @@ -1216,6 +1216,6 @@ For an example, see the ``EntityInitializer`` class inside the Doctrine Bridge. .. _`Twig's documentation`: http://twig.sensiolabs.org/doc/advanced.html#creating-an-extension .. _`Twig official extension repository`: https://github.com/fabpot/Twig-extensions -.. _`KernelEvents`: https://github.com/symfony/symfony/blob/2.2/src/Symfony/Component/HttpKernel/KernelEvents.php +.. _`KernelEvents`: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/KernelEvents.php .. _`SwiftMailer's Plugin Documentation`: http://swiftmailer.org/docs/plugins.html .. _`Twig Loader`: http://twig.sensiolabs.org/doc/api.html#loaders diff --git a/reference/twig_reference.rst b/reference/twig_reference.rst index af020967192..568e21ac668 100644 --- a/reference/twig_reference.rst +++ b/reference/twig_reference.rst @@ -17,10 +17,6 @@ There may also be tags in bundles you use that aren't listed here. Functions --------- -.. versionadded:: 2.2 - The ``render`` and ``controller`` functions are new in Symfony 2.2. Prior, - the ``{% render %}`` tag was used and had a different signature. - +----------------------------------------------------+--------------------------------------------------------------------------------------------+ | Function Syntax | Usage | +====================================================+============================================================================================+ From 3943d8f521a83972b5f373ca8e4f7635cd7113d5 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 3 Nov 2013 10:59:12 -0600 Subject: [PATCH 0068/1181] [#3084] Putting back message that was incorrect in 2.3, but correct in 2.4/master --- cookbook/logging/monolog_email.rst | 8 -------- 1 file changed, 8 deletions(-) diff --git a/cookbook/logging/monolog_email.rst b/cookbook/logging/monolog_email.rst index e6adcc1553b..b429bc8c588 100644 --- a/cookbook/logging/monolog_email.rst +++ b/cookbook/logging/monolog_email.rst @@ -107,14 +107,6 @@ to and from addresses and the subject. You can combine these handlers with other handlers so that the errors still get logged on the server as well as the emails being sent: -.. caution:: - - The default spool setting for swiftmailer is set to ``memory``, which - means that emails are sent at the very end of the request. However, this - does not work with buffered logs at the moment. In order to enable emailing - logs per the example below, you must comment out the ``spool: { type: memory }`` - line in the ``config.yml`` file. - .. configuration-block:: .. code-block:: yaml From 6829df39bc0236b1b67c49b9b007958907b274e8 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 3 Nov 2013 11:37:08 -0600 Subject: [PATCH 0069/1181] Removing versionadded 2.1 that leaked in from a merge up --- book/templating.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/book/templating.rst b/book/templating.rst index 66462490811..f037cb4ac82 100644 --- a/book/templating.rst +++ b/book/templating.rst @@ -676,9 +676,6 @@ that as much code as possible lives in reusable :doc:`services Date: Sun, 3 Nov 2013 12:29:24 -0600 Subject: [PATCH 0070/1181] [#3114] Lining up spaces --- reference/configuration/framework.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/configuration/framework.rst b/reference/configuration/framework.rst index 01752fbe950..b65c5fda0de 100644 --- a/reference/configuration/framework.rst +++ b/reference/configuration/framework.rst @@ -463,8 +463,8 @@ Full Default Configuration form: enabled: false csrf_protection: - enabled: true - field_name: ~ + enabled: true + field_name: ~ # esi configuration esi: From 966045557ed7bc3517aa0f55efd0e152c04d20d7 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 3 Nov 2013 15:07:33 +0100 Subject: [PATCH 0071/1181] use verbose HTTP status code constants --- book/controller.rst | 9 ++++++--- book/from_flat_php_to_symfony2.rst | 5 ++++- book/http_cache.rst | 7 +++++-- book/http_fundamentals.rst | 8 ++++++-- book/internals.rst | 7 +++++-- book/testing.rst | 9 ++++++++- components/http_foundation/introduction.rst | 7 +++++-- cookbook/security/custom_authentication_provider.rst | 7 +++++-- cookbook/service_container/event_listener.rst | 5 ++++- cookbook/testing/insulating_clients.rst | 11 +++++++++-- quick_tour/the_big_picture.rst | 7 +++++-- 11 files changed, 62 insertions(+), 20 deletions(-) diff --git a/book/controller.rst b/book/controller.rst index 7907b70b919..a3ca2610273 100755 --- a/book/controller.rst +++ b/book/controller.rst @@ -501,9 +501,9 @@ value to each variable. directly by duplicating the current request. When this :ref:`sub request ` is executed via the ``http_kernel`` service the ``HttpKernel`` returns a ``Response`` object:: - + use Symfony\Component\HttpKernel\HttpKernelInterface; - + $path = array( '_controller' => 'AcmeHelloBundle:Hello:fancy', 'name' => $name, @@ -750,12 +750,15 @@ headers and content that's sent back to the client:: use Symfony\Component\HttpFoundation\Response; // create a simple Response with a 200 status code (the default) - $response = new Response('Hello '.$name, 200); + $response = new Response('Hello '.$name, Response::HTTP_OK); // create a JSON-response with a 200 status code $response = new Response(json_encode(array('name' => $name))); $response->headers->set('Content-Type', 'application/json'); +.. versionadded:: 2.4 + Support for HTTP status code constants was added in Symfony 2.4. + .. tip:: The ``headers`` property is a diff --git a/book/from_flat_php_to_symfony2.rst b/book/from_flat_php_to_symfony2.rst index 3590fe44353..76b5076f3cb 100644 --- a/book/from_flat_php_to_symfony2.rst +++ b/book/from_flat_php_to_symfony2.rst @@ -476,12 +476,15 @@ the HTTP response being returned. Use them to improve the blog: $response = show_action($request->query->get('id')); } else { $html = '

Page Not Found

'; - $response = new Response($html, 404); + $response = new Response($html, Response::HTTP_NOT_FOUND); } // echo the headers and send the response $response->send(); +.. versionadded:: 2.4 + Support for HTTP status code constants was added in Symfony 2.4. + The controllers are now responsible for returning a ``Response`` object. To make this easier, you can add a new ``render_template()`` function, which, incidentally, acts quite a bit like the Symfony2 templating engine: diff --git a/book/http_cache.rst b/book/http_cache.rst index c1c0b737bea..ab845d1bd85 100644 --- a/book/http_cache.rst +++ b/book/http_cache.rst @@ -1059,15 +1059,18 @@ Here is how you can configure the Symfony2 reverse proxy to support the $response = new Response(); if (!$this->getStore()->purge($request->getUri())) { - $response->setStatusCode(404, 'Not purged'); + $response->setStatusCode(Response::HTTP_NOT_FOUND, 'Not purged'); } else { - $response->setStatusCode(200, 'Purged'); + $response->setStatusCode(Response::HTTP_OK, 'Purged'); } return $response; } } +.. versionadded:: 2.4 + Support for HTTP status code constants was added in Symfony 2.4. + .. caution:: You must protect the ``PURGE`` HTTP method somehow to avoid random people diff --git a/book/http_fundamentals.rst b/book/http_fundamentals.rst index 902a5065b9e..391f549a7d7 100644 --- a/book/http_fundamentals.rst +++ b/book/http_fundamentals.rst @@ -278,12 +278,15 @@ interface to construct the response that needs to be returned to the client:: $response = new Response(); $response->setContent('

Hello world!

'); - $response->setStatusCode(200); + $response->setStatusCode(Response::HTTP_OK); $response->headers->set('Content-Type', 'text/html'); // prints the HTTP headers followed by the content $response->send(); +.. versionadded:: 2.4 + Support for HTTP status code constants was added in Symfony 2.4. + If Symfony offered nothing else, you would already have a toolkit for easily accessing request information and an object-oriented interface for creating the response. Even as you learn the many powerful features in Symfony, keep @@ -364,6 +367,7 @@ on that value. This can get ugly quickly:: // index.php use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; + $request = Request::createFromGlobals(); $path = $request->getPathInfo(); // the URI path being requested @@ -372,7 +376,7 @@ on that value. This can get ugly quickly:: } elseif ($path == '/contact') { $response = new Response('Contact us'); } else { - $response = new Response('Page not found.', 404); + $response = new Response('Page not found.', Response::HTTP_NOT_FOUND); } $response->send(); diff --git a/book/internals.rst b/book/internals.rst index 69078e403e1..33a14abb2c9 100644 --- a/book/internals.rst +++ b/book/internals.rst @@ -417,10 +417,13 @@ and set a new ``Exception`` object, or do nothing:: return new Response( 'Error', - 404 // ignored, - array('X-Status-Code' => 200) + Response::HTTP_NOT_FOUND, // ignored + array('X-Status-Code' => Response::HTTP_OK) ); + .. versionadded:: 2.4 + Support for HTTP status code constants was added in Symfony 2.4. + .. index:: single: Event Dispatcher diff --git a/book/testing.rst b/book/testing.rst index 4deb4229075..34e206f87b0 100644 --- a/book/testing.rst +++ b/book/testing.rst @@ -268,6 +268,10 @@ document:: To get you started faster, here is a list of the most common and useful test assertions:: + use Symfony\Component\HttpFoundation\Response; + + // ... + // Assert that there is at least one h2 tag // with the class "subtitle" $this->assertGreaterThan( @@ -295,7 +299,7 @@ document:: $this->assertTrue($client->getResponse()->isNotFound()); // Assert a specific 200 status code $this->assertEquals( - 200, + Response::HTTP_OK, $client->getResponse()->getStatusCode() ); @@ -306,6 +310,9 @@ document:: // or simply check that the response is a redirect to any URL $this->assertTrue($client->getResponse()->isRedirect()); + .. versionadded:: 2.4 + Support for HTTP status code constants was added with Symfony 2.4. + .. index:: single: Tests; Client diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index f7cb342037e..185b5366fbb 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -309,10 +309,13 @@ code, and an array of HTTP headers:: $response = new Response( 'Content', - 200, + Response::HTTP_OK, array('content-type' => 'text/html') ); +.. versionadded:: 2.4 + Support for HTTP status code constants was added in Symfony 2.4. + These information can also be manipulated after the Response object creation:: $response->setContent('Hello World'); @@ -320,7 +323,7 @@ These information can also be manipulated after the Response object creation:: // the headers public attribute is a ResponseHeaderBag $response->headers->set('Content-Type', 'text/plain'); - $response->setStatusCode(404); + $response->setStatusCode(Response::HTTP_NOT_FOUND); When setting the ``Content-Type`` of the Response, you can set the charset, but it is better to set it via the diff --git a/cookbook/security/custom_authentication_provider.rst b/cookbook/security/custom_authentication_provider.rst index 26e3219c062..729c03b5165 100644 --- a/cookbook/security/custom_authentication_provider.rst +++ b/cookbook/security/custom_authentication_provider.rst @@ -153,18 +153,21 @@ set an authenticated token in the security context if successful. // Deny authentication with a '403 Forbidden' HTTP response $response = new Response(); - $response->setStatusCode(403); + $response->setStatusCode(Response::HTTP_FORBIDDEN); $event->setResponse($response); } // By default deny authorization $response = new Response(); - $response->setStatusCode(403); + $response->setStatusCode(Response::HTTP_FORBIDDEN); $event->setResponse($response); } } +.. versionadded:: 2.4 + Support for HTTP status code constants was added in Symfony 2.4. + This listener checks the request for the expected `X-WSSE` header, matches the value returned for the expected WSSE information, creates a token using that information, and passes the token on to the authentication manager. If diff --git a/cookbook/service_container/event_listener.rst b/cookbook/service_container/event_listener.rst index 7e0b5410f79..91f20364bee 100644 --- a/cookbook/service_container/event_listener.rst +++ b/cookbook/service_container/event_listener.rst @@ -43,7 +43,7 @@ event is just one of the core kernel events:: $response->setStatusCode($exception->getStatusCode()); $response->headers->replace($exception->getHeaders()); } else { - $response->setStatusCode(500); + $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR); } // Send the modified response object to the event @@ -51,6 +51,9 @@ event is just one of the core kernel events:: } } +.. versionadded:: 2.4 + Support for HTTP status code constants was added in Symfony 2.4. + .. tip:: Each event receives a slightly different type of ``$event`` object. For diff --git a/cookbook/testing/insulating_clients.rst b/cookbook/testing/insulating_clients.rst index 3411968eb80..f9c602dcf67 100644 --- a/cookbook/testing/insulating_clients.rst +++ b/cookbook/testing/insulating_clients.rst @@ -7,19 +7,26 @@ How to test the Interaction of several Clients If you need to simulate an interaction between different Clients (think of a chat for instance), create several Clients:: + // ... + $harry = static::createClient(); $sally = static::createClient(); $harry->request('POST', '/say/sally/Hello'); $sally->request('GET', '/messages'); - $this->assertEquals(201, $harry->getResponse()->getStatusCode()); + $this->assertEquals(Response::HTTP_CREATED, $harry->getResponse()->getStatusCode()); $this->assertRegExp('/Hello/', $sally->getResponse()->getContent()); +.. versionadded:: 2.4 + Support for HTTP status code constants was added in Symfony 2.4. + This works except when your code maintains a global state or if it depends on a third-party library that has some kind of global state. In such a case, you can insulate your clients:: + // ... + $harry = static::createClient(); $sally = static::createClient(); @@ -29,7 +36,7 @@ can insulate your clients:: $harry->request('POST', '/say/sally/Hello'); $sally->request('GET', '/messages'); - $this->assertEquals(201, $harry->getResponse()->getStatusCode()); + $this->assertEquals(Response::HTTP_CREATED, $harry->getResponse()->getStatusCode()); $this->assertRegExp('/Hello/', $sally->getResponse()->getContent()); Insulated clients transparently execute their requests in a dedicated and diff --git a/quick_tour/the_big_picture.rst b/quick_tour/the_big_picture.rst index 9ba1161c7a6..8436651ba33 100644 --- a/quick_tour/the_big_picture.rst +++ b/quick_tour/the_big_picture.rst @@ -232,7 +232,10 @@ controller might create the response by hand, based on the request:: $name = $request->query->get('name'); - return new Response('Hello '.$name, 200, array('Content-Type' => 'text/plain')); + return new Response('Hello '.$name, Response::HTTP_OK, array('Content-Type' => 'text/plain')); + +.. versionadded:: 2.4 + Support for HTTP status code constants was added in Symfony 2.4. .. note:: @@ -421,7 +424,7 @@ When loaded and enabled (by default in the ``dev`` :ref:`environment Date: Sat, 9 Nov 2013 13:38:07 +0100 Subject: [PATCH 0072/1181] Bumped version number --- components/dependency_injection/lazy_services.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dependency_injection/lazy_services.rst b/components/dependency_injection/lazy_services.rst index 8f80997777b..3ec19f35fb5 100644 --- a/components/dependency_injection/lazy_services.rst +++ b/components/dependency_injection/lazy_services.rst @@ -40,7 +40,7 @@ the `ProxyManager bridge`_: .. code-block:: json "require": { - "ocramius/proxy-manager": "0.4.*" + "ocramius/proxy-manager": "0.5.*" } to your ``composer.json``. Afterwards compile your container and check From c5ae3dd4c440b25fe150d9599799d4c5cbf2ebe3 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 12 Sep 2013 17:42:39 -0500 Subject: [PATCH 0073/1181] [#2956] Refactoring the scopes entry entirely to not talk about the request anymore, since it has a simpler solution See sha: b84f52c28d969b5143521261d818105824eaea5e for more information. --- cookbook/service_container/scopes.rst | 201 ++++++++++++++------------ 1 file changed, 107 insertions(+), 94 deletions(-) diff --git a/cookbook/service_container/scopes.rst b/cookbook/service_container/scopes.rst index 78ccb76126f..32884424732 100644 --- a/cookbook/service_container/scopes.rst +++ b/cookbook/service_container/scopes.rst @@ -12,7 +12,9 @@ This entry is all about scopes, a somewhat advanced topic related to the If you are trying to inject the ``request`` service, the simple solution is to inject the ``request_stack`` service instead and access the current - Request by calling the ``getCurrentRequest()`` method. + Request by calling the ``getCurrentRequest()`` method. The rest of this + entry talks about scopes in a theoretical and more advanced way. If you're + dealing with scopes for the ``request`` service, simply inject ``request_stack``. Understanding Scopes -------------------- @@ -32,10 +34,22 @@ also defines a third scope: ``request``. This scope is tied to the request, meaning a new instance is created for each subrequest and is unavailable outside the request (for instance in the CLI). +The Example: client Scope +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Other than the ``request`` service (which has a simple solution, see the +above note), no services in the default Symfony2 container belong to any +scope other than ``container`` and ``prototype``. But for the purposes of +this entry, imagine there is another scope ``client`` and a service ``client_configuration`` +that belongs to it. This is not a common situation, but the idea is that +you may enter and exit multiple ``client`` scopes during a request, and each +has its own ``client_configuration`` service. + Scopes add a constraint on the dependencies of a service: a service cannot depend on services from a narrower scope. For example, if you create a generic -``my_foo`` service, but try to inject the ``request`` service, you will receive -a :class:`Symfony\\Component\\DependencyInjection\\Exception\\ScopeWideningInjectionException` +``my_foo`` service, but try to inject the ``client_configuration`` service, +you will receive a +:class:`Symfony\\Component\\DependencyInjection\\Exception\\ScopeWideningInjectionException` when compiling the container. Read the sidebar below for more details. .. sidebar:: Scopes and Dependencies @@ -45,28 +59,29 @@ when compiling the container. Read the sidebar below for more details. every time you ask the container for the ``my_mailer`` service, you get the same object back. This is usually how you want your services to work. - Imagine, however, that you need the ``request`` service in your ``my_mailer`` - service, maybe because you're reading the URL of the current request. - So, you add it as a constructor argument. Let's look at why this presents - a problem: + Imagine, however, that you need the ``client_configuration`` service + in your ``my_mailer`` service, maybe because you're reading some details + from it, such as what the "sender" address should be. You add it as a + constructor argument. Let's look at why this presents a problem: * When requesting ``my_mailer``, an instance of ``my_mailer`` (let's call - it *MailerA*) is created and the ``request`` service (let's call it - *RequestA*) is passed to it. Life is good! + it *MailerA*) is created and the ``client_configuration`` service (let's + call it *ConfigurationA*) is passed to it. Life is good! - * You've now made a subrequest in Symfony, which is a fancy way of saying - that you've called, for example, the ``{{ render(...) }}`` Twig function, - which executes another controller. Internally, the old ``request`` service - (*RequestA*) is actually replaced by a new request instance (*RequestB*). - This happens in the background, and it's totally normal. + * Your application now needs to do something with another client, and + you've architected your application in such a way that you handle this + by entering a new ``client_configuration`` scope and setting a new + ``client_configuration`` service into the container. Let's call this + *ConfigurationB*. - * In your embedded controller, you once again ask for the ``my_mailer`` + * Somewhere in your application, you once again ask for the ``my_mailer`` service. Since your service is in the ``container`` scope, the same instance (*MailerA*) is just re-used. But here's the problem: the - *MailerA* instance still contains the old *RequestA* object, which - is now **not** the correct request object to have (*RequestB* is now - the current ``request`` service). This is subtle, but the mis-match could - cause major problems, which is why it's not allowed. + *MailerA* instance still contains the old *ConfigurationA* object, which + is now **not** the correct configuration object to have (*ConfigurationB* + is now the current ``client_configuration`` service). This is subtle, + but the mis-match could cause major problems, which is why it's not + allowed. So, that's the reason *why* scopes exist, and how they can cause problems. Keep reading to find out the common solutions. @@ -79,19 +94,14 @@ when compiling the container. Read the sidebar below for more details. Using a Service from a narrower Scope ------------------------------------- -The most common problem with "scope" is when your service has a dependency -on the ``request`` service. The *easiest* way to solve this is to instead -inject the ``request_stack`` service and access the current Request by calling -the ``getCurrentRequest()`` method. - -This solution is great, but there are also others: +There are several solutions to the scope problem: * Use setter injection if the dependency is "synchronized"; (see :ref:`using-synchronized-service`). * Put your service in the same scope as the dependency (or a narrower one). If - you depend on the ``request`` service, this means putting your new service - in the ``request`` scope (see :ref:`changing-service-scope`); + you depend on the ``client_configuration`` service, this means putting your + new service in the ``client`` scope (see :ref:`changing-service-scope`); * Pass the entire container to your service and retrieve your dependency from the container each time you need it to be sure you have the right instance @@ -109,42 +119,81 @@ Using a synchronized Service Synchronized services are new in Symfony 2.3. Injecting the container or setting your service to a narrower scope have -drawbacks. For synchronized services (like the ``request``), using setter -injection is a nice option as it has no drawbacks and everything works -without any special code in your service or in your definition:: +drawbacks. Assume first that the ``client_configuration`` service has been +marked as "synchronized": + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + services: + client_configuration: + class: Acme\HelloBundle\Client\ClientConfiguration + scope: client + synchronized: true + + .. code-block:: xml + + + + + + + + + + + .. code-block:: php + + // app/config/config.php + use Symfony\Component\DependencyInjection\Definition; + + $defn = new Definition( + 'Acme\HelloBundle\Client\ClientConfiguration', + array() + ); + $defn->setScope('client'); + $defn->setSynchronized(true); + $container->setDefinition('client_configuration', $defn); + +Now, if you inject this service using setter injection, there are no drawbacks +and everything works without any special code in your service or in your definition:: // src/Acme/HelloBundle/Mail/Mailer.php namespace Acme\HelloBundle\Mail; - use Symfony\Component\HttpFoundation\Request; + use Acme\HelloBundle\Client\ClientConfiguration; class Mailer { - protected $request; + protected $clientConfiguration; - public function setRequest(Request $request = null) + public function setClientConfiguration(ClientConfiguration $clientConfiguration = null) { - $this->request = $request; + $this->clientConfiguration = $clientConfiguration; } public function sendEmail() { - if (null === $this->request) { + if (null === $this->clientConfiguration) { // throw an error? } - // ... do something using the request here + // ... do something using the client configuration here } } -Whenever the ``request`` scope is entered or left, the service container will -automatically call the ``setRequest()`` method with the current ``request`` -instance. +Whenever the ``client`` scope is entered or left, the service container will +automatically call the ``setClientConfiguration()`` method with the current +``client_configuration`` instance. -You might have noticed that the ``setRequest()`` method accepts ``null`` as a -valid value for the ``request`` argument. That's because when leaving the -``request`` scope, the ``request`` instance can be ``null`` (for the master -request for instance). Of course, you should take care of this possibility in +You might have noticed that the ``setClientConfiguration()`` method accepts +``null`` as a valid value for the ``client_configuration`` argument. That's +because when leaving the ``client`` scope, the ``client_configuration`` instance +can be ``null``. Of course, you should take care of this possibility in your code. This should also be taken into account when declaring your service: .. configuration-block:: @@ -156,7 +205,7 @@ your code. This should also be taken into account when declaring your service: greeting_card_manager: class: Acme\HelloBundle\Mail\GreetingCardManager calls: - - [setRequest, ['@?request=']] + - [setClientConfiguration, ['@?client_configuration=']] .. code-block:: xml @@ -165,8 +214,8 @@ your code. This should also be taken into account when declaring your service: - - + + @@ -181,46 +230,10 @@ your code. This should also be taken into account when declaring your service: 'greeting_card_manager', new Definition('Acme\HelloBundle\Mail\GreetingCardManager') ) - ->addMethodCall('setRequest', array( - new Reference('request', ContainerInterface::NULL_ON_INVALID_REFERENCE, false) + ->addMethodCall('setClientConfiguration', array( + new Reference('client_configuration', ContainerInterface::NULL_ON_INVALID_REFERENCE, false) )); -.. tip:: - - You can declare your own ``synchronized`` services very easily; here is - the declaration of the ``request`` service for reference: - - .. configuration-block:: - - .. code-block:: yaml - - services: - request: - scope: request - synthetic: true - synchronized: true - - .. code-block:: xml - - - - - - .. code-block:: php - - use Symfony\Component\DependencyInjection\Definition; - use Symfony\Component\DependencyInjection\ContainerInterface; - - $definition = $container->setDefinition('request') - ->setScope('request') - ->setSynthetic(true) - ->setSynchronized(true); - -.. caution:: - - The service using the synchronized service will need to be public in order - to have its setter called when the scope changes. - .. _changing-service-scope: Changing the Scope of your Service @@ -236,8 +249,8 @@ Changing the scope of a service should be done in its definition: services: greeting_card_manager: class: Acme\HelloBundle\Mail\GreetingCardManager - scope: request - arguments: [@request] + scope: client + arguments: [@client_configuration] .. code-block:: xml @@ -245,9 +258,9 @@ Changing the scope of a service should be done in its definition: - + .. code-block:: php @@ -259,9 +272,9 @@ Changing the scope of a service should be done in its definition: 'greeting_card_manager', new Definition( 'Acme\HelloBundle\Mail\GreetingCardManager', - array(new Reference('request'), + array(new Reference('client_configuration'), )) - )->setScope('request'); + )->setScope('client'); .. _passing-container: @@ -289,15 +302,15 @@ into your service:: public function sendEmail() { - $request = $this->container->get('request'); - // ... do something using the request here + $request = $this->container->get('client_configuration'); + // ... do something using the client configuration here } } .. caution:: - Take care not to store the request in a property of the object for a - future call of the service as it would cause the same issue described + Take care not to store the client configuration in a property of the object + for a future call of the service as it would cause the same issue described in the first section (except that Symfony cannot detect that you are wrong). From d417f7b4363011dacd6f91a99e94e602fe35f97d Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 11 Nov 2013 21:04:18 -0500 Subject: [PATCH 0074/1181] [#2972] Many small tweaks - thanks very much to @WouterJ and @xabbuh --- book/service_container.rst | 2 + cookbook/service_container/scopes.rst | 102 +++++++++++++++----------- 2 files changed, 63 insertions(+), 41 deletions(-) diff --git a/book/service_container.rst b/book/service_container.rst index 2d3b65ab0c5..a5c7b3d0748 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -754,6 +754,8 @@ Injecting the dependency by the setter method just needs a change of syntax: and "setter injection". The Symfony2 service container also supports "property injection". +.. _book-container-request-stack: + Injecting the Request ~~~~~~~~~~~~~~~~~~~~~ diff --git a/cookbook/service_container/scopes.rst b/cookbook/service_container/scopes.rst index 32884424732..03d94e1a426 100644 --- a/cookbook/service_container/scopes.rst +++ b/cookbook/service_container/scopes.rst @@ -12,9 +12,10 @@ This entry is all about scopes, a somewhat advanced topic related to the If you are trying to inject the ``request`` service, the simple solution is to inject the ``request_stack`` service instead and access the current - Request by calling the ``getCurrentRequest()`` method. The rest of this - entry talks about scopes in a theoretical and more advanced way. If you're - dealing with scopes for the ``request`` service, simply inject ``request_stack``. + Request by calling the ``getCurrentRequest()`` method (see :ref:`book-container-request-stack`). + The rest of this entry talks about scopes in a theoretical and more advanced + way. If you're dealing with scopes for the ``request`` service, simply + inject ``request_stack``. Understanding Scopes -------------------- @@ -34,8 +35,8 @@ also defines a third scope: ``request``. This scope is tied to the request, meaning a new instance is created for each subrequest and is unavailable outside the request (for instance in the CLI). -The Example: client Scope -~~~~~~~~~~~~~~~~~~~~~~~~~ +An Example: client Scope +~~~~~~~~~~~~~~~~~~~~~~~~ Other than the ``request`` service (which has a simple solution, see the above note), no services in the default Symfony2 container belong to any @@ -64,14 +65,14 @@ when compiling the container. Read the sidebar below for more details. from it, such as what the "sender" address should be. You add it as a constructor argument. Let's look at why this presents a problem: - * When requesting ``my_mailer``, an instance of ``my_mailer`` (let's call - it *MailerA*) is created and the ``client_configuration`` service (let's - call it *ConfigurationA*) is passed to it. Life is good! + * When requesting ``my_mailer``, an instance of ``my_mailer`` (called + *MailerA* here) is created and the ``client_configuration`` service ( + called *ConfigurationA* here) is passed to it. Life is good! * Your application now needs to do something with another client, and you've architected your application in such a way that you handle this by entering a new ``client_configuration`` scope and setting a new - ``client_configuration`` service into the container. Let's call this + ``client_configuration`` service into the container. Call this *ConfigurationB*. * Somewhere in your application, you once again ask for the ``my_mailer`` @@ -96,14 +97,14 @@ Using a Service from a narrower Scope There are several solutions to the scope problem: -* Use setter injection if the dependency is "synchronized"; (see +* A) Use setter injection if the dependency is "synchronized"; (see :ref:`using-synchronized-service`). -* Put your service in the same scope as the dependency (or a narrower one). If +* B) Put your service in the same scope as the dependency (or a narrower one). If you depend on the ``client_configuration`` service, this means putting your new service in the ``client`` scope (see :ref:`changing-service-scope`); -* Pass the entire container to your service and retrieve your dependency from +* C) Pass the entire container to your service and retrieve your dependency from the container each time you need it to be sure you have the right instance -- your service can live in the default ``container`` scope (see :ref:`passing-container`); @@ -112,15 +113,15 @@ Each scenario is detailed in the following sections. .. _using-synchronized-service: -Using a synchronized Service -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A) Using a synchronized Service +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.3 Synchronized services are new in Symfony 2.3. -Injecting the container or setting your service to a narrower scope have +Both injecting the container and setting your service to a narrower scope have drawbacks. Assume first that the ``client_configuration`` service has been -marked as "synchronized": +marked as ``synchronized``: .. configuration-block:: @@ -132,6 +133,7 @@ marked as "synchronized": class: Acme\HelloBundle\Client\ClientConfiguration scope: client synchronized: true + # ... .. code-block:: xml @@ -139,10 +141,17 @@ marked as "synchronized": + xsi:schemaLocation="http://symfony.com/schema/dic/services + http://symfony.com/schema/dic/services/services-1.0.xsd" + > - + @@ -151,13 +160,13 @@ marked as "synchronized": // app/config/config.php use Symfony\Component\DependencyInjection\Definition; - $defn = new Definition( + $definition = new Definition( 'Acme\HelloBundle\Client\ClientConfiguration', array() ); - $defn->setScope('client'); - $defn->setSynchronized(true); - $container->setDefinition('client_configuration', $defn); + $definition->setScope('client'); + $definition->setSynchronized(true); + $container->setDefinition('client_configuration', $definition); Now, if you inject this service using setter injection, there are no drawbacks and everything works without any special code in your service or in your definition:: @@ -202,8 +211,8 @@ your code. This should also be taken into account when declaring your service: # src/Acme/HelloBundle/Resources/config/services.yml services: - greeting_card_manager: - class: Acme\HelloBundle\Mail\GreetingCardManager + my_mailer: + class: Acme\HelloBundle\Mail\Mailer calls: - [setClientConfiguration, ['@?client_configuration=']] @@ -211,11 +220,16 @@ your code. This should also be taken into account when declaring your service: - - + @@ -227,19 +241,25 @@ your code. This should also be taken into account when declaring your service: use Symfony\Component\DependencyInjection\ContainerInterface; $definition = $container->setDefinition( - 'greeting_card_manager', - new Definition('Acme\HelloBundle\Mail\GreetingCardManager') + 'my_mailer', + new Definition('Acme\HelloBundle\Mail\Mailer') ) ->addMethodCall('setClientConfiguration', array( - new Reference('client_configuration', ContainerInterface::NULL_ON_INVALID_REFERENCE, false) + new Reference( + 'client_configuration', + ContainerInterface::NULL_ON_INVALID_REFERENCE, + false + ) )); .. _changing-service-scope: -Changing the Scope of your Service -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +B) Changing the Scope of your Service +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Changing the scope of a service should be done in its definition: +Changing the scope of a service should be done in its definition. This example +assumes that the ``Mailer`` class has a ``__construct`` function whose first +argument is the ``ClientConfiguration`` object: .. configuration-block:: @@ -247,8 +267,8 @@ Changing the scope of a service should be done in its definition: # src/Acme/HelloBundle/Resources/config/services.yml services: - greeting_card_manager: - class: Acme\HelloBundle\Mail\GreetingCardManager + my_mailer: + class: Acme\HelloBundle\Mail\Mailer scope: client arguments: [@client_configuration] @@ -256,8 +276,8 @@ Changing the scope of a service should be done in its definition: - @@ -269,17 +289,17 @@ Changing the scope of a service should be done in its definition: use Symfony\Component\DependencyInjection\Definition; $definition = $container->setDefinition( - 'greeting_card_manager', + 'my_mailer', new Definition( - 'Acme\HelloBundle\Mail\GreetingCardManager', + 'Acme\HelloBundle\Mail\Mailer', array(new Reference('client_configuration'), )) )->setScope('client'); .. _passing-container: -Passing the Container as a Dependency of your Service -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +C) Passing the Container as a Dependency of your Service +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Setting the scope to a narrower one is not always possible (for instance, a twig extension must be in the ``container`` scope as the Twig environment From 3dcbbc25772b7e87388bf04b79d855b2a2911306 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 11 Nov 2013 21:12:38 -0500 Subject: [PATCH 0075/1181] [#2972] Clarifying how to use the request_stack with an example --- book/service_container.rst | 93 ++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 14 deletions(-) diff --git a/book/service_container.rst b/book/service_container.rst index a5c7b3d0748..8644d93685a 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -762,22 +762,87 @@ Injecting the Request .. versionadded:: 2.4 The ``request_stack`` service was introduced in version 2.4. -Almost all Symfony2 built-in services behave in the same way: a single -instance is created by the container which it returns whenever you get it or -when it is injected into another service. There is one exception in a standard -Symfony2 application: the ``request`` service. - -If you try to inject the ``request`` into a service, you will probably receive -a -:class:`Symfony\\Component\\DependencyInjection\\Exception\\ScopeWideningInjectionException` -exception. That's because the ``request`` can **change** during the life-time -of a container (when a sub-request is created for instance). - As of Symfony 2.4, instead of injecting the ``request`` service, you should inject the ``request_stack`` service instead and access the Request by calling -the ``getCurrentRequest()`` method. For earlier versions, or if you want to -understand this problem better, refer to the cookbook article -:doc:`/cookbook/service_container/scopes`. +the ``getCurrentRequest()`` method: + + namespace Acme\HelloBundle\Newsletter; + + use Symfony\Component\HttpFoundation\RequestStack; + + class NewsletterManager + { + protected $requestStack; + + public function __construct(RequestStack $requestStack) + { + $this->requestStack = $requestStack; + } + + public function anyMethod() + { + $request = $this->requestStack->getCurrentRequest(); + // ... do something with the request + } + + // ... + } + +Now, just inject the ``request_stack``, which behaves like any normal service: + +.. configuration-block:: + + .. code-block:: yaml + + # src/Acme/HelloBundle/Resources/config/services.yml + services: + newsletter_manager: + class: "Acme\HelloBundle\Newsletter\NewsletterManager" + arguments: ["@request_stack"] + + .. code-block:: xml + + + + + + + + + + + + + .. code-block:: php + + // src/Acme/HelloBundle/Resources/config/services.php + use Symfony\Component\DependencyInjection\Definition; + use Symfony\Component\DependencyInjection\Reference; + + // ... + $container->setDefinition('newsletter_manager', new Definition( + 'Acme\HelloBundle\Newsletter\NewsletterManager', + array(new Reference('request_stack')) + )); + +.. sidebar: Why not Inject the request Service? + + Almost all Symfony2 built-in services behave in the same way: a single + instance is created by the container which it returns whenever you get it or + when it is injected into another service. There is one exception in a standard + Symfony2 application: the ``request`` service. + + If you try to inject the ``request`` into a service, you will probably receive + a + :class:`Symfony\\Component\\DependencyInjection\\Exception\\ScopeWideningInjectionException` + exception. That's because the ``request`` can **change** during the life-time + of a container (when a sub-request is created for instance). + .. tip:: From 80a364386ed8016fad881d3b911b6bcb90f055cc Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 12 Nov 2013 11:37:27 +0100 Subject: [PATCH 0076/1181] some tweaks and fixes to d417f7b and 3dcbbc2 --- book/service_container.rst | 7 ++++--- cookbook/service_container/scopes.rst | 21 +++++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/book/service_container.rst b/book/service_container.rst index 8644d93685a..830a660e858 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -763,8 +763,9 @@ Injecting the Request The ``request_stack`` service was introduced in version 2.4. As of Symfony 2.4, instead of injecting the ``request`` service, you should -inject the ``request_stack`` service instead and access the Request by calling -the ``getCurrentRequest()`` method: +inject the ``request_stack`` service and access the ``Request`` by calling +the :method:`Symfony\\Component\\HttpFoundation\\RequestStack::getCurrentRequest` +method:: namespace Acme\HelloBundle\Newsletter; @@ -830,7 +831,7 @@ Now, just inject the ``request_stack``, which behaves like any normal service: array(new Reference('request_stack')) )); -.. sidebar: Why not Inject the request Service? +.. sidebar:: Why not Inject the ``request`` Service? Almost all Symfony2 built-in services behave in the same way: a single instance is created by the container which it returns whenever you get it or diff --git a/cookbook/service_container/scopes.rst b/cookbook/service_container/scopes.rst index 03d94e1a426..44f9ade52b2 100644 --- a/cookbook/service_container/scopes.rst +++ b/cookbook/service_container/scopes.rst @@ -12,10 +12,11 @@ This entry is all about scopes, a somewhat advanced topic related to the If you are trying to inject the ``request`` service, the simple solution is to inject the ``request_stack`` service instead and access the current - Request by calling the ``getCurrentRequest()`` method (see :ref:`book-container-request-stack`). - The rest of this entry talks about scopes in a theoretical and more advanced - way. If you're dealing with scopes for the ``request`` service, simply - inject ``request_stack``. + Request by calling the + :method:`Symfony\\Component\\HttpFoundation\\RequestStack::getCurrentRequest` + method (see :ref:`book-container-request-stack`). The rest of this entry + talks about scopes in a theoretical and more advanced way. If you're + dealing with scopes for the ``request`` service, simply inject ``request_stack``. Understanding Scopes -------------------- @@ -35,7 +36,7 @@ also defines a third scope: ``request``. This scope is tied to the request, meaning a new instance is created for each subrequest and is unavailable outside the request (for instance in the CLI). -An Example: client Scope +An Example: Client Scope ~~~~~~~~~~~~~~~~~~~~~~~~ Other than the ``request`` service (which has a simple solution, see the @@ -92,13 +93,13 @@ when compiling the container. Read the sidebar below for more details. A service can of course depend on a service from a wider scope without any issue. -Using a Service from a narrower Scope +Using a Service from a Narrower Scope ------------------------------------- There are several solutions to the scope problem: -* A) Use setter injection if the dependency is "synchronized"; (see - :ref:`using-synchronized-service`). +* A) Use setter injection if the dependency is ``synchronized`` (see + :ref:`using-synchronized-service`); * B) Put your service in the same scope as the dependency (or a narrower one). If you depend on the ``client_configuration`` service, this means putting your @@ -107,13 +108,13 @@ There are several solutions to the scope problem: * C) Pass the entire container to your service and retrieve your dependency from the container each time you need it to be sure you have the right instance -- your service can live in the default ``container`` scope (see - :ref:`passing-container`); + :ref:`passing-container`). Each scenario is detailed in the following sections. .. _using-synchronized-service: -A) Using a synchronized Service +A) Using a Synchronized Service ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.3 From 343a59e9ea58ed750d1c6211db349d3b2cc4352e Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 13 Nov 2013 08:52:16 -0500 Subject: [PATCH 0077/1181] Removing some 2.1 references that were merged up --- reference/forms/types/options/error_mapping.rst.inc | 3 --- reference/twig_reference.rst | 3 --- 2 files changed, 6 deletions(-) diff --git a/reference/forms/types/options/error_mapping.rst.inc b/reference/forms/types/options/error_mapping.rst.inc index e6b55fb0ff5..05ad2148c34 100644 --- a/reference/forms/types/options/error_mapping.rst.inc +++ b/reference/forms/types/options/error_mapping.rst.inc @@ -3,9 +3,6 @@ error_mapping **type**: ``array`` **default**: ``empty`` -.. versionadded:: 2.1 - The ``error_mapping`` option is new to Symfony 2.1. - This option allows you to modify the target of a validation error. Imagine you have a custom method named ``matchingCityAndZipCode`` that validates diff --git a/reference/twig_reference.rst b/reference/twig_reference.rst index 6c091825062..45a920a9481 100644 --- a/reference/twig_reference.rst +++ b/reference/twig_reference.rst @@ -93,9 +93,6 @@ Functions Filters ------- -.. versionadded:: 2.1 - The ``humanize`` filter was added in Symfony 2.1 - +---------------------------------------------------------------------------------+-------------------------------------------------------------------+ | Filter Syntax | Usage | +=================================================================================+===================================================================+ From ff4a44ee605d525ec02e2c7f8bfa8f1284566aa6 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 16 Nov 2013 16:21:52 -0600 Subject: [PATCH 0078/1181] [#2906][#3190] Removing versionadded:: 2.1 tags after merge --- book/translation.rst | 8 -------- components/translation/introduction.rst | 5 ----- 2 files changed, 13 deletions(-) diff --git a/book/translation.rst b/book/translation.rst index 4dcbe5e2495..7605aee3d16 100644 --- a/book/translation.rst +++ b/book/translation.rst @@ -305,9 +305,6 @@ texts* and complex expressions: Note that this only influences the current template, not any "included" templates (in order to avoid side effects). -.. versionadded:: 2.1 - The ``trans_default_domain`` tag is new in Symfony2.1 - PHP Templates ~~~~~~~~~~~~~ @@ -520,11 +517,6 @@ the framework: 'default_locale' => 'en', )); -.. versionadded:: 2.1 - The ``default_locale`` parameter was defined under the session key - originally, however, as of 2.1 this has been moved. This is because the - locale is now set on the request instead of the session. - .. _book-translation-constraint-messages: Translating Constraint Messages diff --git a/components/translation/introduction.rst b/components/translation/introduction.rst index 31c3074680e..a21ee5d6aea 100644 --- a/components/translation/introduction.rst +++ b/components/translation/introduction.rst @@ -88,11 +88,6 @@ Loader too. The default loaders are: * :class:`Symfony\\Component\\Translation\\Loader\\YamlFileLoader` - to load catalogs from Yaml files (requires the :doc:`Yaml component`). -.. versionadded:: 2.1 - The ``IcuDatFileLoader``, ``IcuResFileLoader``, ``IniFileLoader``, - ``MofileLoader``, ``PoFileLoader`` and ``QtFileLoader`` are new in - Symfony 2.1 - All file loaders require the :doc:`Config component`. At first, you should add one or more loaders to the ``Translator``:: From 55a2de49dce07919f5e79f0d1aaded50e37fe934 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Fri, 22 Nov 2013 18:00:40 -0600 Subject: [PATCH 0079/1181] Removing a versionadded:: 2.1 that came from the merge --- components/filesystem.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/components/filesystem.rst b/components/filesystem.rst index 1a2252a7f6a..2f84a598ffb 100644 --- a/components/filesystem.rst +++ b/components/filesystem.rst @@ -6,10 +6,6 @@ The Filesystem Component The Filesystem component provides basic utilities for the filesystem. -.. versionadded:: 2.1 - The Filesystem component is new to Symfony 2.1. Previously, the ``Filesystem`` - class was located in the HttpKernel component. - Installation ------------ From e9a81bfdf19aac7dc4f85f90d01efc65101bbbf8 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 16 Nov 2013 19:06:59 -0600 Subject: [PATCH 0080/1181] [#3044] Furthering @WouterJ's work on the ExpressionLanguage component This adds more examples, details about how to pass in variables, and working with objects/arrays --- .../expression_language/introduction.rst | 69 ++++++- components/expression_language/syntax.rst | 181 ++++++++++++++++-- 2 files changed, 230 insertions(+), 20 deletions(-) diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst index a7f474c732a..da23a869e0f 100644 --- a/components/expression_language/introduction.rst +++ b/components/expression_language/introduction.rst @@ -10,24 +10,51 @@ The ExpressionLanguage Component (mostly, but not limited to, Booleans). .. versionadded:: 2.4 - The ExpressionLanguage component was new in Symfony 2.4. + The ExpressionLanguage component was added in Symfony 2.4. Installation ------------ You can install the component in 2 different ways: -* Use the official Git repository (https://github.com/symfony/expression-language); * :doc:`Install it via Composer ` (``symfony/expression-language`` on `Packagist`_). +* Use the official Git repository (https://github.com/symfony/expression-language); + +How can the Expression Engine Help Me? +-------------------------------------- + +The purpose of the component is to allow users to use expressions inside +configuration for more complex logic. In the Symfony2 Framework, for example, +expressions can be used in security, for validation rules, and in route matching. + +Besides using the component in the framework itself, the ExpressionLanguage +component is a perfect candidate for the foundation of a *business rule engine*. +The idea is to let the webmaster of a website configure things in a dynamic +way without using PHP and without introducing security problems: + +.. code-block:: text + + # Get the special price if + user.getGroup() in ['good_customers', 'collaborator'] + + # Promote article to the homepage when + article.commentCount > 100 and article.category not in ["misc"] + + # Send an alert when + product.stock < 15 + +Expressions can be seen as a very restricted PHP sandbox and are immune to +external injections as you must explicitly declare which variables are available +in an expression. Usage ----- The ExpressionLanguage component can compile and evaluate expressions. -Expressions are one-liners which most of the time return a boolean, you can -compare them to the expression in an ``if`` statement. A simple example of an -expression is ``1 + 2``. You can also use more complicated expressions, such -as ``someArray[3].someMethod('bar')``. +Expressions are one-liners that often return a Boolean, which can be used +by the code executing the expression in an ``if`` statements. A simple example +of an expression is ``1 + 2``. You can also use more complicated expressions, +such as ``someArray[3].someMethod('bar')``. The component provides 2 ways to work with expressions: @@ -49,7 +76,35 @@ The main class of the component is Expression Syntax ----------------- -See ":doc:`/components/expression_language/syntax`" to learn the syntax of the +See :doc:`/components/expression_language/syntax` to learn the syntax of the ExpressionLanguage component. +Passing in Variables +-------------------- + +You can also pass variables into the expression, which can be of any valid +PHP type (including objects):: + + use Symfony\Component\ExpressionLanguage\ExpressionLanguage; + + $language = new ExpressionLanguage(); + + class Apple + { + public $variety; + } + + $apple = new Apple(); + $apple->variety = 'Honeycrisp'; + + echo $language->evaluate( + 'fruit.variety', + array( + 'fruit' => $apple, + ) + ); + +This will print "Honeycrisp". For more information, see the :doc:`/components/expression_language/syntax` +entry, especially :ref:`component-expression-objects` and :ref:`component-expression-arrays`. + .. _Packagist: https://packagist.org/packages/symfony/expression-language diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index 7c3a59fccb9..4cc7da1192b 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -9,24 +9,102 @@ expression syntax of Twig. In this document, you can find all supported syntaxes. Supported Literals -~~~~~~~~~~~~~~~~~~ +------------------ The component supports: * **strings** - single and double quotes (e.g. ``'hello'``) * **numbers** - e.g. ``103`` -* **arrays** - using twig notation (e.g. ``[1, 2]``) -* **hashes** - using twig notation (e.g. ``{ foo: 'bar' }``) +* **arrays** - using JSON-like notation (e.g. ``[1, 2]``) +* **hashes** - using JSON-like notation (e.g. ``{ foo: 'bar' }``) * **booleans** - ``true`` and ``false`` * **null** - ``null`` +.. _component-expression-objects: + +Working with Objects +-------------------- + +When passing objects into an expression, you can use different syntaxes to +access properties and call methods on the object. + +Accessing Public Methods +~~~~~~~~~~~~~~~~~~~~~~~~ + +Public properties on objects can be accessed by using the ``.`` syntax, similar +to JavaScript:: + + class Apple + { + public $variety; + } + + $apple = new Apple(); + $apple->variety = 'Honeycrisp'; + + echo $language->evaluate( + 'fruit.variety', + array( + 'fruit' => $apple, + ) + ); + +Calling Methods +~~~~~~~~~~~~~~~ + +The ``.`` syntax can also be used to call methods on an object, similar to +JavaScript:: + + class Robot + { + public function sayHi($times) + { + $greetings = array(); + for ($i = 0; $i < $times; $i++) { + $greetings[] = 'Hi'; + } + + return implode(' ', $greetings).'!'; + } + } + + $robot = new Robot(); + + echo $language->evaluate( + 'robot.sayHi(3)', + array( + 'robot' => $robot, + ) + ); + +This will print "Hi Hi Hi!"; + +.. _component-expression-arrays: + +Working with Arrays +------------------- + +If you pass an array into an expression, use the ``[]`` syntax to access +array keys, similar to JavaScript:: + + $data = array('life' => 10, 'universe' => 10, 'everything' => 22); + + echo $language->evaluate( + 'data["life"] + data["universe"] + data["everything"]', + array( + 'data' => $data, + ) + ); + +This will print ``42``. + Supported Operators -~~~~~~~~~~~~~~~~~~~ +------------------- The component comes with a lot of operators: Arithmetic Operators -.................... +~~~~~~~~~~~~~~~~~~~~ * ``+`` (addition) * ``-`` (subtraction) @@ -35,20 +113,33 @@ Arithmetic Operators * ``%`` (modulus) * ``**`` (pow) +For example:: + + echo $language->evaluate( + 'life + universe + everything', + array( + 'life' => 10, + 'universe' => 10, + 'everything' => 22, + ) + ); + +This will print out ``42``. + Assignment Operators -.................... +~~~~~~~~~~~~~~~~~~~~ * ``=`` Bitwise Operators -................. +~~~~~~~~~~~~~~~~~ * ``&`` (and) * ``|`` (or) * ``^`` (xor) Comparison Operators -.................... +~~~~~~~~~~~~~~~~~~~~ * ``==`` (equal) * ``===`` (identical) @@ -67,31 +158,95 @@ Comparison Operators $language->evaluate('not "foo" matches "/bar/"'); // returns true +Examples:: + + $ret1 = $language->evaluate( + 'life == everything', + array( + 'life' => 10, + 'universe' => 10, + 'everything' => 22, + ) + ); + + $ret2 = $language->evaluate( + 'life > everything', + array( + 'life' => 10, + 'universe' => 10, + 'everything' => 22, + ) + ); + +These would both return ``false``. + Logical Operators -................. +~~~~~~~~~~~~~~~~~ * ``not`` or ``!`` * ``and`` or ``&&`` * ``or`` or ``||`` +For example:: + + $ret = $language->evaluate( + 'life < universe or life < everything', + array( + 'life' => 10, + 'universe' => 10, + 'everything' => 22, + ) + ); + +This would return ``true``. + String Operators -................ +~~~~~~~~~~~~~~~~ * ``~`` (concatenation) +For example:: + + $ret4 = $language->evaluate( + 'firstName~" "~lastName', + array( + 'firstName' => 'Arthur', + 'lastName' => 'Dent', + ) + ); + +This would print out ``Arthur Dent``. + Array Operators -............... +~~~~~~~~~~~~~~~ * ``in`` (contain) * ``not in`` (does not contain) +For example:: + + class User + { + public $group; + } + + $user = new User(); + $user->group = 'human_resources'; + + $ret5 = $language->evaluate( + 'user.group in ["human_resources", "marketing"]', + array( + 'user' => $user + ) + ); + Numeric Operators -................. +~~~~~~~~~~~~~~~~~ * ``..`` (range) Ternary Operators -................. +~~~~~~~~~~~~~~~~~ * ``foo ? 'yes' : 'no'`` * ``foo ?: 'no'`` (equal to ``foo ? foo : 'no'``) From a14c39d530eb1ab4e520c49b3bf7ded8c3c9b07b Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 28 Nov 2013 11:16:51 -0600 Subject: [PATCH 0081/1181] [#3191] Many tweaks to expression language component thanks to @WouterJ, @xabbuh and @cordoval. Thanks guys! --- components/expression_language/introduction.rst | 16 ++++++++-------- components/expression_language/syntax.rst | 14 +++++++++----- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst index da23a869e0f..7cdabf56bf1 100644 --- a/components/expression_language/introduction.rst +++ b/components/expression_language/introduction.rst @@ -10,22 +10,22 @@ The ExpressionLanguage Component (mostly, but not limited to, Booleans). .. versionadded:: 2.4 - The ExpressionLanguage component was added in Symfony 2.4. + The ExpressionLanguage component was introduced in Symfony 2.4. Installation ------------ You can install the component in 2 different ways: -* :doc:`Install it via Composer ` (``symfony/expression-language`` on `Packagist`_). -* Use the official Git repository (https://github.com/symfony/expression-language); +* :doc:`Install it via Composer ` (``symfony/expression-language`` on `Packagist`_); +* Use the official Git repository (https://github.com/symfony/expression-language). How can the Expression Engine Help Me? -------------------------------------- The purpose of the component is to allow users to use expressions inside -configuration for more complex logic. In the Symfony2 Framework, for example, -expressions can be used in security, for validation rules, and in route matching. +configuration for more complex logic. For some examples, the Symfony2 Framework +uses expressions in security, for validation rules and in route matching. Besides using the component in the framework itself, the ExpressionLanguage component is a perfect candidate for the foundation of a *business rule engine*. @@ -52,15 +52,15 @@ Usage The ExpressionLanguage component can compile and evaluate expressions. Expressions are one-liners that often return a Boolean, which can be used -by the code executing the expression in an ``if`` statements. A simple example +by the code executing the expression in an ``if`` statement. A simple example of an expression is ``1 + 2``. You can also use more complicated expressions, such as ``someArray[3].someMethod('bar')``. The component provides 2 ways to work with expressions: +* **evaluation**: the expression is evaluated without being compiled to PHP; * **compile**: the expression is compiled to PHP, so it can be cached and - evaluated; -* **evaluation**: the expression is evaluated without being compiled to PHP. + evaluated. The main class of the component is :class:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage`:: diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index 4cc7da1192b..49a80d46082 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -49,6 +49,8 @@ to JavaScript:: ) ); +This will print ``Honeycrisp``; + Calling Methods ~~~~~~~~~~~~~~~ @@ -77,7 +79,7 @@ JavaScript:: ) ); -This will print "Hi Hi Hi!"; +This will print ``Hi Hi Hi!``. .. _component-expression-arrays: @@ -178,7 +180,7 @@ Examples:: ) ); -These would both return ``false``. +Both variables would be set to ``false``. Logical Operators ~~~~~~~~~~~~~~~~~ @@ -198,7 +200,7 @@ For example:: ) ); -This would return ``true``. +This ``$ret`` variable will be set to ``true``. String Operators ~~~~~~~~~~~~~~~~ @@ -207,7 +209,7 @@ String Operators For example:: - $ret4 = $language->evaluate( + echo $language->evaluate( 'firstName~" "~lastName', array( 'firstName' => 'Arthur', @@ -233,13 +235,15 @@ For example:: $user = new User(); $user->group = 'human_resources'; - $ret5 = $language->evaluate( + $inGroup = $language->evaluate( 'user.group in ["human_resources", "marketing"]', array( 'user' => $user ) ); +The ``$inGroup`` would evaluate to ``true``. + Numeric Operators ~~~~~~~~~~~~~~~~~ From cd98a63f8c830fceee35b8d28b049f8d571e5efd Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 28 Nov 2013 11:21:41 -0600 Subject: [PATCH 0082/1181] [#3191] Fixing semicolon thanks to @WouterJ --- components/expression_language/syntax.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index 49a80d46082..3552cad5b7d 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -49,7 +49,7 @@ to JavaScript:: ) ); -This will print ``Honeycrisp``; +This will print ``Honeycrisp``. Calling Methods ~~~~~~~~~~~~~~~ From aea65332045da444e3d39365952d5b02dc97cc5f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 17 Nov 2013 15:02:03 +0100 Subject: [PATCH 0083/1181] documentation for the regex based exclusion of 404 errors with MonologBundle --- cookbook/logging/index.rst | 3 +- .../logging/monolog_regex_based_excludes.rst | 67 +++++++++++++++++++ cookbook/map.rst.inc | 1 + 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 cookbook/logging/monolog_regex_based_excludes.rst diff --git a/cookbook/logging/index.rst b/cookbook/logging/index.rst index c10cfa54716..dda7d7cafdd 100644 --- a/cookbook/logging/index.rst +++ b/cookbook/logging/index.rst @@ -6,4 +6,5 @@ Logging monolog monolog_email - channels_handlers \ No newline at end of file + monolog_regex_based_excludes + channels_handlers diff --git a/cookbook/logging/monolog_regex_based_excludes.rst b/cookbook/logging/monolog_regex_based_excludes.rst new file mode 100644 index 00000000000..9d1b94060fa --- /dev/null +++ b/cookbook/logging/monolog_regex_based_excludes.rst @@ -0,0 +1,67 @@ +.. index:: + single: Logging + single: Logging; Exclude 404 Errors + single: Monolog; Exclude 404 Errors + +How to Configure Monolog to Exclude 404 Errors from the Log +=========================================================== + +Sometimes you get your logs flooded with unwanted 404 HTTP errors, for example, +when an attacker scans your app for some well-known application paths (e.g. +`/phpmyadmin`). When using a ``fingers_crossed`` handler, you can exclude +logging these 404 errors based on a regular expression in the MonologBundle +configuration: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + monolog: + handlers: + main: + # ... + type: fingers_crossed + handler: ... + excluded_404s: + - ^/phpmyadmin + + .. code-block:: xml + + + + + + + ^/phpmyadmin + + + + + .. code-block:: php + + // app/config/config.php + $container->loadFromExtension('monolog', array( + 'handlers' => array( + 'main' => array( + // ... + 'type' => 'fingers_crossed', + 'handler' => ..., + 'excluded_404s' => array( + '^/phpmyadmin', + ), + ), + ), + )); + +.. note:: + + To be able to use ``excluded_404s`` option you need to update your version + of the MonologBundle to 2.4. diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 57c7f9b0a4d..76be17eced8 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -97,6 +97,7 @@ * :doc:`/cookbook/logging/monolog` * :doc:`/cookbook/logging/monolog_email` + * :doc:`/cookbook/logging/monolog_regex_based_excludes` * :doc:`/cookbook/logging/channels_handlers` * :doc:`/cookbook/profiler/index` From 6ec097d42664633457e3baf6c51c72c4fa78b555 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 28 Nov 2013 11:56:03 -0600 Subject: [PATCH 0084/1181] [#3203] Minor tweaks to new 404 logging entry --- cookbook/logging/monolog_regex_based_excludes.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cookbook/logging/monolog_regex_based_excludes.rst b/cookbook/logging/monolog_regex_based_excludes.rst index 9d1b94060fa..42424287d2a 100644 --- a/cookbook/logging/monolog_regex_based_excludes.rst +++ b/cookbook/logging/monolog_regex_based_excludes.rst @@ -6,7 +6,12 @@ How to Configure Monolog to Exclude 404 Errors from the Log =========================================================== -Sometimes you get your logs flooded with unwanted 404 HTTP errors, for example, +.. versionadded:: 2.4 + This feature was introduced to the MonologBundle in version 2.4, which + was first packaged with Symfony at version 2.4. However, the 2.4 version + of the MonologBundle is also compatible with Symfony 2.3. + +Sometimes your logs become flooded with unwanted 404 HTTP errors, for example, when an attacker scans your app for some well-known application paths (e.g. `/phpmyadmin`). When using a ``fingers_crossed`` handler, you can exclude logging these 404 errors based on a regular expression in the MonologBundle @@ -60,8 +65,3 @@ configuration: ), ), )); - -.. note:: - - To be able to use ``excluded_404s`` option you need to update your version - of the MonologBundle to 2.4. From 22b37762f40723846ace0f4b5fad579cac1cee0e Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 28 Nov 2013 12:13:23 -0600 Subject: [PATCH 0085/1181] [#3205] Tweaking versionadded --- cookbook/logging/channels_handlers.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cookbook/logging/channels_handlers.rst b/cookbook/logging/channels_handlers.rst index 073f6f79ee2..817c062f313 100644 --- a/cookbook/logging/channels_handlers.rst +++ b/cookbook/logging/channels_handlers.rst @@ -93,9 +93,8 @@ Configure Additional Channels without Tagged Services ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.3 - This feature was introduced to the MonologBundle in version 2.4. This - version is compatible with Symfony 2.3, but only MonologBundle 2.3 is - installed by default. To use this feature, upgrade your bundle manually. + This feature was introduced to the MonologBundle in version 2.4, which + was first packaged with Symfony at version 2.4. With MonologBundle 2.4 you can configure additional channels without the need to tag your services: From 4dba1ac9a7a60ac2830e5d9af71d72e6fcf9c6a0 Mon Sep 17 00:00:00 2001 From: Maks Rafalko Date: Fri, 22 Nov 2013 20:14:20 +0300 Subject: [PATCH 0086/1181] Changed parameter container to requestStack (2.4+) There is no need to pass @service_container to the voter, @request is enough. please see #3216 --- cookbook/security/voters.rst | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/cookbook/security/voters.rst b/cookbook/security/voters.rst index 344285a7e7d..0d4e526c742 100644 --- a/cookbook/security/voters.rst +++ b/cookbook/security/voters.rst @@ -61,19 +61,18 @@ and compare the IP address against a set of blacklisted IP addresses: // src/Acme/DemoBundle/Security/Authorization/Voter/ClientIpVoter.php namespace Acme\DemoBundle\Security\Authorization\Voter; - use Symfony\Component\DependencyInjection\ContainerInterface; + use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; class ClientIpVoter implements VoterInterface { - private $container; - + protected $requestStack; private $blacklistedIp; - - public function __construct(ContainerInterface $container, array $blacklistedIp = array()) + + public function __construct(RequestStack $requestStack, array $blacklistedIp = array()) { - $this->container = $container; + $this->requestStack = $requestStack; $this->blacklistedIp = $blacklistedIp; } @@ -91,7 +90,7 @@ and compare the IP address against a set of blacklisted IP addresses: public function vote(TokenInterface $token, $object, array $attributes) { - $request = $this->container->get('request'); + $request = $this->requestStack->getCurrentRequest(); if (in_array($request->getClientIp(), $this->blacklistedIp)) { return VoterInterface::ACCESS_DENIED; } @@ -128,7 +127,7 @@ and tag it as a ``security.voter``: services: security.access.blacklist_voter: class: Acme\DemoBundle\Security\Authorization\Voter\ClientIpVoter - arguments: ["@service_container", [123.123.123.123, 171.171.171.171]] + arguments: ["@request_stack", [123.123.123.123, 171.171.171.171]] public: false tags: - { name: security.voter } @@ -138,7 +137,7 @@ and tag it as a ``security.voter``: - + 123.123.123.123 171.171.171.171 @@ -155,7 +154,7 @@ and tag it as a ``security.voter``: $definition = new Definition( 'Acme\DemoBundle\Security\Authorization\Voter\ClientIpVoter', array( - new Reference('service_container'), + new Reference('request_stack'), array('123.123.123.123', '171.171.171.171'), ), ); From 77b84ea6d6724e8009717dbc3b87b47202ab48eb Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Thu, 28 Nov 2013 21:21:55 +0100 Subject: [PATCH 0087/1181] executable permission unset --- book/controller.rst | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 book/controller.rst diff --git a/book/controller.rst b/book/controller.rst old mode 100755 new mode 100644 From 0675b562edf1dc72bf0bab6752ab972a25e70096 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Fri, 29 Nov 2013 08:46:29 +0100 Subject: [PATCH 0088/1181] Removed assignment operator --- components/expression_language/syntax.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index 3552cad5b7d..972f16f65ab 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -128,11 +128,6 @@ For example:: This will print out ``42``. -Assignment Operators -~~~~~~~~~~~~~~~~~~~~ - -* ``=`` - Bitwise Operators ~~~~~~~~~~~~~~~~~ From e506f01321335bf6707889b2e0daf1633a025432 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Fri, 29 Nov 2013 08:49:07 +0100 Subject: [PATCH 0089/1181] Added example of range operator --- components/expression_language/syntax.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index 972f16f65ab..38e4739e0fa 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -244,6 +244,26 @@ Numeric Operators * ``..`` (range) +For example:: + + class User + { + public $age; + } + + $user = new User(); + $user->age = 34; + + $language->evaluate( + 'user.age in 18..45', + array( + 'user' => $user, + ) + ); + +This will evaluate to ``true``, because ``user.age`` is in the range from +``18`` till ``45`` + Ternary Operators ~~~~~~~~~~~~~~~~~ From 0725a8b95a5d9aa7ef38b074f5a16e2cfff74fbd Mon Sep 17 00:00:00 2001 From: Wouter J Date: Fri, 29 Nov 2013 14:19:43 +0100 Subject: [PATCH 0090/1181] Added docs for using functions --- components/expression_language/syntax.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index 38e4739e0fa..5c4d756f107 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -81,6 +81,24 @@ JavaScript:: This will print ``Hi Hi Hi!``. +.. _component-expression-functions: + +Working with Functions +---------------------- + +You can also use registered functions in the expression by using the same +syntax as PHP and JavaScript. The ExpressionLanguage component comes with one +function by default: ``constant()`` Which will return the value of the PHP +constant:: + + define('DB_USER', 'root'); + + echo $language->evaluate( + 'constant("DB_USER")' + ); + +This will print ``root``. + .. _component-expression-arrays: Working with Arrays From 6e2e5836c483240a97b9db3364e4cdeea055d425 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Fri, 29 Nov 2013 14:20:46 +0100 Subject: [PATCH 0091/1181] Added article about custom functions --- components/expression_language/extending.rst | 87 ++++++++++++++++++++ components/expression_language/index.rst | 1 + components/expression_language/syntax.rst | 5 ++ components/map.rst.inc | 1 + 4 files changed, 94 insertions(+) create mode 100644 components/expression_language/extending.rst diff --git a/components/expression_language/extending.rst b/components/expression_language/extending.rst new file mode 100644 index 00000000000..ddcc44d476f --- /dev/null +++ b/components/expression_language/extending.rst @@ -0,0 +1,87 @@ +.. index:: + single: Extending; ExpressionLanguage + +Extending the ExpressionLanguage +================================ + +The ExpressionLanguage can be extended by adding custom functions. For +instance, in the framework, the security has custom functions to check the +user's role. + +.. note:: + + If you want to learn how to use functions in an expression, read + ":ref:`component-expression-functions`". + +Register Functions +------------------ + +Functions will be registered on the current ``ExpressionLanguage`` instance. +That means the functions can be used in any expression executed by that +instance. + +To register a function, use +:method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::register``. +This method has 3 arguments: + +* **name** - The name of the function in an expression; +* **compiler** - A function executed when compiling an expression using the + function; +* **evaluator** - A function executed when the expression is evaluated. + +.. code-block:: php + + use Symfony\Component\ExpressionLanguage\ExpressionLanguage; + + $language = new ExpressionLanguage(); + $language->register('lowercase', function ($str) { + if (!is_string($str)) { + return $str; + } + + return sprintf('strtolower(%s)', $str); + }, function ($str) { + if (!is_string($str)) { + return $str; + } + + return strtolower($str); + }); + + echo $language->evaluate('lowercase("HELLO")'); + +This will print ``hello``. + +Creating a new ExpressionLanguage class +--------------------------------------- + +When you use the ``ExpressionLanguage`` class in your library, it's recommend +to create a new ``ExpressionLanguage`` class and register the functions there. +The class will execute ``registerFunctions`` to register the default +functions, you can override this to also add your own functions:: + + namespace Acme\AwesomeLib\ExpressionLanguage; + + use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; + + class ExpressionLanguage extends BaseExpressionLanguage + { + protected function registerFunctions() + { + parent::registerFunctions(); // do not forget to also register core functions + + $this->register('lowercase', function ($str) { + if (!is_string($str)) { + return $str; + } + + return sprintf('strtolower(%s)', $str); + }, function ($str) { + if (!is_string($str)) { + return $str; + } + + return strtolower($str); + }); + } + } diff --git a/components/expression_language/index.rst b/components/expression_language/index.rst index e6eb657b4be..5ae40be979f 100644 --- a/components/expression_language/index.rst +++ b/components/expression_language/index.rst @@ -6,3 +6,4 @@ Expression Language introduction syntax + extending diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index 5c4d756f107..e105e82bdb8 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -99,6 +99,11 @@ constant:: This will print ``root``. +.. tip:: + + To read how to register your own function to use in an expression, see + ":doc:`/components/expression_language/extending`". + .. _component-expression-arrays: Working with Arrays diff --git a/components/map.rst.inc b/components/map.rst.inc index 5ec6d81f91e..2703a6057fc 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -61,6 +61,7 @@ * :doc:`/components/expression_language/introduction` * :doc:`/components/expression_language/syntax` + * :doc:`/components/expression_language/extending` * **Filesystem** From 4d50f34084ae8f4d775389a536d501530e2d2128 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 28 Nov 2013 14:03:53 -0600 Subject: [PATCH 0092/1181] [#3022] Adding service container expression language details --- .../_service_container_my_mailer.rst.inc | 34 +++++ book/service_container.rst | 131 +++++++++++++----- 2 files changed, 131 insertions(+), 34 deletions(-) create mode 100644 book/includes/_service_container_my_mailer.rst.inc diff --git a/book/includes/_service_container_my_mailer.rst.inc b/book/includes/_service_container_my_mailer.rst.inc new file mode 100644 index 00000000000..601d188a007 --- /dev/null +++ b/book/includes/_service_container_my_mailer.rst.inc @@ -0,0 +1,34 @@ +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + services: + my_mailer: + class: Acme\HelloBundle\Mailer + arguments: [sendmail] + + .. code-block:: xml + + + + + + + + sendmail + + + + + .. code-block:: php + + // app/config/config.php + use Symfony\Component\DependencyInjection\Definition; + + $container->setDefinition('my_mailer', new Definition( + 'Acme\HelloBundle\Mailer', + array('sendmail') + )); \ No newline at end of file diff --git a/book/service_container.rst b/book/service_container.rst index 84ef36c0c01..6f609e175c1 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -103,40 +103,7 @@ for you. In order for this to work, you must *teach* the container how to create the ``Mailer`` service. This is done via configuration, which can be specified in YAML, XML or PHP: -.. configuration-block:: - - .. code-block:: yaml - - # app/config/config.yml - services: - my_mailer: - class: Acme\HelloBundle\Mailer - arguments: [sendmail] - - .. code-block:: xml - - - - - - - - sendmail - - - - - .. code-block:: php - - // app/config/config.php - use Symfony\Component\DependencyInjection\Definition; - - $container->setDefinition('my_mailer', new Definition( - 'Acme\HelloBundle\Mailer', - array('sendmail') - )); +.. include includes/_service_container_my_mailer.rst.inc .. note:: @@ -660,6 +627,102 @@ service needs the ``my_mailer`` service in order to function. When you define this dependency in the service container, the container takes care of all the work of instantiating the classes. +Using the Expression Language +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The service container also supports an "expression" that allows you to inject +very specific values into a service. + +For example, suppose you have a third service (not shown here), called ``mailer_configuration``, +which has a ``getMailerMethod`` method on it, which will return a string +like ``sendmail`` based on some configuration. Remember that the first argument +to the ``my_mailer`` service is the simple string ``sendmail``: + +.. include includes/_service_container_my_mailer.rst.inc + +But instead of hardcoding this, how could we get this value from the ``getMailerMethod`` +of the new ``mailer_configuration`` service? One way is to use an expression: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + services: + my_mailer: + class: Acme\HelloBundle\Mailer + arguments: ["@=service('mailer_configuration').getMailerMethod()"] + + .. code-block:: xml + + + + + + + + service('mailer_configuration').getMailerMethod() + + + + + .. code-block:: php + + // app/config/config.php + use Symfony\Component\DependencyInjection\Definition; + + $container->setDefinition('my_mailer', new Definition( + 'Acme\HelloBundle\Mailer', + array(new Expression("service('mailer_configuration').getMailerMethod()")) + )); + +To learn more about the expression language syntax, see :doc:`/components/expression_language/syntax`. + +In this context, you have access to 2 functions: + +* ``service`` - returns a given service (see the example above); +* ``parameter`` - returns a specific parameter value (syntax is just like ``service``) + +You also have access to the :class:`Symfony\\Component\\DependencyInjection\\ContainerBuilder` +via a ``container`` variable. Here's another example: + +.. configuration-block:: + + .. code-block:: yaml + + services: + my_mailer: + class: Acme\HelloBundle\Mailer + arguments: ["@=container.hasParameter('some_param') ? parameter('some_param') : 'default_value'"] + + .. code-block:: xml + + + + + + + @=container.hasParameter('some_param') ? parameter('some_param') : 'default_value' + + + + + .. code-block:: php + + use Symfony\Component\DependencyInjection\Definition; + + $container->setDefinition('my_mailer', new Definition( + 'Acme\HelloBundle\Mailer', + array(new Expression("@=container.hasParameter('some_param') ? parameter('some_param') : 'default_value'")) + )); + +Expressions can be used in ``parameters``, ``arguments``, ``properties``, +as arguments with ``configurator`` and as arguments to ``calls`` (method calls). + Optional Dependencies: Setter Injection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 22c940431fea57d7fafe4809c212638330175789 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Fri, 29 Nov 2013 16:42:34 -0500 Subject: [PATCH 0093/1181] [#3232][#3022] Making many small tweaks thanks to @WouterJ and @xabbuh --- .../_service_container_my_mailer.rst.inc | 4 ++- book/service_container.rst | 27 +++++++++++++------ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/book/includes/_service_container_my_mailer.rst.inc b/book/includes/_service_container_my_mailer.rst.inc index 601d188a007..efc2eaeac26 100644 --- a/book/includes/_service_container_my_mailer.rst.inc +++ b/book/includes/_service_container_my_mailer.rst.inc @@ -14,7 +14,9 @@ + xsi:schemaLocation="http://symfony.com/schema/dic/services + http://symfony.com/schema/dic/services/services-1.0.xsd" + > diff --git a/book/service_container.rst b/book/service_container.rst index 6f609e175c1..ff355e44f8a 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -630,17 +630,20 @@ the work of instantiating the classes. Using the Expression Language ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. versionadded:: 2.4 + The Expression Language functionality was introduced in Symfony 2.4. + The service container also supports an "expression" that allows you to inject very specific values into a service. For example, suppose you have a third service (not shown here), called ``mailer_configuration``, -which has a ``getMailerMethod`` method on it, which will return a string +which has a ``getMailerMethod()`` method on it, which will return a string like ``sendmail`` based on some configuration. Remember that the first argument to the ``my_mailer`` service is the simple string ``sendmail``: .. include includes/_service_container_my_mailer.rst.inc -But instead of hardcoding this, how could we get this value from the ``getMailerMethod`` +But instead of hardcoding this, how could we get this value from the ``getMailerMethod()`` of the new ``mailer_configuration`` service? One way is to use an expression: .. configuration-block:: @@ -659,7 +662,9 @@ of the new ``mailer_configuration`` service? One way is to use an expression: + xsi:schemaLocation="http://symfony.com/schema/dic/services + http://symfony.com/schema/dic/services/services-1.0.xsd" + > @@ -672,10 +677,11 @@ of the new ``mailer_configuration`` service? One way is to use an expression: // app/config/config.php use Symfony\Component\DependencyInjection\Definition; + use Symfony\Component\ExpressionLanguage\Expression; $container->setDefinition('my_mailer', new Definition( 'Acme\HelloBundle\Mailer', - array(new Expression("service('mailer_configuration').getMailerMethod()")) + array(new Expression('service("mailer_configuration").getMailerMethod()')) )); To learn more about the expression language syntax, see :doc:`/components/expression_language/syntax`. @@ -694,15 +700,17 @@ via a ``container`` variable. Here's another example: services: my_mailer: - class: Acme\HelloBundle\Mailer - arguments: ["@=container.hasParameter('some_param') ? parameter('some_param') : 'default_value'"] + class: Acme\HelloBundle\Mailer + arguments: ["@=container.hasParameter('some_param') ? parameter('some_param') : 'default_value'"] .. code-block:: xml + xsi:schemaLocation="http://symfony.com/schema/dic/services + http://symfony.com/schema/dic/services/services-1.0.xsd" + > @@ -714,10 +722,13 @@ via a ``container`` variable. Here's another example: .. code-block:: php use Symfony\Component\DependencyInjection\Definition; + use Symfony\Component\ExpressionLanguage\Expression; $container->setDefinition('my_mailer', new Definition( 'Acme\HelloBundle\Mailer', - array(new Expression("@=container.hasParameter('some_param') ? parameter('some_param') : 'default_value'")) + array(new Expression( + "@=container.hasParameter('some_param') ? parameter('some_param') : 'default_value'" + )) )); Expressions can be used in ``parameters``, ``arguments``, ``properties``, From 667d590d1492ccfad9ba3b2117d77bfcce4720b6 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Fri, 29 Nov 2013 16:56:02 -0500 Subject: [PATCH 0094/1181] [#3241] Minor tweaks to new expression language functions --- components/expression_language/extending.rst | 15 +++++++-------- components/expression_language/syntax.rst | 6 +++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/components/expression_language/extending.rst b/components/expression_language/extending.rst index ddcc44d476f..d3c8dbbd3d8 100644 --- a/components/expression_language/extending.rst +++ b/components/expression_language/extending.rst @@ -5,18 +5,18 @@ Extending the ExpressionLanguage ================================ The ExpressionLanguage can be extended by adding custom functions. For -instance, in the framework, the security has custom functions to check the -user's role. +instance, in the Symfony Framework, the security has custom functions to check +the user's role. .. note:: If you want to learn how to use functions in an expression, read ":ref:`component-expression-functions`". -Register Functions ------------------- +Registering Functions +--------------------- -Functions will be registered on the current ``ExpressionLanguage`` instance. +Functions are registered on each specific ``ExpressionLanguage`` instance. That means the functions can be used in any expression executed by that instance. @@ -52,13 +52,12 @@ This method has 3 arguments: This will print ``hello``. -Creating a new ExpressionLanguage class +Creating a new ExpressionLanguage Class --------------------------------------- When you use the ``ExpressionLanguage`` class in your library, it's recommend to create a new ``ExpressionLanguage`` class and register the functions there. -The class will execute ``registerFunctions`` to register the default -functions, you can override this to also add your own functions:: +Override ``registerFunctions`` to add your own functions:: namespace Acme\AwesomeLib\ExpressionLanguage; diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index e105e82bdb8..4a45f9fbe55 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -88,7 +88,7 @@ Working with Functions You can also use registered functions in the expression by using the same syntax as PHP and JavaScript. The ExpressionLanguage component comes with one -function by default: ``constant()`` Which will return the value of the PHP +function by default: ``constant()``, which will return the value of the PHP constant:: define('DB_USER', 'root'); @@ -101,7 +101,7 @@ This will print ``root``. .. tip:: - To read how to register your own function to use in an expression, see + To read how to register your own functions to use in an expression, see ":doc:`/components/expression_language/extending`". .. _component-expression-arrays: @@ -285,7 +285,7 @@ For example:: ); This will evaluate to ``true``, because ``user.age`` is in the range from -``18`` till ``45`` +``18`` to ``45``. Ternary Operators ~~~~~~~~~~~~~~~~~ From 4738c754b7114a307518ce3da6668f44dbe256bd Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 1 Dec 2013 14:58:09 -0500 Subject: [PATCH 0095/1181] [#3232] Fixing note about expressions with parameters thanks to @WouterJ --- book/service_container.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/service_container.rst b/book/service_container.rst index ff355e44f8a..bc13aa13aa4 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -731,8 +731,8 @@ via a ``container`` variable. Here's another example: )) )); -Expressions can be used in ``parameters``, ``arguments``, ``properties``, -as arguments with ``configurator`` and as arguments to ``calls`` (method calls). +Expressions can be used in ``arguments``, ``properties``, as arguments with +``configurator`` and as arguments to ``calls`` (method calls). Optional Dependencies: Setter Injection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From ac15bf5c0a7678038f08eea45c8aa2a8fc989e1d Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 1 Dec 2013 15:27:58 -0500 Subject: [PATCH 0096/1181] [#3022] Adding framework documentation for routing expressions --- book/routing.rst | 98 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 4 deletions(-) diff --git a/book/routing.rst b/book/routing.rst index 357a5c47301..9cb545796ca 100644 --- a/book/routing.rst +++ b/book/routing.rst @@ -507,10 +507,11 @@ to the ``{page}`` parameter. | /blog/my-blog-post | blog | {page} = my-blog-post | +--------------------+-------+-----------------------+ -The answer to the problem is to add route *requirements*. The routes in this -example would work perfectly if the ``/blog/{page}`` path *only* matched -URLs where the ``{page}`` portion is an integer. Fortunately, regular expression -requirements can easily be added for each parameter. For example: +The answer to the problem is to add route *requirements* or route *conditions* +(see :ref:`book-routing-conditions`). The routes in this example would work +perfectly if the ``/blog/{page}`` path *only* matched URLs where the ``{page}`` +portion is an integer. Fortunately, regular expression requirements can easily +be added for each parameter. For example: .. configuration-block:: @@ -717,6 +718,95 @@ You can also match on the HTTP *host* of the incoming request. For more information, see :doc:`/components/routing/hostname_pattern` in the Routing component documentation. +.. _book-routing-conditions: + +Completely Customized Route Matching with Conditions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 2.4 + Route conditions were introduced in Symfony 2.4. + +As you've seen, a route can be made to match only certain routing wildcards +(via regular expressions), HTTP methods, or host names. But the routing system +can be extended to almost an infinite flexibility with ``conditions``: + +.. configuration-block:: + + .. code-block:: yaml + + contact: + path: /contact + defaults: { _controller: AcmeDemoBundle:Main:contact } + condition: "context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'" + + .. code-block:: xml + + + + + + AcmeDemoBundle:Main:contact + + + + .. code-block:: php + + use Symfony\Component\Routing\RouteCollection; + use Symfony\Component\Routing\Route; + + $collection = new RouteCollection(); + $collection->add('contact', new Route( + '/contact', array( + '_controller' => 'AcmeDemoBundle:Main:contact', + ), + array(), + array(), + '', + array(), + array(), + 'context.getMethod() in ["GET", "HEAD"] and request.headers.get("User-Agent") matches "/firefox/i"' + )); + + return $collection; + +The ``condition`` is an expression, and you can learn more about it syntax +here: :doc:`/components/expression_language/syntax`. With this, the route +won't match unless the HTTP method is either GET or HEAD *and* if the ``User-Agent`` +header matches ``firefox``. + +You can do any complex logic you need here by leveraging two variables that +are passed into the expression: + +* ``context``: An instance of :class:`Symfony\\Component\\Routing\\RequestContext`, + which holds the most fundamental information about the route being matched; +* ``request``: The Symfony :class:`Symfony\\Component\\HttpFoundation\\Request`` + object (see :ref:`component-http-foundation-request`). + +.. caution:: + + Conditions are *not* taken into account when generating a URL. + +.. sidebar:: Expressions are Compiled to PHP + + Behind the scenes, expressions are compiled down to raw PHP. Our example + would generate the following PHP in the cache directory:: + + if (rtrim($pathinfo, '/contact') === '' && ( + in_array($context->getMethod(), array(0 => "GET", 1 => "HEAD")) + && preg_match("/firefox/i", $request->headers->get("User-Agent")) + )) { + // ... + } + + Because of this, using the ``condition`` key causes no extra roverhead + beyond the time it takes for the underlying PHP to execute. + .. index:: single: Routing; Advanced example single: Routing; _format parameter From be86fef5e8457575239360e74fbb9fb8da27465c Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 1 Dec 2013 16:17:33 -0500 Subject: [PATCH 0097/1181] [#3022] Adding new Expression validation constraint --- .../expression_language/introduction.rst | 2 + reference/constraints.rst | 1 + reference/constraints/Expression.rst | 167 ++++++++++++++++++ reference/constraints/map.rst.inc | 1 + 4 files changed, 171 insertions(+) create mode 100644 reference/constraints/Expression.rst diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst index 7cdabf56bf1..9ba2f5de9a0 100644 --- a/components/expression_language/introduction.rst +++ b/components/expression_language/introduction.rst @@ -32,6 +32,8 @@ component is a perfect candidate for the foundation of a *business rule engine*. The idea is to let the webmaster of a website configure things in a dynamic way without using PHP and without introducing security problems: +.. _component-expression-language-examples: + .. code-block:: text # Get the special price if diff --git a/reference/constraints.rst b/reference/constraints.rst index efbc0e554a6..0b209bbf012 100644 --- a/reference/constraints.rst +++ b/reference/constraints.rst @@ -53,6 +53,7 @@ Validation Constraints Reference constraints/Issn constraints/Callback + constraints/Expression constraints/All constraints/UserPassword constraints/Valid diff --git a/reference/constraints/Expression.rst b/reference/constraints/Expression.rst new file mode 100644 index 00000000000..812b21dbe73 --- /dev/null +++ b/reference/constraints/Expression.rst @@ -0,0 +1,167 @@ +Expression +========== + +.. versionadded:: 2.4 + The Expression constraint was introduced in Symfony 2.4. + +This constraint allows you to use an :ref:`expression ` +for more complex, dynamic validation. See `Basic Usage`_ for an example. +See :doc:`/reference/constraints/Callback` for a different constraint that +gives you similar flexibility. + ++----------------+-----------------------------------------------------------------------------------------------+ +| Applies to | :ref:`class ` or :ref:`property/method ` | ++----------------+-----------------------------------------------------------------------------------------------+ +| Options | - :ref:`expression ` | +| | - `message`_ | ++----------------+-----------------------------------------------------------------------------------------------+ +| Class | :class:`Symfony\\Component\\Validator\\Constraints\\Expression` | ++----------------+-----------------------------------------------------------------------------------------------+ +| Validator | :class:`Symfony\\Component\\Validator\\Constraints\\ExpressionValidator` | ++----------------+-----------------------------------------------------------------------------------------------+ + +Basic Usage +----------- + +Imagine you have a class ``BlogPost`` with ``category`` and ``isTechnicalPost`` +properties:: + + namespace Acme\DemoBundle\Model; + + use Symfony\Component\Validator\Constraints as Assert; + + class BlogPost + { + private $category; + + private $isTechnicalPost; + + // ... + + public function getCategory() + { + return $this->category; + } + + public function setIsTechnicalPost($isTechnicalPost) + { + $this->isTechnicalPost = $isTechnicalPost; + } + + // ... + } + +To validate the object, you have some special requirements: + +* A) If ``isTechnicalPost`` is true, then ``category`` must be either ``php`` + or ``symfony``; + +* B) If ``isTechnicalPost`` is false, then ``category`` can be anything. + +One way to accomplish this is with the Expression constraint: + +.. configuration-block:: + + .. code-block:: yaml + + # src/Acme/DemoBundle/Resources/config/validation.yml + Acme\DemoBundle\Model\BlogPost: + constraints: + - Expression: + expression: "this.getCategory() in ['php', 'symfony'] or !this.isTechnicalPost()" + message: "If this is a tech post, the category should be php or symfony!" + + .. code-block:: php-annotations + + // src/Acme/DemoBundle/Model/BlogPost.php + namespace Acme\DemoBundle\Model\BlogPost; + + use Symfony\Component\Validator\Constraints as Assert; + + /** + * @Assert\Expression( + * "this.getCategory() in ['php', 'symfony'] or !this.isTechnicalPost()", + * message="If this is a tech post, the category should be php or symfony!" + * ) + */ + class BlogPost + { + // ... + } + + .. code-block:: xml + + + + + + + + + + + .. code-block:: php + + // src/Acme/DemoBundle/Model/BlogPost.php + namespace Acme\DemoBundle\Model\BlogPost; + + use Symfony\Component\Validator\Mapping\ClassMetadata; + use Symfony\Component\Validator\Constraints as Assert; + + class BlogPost + { + public static function loadValidatorMetadata(ClassMetadata $metadata) + { + $metadata->addConstraint(new Assert\Expression(array( + 'expression' => 'this.getCategory() in ["php", "symfony"] or !this.isTechnicalPost()', + 'message' => 'If this is a tech post, the category should be php or symfony!', + ))); + } + + // ... + } + +The :ref:`expression ` option is the +expression that must return true in order for validation to pass. To learn +more about the expression language syntax, see +:doc:`/components/expression_language/syntax`. + +For more information about the expression and what variables you have available +to you, see the :ref:`expression ` +option details below. + +Available Options +----------------- + +.. _reference-constraint-expression-option: + +expression +~~~~~~~~~~ + +**type**: ``string`` [:ref:`default option `] + +The expression that will be evaluated. If the expression evaluates to a false +value (using ``==``, not ``===``), validation will fail. + +To learn more about the expression language syntax, see +:doc:`/components/expression_language/syntax`. + +Inside of the expression, you have access to up to 2 variables: + +Depending on how you use the constraint, you have access to 1 or 2 variables +in your expression: + +* ``this``: The object being validated (e.g. an instance of BlogPost); +* ``value``: The value of the property being validated (only available when + the constraint is applied directly to a property); + +message +~~~~~~~ + +**type**: ``string`` **default**: ``This value is not valid.`` + +The default message supplied when the expression evaluates to false. diff --git a/reference/constraints/map.rst.inc b/reference/constraints/map.rst.inc index 84186b01d25..237329866d4 100644 --- a/reference/constraints/map.rst.inc +++ b/reference/constraints/map.rst.inc @@ -76,6 +76,7 @@ Other Constraints ~~~~~~~~~~~~~~~~~ * :doc:`Callback ` +* :doc:`Expression ` * :doc:`All ` * :doc:`UserPassword ` * :doc:`Valid ` From d72759a958fe048ff54d7f7a6f4df847bf515a84 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 1 Dec 2013 17:45:14 -0500 Subject: [PATCH 0098/1181] [#3022] Adding all of the security-related expression functionality docs --- book/security.rst | 164 +++++++++++++++++++++++++++++++++++ reference/twig_reference.rst | 6 ++ 2 files changed, 170 insertions(+) diff --git a/book/security.rst b/book/security.rst index 04f97dfcf95..6bc3203593b 100644 --- a/book/security.rst +++ b/book/security.rst @@ -864,6 +864,8 @@ options: (internally, an :class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException` is thrown); +* ``allow_if`` If the expression returns false, then access is denied; + * ``requires_channel`` If the incoming request's channel (e.g. ``http``) does not match this value (e.g. ``https``), the user will be redirected (e.g. redirected from ``http`` to ``https``, or vice versa). @@ -951,6 +953,56 @@ address): * The second access rule is not examined as the first rule matched. +Securing by an Expression +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 2.4 + The ``allow_if`` functionality was introduced in Symfony 2.4. + +Once an ``access_control`` entry is matched, you can deny access via the +``roles`` key or use more complex logic with an expression in the ``allow_if`` +key: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + security: + # ... + access_control: + - + path: ^/_internal/secure + allow_if: "'127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')" + + .. code-block:: xml + + + + + + .. code-block:: php + + 'access_control' => array( + array( + 'path' => '^/_internal/secure', + 'allow_if' => '"127.0.0.1" == request.getClientIp() or has_role("ROLE_ADMIN")', + ), + ), + +In this case, when the user tries to access any URL starting with ``/_internal/secure``, +she will only be granted access if the IP address is ``127.0.0.1`` or if +the user has the ``ROLE_ADMIN`` role. + +Inside the expression, you have access to a number of different variables +and functions including ``request``, which is the Symfony +:class:`Symfony\\Component\\HttpFoundation\\Request` object (see +:ref:`component-http-foundation-request`). + +For a list of the other functions and variables, see +:ref:`functions and variables `. + .. _book-security-securing-channel: Securing by Channel @@ -1656,6 +1708,8 @@ doesn't need to be defined anywhere - you can just start using it. Symfony2. If you define your own roles with a dedicated ``Role`` class (more advanced), don't use the ``ROLE_`` prefix. +.. _book-security-role-hierarchy: + Hierarchical Roles ~~~~~~~~~~~~~~~~~~ @@ -1834,6 +1888,31 @@ the built-in helper function: idea to have a main firewall that covers all URLs (as has been shown in this chapter). +.. _book-security-template-expression: + +.. versionadded:: 2.4 + The ``expression`` functionality was introduced in Symfony 2.4. + +You can also use expressions inside your templates: + +.. configuration-block:: + + .. code-block:: html+jinja + + {% if is_granted(expression('has_role("ROLE_ADMIN")')) %} + Delete + {% endif %} + + .. code-block:: html+php + + isGranted(new Expression( + 'has_role("ROLE_ADMIN")' + ))): ?> + Delete + + +For more details on expressions and security, see :ref:`book-security-expressions`. + Access Control in Controllers ----------------------------- @@ -1856,6 +1935,91 @@ method of the security context:: A firewall must be active or an exception will be thrown when the ``isGranted`` method is called. See the note above about templates for more details. +.. _book-security-expressions: + +Complex Access Controls with Expressions +---------------------------------------- + +.. versionadded:: 2.4 + The expression functionality was introduced in Symfony 2.4. + +In addition to a role like ``ROLE_ADMIN``, the ``isGranted`` method also +accepts an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` object:: + + use Symfony\Component\Security\Core\Exception\AccessDeniedException; + use Symfony\Component\ExpressionLanguage\Expression; + // ... + + public function indexAction() + { + if (!$this->get('security.context')->isGranted(new Expression( + '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())' + ))) { + throw new AccessDeniedException(); + } + + // ... + } + +In this example, if the current user has ``ROLE_ADMIN`` or if the current +user object's ``isSuperAdmin`` method returns ``true``, then access will +be granted (note: your User object may not have an ``isSuperAdmin`` method, +that method is invented for this example). This uses an expression and you +can learn more about the expression language syntax, see :doc:`/components/expression_language/syntax`. + +.. _book-security-expression-variables: + +Inside the expression, you have access to a number of variables: + +* ``user`` The user object (or the string ``anon`` if you're not authenticated); +* ``roles`` The array of roles the user has, including from the + :ref:`role hierarchy ` but not including + the ``IS_AUTHENTICATED_*`` attributes (see the functions below); +* ``object``: The object (if any) that's passed as the second argument to + ``isGranted`` ; +* ``token`` The token object; +* ``trust_resolver``: The :class:`Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolverInterface`, + object: probably not useful directly. + +Additionally, you have access to a number of functions inside the expression. +**Note**: some of these functions *look* similar to the ``IS_AUTHENTICATED_*`` +attributes, but work differently. See the note below: + +* ``is_authenticated``: Returns true if the user is authenticated via "remember-me" + or authenticated "fully" - i.e. returns true if the user is "logged in"; +* ``is_anonymous``: Equal to using ``IS_AUTHENTICATED_ANONYMOUSLY`` with + the ``isGranted`` function; +* ``is_remember_me``: Similar, but not equal to ``IS_AUTHENTICATED_REMEMBERED``, + see below; +* ``is_fully_authenticated``: Similar, but not equal to ``IS_AUTHENTICATED_FULLY``, + see below; +* ``has_role``: Checks to see if the user has the given role - equivalent + to an expression like ``'ROLE_ADMIN' in roles``. + +.. sidebar:: ``is_remember_me`` is different than checking ``IS_AUTHENTICATED_REMEMBERED`` + + The ``is_remember_me`` and ``is_authenticated_fully`` functions are *similar* + to using ``IS_AUTHENTICATED_REMEMBERED`` and ``IS_AUTHENTICATED_FULLY`` + with the ``isGranted`` function - but they are **not** the same. The + following shows the difference:: + + use Symfony\Component\ExpressionLanguage\Expression; + // ... + + $sc = $this->get('security.context'); + $access1 = $sc->isGranted('IS_AUTHENTICATED_REMEMBERED'); + + $access2 = $sc->isGranted(new Expression( + 'is_remember_me() or is_fully_authenticated()' + )); + + Here, ``$access1`` and ``$access2`` will be the same value. Unlike the + behavior of ``IS_AUTHENTICATED_REMEMBERED`` and ``IS_AUTHENTICATED_FULLY``, + the ``is_remember_me`` function *only* returns true if the user is authenticated + via a remember me cookie and ``is_fully_authenticated`` *only* returns + true if the user has actually logged in during this session (i.e. is + full-fledged). + Impersonating a User -------------------- diff --git a/reference/twig_reference.rst b/reference/twig_reference.rst index 50e43658ece..09ced4ce114 100644 --- a/reference/twig_reference.rst +++ b/reference/twig_reference.rst @@ -21,6 +21,9 @@ Functions The ``render`` and ``controller`` functions are new in Symfony 2.2. Prior, the ``{% render %}`` tag was used and had a different signature. +.. versionadded:: 2.4 + The ``expression`` function was introduced in Symfony 2.4. + +----------------------------------------------------+--------------------------------------------------------------------------------------------+ | Function Syntax | Usage | +====================================================+============================================================================================+ @@ -89,6 +92,9 @@ Functions +----------------------------------------------------+--------------------------------------------------------------------------------------------+ | ``url(name, parameters = {})`` | Equal to ``path(...)`` but it generates an absolute URL | +----------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``expression(expression)`` | Creates an :class:Symfony\\Component\\ExpressionLanguage\\Expression in Twig. See | +| | ":ref:`Template Expressions `". | ++----------------------------------------------------+--------------------------------------------------------------------------------------------+ Filters ------- From 33676dca47c4a3aa44f7b78fb41e917c0b19f189 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 1 Dec 2013 17:55:35 -0500 Subject: [PATCH 0099/1181] [#3022] Adding a quick cookbook entry to highlight where the expression component is used in the framework --- book/security.rst | 2 ++ book/service_container.rst | 2 ++ .../expression_language/introduction.rst | 2 +- cookbook/expression/expressions.rst | 24 +++++++++++++++++++ cookbook/expression/index.rst | 7 ++++++ cookbook/index.rst | 1 + cookbook/map.rst.inc | 4 ++++ 7 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 cookbook/expression/expressions.rst create mode 100644 cookbook/expression/index.rst diff --git a/book/security.rst b/book/security.rst index 6bc3203593b..efe7f7a3b63 100644 --- a/book/security.rst +++ b/book/security.rst @@ -953,6 +953,8 @@ address): * The second access rule is not examined as the first rule matched. +.. _book-security-allow-if: + Securing by an Expression ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/book/service_container.rst b/book/service_container.rst index bc13aa13aa4..3dc5698c853 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -627,6 +627,8 @@ service needs the ``my_mailer`` service in order to function. When you define this dependency in the service container, the container takes care of all the work of instantiating the classes. +.. _book-services-expressions: + Using the Expression Language ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst index 9ba2f5de9a0..78fd8ae8a74 100644 --- a/components/expression_language/introduction.rst +++ b/components/expression_language/introduction.rst @@ -3,7 +3,7 @@ Single: Components; Expression Language The ExpressionLanguage Component -================================= +================================ The ExpressionLanguage component provides an engine that can compile and evaluate expressions. An expression is a one-liner that returns a value diff --git a/cookbook/expression/expressions.rst b/cookbook/expression/expressions.rst new file mode 100644 index 00000000000..71313a24951 --- /dev/null +++ b/cookbook/expression/expressions.rst @@ -0,0 +1,24 @@ +.. index:: + single: Expressions in the Framework + +How to use Expressions in Security, Routing, Services, and Validation +===================================================================== + +.. versionadded:: 2.4 + The expression functionality was introduced in Symfony 2.4. + +In Symfony 2.4, a powerful :doc:`ExpressionLanguage ` +component was added to Symfony. This allows us to add highly customized +logic inside configuration. + +The Symfony Framework leverages expressions out of the box in the following +ways: + +* :ref:`Configuring services `; +* :ref:`Route matching conditions `; +* :ref:`Checking security ` and + :ref:`access controls with allow_if `; +* :doc:`Validation `. + +For more information about how to create and work with expressions, see +:doc:`/components/expression_language/syntax`. \ No newline at end of file diff --git a/cookbook/expression/index.rst b/cookbook/expression/index.rst new file mode 100644 index 00000000000..909ecc72224 --- /dev/null +++ b/cookbook/expression/index.rst @@ -0,0 +1,7 @@ +Expressions +=========== + +.. toctree:: + :maxdepth: 2 + + expressions diff --git a/cookbook/index.rst b/cookbook/index.rst index 07869cad14a..428661bc374 100644 --- a/cookbook/index.rst +++ b/cookbook/index.rst @@ -15,6 +15,7 @@ The Cookbook doctrine/index email/index event_dispatcher/index + expression/index form/index logging/index profiler/index diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 76be17eced8..b901380cfa5 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -78,6 +78,10 @@ * :doc:`/cookbook/event_dispatcher/method_behavior` * (service container) :doc:`/cookbook/service_container/event_listener` +* :doc:`/cookbook/expression/index` + + * :doc:`/cookbook/expression/expressions` + * :doc:`/cookbook/form/index` * :doc:`/cookbook/form/form_customization` From 0cf18287b2f861d27d09edf0d728c04a442a3c3c Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 1 Dec 2013 18:37:09 -0500 Subject: [PATCH 0100/1181] [#3022][#3258] Tweaks thanks to @cordoval --- book/routing.rst | 10 +++++----- book/security.rst | 4 ++-- cookbook/expression/expressions.rst | 2 +- reference/constraints/Expression.rst | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/book/routing.rst b/book/routing.rst index 9cb545796ca..a9dbe814863 100644 --- a/book/routing.rst +++ b/book/routing.rst @@ -728,7 +728,7 @@ Completely Customized Route Matching with Conditions As you've seen, a route can be made to match only certain routing wildcards (via regular expressions), HTTP methods, or host names. But the routing system -can be extended to almost an infinite flexibility with ``conditions``: +can be extended to have an almost infinite flexibility using ``conditions``: .. configuration-block:: @@ -775,13 +775,13 @@ can be extended to almost an infinite flexibility with ``conditions``: return $collection; -The ``condition`` is an expression, and you can learn more about it syntax +The ``condition`` is an expression, and you can learn more about its syntax here: :doc:`/components/expression_language/syntax`. With this, the route won't match unless the HTTP method is either GET or HEAD *and* if the ``User-Agent`` header matches ``firefox``. -You can do any complex logic you need here by leveraging two variables that -are passed into the expression: +You can do any complex logic you need in the expression by leveraging two +variables that are passed into the expression: * ``context``: An instance of :class:`Symfony\\Component\\Routing\\RequestContext`, which holds the most fundamental information about the route being matched; @@ -804,7 +804,7 @@ are passed into the expression: // ... } - Because of this, using the ``condition`` key causes no extra roverhead + Because of this, using the ``condition`` key causes no extra overhead beyond the time it takes for the underlying PHP to execute. .. index:: diff --git a/book/security.rst b/book/security.rst index efe7f7a3b63..0048b4ef423 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1981,7 +1981,7 @@ Inside the expression, you have access to a number of variables: ``isGranted`` ; * ``token`` The token object; * ``trust_resolver``: The :class:`Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolverInterface`, - object: probably not useful directly. + object: you'll probably use the ``is_*`` functions below instead. Additionally, you have access to a number of functions inside the expression. **Note**: some of these functions *look* similar to the ``IS_AUTHENTICATED_*`` @@ -2018,7 +2018,7 @@ attributes, but work differently. See the note below: Here, ``$access1`` and ``$access2`` will be the same value. Unlike the behavior of ``IS_AUTHENTICATED_REMEMBERED`` and ``IS_AUTHENTICATED_FULLY``, the ``is_remember_me`` function *only* returns true if the user is authenticated - via a remember me cookie and ``is_fully_authenticated`` *only* returns + via a remember-me cookie and ``is_fully_authenticated`` *only* returns true if the user has actually logged in during this session (i.e. is full-fledged). diff --git a/cookbook/expression/expressions.rst b/cookbook/expression/expressions.rst index 71313a24951..aba6431edfc 100644 --- a/cookbook/expression/expressions.rst +++ b/cookbook/expression/expressions.rst @@ -21,4 +21,4 @@ ways: * :doc:`Validation `. For more information about how to create and work with expressions, see -:doc:`/components/expression_language/syntax`. \ No newline at end of file +:doc:`/components/expression_language/syntax`. diff --git a/reference/constraints/Expression.rst b/reference/constraints/Expression.rst index 812b21dbe73..db6c726fd33 100644 --- a/reference/constraints/Expression.rst +++ b/reference/constraints/Expression.rst @@ -130,7 +130,7 @@ expression that must return true in order for validation to pass. To learn more about the expression language syntax, see :doc:`/components/expression_language/syntax`. -For more information about the expression and what variables you have available +For more information about the expression and what variables are available to you, see the :ref:`expression ` option details below. From bc22f16911167b05b1c56397e26f22b28b4cdd5e Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 2 Dec 2013 07:52:15 -0500 Subject: [PATCH 0101/1181] [#3022][#3258] Enhancing example at @ggam's suggestion --- book/security.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/book/security.rst b/book/security.rst index 0048b4ef423..da607eaada9 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1901,14 +1901,16 @@ You can also use expressions inside your templates: .. code-block:: html+jinja - {% if is_granted(expression('has_role("ROLE_ADMIN")')) %} + {% if is_granted(expression( + '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())' + )) %} Delete {% endif %} .. code-block:: html+php isGranted(new Expression( - 'has_role("ROLE_ADMIN")' + '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())' ))): ?> Delete From 00002508843a5d05a54c0f92deb7ca2d60c90a34 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 2 Dec 2013 07:58:25 -0500 Subject: [PATCH 0102/1181] [#3258] A bunch of fixes thanks to @WouterJ --- book/security.rst | 16 ++++++++-------- reference/constraints/Expression.rst | 10 +++++----- reference/twig_reference.rst | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/book/security.rst b/book/security.rst index da607eaada9..974a0f88f9d 100644 --- a/book/security.rst +++ b/book/security.rst @@ -994,7 +994,7 @@ key: ), In this case, when the user tries to access any URL starting with ``/_internal/secure``, -she will only be granted access if the IP address is ``127.0.0.1`` or if +they will only be granted access if the IP address is ``127.0.0.1`` or if the user has the ``ROLE_ADMIN`` role. Inside the expression, you have access to a number of different variables @@ -1966,10 +1966,12 @@ accepts an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` object:: } In this example, if the current user has ``ROLE_ADMIN`` or if the current -user object's ``isSuperAdmin`` method returns ``true``, then access will +user object's ``isSuperAdmin()`` method returns ``true``, then access will be granted (note: your User object may not have an ``isSuperAdmin`` method, -that method is invented for this example). This uses an expression and you -can learn more about the expression language syntax, see :doc:`/components/expression_language/syntax`. +that method is invented for this example). + +This uses an expression and you can learn more about the expression language +syntax, see :doc:`/components/expression_language/syntax`. .. _book-security-expression-variables: @@ -1985,11 +1987,9 @@ Inside the expression, you have access to a number of variables: * ``trust_resolver``: The :class:`Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolverInterface`, object: you'll probably use the ``is_*`` functions below instead. -Additionally, you have access to a number of functions inside the expression. -**Note**: some of these functions *look* similar to the ``IS_AUTHENTICATED_*`` -attributes, but work differently. See the note below: +Additionally, you have access to a number of functions inside the expression: -* ``is_authenticated``: Returns true if the user is authenticated via "remember-me" +* ``is_authenticated``: Returns ``true`` if the user is authenticated via "remember-me" or authenticated "fully" - i.e. returns true if the user is "logged in"; * ``is_anonymous``: Equal to using ``IS_AUTHENTICATED_ANONYMOUSLY`` with the ``isGranted`` function; diff --git a/reference/constraints/Expression.rst b/reference/constraints/Expression.rst index db6c726fd33..430e53ecba1 100644 --- a/reference/constraints/Expression.rst +++ b/reference/constraints/Expression.rst @@ -69,7 +69,7 @@ One way to accomplish this is with the Expression constraint: constraints: - Expression: expression: "this.getCategory() in ['php', 'symfony'] or !this.isTechnicalPost()" - message: "If this is a tech post, the category should be php or symfony!" + message: "If this is a tech post, the category should be either php or symfony!" .. code-block:: php-annotations @@ -80,8 +80,8 @@ One way to accomplish this is with the Expression constraint: /** * @Assert\Expression( - * "this.getCategory() in ['php', 'symfony'] or !this.isTechnicalPost()", - * message="If this is a tech post, the category should be php or symfony!" + * "this.getCategory() in ['php', 'symfony'] or !this.isTechnicalPost()", + * message="If this is a tech post, the category should be either php or symfony!" * ) */ class BlogPost @@ -98,7 +98,7 @@ One way to accomplish this is with the Expression constraint: this.getCategory() in ['php', 'symfony'] or !this.isTechnicalPost()
@@ -118,7 +118,7 @@ One way to accomplish this is with the Expression constraint: { $metadata->addConstraint(new Assert\Expression(array( 'expression' => 'this.getCategory() in ["php", "symfony"] or !this.isTechnicalPost()', - 'message' => 'If this is a tech post, the category should be php or symfony!', + 'message' => 'If this is a tech post, the category should be either php or symfony!', ))); } diff --git a/reference/twig_reference.rst b/reference/twig_reference.rst index 09ced4ce114..5724193f15a 100644 --- a/reference/twig_reference.rst +++ b/reference/twig_reference.rst @@ -92,7 +92,7 @@ Functions +----------------------------------------------------+--------------------------------------------------------------------------------------------+ | ``url(name, parameters = {})`` | Equal to ``path(...)`` but it generates an absolute URL | +----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``expression(expression)`` | Creates an :class:Symfony\\Component\\ExpressionLanguage\\Expression in Twig. See | +| ``expression(expression)`` | Creates an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` in Twig. See | | | ":ref:`Template Expressions `". | +----------------------------------------------------+--------------------------------------------------------------------------------------------+ From a9e0e66dd5967788a3b5862022e0080a9b2bb300 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Mon, 2 Dec 2013 14:50:47 +0100 Subject: [PATCH 0103/1181] Added Caching article --- components/expression_language/caching.rst | 61 +++++++++++++++++++ components/expression_language/index.rst | 1 + .../expression_language/introduction.rst | 6 ++ components/map.rst.inc | 1 + 4 files changed, 69 insertions(+) create mode 100644 components/expression_language/caching.rst diff --git a/components/expression_language/caching.rst b/components/expression_language/caching.rst new file mode 100644 index 00000000000..44b0760612d --- /dev/null +++ b/components/expression_language/caching.rst @@ -0,0 +1,61 @@ +.. index:: + single: Caching; ExpressionLanguage + +Caching Expressions Using ParserCaches +====================================== + +The ExpressionLanguage component already provides a +:method:`Symfony\\Component\\ExpresionLanguage\\ExpressionLanguage::compile` +method to be able to cache the expressions in plain PHP. But internally, the +component also caches the parsed expressions, so duplicated expressions can be +compiled/evaluated quicker. + +The Workflow +------------ + +Both ``evaluate`` and ``compile`` needs to do some things before it can +provide the return values. For ``evaluate``, this overhead is even bigger. + +Both methods need to tokenize and parse the expression. This is done by the +:method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::parse` +method. It'll return a :class:`Symfony\\Component\\ExpressionLanguage\\ParsedExpression`. +Now, the ``compile`` method just returns the string conversion of this object. +The ``evaluate`` method needs to loop through the "nodes" (pieces of an +expression saved in the ``ParsedExpression``) and evaluate them on the fly. + +To save time, the ``ExpressionLanguage`` caches the ``ParsedExpression``, so +it can skip the tokenize and parse steps with duplicate expressions. +The caching is done by a +:class:`Symfony\\Component\\ExpressionLanguage\\ParserCache\\ParserCacheInterface` +instance (by default, it uses an +:class:`Symfony\\Component\\ExpressionLanguage\\ParserCache\\ArrayParserCache`). +You can customize this by creating a custom ``ParserCache`` and injecting this +in the object using the constructor:: + + use Symfony\Component\ExpressionLanguage\ExpressionLanguage; + use Acme\ExpressionLanguage\ParserCache\MyDatabaseParserCache; + + $cache = new MyDatabaseParserCache(...); + $language = new ExpressionLanguage($cache); + +Using Parsed and Serialized Expressions +--------------------------------------- + +Both ``evaluate`` and ``compile`` can handle ``ParsedExpression`` and +``SerializedParsedExpression``:: + + use Symfony\Component\ExpressionLanguage\ParsedExpression; + // ... + + $expression = new ParsedExpression($language->parse('1 + 4')); + + echo $language->evaluate($expression); // prints 5 + +.. code-block:: php + + use Symfony\Component\ExpressionLanguage\SerializedParsedExpression; + // ... + + $expression = new SerializedParsedExpression(serialize($language->parse('1 + 4'))); + + echo $language->evaluate($expression); // prints 5 diff --git a/components/expression_language/index.rst b/components/expression_language/index.rst index 5ae40be979f..aa63907d921 100644 --- a/components/expression_language/index.rst +++ b/components/expression_language/index.rst @@ -7,3 +7,4 @@ Expression Language introduction syntax extending + caching diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst index 78fd8ae8a74..a53c8aa960d 100644 --- a/components/expression_language/introduction.rst +++ b/components/expression_language/introduction.rst @@ -109,4 +109,10 @@ PHP type (including objects):: This will print "Honeycrisp". For more information, see the :doc:`/components/expression_language/syntax` entry, especially :ref:`component-expression-objects` and :ref:`component-expression-arrays`. +Caching +------- + +The component provides some different caching strategies, read more about them +in :doc:`/components/expression_language/caching`. + .. _Packagist: https://packagist.org/packages/symfony/expression-language diff --git a/components/map.rst.inc b/components/map.rst.inc index 2703a6057fc..a5f2d0f8db7 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -62,6 +62,7 @@ * :doc:`/components/expression_language/introduction` * :doc:`/components/expression_language/syntax` * :doc:`/components/expression_language/extending` + * :doc:`/components/expression_language/caching` * **Filesystem** From d6b3a14363927d765809e9e1da56ed03064acd8c Mon Sep 17 00:00:00 2001 From: Zbigniew Czapran Date: Mon, 2 Dec 2013 16:54:16 +0100 Subject: [PATCH 0104/1181] [Cookbook] Fixes a link to the Request class --- book/routing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/routing.rst b/book/routing.rst index a9dbe814863..50473a337c6 100644 --- a/book/routing.rst +++ b/book/routing.rst @@ -785,7 +785,7 @@ variables that are passed into the expression: * ``context``: An instance of :class:`Symfony\\Component\\Routing\\RequestContext`, which holds the most fundamental information about the route being matched; -* ``request``: The Symfony :class:`Symfony\\Component\\HttpFoundation\\Request`` +* ``request``: The Symfony :class:`Symfony\\Component\\HttpFoundation\\Request` object (see :ref:`component-http-foundation-request`). .. caution:: From 0a59f6d4956ccbfe2b58326969c166cd1c14f6f8 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Mon, 2 Dec 2013 16:54:39 +0100 Subject: [PATCH 0105/1181] Added doctrine note --- components/expression_language/caching.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/components/expression_language/caching.rst b/components/expression_language/caching.rst index 44b0760612d..12953e66cb2 100644 --- a/components/expression_language/caching.rst +++ b/components/expression_language/caching.rst @@ -38,6 +38,12 @@ in the object using the constructor:: $cache = new MyDatabaseParserCache(...); $language = new ExpressionLanguage($cache); +.. note:: + + The `DoctrineBridge`_ has a ParserCache implementation using the + `doctrine cache library`_, which gives you caching for all sorts of cache + strategies, like Apc, Filesystem and Apc. + Using Parsed and Serialized Expressions --------------------------------------- @@ -59,3 +65,6 @@ Both ``evaluate`` and ``compile`` can handle ``ParsedExpression`` and $expression = new SerializedParsedExpression(serialize($language->parse('1 + 4'))); echo $language->evaluate($expression); // prints 5 + +.. _DoctrineBridge: https://github.com/symfony/DoctrineBridge +.. _`doctrine cache library`: http://docs.doctrine-project.org/projects/doctrine-common/en/latest/reference/caching.html From be60602ac81e851e1e4b10b423c618a5a18aad2a Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 2 Dec 2013 19:09:21 -0500 Subject: [PATCH 0106/1181] [#3260] Minor tweaks when proofreading --- components/expression_language/caching.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/components/expression_language/caching.rst b/components/expression_language/caching.rst index 12953e66cb2..5adebc50d94 100644 --- a/components/expression_language/caching.rst +++ b/components/expression_language/caching.rst @@ -1,11 +1,11 @@ .. index:: single: Caching; ExpressionLanguage -Caching Expressions Using ParserCaches -====================================== +Caching Expressions Using Parser Caches +======================================= The ExpressionLanguage component already provides a -:method:`Symfony\\Component\\ExpresionLanguage\\ExpressionLanguage::compile` +:method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::compile` method to be able to cache the expressions in plain PHP. But internally, the component also caches the parsed expressions, so duplicated expressions can be compiled/evaluated quicker. @@ -13,17 +13,17 @@ compiled/evaluated quicker. The Workflow ------------ -Both ``evaluate`` and ``compile`` needs to do some things before it can +Both ``evaluate`` and ``compile`` need to do some things before each can provide the return values. For ``evaluate``, this overhead is even bigger. Both methods need to tokenize and parse the expression. This is done by the :method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::parse` -method. It'll return a :class:`Symfony\\Component\\ExpressionLanguage\\ParsedExpression`. +method. It returns a :class:`Symfony\\Component\\ExpressionLanguage\\ParsedExpression`. Now, the ``compile`` method just returns the string conversion of this object. The ``evaluate`` method needs to loop through the "nodes" (pieces of an expression saved in the ``ParsedExpression``) and evaluate them on the fly. -To save time, the ``ExpressionLanguage`` caches the ``ParsedExpression``, so +To save time, the ``ExpressionLanguage`` caches the ``ParsedExpression`` so it can skip the tokenize and parse steps with duplicate expressions. The caching is done by a :class:`Symfony\\Component\\ExpressionLanguage\\ParserCache\\ParserCacheInterface` From a2ec22b2a83fc68f6e82cf21a1e71e38089197c8 Mon Sep 17 00:00:00 2001 From: Christoph Schmidt Date: Tue, 3 Dec 2013 15:51:17 +0100 Subject: [PATCH 0107/1181] Update Callback.rst add square brackets to yaml codeblock (constraints: - Callback: [validate]). Otherwise an error "Expected argument of type array, string given" is thrown --- reference/constraints/Callback.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/constraints/Callback.rst b/reference/constraints/Callback.rst index e59754f450a..e370c46ecf1 100644 --- a/reference/constraints/Callback.rst +++ b/reference/constraints/Callback.rst @@ -42,7 +42,7 @@ Configuration # src/Acme/BlogBundle/Resources/config/validation.yml Acme\BlogBundle\Entity\Author: constraints: - - Callback: validate + - Callback: [validate] .. code-block:: php-annotations From 1f385daa2c88b4975f7b761c740689712fe14982 Mon Sep 17 00:00:00 2001 From: Philipp Rieber Date: Wed, 4 Dec 2013 07:03:19 +0100 Subject: [PATCH 0108/1181] [Components][HttpKernel] Add FINISH_REQUEST to events table --- components/http_kernel/introduction.rst | 32 +++++++++++++------------ 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/components/http_kernel/introduction.rst b/components/http_kernel/introduction.rst index 33cf6f17cf3..92fe16307e6 100644 --- a/components/http_kernel/introduction.rst +++ b/components/http_kernel/introduction.rst @@ -569,21 +569,23 @@ each event has their own event object: .. _component-http-kernel-event-table: -+-------------------+-------------------------------+-------------------------------------------------------------------------------------+ -| **Name** | ``KernelEvents`` **Constant** | **Argument passed to the listener** | -+-------------------+-------------------------------+-------------------------------------------------------------------------------------+ -| kernel.request | ``KernelEvents::REQUEST`` | :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent` | -+-------------------+-------------------------------+-------------------------------------------------------------------------------------+ -| kernel.controller | ``KernelEvents::CONTROLLER`` | :class:`Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent` | -+-------------------+-------------------------------+-------------------------------------------------------------------------------------+ -| kernel.view | ``KernelEvents::VIEW`` | :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForControllerResultEvent` | -+-------------------+-------------------------------+-------------------------------------------------------------------------------------+ -| kernel.response | ``KernelEvents::RESPONSE`` | :class:`Symfony\\Component\\HttpKernel\\Event\\FilterResponseEvent` | -+-------------------+-------------------------------+-------------------------------------------------------------------------------------+ -| kernel.terminate | ``KernelEvents::TERMINATE`` | :class:`Symfony\\Component\\HttpKernel\\Event\\PostResponseEvent` | -+-------------------+-------------------------------+-------------------------------------------------------------------------------------+ -| kernel.exception | ``KernelEvents::EXCEPTION`` | :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent` | -+-------------------+-------------------------------+-------------------------------------------------------------------------------------+ ++-----------------------+----------------------------------+-------------------------------------------------------------------------------------+ +| **Name** | ``KernelEvents`` **Constant** | **Argument passed to the listener** | ++-----------------------+----------------------------------+-------------------------------------------------------------------------------------+ +| kernel.request | ``KernelEvents::REQUEST`` | :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent` | ++-----------------------+----------------------------------+-------------------------------------------------------------------------------------+ +| kernel.controller | ``KernelEvents::CONTROLLER`` | :class:`Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent` | ++-----------------------+----------------------------------+-------------------------------------------------------------------------------------+ +| kernel.view | ``KernelEvents::VIEW`` | :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForControllerResultEvent` | ++-----------------------+----------------------------------+-------------------------------------------------------------------------------------+ +| kernel.response | ``KernelEvents::RESPONSE`` | :class:`Symfony\\Component\\HttpKernel\\Event\\FilterResponseEvent` | ++-----------------------+----------------------------------+-------------------------------------------------------------------------------------+ +| kernel.finish_request | ``KernelEvents::FINISH_REQUEST`` | :class:`Symfony\\Component\\HttpKernel\\Event\\FinishRequestEvent` | ++-----------------------+----------------------------------+-------------------------------------------------------------------------------------+ +| kernel.terminate | ``KernelEvents::TERMINATE`` | :class:`Symfony\\Component\\HttpKernel\\Event\\PostResponseEvent` | ++-----------------------+----------------------------------+-------------------------------------------------------------------------------------+ +| kernel.exception | ``KernelEvents::EXCEPTION`` | :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent` | ++-----------------------+----------------------------------+-------------------------------------------------------------------------------------+ .. _http-kernel-working-example: From 986e876fbe1caf233df02b8abf5cc2dd83a21e60 Mon Sep 17 00:00:00 2001 From: Julius Beckmann Date: Thu, 5 Dec 2013 20:28:04 +0100 Subject: [PATCH 0109/1181] Updated install page to v2.4.* --- book/installation.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/book/installation.rst b/book/installation.rst index d8097d0d505..265fb48582b 100644 --- a/book/installation.rst +++ b/book/installation.rst @@ -57,7 +57,7 @@ Distribution: .. code-block:: bash - $ php composer.phar create-project symfony/framework-standard-edition /path/to/webroot/Symfony 2.3.* + $ php composer.phar create-project symfony/framework-standard-edition /path/to/webroot/Symfony 2.4.* .. tip:: @@ -104,10 +104,10 @@ one of the following commands (replacing ``###`` with your actual filename): .. code-block:: bash # for .tgz file - $ tar zxvf Symfony_Standard_Vendors_2.3.###.tgz + $ tar zxvf Symfony_Standard_Vendors_2.4.###.tgz # for a .zip file - $ unzip Symfony_Standard_Vendors_2.3.###.zip + $ unzip Symfony_Standard_Vendors_2.4.###.zip If you've downloaded "without vendors", you'll definitely need to read the next section. From a7f2c9870866ee096a4d7426d1a8b0d700023fd5 Mon Sep 17 00:00:00 2001 From: pauliusmasiliunas Date: Sat, 7 Dec 2013 23:19:55 +0200 Subject: [PATCH 0110/1181] Change symfony version on composer.json --- book/from_flat_php_to_symfony2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/from_flat_php_to_symfony2.rst b/book/from_flat_php_to_symfony2.rst index b3551b2efae..756bf91ac75 100644 --- a/book/from_flat_php_to_symfony2.rst +++ b/book/from_flat_php_to_symfony2.rst @@ -433,7 +433,7 @@ content: { "require": { - "symfony/symfony": "2.3.*" + "symfony/symfony": "2.4.*" }, "autoload": { "files": ["model.php","controllers.php"] From 7e1e4a22d66a9f51531687afd0c71004ccb254dd Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 8 Dec 2013 14:09:58 +0100 Subject: [PATCH 0111/1181] some tweaks to the Expression Language cache chapter --- components/expression_language/caching.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/components/expression_language/caching.rst b/components/expression_language/caching.rst index 5adebc50d94..41c9d2a1c26 100644 --- a/components/expression_language/caching.rst +++ b/components/expression_language/caching.rst @@ -13,14 +13,15 @@ compiled/evaluated quicker. The Workflow ------------ -Both ``evaluate`` and ``compile`` need to do some things before each can -provide the return values. For ``evaluate``, this overhead is even bigger. +Both :method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::evaluate` +and ``compile()`` need to do some things before each can provide the return +values. For ``evaluate()``, this overhead is even bigger. -Both methods need to tokenize and parse the expression. This is done by the +Both methods need to tokenize and parse the expression. This is done by the :method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::parse` method. It returns a :class:`Symfony\\Component\\ExpressionLanguage\\ParsedExpression`. -Now, the ``compile`` method just returns the string conversion of this object. -The ``evaluate`` method needs to loop through the "nodes" (pieces of an +Now, the ``compile()`` method just returns the string conversion of this object. +The ``evaluate()`` method needs to loop through the "nodes" (pieces of an expression saved in the ``ParsedExpression``) and evaluate them on the fly. To save time, the ``ExpressionLanguage`` caches the ``ParsedExpression`` so @@ -40,14 +41,14 @@ in the object using the constructor:: .. note:: - The `DoctrineBridge`_ has a ParserCache implementation using the + The `DoctrineBridge`_ provides a Parser Cache implementation using the `doctrine cache library`_, which gives you caching for all sorts of cache - strategies, like Apc, Filesystem and Apc. + strategies, like Apc, Filesystem and Memcached. Using Parsed and Serialized Expressions --------------------------------------- -Both ``evaluate`` and ``compile`` can handle ``ParsedExpression`` and +Both ``evaluate()`` and ``compile()`` can handle ``ParsedExpression`` and ``SerializedParsedExpression``:: use Symfony\Component\ExpressionLanguage\ParsedExpression; From 7bf21c277f1d1487d7395a79b191b92fb0662b0b Mon Sep 17 00:00:00 2001 From: Dorthe Luebbert Date: Sat, 7 Dec 2013 14:48:21 +0100 Subject: [PATCH 0112/1181] changed create-project example with the current version of composer you can use wildcards like "2.3.*" :-) --- quick_tour/the_big_picture.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quick_tour/the_big_picture.rst b/quick_tour/the_big_picture.rst index 1ab6cea7eea..0d56e6cf381 100644 --- a/quick_tour/the_big_picture.rst +++ b/quick_tour/the_big_picture.rst @@ -66,7 +66,7 @@ have a ``Symfony/`` directory that looks like this: .. code-block:: bash - $ php composer.phar create-project symfony/framework-standard-edition Symfony 2.3.0 + $ php composer.phar create-project symfony/framework-standard-edition Symfony 2.3.* .. _`quick-tour-big-picture-built-in-server`: From 621296819d699c08cf7327506040a0b6d517a7ea Mon Sep 17 00:00:00 2001 From: Dorthe Luebbert Date: Sun, 8 Dec 2013 09:20:24 +0100 Subject: [PATCH 0113/1181] changed version in create project example to 2.4.* and remove the hint above as it is not longer necessary due to the new wildcard feature in composer --- quick_tour/the_big_picture.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/quick_tour/the_big_picture.rst b/quick_tour/the_big_picture.rst index 0d56e6cf381..2305a55990e 100644 --- a/quick_tour/the_big_picture.rst +++ b/quick_tour/the_big_picture.rst @@ -61,12 +61,11 @@ have a ``Symfony/`` directory that looks like this: .. note:: If you are familiar with `Composer`_, you can download Composer and then - run the following command instead of downloading the archive (replacing - ``2.3.0`` with the latest Symfony release like ``2.3.1``): + run the following command instead of downloading the archive: .. code-block:: bash - $ php composer.phar create-project symfony/framework-standard-edition Symfony 2.3.* + $ php composer.phar create-project symfony/framework-standard-edition Symfony 2.4.* .. _`quick-tour-big-picture-built-in-server`: From 6e610bfe88819ca481f1fc88603a2ba5532574c7 Mon Sep 17 00:00:00 2001 From: William Durand Date: Thu, 12 Dec 2013 16:19:07 +0100 Subject: [PATCH 0114/1181] [Components] [ExpressionLanguage] Fix missing quote --- components/expression_language/extending.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/expression_language/extending.rst b/components/expression_language/extending.rst index d3c8dbbd3d8..0c92bc5fa83 100644 --- a/components/expression_language/extending.rst +++ b/components/expression_language/extending.rst @@ -21,7 +21,7 @@ That means the functions can be used in any expression executed by that instance. To register a function, use -:method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::register``. +:method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::register`. This method has 3 arguments: * **name** - The name of the function in an expression; From a45464f578b1901abb09e5176594ea0cf4ade823 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Thu, 12 Dec 2013 14:18:56 +0000 Subject: [PATCH 0115/1181] Added missing argument to the evaluator function --- components/expression_language/extending.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/expression_language/extending.rst b/components/expression_language/extending.rst index d3c8dbbd3d8..d3b278c627b 100644 --- a/components/expression_language/extending.rst +++ b/components/expression_language/extending.rst @@ -40,7 +40,7 @@ This method has 3 arguments: } return sprintf('strtolower(%s)', $str); - }, function ($str) { + }, function ($arguments, $str) { if (!is_string($str)) { return $str; } @@ -75,7 +75,7 @@ Override ``registerFunctions`` to add your own functions:: } return sprintf('strtolower(%s)', $str); - }, function ($str) { + }, function ($arguments, $str) { if (!is_string($str)) { return $str; } From 2f486ce60aa1eb9466fe4527bd6c53a6e1343ded Mon Sep 17 00:00:00 2001 From: Mathieu Lemoine Date: Thu, 12 Dec 2013 14:18:43 -0500 Subject: [PATCH 0116/1181] [Security][Acl] Documentation for the new updateUserSecurityIdentity method in Dbal\MutableAclProvider --- cookbook/security/acl_advanced.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cookbook/security/acl_advanced.rst b/cookbook/security/acl_advanced.rst index 1bc217d8e6e..45d164aa29c 100644 --- a/cookbook/security/acl_advanced.rst +++ b/cookbook/security/acl_advanced.rst @@ -45,6 +45,13 @@ Security Identities This is analog to the object identity, but represents a user, or a role in your application. Each role, or user has its own security identity. +.. versionadded:: 2.5 + For users, the security identity is based on the username. This means that, + if for any reason, a user's username was to change, you must ensure its + security identity is updated too. The method ``updateUserSecurityIdentity`` + of the :class:`Symfony\\Component\\Security\\Acl\\Dbal\\MutableAclProvider` + class is there to handle the update. + Database Table Structure ------------------------ From 37deaa779402d85bc7df4b3d1a50a9949b7e88e0 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 19 Aug 2013 19:32:06 +0200 Subject: [PATCH 0117/1181] document the new authentication customization options --- cookbook/map.rst.inc | 1 + cookbook/security/custom_authenticator.rst | 208 +++++++++++++++++++++ cookbook/security/index.rst | 1 + 3 files changed, 210 insertions(+) create mode 100644 cookbook/security/custom_authenticator.rst diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index b901380cfa5..686620c99f7 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -135,6 +135,7 @@ * :doc:`/cookbook/security/form_login` * :doc:`/cookbook/security/securing_services` * :doc:`/cookbook/security/custom_provider` + * :doc:`/cookbook/security/custom_authenticator` * :doc:`/cookbook/security/custom_authentication_provider` * :doc:`/cookbook/security/target_path` diff --git a/cookbook/security/custom_authenticator.rst b/cookbook/security/custom_authenticator.rst new file mode 100644 index 00000000000..817952489e8 --- /dev/null +++ b/cookbook/security/custom_authenticator.rst @@ -0,0 +1,208 @@ +.. index:: + single: Security; Custom Authenticator + +How to create a custom Authenticator +==================================== + +Introduction +------------ + +Imagine you want to allow access to your website only between 2pm and 4pm (for +the UTC timezone). Before Symfony 2.4, you had to create a custom token, factory, +listener and provider. + +The Authenticator +----------------- + +Thanks to new simplified authentication customization options in Symfony 2.4, +you don't need to create a whole bunch of new classes, but use the +:class:`Symfony\\Component\\Security\\Core\\Authentication\\SimpleFormAuthenticatorInterface` +interface instead:: + + // src/Acme/HelloBundle/Security/TimeAuthenticator.php + namespace Acme\HelloBundle\Security; + + use Symfony\Component\HttpFoundation\Request; + use Symfony\Component\Security\Core\Authentication\SimpleFormAuthenticatorInterface; + use Symfony\Component\Security\Core\Authentication\TokenInterface; + use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; + use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; + use Symfony\Component\Security\Core\Exception\AuthenticationException; + use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; + use Symfony\Component\Security\Core\User\UserProviderInterface; + + class TimeAuthenticator implements SimpleFormAuthenticatorInterface + { + private $encoderFactory; + + public function __construct(EncoderFactoryInterface $encoderFactory) + { + $this->encoderFactory = $encoderFactory; + } + + public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) + { + try { + $user = $userProvider->loadUserByUsername($token->getUsername()); + } catch (UsernameNotFoundException $e) { + throw new AuthenticationException('Invalid username or password'); + } + + $encoder = $this->encoderFactory->getEncoder($user); + $passwordValid = $encoder->isPasswordValid( + $user->getPassword(), + $token->getCredentials(), + $user->getSalt() + ); + + if ($passwordValid) { + $currentHour = date('G'); + if ($currentHour < 14 || $currentHour > 16) { + throw new AuthenticationException( + 'You can only log in between 2 and 4!', + 100 + ); + } + + return new UsernamePasswordToken( + $user->getUsername(), + $user->getPassword(), + $providerKey, + $user->getRoles() + ); + } + + throw new AuthenticationException('Invalid username or password'); + } + + public function supportsToken(TokenInterface $token, $providerKey) + { + return $token instanceof UsernamePasswordToken + && $token->getProviderKey() === $providerKey; + } + + public function createToken(Request $request, $username, $password, $providerKey) + { + return new UsernamePasswordToken($username, $password, $providerKey); + } + } + +.. versionadded:: 2.4 + The ``SimpleFormAuthenticatorInterface`` interface was added in Symfony 2.4. + +How it works +------------ + +There are a lot of things going on: + +* ``createToken()`` creates a Token that will be used to authenticate the user; +* ``authenticateToken()`` checks that the Token is allowed to log in by first + getting the User via the user provider and then, by checking the password + and the current time (a Token with roles is authenticated); +* ``supportsToken()`` is just a way to allow several authentication mechanisms to + be used for the same firewall (that way, you can for instance first try to + authenticate the user via a certificate or an API key and fall back to a + form login); +* An encoder is needed to check the user password's validity; this is a + service provided by default:: + + $encoder = $this->encoderFactory->getEncoder($user); + $passwordValid = $encoder->isPasswordValid( + $user->getPassword(), + $token->getCredentials(), + $user->getSalt() + ); + +Configuration +------------- + +Now, configure your ``TimeAuthenticator`` as a service: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + services: + time_authenticator: + class: Acme\HelloBundle\Security\TimeAuthenticator + arguments: [@security.encoder_factory] + + .. code-block:: xml + + + + + + + + + .. code-block:: php + + // app/config/config.php + use Symfony\Component\DependencyInjection\Definition; + use Symfony\Component\DependencyInjection\Reference; + + $container->setDefinition('time_authenticator', new Definition( + 'Acme\HelloBundle\Security\TimeAuthenticator', + array(new Reference('security.encoder_factory')) + )); + +Then, activate it in your ``firewalls`` section using the ``simple-form`` key +like this: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + security: + # ... + + firewalls: + secured_area: + pattern: ^/admin + provider: authenticator + simple-form: + provider: ... + authenticator: time_authenticator + check_path: login_check + login_path: login + + .. code-block:: xml + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'pattern' => '^/admin', + 'provider' => 'authenticator', + 'simple-form' => array( + 'provider' => ..., + 'authenticator' => 'time_authenticator', + 'check_path' => 'login_check', + 'login_path' => 'login', + ), + ), + ), + )); diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst index a8edbdc4317..c61b279ff3c 100644 --- a/cookbook/security/index.rst +++ b/cookbook/security/index.rst @@ -13,5 +13,6 @@ Security form_login securing_services custom_provider + custom_authenticator custom_authentication_provider target_path From 1bd187fe17c599682da7b0547ed43ab7ddbc196a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 19 Aug 2013 20:10:58 +0200 Subject: [PATCH 0118/1181] fixes thanks to @WouterJ --- cookbook/security/custom_authenticator.rst | 40 +++++++++++++--------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/cookbook/security/custom_authenticator.rst b/cookbook/security/custom_authenticator.rst index 817952489e8..de17f80d7d9 100644 --- a/cookbook/security/custom_authenticator.rst +++ b/cookbook/security/custom_authenticator.rst @@ -1,12 +1,9 @@ .. index:: single: Security; Custom Authenticator -How to create a custom Authenticator +How to create a Custom Authenticator ==================================== -Introduction ------------- - Imagine you want to allow access to your website only between 2pm and 4pm (for the UTC timezone). Before Symfony 2.4, you had to create a custom token, factory, listener and provider. @@ -14,8 +11,8 @@ listener and provider. The Authenticator ----------------- -Thanks to new simplified authentication customization options in Symfony 2.4, -you don't need to create a whole bunch of new classes, but use the +But now, thanks to new simplified authentication customization options in +Symfony 2.4, you don't need to create a whole bunch of new classes, but use the :class:`Symfony\\Component\\Security\\Core\\Authentication\\SimpleFormAuthenticatorInterface` interface instead:: @@ -90,7 +87,7 @@ interface instead:: .. versionadded:: 2.4 The ``SimpleFormAuthenticatorInterface`` interface was added in Symfony 2.4. -How it works +How it Works ------------ There are a lot of things going on: @@ -131,18 +128,26 @@ Now, configure your ``TimeAuthenticator`` as a service: .. code-block:: xml - - - - - + + + + + + + + .. code-block:: php // app/config/config.php use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; + + // ... $container->setDefinition('time_authenticator', new Definition( 'Acme\HelloBundle\Security\TimeAuthenticator', @@ -180,11 +185,12 @@ like this: xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - + + check-path="login_check" + login-path="login" /> From 8ddb26b36960ee35cf654ab61ae263eabbb76409 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 13 Sep 2013 14:09:41 +0200 Subject: [PATCH 0119/1181] clarify the authenticator type --- cookbook/map.rst.inc | 2 +- ....rst => custom_password_authenticator.rst} | 33 ++++++++++++------- cookbook/security/index.rst | 2 +- 3 files changed, 24 insertions(+), 13 deletions(-) rename cookbook/security/{custom_authenticator.rst => custom_password_authenticator.rst} (94%) diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 686620c99f7..e876acec3d3 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -135,7 +135,7 @@ * :doc:`/cookbook/security/form_login` * :doc:`/cookbook/security/securing_services` * :doc:`/cookbook/security/custom_provider` - * :doc:`/cookbook/security/custom_authenticator` + * :doc:`/cookbook/security/custom_password_authenticator` * :doc:`/cookbook/security/custom_authentication_provider` * :doc:`/cookbook/security/target_path` diff --git a/cookbook/security/custom_authenticator.rst b/cookbook/security/custom_password_authenticator.rst similarity index 94% rename from cookbook/security/custom_authenticator.rst rename to cookbook/security/custom_password_authenticator.rst index de17f80d7d9..2560bd52223 100644 --- a/cookbook/security/custom_authenticator.rst +++ b/cookbook/security/custom_password_authenticator.rst @@ -1,15 +1,18 @@ .. index:: - single: Security; Custom Authenticator + single: Security; Custom Password Authenticator -How to create a Custom Authenticator -==================================== +How to create a Custom Password Authenticator +============================================= Imagine you want to allow access to your website only between 2pm and 4pm (for the UTC timezone). Before Symfony 2.4, you had to create a custom token, factory, listener and provider. -The Authenticator ------------------ +The Password Authenticator +-------------------------- + +.. versionadded:: 2.4 + The ``SimpleFormAuthenticatorInterface`` interface was added in Symfony 2.4. But now, thanks to new simplified authentication customization options in Symfony 2.4, you don't need to create a whole bunch of new classes, but use the @@ -84,9 +87,6 @@ interface instead:: } } -.. versionadded:: 2.4 - The ``SimpleFormAuthenticatorInterface`` interface was added in Symfony 2.4. - How it Works ------------ @@ -121,6 +121,8 @@ Now, configure your ``TimeAuthenticator`` as a service: # app/config/config.yml services: + # ... + time_authenticator: class: Acme\HelloBundle\Security\TimeAuthenticator arguments: [@security.encoder_factory] @@ -134,9 +136,12 @@ Now, configure your ``TimeAuthenticator`` as a service: xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + - + class="Acme\HelloBundle\Security\TimeAuthenticator" + > + @@ -185,12 +190,15 @@ like this: xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + + login-path="login" + /> @@ -198,6 +206,9 @@ like this: .. code-block:: php // app/config/security.php + + // .. + $container->loadFromExtension('security', array( 'firewalls' => array( 'secured_area' => array( diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst index c61b279ff3c..6de91f12a88 100644 --- a/cookbook/security/index.rst +++ b/cookbook/security/index.rst @@ -13,6 +13,6 @@ Security form_login securing_services custom_provider - custom_authenticator + custom_password_authenticator custom_authentication_provider target_path From afdb708ded8d4ae88a3a00fbf464279bb0cb5c58 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 13 Sep 2013 17:37:15 +0200 Subject: [PATCH 0120/1181] add example on how to use the new SimplePreAuthenticatorInterface --- cookbook/map.rst.inc | 1 + cookbook/security/api_key_authentication.rst | 208 +++++++++++++++++++ cookbook/security/index.rst | 1 + 3 files changed, 210 insertions(+) create mode 100644 cookbook/security/api_key_authentication.rst diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index e876acec3d3..37d9c9dcf0a 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -136,6 +136,7 @@ * :doc:`/cookbook/security/securing_services` * :doc:`/cookbook/security/custom_provider` * :doc:`/cookbook/security/custom_password_authenticator` + * :doc:`/cookbook/security/api_key_authentication` * :doc:`/cookbook/security/custom_authentication_provider` * :doc:`/cookbook/security/target_path` diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst new file mode 100644 index 00000000000..48aa3f0aa20 --- /dev/null +++ b/cookbook/security/api_key_authentication.rst @@ -0,0 +1,208 @@ +.. index:: + single: Security; Custom Request Authenticator + +How to Authenticate Users with API Keys +======================================= + +Nowadays, it's quite usual to authenticate the user via an API key (when developing +a web service for instance). The API key is provided for every request and is +passed as a query string parameter or via a HTTP header. + +The API Key Authenticator +------------------------- + +.. versionadded:: 2.4 + The ``SimplePreAuthenticatorInterface`` interface was added in Symfony 2.4. + +Authenticating a user based on the Request information should be done via a +pre-authentication mechanism. The :class:`Symfony\\Component\\Security\\Core\\Authentication\\SimplePreAuthenticatorInterface` +interface allows to implement such a scheme really easily:: + + // src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php + namespace Acme\HelloBundle\Security; + + use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface; + use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; + use Symfony\Component\Security\Core\Exception\AuthenticationException; + use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; + use Symfony\Component\HttpFoundation\Request; + use Symfony\Component\Security\Core\User\User; + use Symfony\Component\Security\Core\User\UserProviderInterface; + use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; + use Symfony\Component\Security\Core\Exception\BadCredentialsException; + + class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface + { + protected $userProvider; + + public function __construct(ApiKeyUserProviderInterface $userProvider) + { + $this->userProvider = $userProvider; + } + + public function createToken(Request $request, $providerKey) + { + if (!$request->query->has('apikey')) { + throw new BadCredentialsException('No API key found'); + } + + return new PreAuthenticatedToken( + 'anon.', + $request->query->get('apikey'), + $providerKey + ); + } + + public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) + { + $apikey = $token->getCredentials(); + if (!$this->userProvider->getUsernameForApiKey($apikey)) { + throw new AuthenticationException( + sprintf('API Key "%s" does not exist.', $apikey) + ); + } + + $user = new User( + $this->userProvider->getUsernameForApiKey($apikey), + $apikey, + array('ROLE_USER') + ); + + return new PreAuthenticatedToken( + $user, + $apikey, + $providerKey, + $user->getRoles() + ); + } + + public function supportsToken(TokenInterface $token, $providerKey) + { + return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey; + } + } + +``$userProvider`` can be any user provider implementing an interface similar to +this:: + + // src/Acme/HelloBundle/Security/ApiKeyUserProviderInterface.php + namespace Acme\HelloBundle\Security; + + use Symfony\Component\Security\Core\User\UserProviderInterface; + + interface ApiKeyUserProviderInterface extends UserProviderInterface + { + public function getUsernameForApiKey($apikey); + } + +.. note:: + + Read the dedicated article to learn + :doc:`how to create a custom user provider `. + +To access a resource protected by such an authenticator, you need to add an apikey +parameter to the query string, like in ``http://example.com/admin/foo?apikey=37b51d194a7513e45b56f6524f2d51f2``. + +Configuration +------------- + +Configure your ``ApiKeyAuthenticator`` as a service: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + services: + # ... + + apikey_authenticator: + class: Acme\HelloBundle\Security\ApiKeyAuthenticator + arguments: [@your_api_key_user_provider] + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/config.php + use Symfony\Component\DependencyInjection\Definition; + use Symfony\Component\DependencyInjection\Reference; + + // ... + + $container->setDefinition('apikey_authenticator', new Definition( + 'Acme\HelloBundle\Security\ApiKeyAuthenticator', + array(new Reference('your_api_key_user_provider')) + )); + +Then, activate it in your firewalls section using the ``simple-preauth`` key +like this: + +.. configuration-block:: + + .. code-block:: yaml + + security: + firewalls: + secured_area: + pattern: ^/admin + simple-preauth: + provider: ... + authenticator: apikey_authenticator + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + + // .. + + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'pattern' => '^/admin', + 'provider' => 'authenticator', + 'simple-preauth' => array( + 'provider' => ..., + 'authenticator' => 'apikey_authenticator', + ), + ), + ), + )); diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst index 6de91f12a88..d0856f144cf 100644 --- a/cookbook/security/index.rst +++ b/cookbook/security/index.rst @@ -14,5 +14,6 @@ Security securing_services custom_provider custom_password_authenticator + api_key_authentication custom_authentication_provider target_path From a7b80a6bdb1a2a042d61a97d7b9c8adf0021590f Mon Sep 17 00:00:00 2001 From: Bilal Amarni Date: Tue, 17 Dec 2013 12:49:33 +0100 Subject: [PATCH 0121/1181] [Form] added multiple option to file type doc --- reference/forms/types/file.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/reference/forms/types/file.rst b/reference/forms/types/file.rst index a33dae8d992..03da93ffa78 100644 --- a/reference/forms/types/file.rst +++ b/reference/forms/types/file.rst @@ -9,6 +9,8 @@ The ``file`` type represents a file input in your form. +-------------+---------------------------------------------------------------------+ | Rendered as | ``input`` ``file`` field | +-------------+---------------------------------------------------------------------+ +| Options | - `multiple`_ | ++-------------+---------------------------------------------------------------------+ | Inherited | - `required`_ | | options | - `label`_ | | | - `read_only`_ | @@ -76,6 +78,16 @@ before using it directly. Read the :doc:`cookbook ` for an example of how to manage a file upload associated with a Doctrine entity. +Field Options +------------- + +multiple +~~~~~~~~ + +**type**: ``Boolean`` **default**: ``false`` + +When set to true, the user will be able to upload multiple files at the same time. + Inherited options ----------------- From bf98517e92118e97a53e96fbbd6ec5259cbabc1e Mon Sep 17 00:00:00 2001 From: Bilal Amarni Date: Tue, 17 Dec 2013 12:52:22 +0100 Subject: [PATCH 0122/1181] fixed spaces --- reference/forms/types/file.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/forms/types/file.rst b/reference/forms/types/file.rst index 03da93ffa78..78d08fba3e4 100644 --- a/reference/forms/types/file.rst +++ b/reference/forms/types/file.rst @@ -9,7 +9,7 @@ The ``file`` type represents a file input in your form. +-------------+---------------------------------------------------------------------+ | Rendered as | ``input`` ``file`` field | +-------------+---------------------------------------------------------------------+ -| Options | - `multiple`_ | +| Options | - `multiple`_ | +-------------+---------------------------------------------------------------------+ | Inherited | - `required`_ | | options | - `label`_ | From 110e22b37734ace0c2a97858d00123f38aa53460 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 17 Dec 2013 06:13:23 -0600 Subject: [PATCH 0123/1181] [#2914][WIP] Additions to the new authentication articles The biggest difference is the extension of the API article to give more details about the user provider and to talk about how you might store authentication information in the session. --- cookbook/security/_supportsToken.rst.inc | 10 + cookbook/security/api_key_authentication.rst | 394 ++++++++++++++++-- .../custom_authentication_provider.rst | 9 + .../custom_password_authenticator.rst | 95 +++-- 4 files changed, 446 insertions(+), 62 deletions(-) create mode 100644 cookbook/security/_supportsToken.rst.inc diff --git a/cookbook/security/_supportsToken.rst.inc b/cookbook/security/_supportsToken.rst.inc new file mode 100644 index 00000000000..a199364068e --- /dev/null +++ b/cookbook/security/_supportsToken.rst.inc @@ -0,0 +1,10 @@ +After Symfony calls ``createToken``, it will then call ``supportsToken`` on +your class (and any other authentication listeners) to figure out who should +handle it. This is just a way to allow several authentication mechanisms to +be used for the same firewall (that way, you can for instance first try to +authenticate the user via a certificate or an API key and fall back to a +form login). + +Mostly, you just need to make sure that this method returns ``true`` for a +token that has been created by ``createToken``. Your logic should probably +look exactly like this example. \ No newline at end of file diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index 48aa3f0aa20..26bc5b67bcf 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -6,7 +6,7 @@ How to Authenticate Users with API Keys Nowadays, it's quite usual to authenticate the user via an API key (when developing a web service for instance). The API key is provided for every request and is -passed as a query string parameter or via a HTTP header. +passed as a query string parameter or via an HTTP header. The API Key Authenticator ------------------------- @@ -16,7 +16,11 @@ The API Key Authenticator Authenticating a user based on the Request information should be done via a pre-authentication mechanism. The :class:`Symfony\\Component\\Security\\Core\\Authentication\\SimplePreAuthenticatorInterface` -interface allows to implement such a scheme really easily:: +allows you to implement such a scheme really easily. + +Your exact situation may differ, but in this example, a token is read +from an ``apikey`` query parameter, the proper username is loaded from that +value, and then a User object is created:: // src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php namespace Acme\HelloBundle\Security; @@ -26,7 +30,6 @@ interface allows to implement such a scheme really easily:: use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; use Symfony\Component\HttpFoundation\Request; - use Symfony\Component\Security\Core\User\User; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\BadCredentialsException; @@ -55,22 +58,18 @@ interface allows to implement such a scheme really easily:: public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) { - $apikey = $token->getCredentials(); - if (!$this->userProvider->getUsernameForApiKey($apikey)) { + $apiKey = $token->getCredentials(); + if (!$username = $this->userProvider->getUsernameForApiKey($apiKey)) { throw new AuthenticationException( - sprintf('API Key "%s" does not exist.', $apikey) + sprintf('API Key "%s" does not exist.', $apiKey) ); } - $user = new User( - $this->userProvider->getUsernameForApiKey($apikey), - $apikey, - array('ROLE_USER') - ); + $user = $this->userProvider->loadUserByUsername($username); return new PreAuthenticatedToken( $user, - $apikey, + $apiKey, $providerKey, $user->getRoles() ); @@ -82,17 +81,101 @@ interface allows to implement such a scheme really easily:: } } -``$userProvider`` can be any user provider implementing an interface similar to -this:: +Once you've :ref:`configured ` everything, +you'll be able to authenticate by adding an apikey parameter to the query +string, like ``http://example.com/admin/foo?apikey=37b51d194a7513e45b56f6524f2d51f2``. + +The authentication process has several steps, and your implementation will +probably differ: + +1. createToken +~~~~~~~~~~~~~~ + +Early in the request cycle, Symfony calls ``createToken``. Your job here +is to create a token object that contains all of the information from the +request that you need to authenticate the user (e.g. the ``apikey`` query +parameter). If that information is missing, throwing the +:class:`Symfony\\Component\\Security\\Core\\Exception\\BadCredentialsException` +will cause authentication to fail. + +2. supportsToken +~~~~~~~~~~~~~~~~ + +.. include:: _supportsToken.rst.inc + +3. authenticateToken +~~~~~~~~~~~~~~~~~~~~ + +If ``supportsToken`` returns ``true``, Symfony will now call ``authenticateToken``. +One key part is the ``$userProvider``, which is an external class that helps +you load information about the user. You'll learn more about this next. - // src/Acme/HelloBundle/Security/ApiKeyUserProviderInterface.php +In this specific example, the following things happen in ``authenticateToken``: + +#. First, you use the ``$userProvider`` to somehow look up the ``$username`` that + corresponds to the ``$apiKey``; +#. Second, you use the ``$userProvider`` again to load or create a ``User`` + object for the ``$username``; +#. Finally, you create an *authenticated token* (i.e. a token with at least one + role) that has the proper roles and the User object attached to it. + +The goal is ultimately to use the ``$apiKey`` to find or create a User object. +*How* you do this (e.g. query a database) and the exact class for your User +object may vary. Those differences will be most obvious in your user provider. + +The User Provider +~~~~~~~~~~~~~~~~~ + +The ``$userProvider`` can be any user provider (see +:doc:`how to create a custom user provider `). +In this example, the ``$apiKey`` is used to somehow find the username for +the user. This work is done in a ``getUsernameForApiKey`` method, which is +created entirely custom for our use-case (i.e. this isn't a method that's +used by Symfony's core user provider system). + +The ``$userProvider`` might look something like this:: + + // src/Acme/HelloBundle/Security/ApiKeyUserProvider.php namespace Acme\HelloBundle\Security; use Symfony\Component\Security\Core\User\UserProviderInterface; + use Symfony\Component\Security\Core\User\User; - interface ApiKeyUserProviderInterface extends UserProviderInterface + class ApiKeyUserProvider extends UserProviderInterface { - public function getUsernameForApiKey($apikey); + public function getUsernameForApiKey($apiKey) + { + // Look up the username based on the token in the database, via + // an API call, or do something entirely different + $username = // ... + + return $username; + } + + public function loadUserByUsername($username) + { + return new User( + $username, + null, + // the roles for the user - you may choose to determine + // these dynamically somehow based on the user + array('ROLE_USER') + ); + } + + public function refreshUser(UserInterface $user) + { + // this is used for storing authentication in the session + // but in this example, the token is sent in each request, + // so authentication can be stateless. Throwing this exception + // is proper to make things stateless + throw new UnsupportedUserException(); + } + + public function supportsClass($class) + { + return $class === 'Symfony\Component\Security\Core\User\User'; + } } .. note:: @@ -100,13 +183,38 @@ this:: Read the dedicated article to learn :doc:`how to create a custom user provider `. -To access a resource protected by such an authenticator, you need to add an apikey -parameter to the query string, like in ``http://example.com/admin/foo?apikey=37b51d194a7513e45b56f6524f2d51f2``. +The logic inside ``getUsernameForApiKey`` is up to you. You may somehow transform +the API key (e.g. ``37b51d``) into a username (e.g. ``jondoe``) by looking +up some information in a "token" database table. + +The same is true for ``loadUserByUsername``. In this example, Symfony's core +:class:`Symfony\\Component\\Security\\Core\\User\\User` class is simply created. +This makes sense if you don't need to store any extra information on your +User object (e.g. ``firstName``). But if you do, you may instead have your *own* +user class which you create and populate here by querying a database. This +would allow you to have custom data on the User object. + +Finally, just make sure that ``supportsClass`` return ``true`` for User +objects with the same class as whatever user you return in ``loadUserByUsername``. +If your authentication is stateless like in this example (i.e. you expect +the user to send the API key with every request and so you don't save the +login to the session), then you can simply throw the ``UnsupportedUserException`` +exception in ``refreshUser``. + +.. note:: + + If you *do* want to store authentication data in the session so that + the key doesn't need to be sent on every request, see :ref:`cookbook-security-api-key-session`. + +.. _cookbook-security-api-key-config: Configuration ------------- -Configure your ``ApiKeyAuthenticator`` as a service: +Once you have your ``ApiKeyAuthentication`` all setup, you need to register +it as a service and use it in ``security.yml``. First, register it as a service. +This assumes that you have already setup your custom user provider as a service +called ``your_api_key_user_provider`` (see :doc:`/cookbook/security/custom_provider`). .. configuration-block:: @@ -118,7 +226,7 @@ Configure your ``ApiKeyAuthenticator`` as a service: apikey_authenticator: class: Acme\HelloBundle\Security\ApiKeyAuthenticator - arguments: [@your_api_key_user_provider] + arguments: ["@your_api_key_user_provider"] .. code-block:: xml @@ -152,20 +260,23 @@ Configure your ``ApiKeyAuthenticator`` as a service: array(new Reference('your_api_key_user_provider')) )); -Then, activate it in your firewalls section using the ``simple-preauth`` key -like this: +Now, activate it in the ``firewalls`` section of ``security.yml`` using the +``simple_preauth`` key: .. configuration-block:: .. code-block:: yaml + # app/config/security.yml security: - firewalls: - secured_area: - pattern: ^/admin - simple-preauth: - provider: ... - authenticator: apikey_authenticator + # ... + + firewalls: + secured_area: + pattern: ^/admin + stateless: true + simple_preauth: + authenticator: apikey_authenticator .. code-block:: xml @@ -181,7 +292,7 @@ like this: @@ -198,11 +309,228 @@ like this: 'firewalls' => array( 'secured_area' => array( 'pattern' => '^/admin', - 'provider' => 'authenticator', - 'simple-preauth' => array( - 'provider' => ..., + 'stateless' => true, + 'simple_preauth' => array( 'authenticator' => 'apikey_authenticator', ), ), ), )); + +That's it! Now, your ``ApiKeyAuthentication`` should be called at the beginning +of each request and your authentication process will take place. + +The ``stateless`` configuration parameter prevents Symfony from trying to +store the authentication information in the session, which isn't necessary +since the client will send the ``apikey`` on each request. If you *do* need +to store authentication in the session, keep reading! + +.. _cookbook-security-api-key-session: + +Storing Authentication in the Session +------------------------------------- + +So far, this entry has described a situation where some sort of authentication +token is sent on every request. But in some situations (like an OAuth flow), +the token may be sent on only *one* request. In this case, you will want to +authenticate the user and store that authentication in the session so that +the user is automatically logged in for every subsequent request. + +To make this work, first remove the ``stateless`` key from your firewall +configuration or set it to ``false``: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + security: + # ... + + firewalls: + secured_area: + pattern: ^/admin + stateless: false + simple_preauth: + authenticator: apikey_authenticator + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + + // .. + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'pattern' => '^/admin', + 'stateless' => false, + 'simple_preauth' => array( + 'authenticator' => 'apikey_authenticator', + ), + ), + ), + )); + +Storing authentication information in the session works like this: + +#. At the end of each request, Symfony serializes the token object (returned + from ``authenticateToken``), which also serializes the User object (since + it's set on a property on the token); +#. On the next request the token is deserialized and the deserialized User + object is passed to the ``refreshUser`` function of the user provider. + +The second step is the important one: Symfony calls ``refreshUser`` and passes +you the user object that was serialized in the session. If your users are +stored in the database, then you may want to re-query for a fresh version +of the user to make sure it's not out-of-date. But regardless of your requirements, +``refreshUser`` should now return the User object:: + + // src/Acme/HelloBundle/Security/ApiKeyUserProvider.php + + // ... + + class ApiKeyUserProvider extends UserProviderInterface + { + // ... + + public function refreshUser(UserInterface $user) + { + // $user is the User that you set in the token inside authenticateToken + // after it has been deserialized from the session + + // you might use $user to query the database for a fresh user + $id = $user->getId(); + // use $id to make a query + + // if you are *not* reading from a database and are just creating + // a User object (like in this example), you can just return it + return $user; + } + } + +.. note:: + + You'll also want to make sure that your User object is being serialized + correctly. If your User object has private properties, PHP can't serialize + those. In this case, you may get back a User object that has a ``null`` + value for each property. For an example, see :doc:`/cookbook/security/entity_provider`. + +Only Authenticating for certain URLs +------------------------------------ + +This entry has assumed that you want to look for the ``apikey`` authentication +on *every* request. But in some situations (like an OAuth flow), you only +really need to look for authentication information once the user has reached +a certain URL (e.g. the redirect URL in OAuth). + +Fortunately, handling this situation is easy: just check to see what the +current URL is before creating the token in ``createToken``:: + + // src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php + + // ... + use Symfony\Component\Security\Http\HttpUtils; + + class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface + { + protected $userProvider; + + protected $httpUtils; + + public function __construct(ApiKeyUserProviderInterface $userProvider, HttpUtils $httpUtils) + { + $this->userProvider = $userProvider; + $this->httpUtils = $httpUtils; + } + + public function createToken(Request $request, $providerKey) + { + // set the only URL where we should look for auth information + // and only return the token if we're at that URL + $targetUrl = '/login/check'; + if (!$this->httpUtils->checkRequestPath($request, $targetUrl)) { + return; + } + + // ... + } + } + +This uses a handy :class:`Symfony\\Component\\Security\\Http\\HttpUtils` +class to see if the current URL matches the URL you're looking for. In this +case, the URL (``/login/check``) has been hardcoded in the class, but you +could also inject it as the third constructor argument. + +Next, just update your service configuration to inject the ``security.http_utils`` +service: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + services: + # ... + + apikey_authenticator: + class: Acme\HelloBundle\Security\ApiKeyAuthenticator + arguments: ["@your_api_key_user_provider", "@security.http_utils"] + + .. code-block:: xml + + + + + + + + + + + + + + + .. code-block:: php + + // app/config/config.php + use Symfony\Component\DependencyInjection\Definition; + use Symfony\Component\DependencyInjection\Reference; + + // ... + + $container->setDefinition('apikey_authenticator', new Definition( + 'Acme\HelloBundle\Security\ApiKeyAuthenticator', + array( + new Reference('your_api_key_user_provider'), + new Reference('security.http_utils') + ) + )); + +That's it! Have fun! diff --git a/cookbook/security/custom_authentication_provider.rst b/cookbook/security/custom_authentication_provider.rst index 009d34a401a..8b67ea391de 100644 --- a/cookbook/security/custom_authentication_provider.rst +++ b/cookbook/security/custom_authentication_provider.rst @@ -4,6 +4,15 @@ How to create a custom Authentication Provider ============================================== +.. tip:: + + Creating a custom authentication system is hard, and this entry will walk + you through that process. But depending on your needs, you may be able + to use solve your problem in a simpler way using these documents: + + * :doc:`/cookbook/security/custom_password_authenticator` + * :doc:`/cookbook/security/api_key_authentication` + If you have read the chapter on :doc:`/book/security`, you understand the distinction Symfony2 makes between authentication and authorization in the implementation of security. This chapter discusses the core classes involved diff --git a/cookbook/security/custom_password_authenticator.rst b/cookbook/security/custom_password_authenticator.rst index 2560bd52223..ef9f9be035f 100644 --- a/cookbook/security/custom_password_authenticator.rst +++ b/cookbook/security/custom_password_authenticator.rst @@ -1,12 +1,13 @@ .. index:: single: Security; Custom Password Authenticator -How to create a Custom Password Authenticator -============================================= +How to create a Custom Form Password Authenticator +================================================== -Imagine you want to allow access to your website only between 2pm and 4pm (for -the UTC timezone). Before Symfony 2.4, you had to create a custom token, factory, -listener and provider. +Imagine you want to allow access to your website only between 2pm and 4pm +UTC. Before Symfony 2.4, you had to create a custom token, factory, listener +and provider. In this entry, you'll learn how to do this for a login form +(i.e. where your user submits their username and password). The Password Authenticator -------------------------- @@ -14,10 +15,10 @@ The Password Authenticator .. versionadded:: 2.4 The ``SimpleFormAuthenticatorInterface`` interface was added in Symfony 2.4. -But now, thanks to new simplified authentication customization options in -Symfony 2.4, you don't need to create a whole bunch of new classes, but use the -:class:`Symfony\\Component\\Security\\Core\\Authentication\\SimpleFormAuthenticatorInterface` -interface instead:: +First, create a new class that implements +:class:`Symfony\\Component\\Security\\Core\\Authentication\\SimpleFormAuthenticatorInterface`. +Eventually, this will allow you to create custom logic for authenticating +the user:: // src/Acme/HelloBundle/Security/TimeAuthenticator.php namespace Acme\HelloBundle\Security; @@ -90,18 +91,43 @@ interface instead:: How it Works ------------ -There are a lot of things going on: +Great! Now you just need to setup some :ref:`cookbook-security-password-authenticator-config`. +But first, you can find out more about what each method in this class does. -* ``createToken()`` creates a Token that will be used to authenticate the user; -* ``authenticateToken()`` checks that the Token is allowed to log in by first - getting the User via the user provider and then, by checking the password - and the current time (a Token with roles is authenticated); -* ``supportsToken()`` is just a way to allow several authentication mechanisms to - be used for the same firewall (that way, you can for instance first try to - authenticate the user via a certificate or an API key and fall back to a - form login); -* An encoder is needed to check the user password's validity; this is a - service provided by default:: +1) createToken +~~~~~~~~~~~~~~ + +When Symfony begins handling a request, ``createToken`` is called, where +you create a :class:`Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface` +object that contains whatever information you need in ``authenticateToken`` +to authenticate the user (e.g. the username and password). + +Whatever token object you create here will be passed to you later in ``authenticateToken``. + +2) supportsToken +~~~~~~~~~~~~~~~~ + +.. include:: _supportsToken.rst.inc + +3) authenticateToken +~~~~~~~~~~~~~~~~~~~~ + +If ``supportsToken`` returns ``true``, Symfony will now call ``authenticateToken``. +Your job here is to checks that the token is allowed to log in by first +getting the User object via the user provider and then, by checking the password +and the current time. + +.. note:: + + The "flow" of how you get the User object and determine whether or not + the token is valid (e.g. checking the password), may vary based on your + requirements. + +Ultimately, your job is to return a *new* token object that is "authenticated" +(i.e. it has at least 1 role set on it) and which has the User object inside +of it. + +Inside this method, an encoder is needed to check the password's validity:: $encoder = $this->encoderFactory->getEncoder($user); $passwordValid = $encoder->isPasswordValid( @@ -110,6 +136,12 @@ There are a lot of things going on: $user->getSalt() ); +This is a service that is already available in Symfony and the password algorithm +is configured in ``security.yml`` under the ``encoders`` key. Below, you'll +see how to inject that into the ``TimeAuthenticator``. + +.. _cookbook-security-password-authenticator-config: + Configuration ------------- @@ -125,7 +157,7 @@ Now, configure your ``TimeAuthenticator`` as a service: time_authenticator: class: Acme\HelloBundle\Security\TimeAuthenticator - arguments: [@security.encoder_factory] + arguments: ["@security.encoder_factory"] .. code-block:: xml @@ -159,8 +191,8 @@ Now, configure your ``TimeAuthenticator`` as a service: array(new Reference('security.encoder_factory')) )); -Then, activate it in your ``firewalls`` section using the ``simple-form`` key -like this: +Then, activate it in the ``firewalls`` section of ``security.yml`` using +the ``simple_form`` key: .. configuration-block:: @@ -173,9 +205,8 @@ like this: firewalls: secured_area: pattern: ^/admin - provider: authenticator - simple-form: - provider: ... + # ... + simple_form: authenticator: time_authenticator check_path: login_check login_path: login @@ -194,7 +225,7 @@ like this: + > array( 'secured_area' => array( 'pattern' => '^/admin', - 'provider' => 'authenticator', - 'simple-form' => array( + 'simple_form' => array( 'provider' => ..., 'authenticator' => 'time_authenticator', 'check_path' => 'login_check', @@ -223,3 +253,10 @@ like this: ), ), )); + +The ``simple_form`` key has the same options as the normal ``form_login`` +option, but with the additional ``authenticator`` key that points to the +new service. For details, see :ref:`reference-security-firewall-form-login`. + +If creating a login form in general is new to you or you don't understand +the ``check_path`` or ``login_path`` options, see :doc:`/cookbook/security/form_login`. From 827014eea11d20931683d98968ce6bd659e44555 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Fri, 13 Sep 2013 21:42:44 +0100 Subject: [PATCH 0124/1181] Documented xml namespace autodiscovery. --- components/dom_crawler.rst | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index 61f28d37e95..65cdd93eb38 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -95,6 +95,52 @@ To remove a node the anonymous function must return false. All filter methods return a new :class:`Symfony\\Component\\DomCrawler\\Crawler` instance with filtered content. +Both :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath` and +:method:`Symfony\\Component\\DomCrawler\\Crawler::filter` methods work with +XML namespaces, which are automatically registered. + +.. versionadded:: 2.4 + Auto discovery of namespaces was introduced in Symfony 2.4. + +Consider an XML below: + + + + tag:youtube.com,2008:video:kgZRZmEc9j4 + + + + Chordates - CrashCourse Biology #24 + widescreen + + + +It can be filtered with ``DomCrawler`` without a need to register namespace +aliases both with :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath`:: + + $crawler = $crawler->filterXPath('//default:entry/media:group//yt:aspectRatio'); + +and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter`:: + + use Symfony\Component\CssSelector\CssSelector; + + CssSelector::disableHtmlExtension(); + $crawler = $crawler->filter('default|entry media|group yt|aspectRatio'); + +.. note:: + + The default namespace is registered with a name "default". + +.. caution:: + + To query an XML with a CSS selector, the HTML extension needs to be disabled with + :method:`Symfony\\Component\\CssSelector\\CssSelector::disableHtmlExtension` + to avoid converting the selector to lowercase. + + Node Traversing ~~~~~~~~~~~~~~~ From 47bc7dc258189b55dd74f9618b14ab0d348ce7f2 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Wed, 18 Sep 2013 13:22:31 +0100 Subject: [PATCH 0125/1181] Documented changing of default namespace prefix. --- components/dom_crawler.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index 65cdd93eb38..17d4a8fc2b2 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -132,7 +132,9 @@ and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter`:: .. note:: - The default namespace is registered with a name "default". + The default namespace is registered with a prefix "default". It can be + changed with the + :method:`Symfony\\Component\\DomCrawler\\Crawler::setDefaultNamespacePrefix`. .. caution:: From 68fa18e8fc53924e32fe77f28e02950ce28088cd Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Sun, 22 Sep 2013 23:41:41 +0100 Subject: [PATCH 0126/1181] Documented explicit namespace registration. --- components/dom_crawler.rst | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index 17d4a8fc2b2..0062a4bbd7c 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -97,10 +97,12 @@ To remove a node the anonymous function must return false. Both :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath` and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter` methods work with -XML namespaces, which are automatically registered. +XML namespaces, which can be either automatically discovered or registered +explicitly. .. versionadded:: 2.4 - Auto discovery of namespaces was introduced in Symfony 2.4. + Auto discovery and explicit registration of namespaces was introduced + in Symfony 2.4. Consider an XML below: @@ -136,13 +138,18 @@ and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter`:: changed with the :method:`Symfony\\Component\\DomCrawler\\Crawler::setDefaultNamespacePrefix`. +Namespaces can be explicitly registered with the +:method:`Symfony\\Component\\DomCrawler\\Crawler::registerNamespace`:: + + $crawler->registerNamespace('m', 'http://search.yahoo.com/mrss/'); + $crawler = $crawler->filterXPath('//m:group//yt:aspectRatio'); + .. caution:: To query an XML with a CSS selector, the HTML extension needs to be disabled with :method:`Symfony\\Component\\CssSelector\\CssSelector::disableHtmlExtension` to avoid converting the selector to lowercase. - Node Traversing ~~~~~~~~~~~~~~~ From baec6deae76d311a0f41d2dde232c1bf5f8a4c72 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 16 Dec 2013 22:25:11 +0000 Subject: [PATCH 0127/1181] Added a note about removing the default namespace. --- components/dom_crawler.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index 0062a4bbd7c..af4cc3f93d0 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -138,6 +138,9 @@ and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter`:: changed with the :method:`Symfony\\Component\\DomCrawler\\Crawler::setDefaultNamespacePrefix`. + The default namespace is removed when loading the content if it's the only + namespace in the document. It's done to simplify the xpath queries. + Namespaces can be explicitly registered with the :method:`Symfony\\Component\\DomCrawler\\Crawler::registerNamespace`:: From daf5d3c8776531cd7f60fe4078ab84eff16852e1 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 17 Dec 2013 11:29:48 -0600 Subject: [PATCH 0128/1181] [#2979] Minor tweaks --- components/dom_crawler.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index af4cc3f93d0..568f0202417 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -95,7 +95,7 @@ To remove a node the anonymous function must return false. All filter methods return a new :class:`Symfony\\Component\\DomCrawler\\Crawler` instance with filtered content. -Both :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath` and +Both the :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath` and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter` methods work with XML namespaces, which can be either automatically discovered or registered explicitly. @@ -104,7 +104,7 @@ explicitly. Auto discovery and explicit registration of namespaces was introduced in Symfony 2.4. -Consider an XML below: +Consider the XML below: -It can be filtered with ``DomCrawler`` without a need to register namespace +This can be filtered with the ``Crawler`` without needing to register namespace aliases both with :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath`:: $crawler = $crawler->filterXPath('//default:entry/media:group//yt:aspectRatio'); @@ -136,21 +136,22 @@ and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter`:: The default namespace is registered with a prefix "default". It can be changed with the - :method:`Symfony\\Component\\DomCrawler\\Crawler::setDefaultNamespacePrefix`. + :method:`Symfony\\Component\\DomCrawler\\Crawler::setDefaultNamespacePrefix` + method. The default namespace is removed when loading the content if it's the only namespace in the document. It's done to simplify the xpath queries. Namespaces can be explicitly registered with the -:method:`Symfony\\Component\\DomCrawler\\Crawler::registerNamespace`:: +:method:`Symfony\\Component\\DomCrawler\\Crawler::registerNamespace` method:: $crawler->registerNamespace('m', 'http://search.yahoo.com/mrss/'); $crawler = $crawler->filterXPath('//m:group//yt:aspectRatio'); .. caution:: - To query an XML with a CSS selector, the HTML extension needs to be disabled with - :method:`Symfony\\Component\\CssSelector\\CssSelector::disableHtmlExtension` + To query XML with a CSS selector, the HTML extension needs to be disabled with + :method:`CssSelector::disableHtmlExtension ` to avoid converting the selector to lowercase. Node Traversing From 14c538217b32d47833e02281c85c4c0d48fe5b8a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 15 Sep 2013 15:17:31 +0200 Subject: [PATCH 0129/1181] document how to restrict a firewall to a specific host --- cookbook/map.rst.inc | 1 + cookbook/security/host_restriction.rst | 62 ++++++++++++++++++++++++++ cookbook/security/index.rst | 1 + 3 files changed, 64 insertions(+) create mode 100644 cookbook/security/host_restriction.rst diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 37d9c9dcf0a..92c7bdc8957 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -132,6 +132,7 @@ * :doc:`/cookbook/security/acl` * :doc:`/cookbook/security/acl_advanced` * :doc:`/cookbook/security/force_https` + * :doc:`/cookbook/security/host_restriction` * :doc:`/cookbook/security/form_login` * :doc:`/cookbook/security/securing_services` * :doc:`/cookbook/security/custom_provider` diff --git a/cookbook/security/host_restriction.rst b/cookbook/security/host_restriction.rst new file mode 100644 index 00000000000..fcb2960651b --- /dev/null +++ b/cookbook/security/host_restriction.rst @@ -0,0 +1,62 @@ +.. index:: + single: Security; Restrict Security Firewalls to a Host + +How to restrict Firewalls to a Specific Host +============================================ + +.. versionadded:: 2.4 + Support for restricting security firewalls to a specific host was added in + Symfony 2.4. + +When using the Security component, you can create firewalls that match certain +url patterns and thereby restrict access to all urls matching these patterns. +Additionally, you can restrict a firewall to a host using the ``host`` key: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + + # ... + + security: + firewalls: + secured_area: + pattern: ^/ + host: admin\.example\.com + http_basic: true + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + + // ... + + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'pattern' => '^/', + 'host' => 'admin.example.com', + 'http_basic' => true, + ), + ), + )); diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst index d0856f144cf..e9cad89cb50 100644 --- a/cookbook/security/index.rst +++ b/cookbook/security/index.rst @@ -10,6 +10,7 @@ Security acl acl_advanced force_https + host_restriction form_login securing_services custom_provider From 0a9241d1756aba87382b6b325a06481824fe5461 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 17 Dec 2013 11:35:03 -0600 Subject: [PATCH 0130/1181] [#2953][#2986] Tweaks to firewall hostname Biggest change is to clarify that matching a firewall has no guarantee (is unrelated) to whether or not access is restricted. Also, fixed up some of the regex. --- cookbook/security/host_restriction.rst | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/cookbook/security/host_restriction.rst b/cookbook/security/host_restriction.rst index fcb2960651b..9ac7a294a8e 100644 --- a/cookbook/security/host_restriction.rst +++ b/cookbook/security/host_restriction.rst @@ -1,7 +1,7 @@ .. index:: single: Security; Restrict Security Firewalls to a Host -How to restrict Firewalls to a Specific Host +How to Restrict Firewalls to a Specific Host ============================================ .. versionadded:: 2.4 @@ -9,8 +9,9 @@ How to restrict Firewalls to a Specific Host Symfony 2.4. When using the Security component, you can create firewalls that match certain -url patterns and thereby restrict access to all urls matching these patterns. -Additionally, you can restrict a firewall to a host using the ``host`` key: +URL patterns and therefore are activated for all pages whose URL matches +that pattern. Additionally, you can restrict the initialization of a firewall +to a host using the ``host`` key: .. configuration-block:: @@ -24,7 +25,7 @@ Additionally, you can restrict a firewall to a host using the ``host`` key: firewalls: secured_area: pattern: ^/ - host: admin\.example\.com + host: ^admin\.example\.com$ http_basic: true .. code-block:: xml @@ -39,7 +40,7 @@ Additionally, you can restrict a firewall to a host using the ``host`` key: - + @@ -55,8 +56,15 @@ Additionally, you can restrict a firewall to a host using the ``host`` key: 'firewalls' => array( 'secured_area' => array( 'pattern' => '^/', - 'host' => 'admin.example.com', + 'host' => '^admin\.example\.com$', 'http_basic' => true, ), ), )); + +The ``host`` (like the ``path``) is a regular expression. In this example, +the firewall will only be activated if the host is equal exactly (due to +the ``^`` and ``$`` regex characters) to the hostname ``admin.example.com``. +If the hostname does not match this pattern, the firewall will not be activated +and subsequent firewalls will have the opportunity to be matched for this +request. From 77455c94b4b3884f88c79032bbcdf0e4e0bc0439 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 17 Dec 2013 16:29:26 -0600 Subject: [PATCH 0131/1181] [#2986] Fix thanks to @WouterJ --- cookbook/security/host_restriction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/host_restriction.rst b/cookbook/security/host_restriction.rst index 9ac7a294a8e..232f1cd5ff6 100644 --- a/cookbook/security/host_restriction.rst +++ b/cookbook/security/host_restriction.rst @@ -62,7 +62,7 @@ to a host using the ``host`` key: ), )); -The ``host`` (like the ``path``) is a regular expression. In this example, +The ``host`` (like the ``pattern``) is a regular expression. In this example, the firewall will only be activated if the host is equal exactly (due to the ``^`` and ``$`` regex characters) to the hostname ``admin.example.com``. If the hostname does not match this pattern, the firewall will not be activated From e6728fe719845d6d301fa5cb429df55662b6b484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Unai=20Rold=C3=A1n=20Arellano?= Date: Wed, 18 Dec 2013 19:52:53 +0100 Subject: [PATCH 0132/1181] Update composer installation command The actual command have a reference to 2.3.* version --- book/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/installation.rst b/book/installation.rst index 5e311dc6685..1eef13e5570 100644 --- a/book/installation.rst +++ b/book/installation.rst @@ -57,7 +57,7 @@ Distribution: .. code-block:: bash - $ php composer.phar create-project symfony/framework-standard-edition /path/to/webroot/Symfony 2.3.* + $ php composer.phar create-project symfony/framework-standard-edition /path/to/webroot/Symfony 2.4.* .. tip:: From 2ebb4bfa2cc7ba214a6f215f2e8790341fcd3f79 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 18 Dec 2013 19:06:45 +0100 Subject: [PATCH 0133/1181] adding XML code block --- components/dom_crawler.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index 568f0202417..690f0de90e0 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -106,11 +106,14 @@ explicitly. Consider the XML below: +.. code-block:: xml + + xmlns="http://www.w3.org/2005/Atom" + xmlns:media="http://search.yahoo.com/mrss/" + xmlns:yt="http://gdata.youtube.com/schemas/2007" + > tag:youtube.com,2008:video:kgZRZmEc9j4 From abc3a188005090c48ef8e2bb3392566cd70e73e1 Mon Sep 17 00:00:00 2001 From: "I. Fournier" Date: Thu, 19 Dec 2013 11:47:06 +0100 Subject: [PATCH 0134/1181] Update process.rst This method was initially named flush but was changed to clear --- components/process.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/process.rst b/components/process.rst index bb8ad25df54..7680dc7adfa 100644 --- a/components/process.rst +++ b/components/process.rst @@ -46,11 +46,11 @@ and :method:`Symfony\\Component\\Process\\Process::getIncrementalErrorOutput` methods returns the new outputs since the last call. .. versionadded:: 2.4 - The ``flushOutput()`` and ``flushErrorOutput()`` methods were added in Symfony 2.4. + The ``clearOutput()`` and ``clearErrorOutput()`` methods were added in Symfony 2.4. -The :method:`Symfony\\Component\\Process\\Process::flushOutput` method flushes +The :method:`Symfony\\Component\\Process\\Process::clearOutput` method clears the contents of the output and -:method:`Symfony\\Component\\Process\\Process::flushErrorOutput` flushes +:method:`Symfony\\Component\\Process\\Process::clearErrorOutput` clears the contents of the error output. Getting real-time Process Output From d86e542abe3131edd1f2e2b88563b732ef84464d Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 19 Dec 2013 12:43:09 -0500 Subject: [PATCH 0135/1181] [#3315] Adding a little bit more information about the $arguments argument --- components/expression_language/extending.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/expression_language/extending.rst b/components/expression_language/extending.rst index d3b278c627b..8d52ba2bb59 100644 --- a/components/expression_language/extending.rst +++ b/components/expression_language/extending.rst @@ -50,7 +50,10 @@ This method has 3 arguments: echo $language->evaluate('lowercase("HELLO")'); -This will print ``hello``. +This will print ``hello``. Both the **compiler** and **evaluator** are passed +an ``arguments`` variable as their first argument, which is equal to the +second argument to ``evaluate()`` or ``compile()`` (e.g. the "values" when +evaluating or the "names" if compiling). Creating a new ExpressionLanguage Class --------------------------------------- From 2a10a46c9dc1709fd926d2d79490b365bbaf00df Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 23 Dec 2013 17:37:35 -0500 Subject: [PATCH 0136/1181] [#3319] Linking to the whole method --- cookbook/security/acl_advanced.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cookbook/security/acl_advanced.rst b/cookbook/security/acl_advanced.rst index 45d164aa29c..163760c1a80 100644 --- a/cookbook/security/acl_advanced.rst +++ b/cookbook/security/acl_advanced.rst @@ -48,9 +48,9 @@ your application. Each role, or user has its own security identity. .. versionadded:: 2.5 For users, the security identity is based on the username. This means that, if for any reason, a user's username was to change, you must ensure its - security identity is updated too. The method ``updateUserSecurityIdentity`` - of the :class:`Symfony\\Component\\Security\\Acl\\Dbal\\MutableAclProvider` - class is there to handle the update. + security identity is updated too. The + :method:`MutableAclProvider::updateUserSecurityIdentity ` + ``updateUserSecurityIdentity`` method is there to handle the update. Database Table Structure ------------------------ From 2cbca5f03c71f59792e6f43d39aad3c4d539964c Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 23 Dec 2013 17:44:18 -0500 Subject: [PATCH 0137/1181] Removing versionadded 2.1 from merge --- reference/forms/types/options/disabled.rst.inc | 3 --- 1 file changed, 3 deletions(-) diff --git a/reference/forms/types/options/disabled.rst.inc b/reference/forms/types/options/disabled.rst.inc index 89e8177a6e3..130b7d7f6b3 100644 --- a/reference/forms/types/options/disabled.rst.inc +++ b/reference/forms/types/options/disabled.rst.inc @@ -1,9 +1,6 @@ disabled ~~~~~~~~ -.. versionadded:: 2.1 - The ``disabled`` option is new in version 2.1 - **type**: ``boolean`` **default**: ``false`` If you don't want a user to modify the value of a field, you can set From 34551d2cd380d8cf32988bea0e6ed4000607884d Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 26 Dec 2013 10:34:20 -0500 Subject: [PATCH 0138/1181] [#3319] Fixing typos thanks to @xabbuh --- cookbook/security/acl_advanced.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook/security/acl_advanced.rst b/cookbook/security/acl_advanced.rst index 163760c1a80..01228220bb6 100644 --- a/cookbook/security/acl_advanced.rst +++ b/cookbook/security/acl_advanced.rst @@ -49,8 +49,8 @@ your application. Each role, or user has its own security identity. For users, the security identity is based on the username. This means that, if for any reason, a user's username was to change, you must ensure its security identity is updated too. The - :method:`MutableAclProvider::updateUserSecurityIdentity ` - ``updateUserSecurityIdentity`` method is there to handle the update. + :method:`MutableAclProvider::updateUserSecurityIdentity() ` + method is there to handle the update. Database Table Structure ------------------------ From 4834b7739f1e1bda169f75f62d211e3ca665cfee Mon Sep 17 00:00:00 2001 From: Tom Van Looy Date: Sat, 14 Dec 2013 17:50:28 +0100 Subject: [PATCH 0139/1181] How to Configure Monolog to display Console messages --- components/console/introduction.rst | 8 ++ cookbook/logging/index.rst | 1 + cookbook/logging/monolog.rst | 4 +- cookbook/logging/monolog_console.rst | 176 +++++++++++++++++++++++++++ cookbook/map.rst.inc | 1 + reference/configuration/monolog.rst | 11 ++ 6 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 cookbook/logging/monolog_console.rst diff --git a/components/console/introduction.rst b/components/console/introduction.rst index 6af03289796..6f60f2e7512 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -160,6 +160,8 @@ You can also set these colors and options inside the tagname:: // bold text on a yellow background $output->writeln('foo'); +.. verbosity-levels: + Verbosity Levels ~~~~~~~~~~~~~~~~ @@ -226,6 +228,11 @@ When the quiet level is used, all output is suppressed as the default :method:`Symfony\Component\Console\Output::write ` method returns without actually printing. +.. tip:: + + You can use `MonologBundle`_ 2.4 to display messages on the console. This + is cleaner than wrapping your output calls in conditions (see :doc:/cookbook/logging/monolog_console). + Using Command Arguments ----------------------- @@ -520,3 +527,4 @@ Learn More! .. _Packagist: https://packagist.org/packages/symfony/console .. _ANSICON: https://github.com/adoxa/ansicon/downloads +.. _MonologBundle: https://github.com/symfony/MonologBundle diff --git a/cookbook/logging/index.rst b/cookbook/logging/index.rst index dda7d7cafdd..2570b3d5627 100644 --- a/cookbook/logging/index.rst +++ b/cookbook/logging/index.rst @@ -6,5 +6,6 @@ Logging monolog monolog_email + monolog_console monolog_regex_based_excludes channels_handlers diff --git a/cookbook/logging/monolog.rst b/cookbook/logging/monolog.rst index 32e064598e1..c2c6559dd75 100644 --- a/cookbook/logging/monolog.rst +++ b/cookbook/logging/monolog.rst @@ -23,8 +23,7 @@ your controller:: } The ``logger`` service has different methods for different logging levels. -See :class:`Symfony\\Component\\HttpKernel\\Log\\LoggerInterface` for details -on which methods are available. +See LoggerInterface_ for details on which methods are available. Handlers and Channels: Writing logs to different Locations ---------------------------------------------------------- @@ -351,3 +350,4 @@ using a processor. handler level instead of globally. .. _Monolog: https://github.com/Seldaek/monolog +.. _LoggerInterface: https://github.com/php-fig/log/blob/master/Psr/Log/LoggerInterface.php diff --git a/cookbook/logging/monolog_console.rst b/cookbook/logging/monolog_console.rst new file mode 100644 index 00000000000..358bd5bee2a --- /dev/null +++ b/cookbook/logging/monolog_console.rst @@ -0,0 +1,176 @@ +.. index:: + single: Logging; Console messages + +How to Configure Monolog to Display Console Messages +==================================================== + +It is possible to use the console to print messages for a certain :ref:`verbosity-levels` +using the :class:`Symfony\\Component\\Console\\Output\\OutputInterface` +instance that is passed when a command gets executed. + +When a lot of logging has to happen, it's cumbersome to print information +depending on the verbosity settings (``-v``, ``-vv``, ``-vvv``) because the +calls need to be wrapped in conditions. The code quickly gets verbose or dirty. +For example:: + + use Symfony\Component\Console\Input\InputInterface; + use Symfony\Component\Console\Output\OutputInterface; + + protected function execute(InputInterface $input, OutputInterface $output) + { + if ($output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) { + $output->writeln('Some info'); + } + + if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) { + $output->writeln('Some more info'); + } + } + +Instead of using these semantic methods to test for each of the verbosity +levels, `MonologBundle`_ 2.4 provides a `ConsoleHandler`_ that listens to +console events and writes log messages to the console output depending on the +current log level and the console verbosity. + +The example above could then be rewritten as:: + + use Symfony\Component\Console\Input\InputInterface; + use Symfony\Component\Console\Output\OutputInterface; + + protected function execute(InputInterface $input, OutputInterface $output) + { + $logger->debug('Some info'); + + $logger->notice('Some more info'); + } + +These messages will get displayed on the console, timestamped, colored +depending on the log level and error logs are written to the error output +(php://stderr). There is no need to conditionally handle the verbosity +settings anymore. + +The Monolog console handler is enabled in the Monolog configuration. This is +the default in Symfony Standard Edition 2.4 too. + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + monolog: + handlers: + console: + type: console + + .. code-block:: xml + + + + + + + + + + + .. code-block:: php + + // app/config/config.php + $container->loadFromExtension('monolog', array( + 'handlers' => array( + 'console' => array( + 'type' => 'console', + ), + ), + )); + +With the ``verbosity_levels`` option you can adapt the mapping between +verbosity and log level. In the given example it will also show notices in +normal verbosity mode (instead of warnings only). Additionally, it will only +use messages logged with the custom ``my_channel`` channel and it changes the +display style via a custom formatter. See also the :doc:`reference/configuration/monolog` +for more information: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + monolog: + handlers: + console: + type: console + verbosity_levels: + VERBOSITY_NORMAL: NOTICE + channels: my_channel + formatter: my_formatter + + .. code-block:: xml + + + + + + + + + my_channel + + + + + .. code-block:: php + + // app/config/config.php + $container->loadFromExtension('monolog', array( + 'handlers' => array( + 'console' => array( + 'type' => 'console', + 'verbosity_levels' => array( + 'VERBOSITY_NORMAL' => 'NOTICE', + ), + 'channels' => 'my_channel', + 'formatter' => 'my_formatter', + ), + ), + )); + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/services.yml + services: + my_formatter: + class: Symfony\Bridge\Monolog\Formatter\ConsoleFormatter + arguments: + - "[%%datetime%%] %%start_tag%%%%message%%%%end_tag%% (%%level_name%%) %%context%% %%extra%%\n" + + .. code-block:: xml + + + + + + + + [%%datetime%%] %%start_tag%%%%message%%%%end_tag%% (%%level_name%%) %%context%% %%extra%%\n + + + + + + .. code-block:: php + + // app/config/services.php + $container + ->register('my_formatter', 'Symfony\Bridge\Monolog\Formatter\ConsoleFormatter') + ->addArgument('[%%datetime%%] %%start_tag%%%%message%%%%end_tag%% (%%level_name%%) %%context%% %%extra%%\n') + ; + +.. _ConsoleHandler: https://github.com/symfony/MonologBridge/blob/master/Handler/ConsoleHandler.php +.. _MonologBundle: https://github.com/symfony/MonologBundle diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index b612238e7ac..64590e38e1d 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -101,6 +101,7 @@ * :doc:`/cookbook/logging/monolog` * :doc:`/cookbook/logging/monolog_email` + * :doc:`/cookbook/logging/monolog_console` * :doc:`/cookbook/logging/monolog_regex_based_excludes` * :doc:`/cookbook/logging/channels_handlers` diff --git a/reference/configuration/monolog.rst b/reference/configuration/monolog.rst index 24365fbd682..1b09cbc020c 100644 --- a/reference/configuration/monolog.rst +++ b/reference/configuration/monolog.rst @@ -25,6 +25,13 @@ MonologBundle Configuration ("monolog") action_level: WARNING buffer_size: 30 handler: custom + console: + type: console + verbosity_levels: + VERBOSITY_NORMAL: WARNING + VERBOSITY_VERBOSE: NOTICE + VERBOSITY_VERY_VERBOSE: INFO + VERBOSITY_DEBUG: DEBUG custom: type: service id: my_handler @@ -84,6 +91,10 @@ MonologBundle Configuration ("monolog") action-level="warning" handler="custom" /> + Date: Thu, 26 Dec 2013 12:56:01 -0500 Subject: [PATCH 0140/1181] [#3340] Tweaks to console logging: * Tweaked language in the components section to be more useful for component people * Added versionadded * Tweaked description of how this feature works --- components/console/introduction.rst | 7 ++++--- cookbook/logging/monolog_console.rst | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/components/console/introduction.rst b/components/console/introduction.rst index 6f60f2e7512..ea60102dcd6 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -230,8 +230,10 @@ method returns without actually printing. .. tip:: - You can use `MonologBundle`_ 2.4 to display messages on the console. This - is cleaner than wrapping your output calls in conditions (see :doc:/cookbook/logging/monolog_console). + The MonologBridge provides a :class:`Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler` + class that allows you to display messages on the console. This is cleaner + than wrapping your output calls in conditions. For an example use in + the Symfony Framework, see :doc:/cookbook/logging/monolog_console. Using Command Arguments ----------------------- @@ -527,4 +529,3 @@ Learn More! .. _Packagist: https://packagist.org/packages/symfony/console .. _ANSICON: https://github.com/adoxa/ansicon/downloads -.. _MonologBundle: https://github.com/symfony/MonologBundle diff --git a/cookbook/logging/monolog_console.rst b/cookbook/logging/monolog_console.rst index 358bd5bee2a..3a22b7dcfbc 100644 --- a/cookbook/logging/monolog_console.rst +++ b/cookbook/logging/monolog_console.rst @@ -4,7 +4,11 @@ How to Configure Monolog to Display Console Messages ==================================================== -It is possible to use the console to print messages for a certain :ref:`verbosity-levels` +.. versionadded:: 2.3 + This feature was introduced to the MonologBundle in version 2.4, which + was first packaged with Symfony at version 2.4 (but compatible with Symfony 2.3). + +It is possible to use the console to print messages for certain :ref:`verbosity-levels` using the :class:`Symfony\\Component\\Console\\Output\\OutputInterface` instance that is passed when a command gets executed. @@ -39,15 +43,18 @@ The example above could then be rewritten as:: protected function execute(InputInterface $input, OutputInterface $output) { + // assuming the Command extends ContainerAwareCommand... + $logger = $this->getContainer()->get('logger'); $logger->debug('Some info'); $logger->notice('Some more info'); } -These messages will get displayed on the console, timestamped, colored -depending on the log level and error logs are written to the error output -(php://stderr). There is no need to conditionally handle the verbosity -settings anymore. +Depending on the verbosity level that the command is run in and the user's +configuration (see below), these messages may or may not be displayed to +the console. If they are displayed, they are timestamped and colored appropriately. +Additionally, error logs are written to the error output (php://stderr). +There is no need to conditionally handle the verbosity settings anymore. The Monolog console handler is enabled in the Monolog configuration. This is the default in Symfony Standard Edition 2.4 too. From 4ef1a714acc1cb516c8624be714b77744d8f84e7 Mon Sep 17 00:00:00 2001 From: yanickj Date: Tue, 17 Dec 2013 12:04:48 -0500 Subject: [PATCH 0141/1181] Synchronized setter injection occurs on Container::set() not on Container::enterScope() --- cookbook/service_container/scopes.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cookbook/service_container/scopes.rst b/cookbook/service_container/scopes.rst index 8f6fd9fd34d..663636fded3 100644 --- a/cookbook/service_container/scopes.rst +++ b/cookbook/service_container/scopes.rst @@ -134,6 +134,7 @@ marked as ``synchronized``: class: Acme\HelloBundle\Client\ClientConfiguration scope: client synchronized: true + synthetic: true # ... .. code-block:: xml @@ -151,6 +152,7 @@ marked as ``synchronized``: id="client_configuration" scope="client" synchronized="true" + synthetic="true" class="Acme\HelloBundle\Client\ClientConfiguration" /> @@ -196,9 +198,9 @@ and everything works without any special code in your service or in your definit } } -Whenever the ``client`` scope is entered or left, the service container will -automatically call the ``setClientConfiguration()`` method with the current -``client_configuration`` instance. +Whenever the ``client`` scope is active, the service container will +automatically call the ``setClientConfiguration()`` method when the +``client_configuration`` service is set in the container. You might have noticed that the ``setClientConfiguration()`` method accepts ``null`` as a valid value for the ``client_configuration`` argument. That's From 0dfffffe38eea592a5bef4fccf59c0915386ae0b Mon Sep 17 00:00:00 2001 From: yanickj Date: Tue, 17 Dec 2013 13:30:59 -0500 Subject: [PATCH 0142/1181] Update PHP example to include synthetic attribute. --- cookbook/service_container/scopes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/cookbook/service_container/scopes.rst b/cookbook/service_container/scopes.rst index 663636fded3..59d4cd425a4 100644 --- a/cookbook/service_container/scopes.rst +++ b/cookbook/service_container/scopes.rst @@ -169,6 +169,7 @@ marked as ``synchronized``: ); $definition->setScope('client'); $definition->setSynchronized(true); + $definition->setSynthetic(true); $container->setDefinition('client_configuration', $definition); Now, if you inject this service using setter injection, there are no drawbacks From 04890d72cfe807d27700657acc729fd8eedc8efd Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 31 Dec 2013 14:32:01 +0100 Subject: [PATCH 0143/1181] clarify that the ConsoleHandler was added to the MonologBridge and not the MonologBundle --- components/console/introduction.rst | 2 +- cookbook/logging/monolog_console.rst | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/components/console/introduction.rst b/components/console/introduction.rst index ea60102dcd6..4ca2bcfe8c1 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -160,7 +160,7 @@ You can also set these colors and options inside the tagname:: // bold text on a yellow background $output->writeln('foo'); -.. verbosity-levels: +.. _verbosity-levels: Verbosity Levels ~~~~~~~~~~~~~~~~ diff --git a/cookbook/logging/monolog_console.rst b/cookbook/logging/monolog_console.rst index 3a22b7dcfbc..7945193022e 100644 --- a/cookbook/logging/monolog_console.rst +++ b/cookbook/logging/monolog_console.rst @@ -4,13 +4,13 @@ How to Configure Monolog to Display Console Messages ==================================================== -.. versionadded:: 2.3 - This feature was introduced to the MonologBundle in version 2.4, which - was first packaged with Symfony at version 2.4 (but compatible with Symfony 2.3). +.. versionadded:: 2.4 + This feature was introduced to the MonologBridge in Symfony 2.4. -It is possible to use the console to print messages for certain :ref:`verbosity-levels` -using the :class:`Symfony\\Component\\Console\\Output\\OutputInterface` -instance that is passed when a command gets executed. +It is possible to use the console to print messages for certain +:ref:`verbosity levels ` using the +:class:`Symfony\\Component\\Console\\Output\\OutputInterface` instance that +is passed when a command gets executed. When a lot of logging has to happen, it's cumbersome to print information depending on the verbosity settings (``-v``, ``-vv``, ``-vvv``) because the @@ -32,7 +32,7 @@ For example:: } Instead of using these semantic methods to test for each of the verbosity -levels, `MonologBundle`_ 2.4 provides a `ConsoleHandler`_ that listens to +levels, the `MonologBridge`_ provides a `ConsoleHandler`_ that listens to console events and writes log messages to the console output depending on the current log level and the console verbosity. @@ -96,8 +96,9 @@ With the ``verbosity_levels`` option you can adapt the mapping between verbosity and log level. In the given example it will also show notices in normal verbosity mode (instead of warnings only). Additionally, it will only use messages logged with the custom ``my_channel`` channel and it changes the -display style via a custom formatter. See also the :doc:`reference/configuration/monolog` -for more information: +display style via a custom formatter (see the +:doc:`MonologBundle reference ` for more +information): .. configuration-block:: @@ -180,4 +181,4 @@ for more information: ; .. _ConsoleHandler: https://github.com/symfony/MonologBridge/blob/master/Handler/ConsoleHandler.php -.. _MonologBundle: https://github.com/symfony/MonologBundle +.. _MonologBridge: https://github.com/symfony/MonologBridge From bd1e53e84058decccd141580d256a9013be401b2 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 1 Jan 2014 16:51:39 -0600 Subject: [PATCH 0144/1181] Revert "[#3338] Removing delete_empty details because this is first being committed to 2.3" This re-introduces the delete_empty documentation to the master (2.5) branch, since it should live there. This reverts commit 72fa7b4767b5b86053ca92f4052de2dc7c2dac09. --- reference/forms/types/collection.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/reference/forms/types/collection.rst b/reference/forms/types/collection.rst index b6c014784b5..0decd3c547e 100644 --- a/reference/forms/types/collection.rst +++ b/reference/forms/types/collection.rst @@ -19,6 +19,7 @@ forms, which is useful when creating forms that expose one-to-many relationships | | - `allow_delete`_ | | | - `prototype`_ | | | - `prototype_name`_ | +| | - `delete_empty`_ | +-------------+-----------------------------------------------------------------------------+ | Inherited | - `label`_ | | | - `label_attr`_ | @@ -335,6 +336,16 @@ If you have several collections in your form, or worse, nested collections you may want to change the placeholder so that unrelated placeholders are not replaced with the same value. +delete_empty +~~~~~~~~~~~~ + +**type**: ``Boolean`` **default**: ``false`` + +If you want to explicitly remove entirely empty collection entries from your +form you have to set this option to true. However, existing collection entries +will only be deleted if you have the allow_delete_ option enabled. Otherwise +the empty values will be kept. + Inherited options ----------------- From 42084dd5bcd9109ea65429ccd5ae7837813125c6 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 1 Jan 2014 16:53:05 -0600 Subject: [PATCH 0145/1181] [#3338] Adding versionadded --- reference/forms/types/collection.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/reference/forms/types/collection.rst b/reference/forms/types/collection.rst index 0decd3c547e..fe1e6ee8cb5 100644 --- a/reference/forms/types/collection.rst +++ b/reference/forms/types/collection.rst @@ -339,6 +339,9 @@ replaced with the same value. delete_empty ~~~~~~~~~~~~ +.. versionadded:: 2.5 + The delete_empty option was introduced in Symfony 2.5. + **type**: ``Boolean`` **default**: ``false`` If you want to explicitly remove entirely empty collection entries from your From 6da1df65eaed400d4c6ebabdc90ed9ac1a937535 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 1 Jan 2014 19:24:47 -0600 Subject: [PATCH 0146/1181] [#3357] Many many changes thanks to @WouterJ and @xabbuh --- cookbook/security/_supportsToken.rst.inc | 16 ++-- cookbook/security/api_key_authentication.rst | 87 ++++++++++--------- .../custom_authentication_provider.rst | 2 +- .../custom_password_authenticator.rst | 28 +++--- 4 files changed, 69 insertions(+), 64 deletions(-) diff --git a/cookbook/security/_supportsToken.rst.inc b/cookbook/security/_supportsToken.rst.inc index a199364068e..aede5833cfb 100644 --- a/cookbook/security/_supportsToken.rst.inc +++ b/cookbook/security/_supportsToken.rst.inc @@ -1,10 +1,10 @@ -After Symfony calls ``createToken``, it will then call ``supportsToken`` on -your class (and any other authentication listeners) to figure out who should -handle it. This is just a way to allow several authentication mechanisms to -be used for the same firewall (that way, you can for instance first try to -authenticate the user via a certificate or an API key and fall back to a -form login). +After Symfony calls ``createToken()``, it will then call ``supportsToken()`` +on your class (and any other authentication listeners) to figure out who should +handle the token. This is just a way to allow several authentication mechanisms +to be used for the same firewall (that way, you can for instance first try +to authenticate the user via a certificate or an API key and fall back to +a form login). Mostly, you just need to make sure that this method returns ``true`` for a -token that has been created by ``createToken``. Your logic should probably -look exactly like this example. \ No newline at end of file +token that has been created by ``createToken()``. Your logic should probably +look exactly like this example. diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index 26bc5b67bcf..cd2812ebd88 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -20,7 +20,7 @@ allows you to implement such a scheme really easily. Your exact situation may differ, but in this example, a token is read from an ``apikey`` query parameter, the proper username is loaded from that -value, and then a User object is created:: +value and then a User object is created:: // src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php namespace Acme\HelloBundle\Security; @@ -59,7 +59,9 @@ value, and then a User object is created:: public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) { $apiKey = $token->getCredentials(); - if (!$username = $this->userProvider->getUsernameForApiKey($apiKey)) { + $username = $this->userProvider->getUsernameForApiKey($apiKey) + + if (!$username) { throw new AuthenticationException( sprintf('API Key "%s" does not exist.', $apiKey) ); @@ -91,10 +93,10 @@ probably differ: 1. createToken ~~~~~~~~~~~~~~ -Early in the request cycle, Symfony calls ``createToken``. Your job here +Early in the request cycle, Symfony calls ``createToken()``. Your job here is to create a token object that contains all of the information from the request that you need to authenticate the user (e.g. the ``apikey`` query -parameter). If that information is missing, throwing the +parameter). If that information is missing, throwing a :class:`Symfony\\Component\\Security\\Core\\Exception\\BadCredentialsException` will cause authentication to fail. @@ -106,11 +108,11 @@ will cause authentication to fail. 3. authenticateToken ~~~~~~~~~~~~~~~~~~~~ -If ``supportsToken`` returns ``true``, Symfony will now call ``authenticateToken``. +If ``supportsToken()`` returns ``true``, Symfony will now call ``authenticateToken()``. One key part is the ``$userProvider``, which is an external class that helps you load information about the user. You'll learn more about this next. -In this specific example, the following things happen in ``authenticateToken``: +In this specific example, the following things happen in ``authenticateToken()``: #. First, you use the ``$userProvider`` to somehow look up the ``$username`` that corresponds to the ``$apiKey``; @@ -119,18 +121,18 @@ In this specific example, the following things happen in ``authenticateToken``: #. Finally, you create an *authenticated token* (i.e. a token with at least one role) that has the proper roles and the User object attached to it. -The goal is ultimately to use the ``$apiKey`` to find or create a User object. -*How* you do this (e.g. query a database) and the exact class for your User -object may vary. Those differences will be most obvious in your user provider. +The goal is ultimately to use the ``$apiKey`` to find or create a ``User`` +object. *How* you do this (e.g. query a database) and the exact class for +your ``User`` object may vary. Those differences will be most obvious in your +user provider. The User Provider ~~~~~~~~~~~~~~~~~ -The ``$userProvider`` can be any user provider (see -:doc:`how to create a custom user provider `). +The ``$userProvider`` can be any user provider (see :doc:`/cookbook/security/custom_provider`). In this example, the ``$apiKey`` is used to somehow find the username for -the user. This work is done in a ``getUsernameForApiKey`` method, which is -created entirely custom for our use-case (i.e. this isn't a method that's +the user. This work is done in a ``getUsernameForApiKey()`` method, which +is created entirely custom for this use-case (i.e. this isn't a method that's used by Symfony's core user provider system). The ``$userProvider`` might look something like this:: @@ -140,6 +142,8 @@ The ``$userProvider`` might look something like this:: use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\User; + use Symfony\Component\Security\Core\User\UserInterface; + use Symfony\Component\Security\Core\Exception\UnsupportedUserException; class ApiKeyUserProvider extends UserProviderInterface { @@ -147,7 +151,7 @@ The ``$userProvider`` might look something like this:: { // Look up the username based on the token in the database, via // an API call, or do something entirely different - $username = // ... + $username = ...; return $username; } @@ -174,7 +178,7 @@ The ``$userProvider`` might look something like this:: public function supportsClass($class) { - return $class === 'Symfony\Component\Security\Core\User\User'; + return 'Symfony\Component\Security\Core\User\User' === $class; } } @@ -183,23 +187,23 @@ The ``$userProvider`` might look something like this:: Read the dedicated article to learn :doc:`how to create a custom user provider `. -The logic inside ``getUsernameForApiKey`` is up to you. You may somehow transform +The logic inside ``getUsernameForApiKey()`` is up to you. You may somehow transform the API key (e.g. ``37b51d``) into a username (e.g. ``jondoe``) by looking up some information in a "token" database table. -The same is true for ``loadUserByUsername``. In this example, Symfony's core +The same is true for ``loadUserByUsername()``. In this example, Symfony's core :class:`Symfony\\Component\\Security\\Core\\User\\User` class is simply created. This makes sense if you don't need to store any extra information on your User object (e.g. ``firstName``). But if you do, you may instead have your *own* user class which you create and populate here by querying a database. This -would allow you to have custom data on the User object. +would allow you to have custom data on the ``User`` object. -Finally, just make sure that ``supportsClass`` return ``true`` for User -objects with the same class as whatever user you return in ``loadUserByUsername``. +Finally, just make sure that ``supportsClass()`` returns ``true`` for User +objects with the same class as whatever user you return in ``loadUserByUsername()``. If your authentication is stateless like in this example (i.e. you expect the user to send the API key with every request and so you don't save the login to the session), then you can simply throw the ``UnsupportedUserException`` -exception in ``refreshUser``. +exception in ``refreshUser()``. .. note:: @@ -212,9 +216,10 @@ Configuration ------------- Once you have your ``ApiKeyAuthentication`` all setup, you need to register -it as a service and use it in ``security.yml``. First, register it as a service. -This assumes that you have already setup your custom user provider as a service -called ``your_api_key_user_provider`` (see :doc:`/cookbook/security/custom_provider`). +it as a service and use it in your security configuration (e.g. ``security.yml``). +First, register it as a service. This assumes that you have already setup +your custom user provider as a service called ``your_api_key_user_provider`` +(see :doc:`/cookbook/security/custom_provider`). .. configuration-block:: @@ -260,8 +265,8 @@ called ``your_api_key_user_provider`` (see :doc:`/cookbook/security/custom_provi array(new Reference('your_api_key_user_provider')) )); -Now, activate it in the ``firewalls`` section of ``security.yml`` using the -``simple_preauth`` key: +Now, activate it in the ``firewalls`` section of your security configuration +using the ``simple_preauth`` key: .. configuration-block:: @@ -395,32 +400,31 @@ configuration or set it to ``false``: Storing authentication information in the session works like this: #. At the end of each request, Symfony serializes the token object (returned - from ``authenticateToken``), which also serializes the User object (since - it's set on a property on the token); -#. On the next request the token is deserialized and the deserialized User - object is passed to the ``refreshUser`` function of the user provider. + from ``authenticateToken()``), which also serializes the ``User`` object + (since it's set on a property on the token); +#. On the next request the token is deserialized and the deserialized ``User`` + object is passed to the ``refreshUser()`` function of the user provider. -The second step is the important one: Symfony calls ``refreshUser`` and passes +The second step is the important one: Symfony calls ``refreshUser()`` and passes you the user object that was serialized in the session. If your users are stored in the database, then you may want to re-query for a fresh version of the user to make sure it's not out-of-date. But regardless of your requirements, -``refreshUser`` should now return the User object:: +``refreshUser()`` should now return the User object:: // src/Acme/HelloBundle/Security/ApiKeyUserProvider.php // ... - class ApiKeyUserProvider extends UserProviderInterface { // ... public function refreshUser(UserInterface $user) { - // $user is the User that you set in the token inside authenticateToken + // $user is the User that you set in the token inside authenticateToken() // after it has been deserialized from the session // you might use $user to query the database for a fresh user - $id = $user->getId(); + // $id = $user->getId(); // use $id to make a query // if you are *not* reading from a database and are just creating @@ -431,12 +435,12 @@ of the user to make sure it's not out-of-date. But regardless of your requiremen .. note:: - You'll also want to make sure that your User object is being serialized - correctly. If your User object has private properties, PHP can't serialize + You'll also want to make sure that your ``User`` object is being serialized + correctly. If your ``User`` object has private properties, PHP can't serialize those. In this case, you may get back a User object that has a ``null`` value for each property. For an example, see :doc:`/cookbook/security/entity_provider`. -Only Authenticating for certain URLs +Only Authenticating for Certain URLs ------------------------------------ This entry has assumed that you want to look for the ``apikey`` authentication @@ -445,12 +449,13 @@ really need to look for authentication information once the user has reached a certain URL (e.g. the redirect URL in OAuth). Fortunately, handling this situation is easy: just check to see what the -current URL is before creating the token in ``createToken``:: +current URL is before creating the token in ``createToken()``:: // src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php // ... use Symfony\Component\Security\Http\HttpUtils; + use Symfony\Component\HttpFoundation\Request; class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface { @@ -477,8 +482,8 @@ current URL is before creating the token in ``createToken``:: } } -This uses a handy :class:`Symfony\\Component\\Security\\Http\\HttpUtils` -class to see if the current URL matches the URL you're looking for. In this +This uses the handy :class:`Symfony\\Component\\Security\\Http\\HttpUtils` +class to check if the current URL matches the URL you're looking for. In this case, the URL (``/login/check``) has been hardcoded in the class, but you could also inject it as the third constructor argument. diff --git a/cookbook/security/custom_authentication_provider.rst b/cookbook/security/custom_authentication_provider.rst index 8b67ea391de..b77b978fe11 100644 --- a/cookbook/security/custom_authentication_provider.rst +++ b/cookbook/security/custom_authentication_provider.rst @@ -8,7 +8,7 @@ How to create a custom Authentication Provider Creating a custom authentication system is hard, and this entry will walk you through that process. But depending on your needs, you may be able - to use solve your problem in a simpler way using these documents: + to solve your problem in a simpler way using these documents: * :doc:`/cookbook/security/custom_password_authenticator` * :doc:`/cookbook/security/api_key_authentication` diff --git a/cookbook/security/custom_password_authenticator.rst b/cookbook/security/custom_password_authenticator.rst index ef9f9be035f..2f4b86c4647 100644 --- a/cookbook/security/custom_password_authenticator.rst +++ b/cookbook/security/custom_password_authenticator.rst @@ -1,7 +1,7 @@ .. index:: single: Security; Custom Password Authenticator -How to create a Custom Form Password Authenticator +How to Create a Custom Form Password Authenticator ================================================== Imagine you want to allow access to your website only between 2pm and 4pm @@ -97,12 +97,12 @@ But first, you can find out more about what each method in this class does. 1) createToken ~~~~~~~~~~~~~~ -When Symfony begins handling a request, ``createToken`` is called, where +When Symfony begins handling a request, ``createToken()`` is called, where you create a :class:`Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface` -object that contains whatever information you need in ``authenticateToken`` +object that contains whatever information you need in ``authenticateToken()`` to authenticate the user (e.g. the username and password). -Whatever token object you create here will be passed to you later in ``authenticateToken``. +Whatever token object you create here will be passed to you later in ``authenticateToken()``. 2) supportsToken ~~~~~~~~~~~~~~~~ @@ -112,20 +112,20 @@ Whatever token object you create here will be passed to you later in ``authentic 3) authenticateToken ~~~~~~~~~~~~~~~~~~~~ -If ``supportsToken`` returns ``true``, Symfony will now call ``authenticateToken``. -Your job here is to checks that the token is allowed to log in by first -getting the User object via the user provider and then, by checking the password +If ``supportsToken`` returns ``true``, Symfony will now call ``authenticateToken()``. +Your job here is to check that the token is allowed to log in by first +getting the ``User`` object via the user provider and then, by checking the password and the current time. .. note:: - The "flow" of how you get the User object and determine whether or not + The "flow" of how you get the ``User`` object and determine whether or not the token is valid (e.g. checking the password), may vary based on your requirements. Ultimately, your job is to return a *new* token object that is "authenticated" -(i.e. it has at least 1 role set on it) and which has the User object inside -of it. +(i.e. it has at least 1 role set on it) and which has the ``User`` object +inside of it. Inside this method, an encoder is needed to check the password's validity:: @@ -137,8 +137,8 @@ Inside this method, an encoder is needed to check the password's validity:: ); This is a service that is already available in Symfony and the password algorithm -is configured in ``security.yml`` under the ``encoders`` key. Below, you'll -see how to inject that into the ``TimeAuthenticator``. +is configured in the security configuration (e.g. ``security.yml``) under +the ``encoders`` key. Below, you'll see how to inject that into the ``TimeAuthenticator``. .. _cookbook-security-password-authenticator-config: @@ -191,8 +191,8 @@ Now, configure your ``TimeAuthenticator`` as a service: array(new Reference('security.encoder_factory')) )); -Then, activate it in the ``firewalls`` section of ``security.yml`` using -the ``simple_form`` key: +Then, activate it in the ``firewalls`` section of the security configuration +using the ``simple_form`` key: .. configuration-block:: From 33d27cc14dd55c36247397522a90a6a1456fff89 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 1 Jan 2014 19:32:16 -0600 Subject: [PATCH 0147/1181] [#3362] Updating composer install version on the master branch --- book/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/installation.rst b/book/installation.rst index 3604f1236c5..c5a7ed955ff 100644 --- a/book/installation.rst +++ b/book/installation.rst @@ -57,7 +57,7 @@ Distribution: .. code-block:: bash - $ php composer.phar create-project symfony/framework-standard-edition /path/to/webroot/Symfony 2.4.* + $ php composer.phar create-project symfony/framework-standard-edition /path/to/webroot/Symfony dev-master .. tip:: From 78e07b92b01f7d964137d4a0cfda1b465230dbe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Andrieu?= Date: Mon, 23 Dec 2013 17:06:36 +0100 Subject: [PATCH 0148/1181] Documentation should refers to @Security and no @Secure --- book/security.rst | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/book/security.rst b/book/security.rst index 879f8bb7061..89d4b9a8e54 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1062,6 +1062,72 @@ the user will be redirected to ``https``: ), ), +.. _book-security-securing-controller: + +Securing a Controller +~~~~~~~~~~~~~~~~~~~~~ + +Protecting your application based on URL patterns is easy, but may not be +fine-grained enough in certain cases. When necessary, you can easily force +authorization from inside a controller:: + + // ... + use Symfony\Component\Security\Core\Exception\AccessDeniedException; + + public function helloAction($name) + { + if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException(); + } + + // ... + } + +.. _book-security-securing-controller-annotations: + +Thanks to the FrameworkExtraBundle, you can also secure your controller using annotations:: + + // ... + use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; + + /** + * @Security("has_role('ROLE_ADMIN')") + */ + public function helloAction($name) + { + // ... + } + +For more information, see the `SensioFrameworkExtraBundle`_ documentation. + +Securing other Services +~~~~~~~~~~~~~~~~~~~~~~~ + +In fact, anything in Symfony can be protected using a strategy similar to +the one seen in the previous section. For example, suppose you have a service +(i.e. a PHP class) whose job is to send emails from one user to another. +You can restrict use of this class - no matter where it's being used from - +to users that have a specific role. + +For more information on how you can use the Security component to secure +different services and methods in your application, see :doc:`/cookbook/security/securing_services`. + +Access Control Lists (ACLs): Securing Individual Database Objects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Imagine you are designing a blog system where your users can comment on your +posts. Now, you want a user to be able to edit their own comments, but not +those of other users. Also, as the admin user, you yourself want to be able +to edit *all* comments. + +The Security component comes with an optional access control list (ACL) system +that you can use when you need to control access to individual instances +of an object in your system. *Without* ACL, you can secure your system so that +only certain users can edit blog comments in general. But *with* ACL, you +can restrict or allow access on a comment-by-comment basis. + +For more information, see the cookbook article: :doc:`/cookbook/security/acl`. + Users ----- From 669d72e808d1ecf6fc8838be2c28a2e6514a5397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Andrieu?= Date: Tue, 24 Dec 2013 13:46:01 +0100 Subject: [PATCH 0149/1181] Fixed SensioFrameworkExtraBundle complete name --- book/security.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/security.rst b/book/security.rst index 89d4b9a8e54..453750dae79 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1085,7 +1085,7 @@ authorization from inside a controller:: .. _book-security-securing-controller-annotations: -Thanks to the FrameworkExtraBundle, you can also secure your controller using annotations:: +Thanks to the SensioFrameworkExtraBundle, you can also secure your controller using annotations:: // ... use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; From 447b716dc42ddcb0cf4c83b8be12c6ed546ea2fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Andrieu?= Date: Mon, 30 Dec 2013 10:28:05 +0100 Subject: [PATCH 0150/1181] Fixed internal url linked to @Security annotation --- book/security.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/book/security.rst b/book/security.rst index 453750dae79..faba77d112a 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1098,7 +1098,7 @@ Thanks to the SensioFrameworkExtraBundle, you can also secure your controller us // ... } -For more information, see the `SensioFrameworkExtraBundle`_ documentation. +For more information, see the :doc:`FrameworkExtraBundle documentation `. Securing other Services ~~~~~~~~~~~~~~~~~~~~~~~ @@ -2164,7 +2164,6 @@ Learn more from the Cookbook * :doc:`Access Control Lists (ACLs) ` * :doc:`/cookbook/security/remember_me` -.. _`JMSSecurityExtraBundle`: http://jmsyst.com/bundles/JMSSecurityExtraBundle/1.2 .. _`FOSUserBundle`: https://github.com/FriendsOfSymfony/FOSUserBundle .. _`implement the \Serializable interface`: http://php.net/manual/en/class.serializable.php .. _`functions-online.com`: http://www.functions-online.com/sha1.html From 16f0226c3437ce591830c4509582fb4f5a912ee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Andrieu?= Date: Mon, 30 Dec 2013 10:51:05 +0100 Subject: [PATCH 0151/1181] Moved complete role to a new line --- book/security.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/book/security.rst b/book/security.rst index faba77d112a..e60e581abc5 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1098,7 +1098,8 @@ Thanks to the SensioFrameworkExtraBundle, you can also secure your controller us // ... } -For more information, see the :doc:`FrameworkExtraBundle documentation `. +For more information, see the +:doc:`FrameworkExtraBundle documentation `. Securing other Services ~~~~~~~~~~~~~~~~~~~~~~~ From bfe3a203e33a53f5b581bcafa9be67a261067a97 Mon Sep 17 00:00:00 2001 From: Philipp Rieber Date: Sat, 4 Jan 2014 11:47:25 +0100 Subject: [PATCH 0152/1181] [Validation] Add "hasser" support --- book/validation.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/book/validation.rst b/book/validation.rst index ea5315afaae..ca2880f5881 100644 --- a/book/validation.rst +++ b/book/validation.rst @@ -583,8 +583,8 @@ Getters Constraints can also be applied to the return value of a method. Symfony2 allows you to add a constraint to any public method whose name starts with -"get" or "is". In this guide, both of these types of methods are referred -to as "getters". +"get", "is" or "has". In this guide, these types of methods are referred to +as "getters". The benefit of this technique is that it allows you to validate your object dynamically. For example, suppose you want to make sure that a password field @@ -665,9 +665,9 @@ Now, create the ``isPasswordLegal()`` method, and include the logic you need:: .. note:: The keen-eyed among you will have noticed that the prefix of the getter - ("get" or "is") is omitted in the mapping. This allows you to move the - constraint to a property with the same name later (or vice versa) without - changing your validation logic. + ("get", "is" or "has") is omitted in the mapping. This allows you to move + the constraint to a property with the same name later (or vice versa) + without changing your validation logic. .. _validation-class-target: From b35e62b28e32760f9d90128ec8a3fd78f6c8fb47 Mon Sep 17 00:00:00 2001 From: Mathieu Lemoine Date: Sat, 4 Jan 2014 12:25:32 -0500 Subject: [PATCH 0153/1181] [Contributing] Clarify the rebase operation I just mentioned the fact that `push -f` is usually required when rebasing and explicit that the "2.2 when bugfixing" is a follow up on the previous example (Not necessarily explicit at first). --- contributing/code/patches.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contributing/code/patches.rst b/contributing/code/patches.rst index d2dae74d2fd..cf262b0faa7 100644 --- a/contributing/code/patches.rst +++ b/contributing/code/patches.rst @@ -228,7 +228,8 @@ while to finish your changes): .. tip:: - Replace `master` with `2.2` if you are working on a bugfix + Replace ``master`` with the branch you selected previously (e.g. ``2.2``) + if you are working on a bugfix When doing the ``rebase`` command, you might have to fix merge conflicts. ``git status`` will show you the *unmerged* files. Resolve all the conflicts, @@ -243,7 +244,7 @@ Check that all tests still pass and push your branch remotely: .. code-block:: bash - $ git push origin BRANCH_NAME + $ git push -f origin BRANCH_NAME Make a Pull Request ~~~~~~~~~~~~~~~~~~~ From bb9004ef6cd181fd7fba1f6d7dae1e2c5e129b3f Mon Sep 17 00:00:00 2001 From: Philipp Rieber Date: Sat, 4 Jan 2014 19:09:24 +0100 Subject: [PATCH 0154/1181] Add "versionadded" directive for 2.5 --- book/validation.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/book/validation.rst b/book/validation.rst index ca2880f5881..4168ae079bb 100644 --- a/book/validation.rst +++ b/book/validation.rst @@ -586,6 +586,9 @@ allows you to add a constraint to any public method whose name starts with "get", "is" or "has". In this guide, these types of methods are referred to as "getters". +.. versionadded:: 2.5 + Support for methods starting with ``has`` is new in Symfony 2.5. + The benefit of this technique is that it allows you to validate your object dynamically. For example, suppose you want to make sure that a password field doesn't match the first name of the user (for security reasons). You can From 6796ba87cc48f5fe2bf940e93c5b8562d54fdae8 Mon Sep 17 00:00:00 2001 From: Mathieu Lemoine Date: Sat, 4 Jan 2014 13:33:59 -0500 Subject: [PATCH 0155/1181] [Contributing] Fix single vs double backtick issues --- contributing/code/patches.rst | 46 +++++++++++++++++------------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/contributing/code/patches.rst b/contributing/code/patches.rst index cf262b0faa7..f4a1c28fde5 100644 --- a/contributing/code/patches.rst +++ b/contributing/code/patches.rst @@ -72,7 +72,7 @@ Get the Symfony2 source code: * Fork the `Symfony2 repository`_ (click on the "Fork" button); * After the "forking action" has completed, clone your fork locally - (this will create a `symfony` directory): + (this will create a ``symfony`` directory): .. code-block:: bash @@ -105,16 +105,16 @@ Choose the right Branch ~~~~~~~~~~~~~~~~~~~~~~~ Before working on a patch, you must determine on which branch you need to -work. The branch should be based on the `master` branch if you want to add a +work. The branch should be based on the ``master`` branch if you want to add a new feature. But if you want to fix a bug, use the oldest but still maintained -version of Symfony where the bug happens (like `2.2`). +version of Symfony where the bug happens (like ``2.2``). .. note:: All bug fixes merged into maintenance branches are also merged into more recent branches on a regular basis. For instance, if you submit a patch - for the `2.2` branch, the patch will also be applied by the core team on - the `master` branch. + for the ``2.2`` branch, the patch will also be applied by the core team on + the ``master`` branch. Create a Topic Branch ~~~~~~~~~~~~~~~~~~~~~ @@ -126,14 +126,14 @@ topic branch: $ git checkout -b BRANCH_NAME master -Or, if you want to provide a bugfix for the 2.2 branch, first track the remote -`2.2` branch locally: +Or, if you want to provide a bugfix for the ``2.2`` branch, first track the remote +``2.2`` branch locally: .. code-block:: bash $ git checkout -t origin/2.2 -Then create a new branch off the 2.2 branch to work on the bugfix: +Then create a new branch off the ``2.2`` branch to work on the bugfix: .. code-block:: bash @@ -141,11 +141,11 @@ Then create a new branch off the 2.2 branch to work on the bugfix: .. tip:: - Use a descriptive name for your branch (`ticket_XXX` where `XXX` is the + Use a descriptive name for your branch (``ticket_XXX`` where ``XXX`` is the ticket number is a good convention for bug fixes). The above checkout commands automatically switch the code to the newly created -branch (check the branch you are working on with `git branch`). +branch (check the branch you are working on with ``git branch``). Work on your Patch ~~~~~~~~~~~~~~~~~~ @@ -154,7 +154,7 @@ Work on the code as much as you want and commit as much as you want; but keep in mind the following: * Read about the Symfony :doc:`conventions ` and follow the - coding :doc:`standards ` (use `git diff --check` to check for + coding :doc:`standards ` (use ``git diff --check`` to check for trailing spaces -- also read the tip below); * Add unit tests to prove that the bug is fixed or that the new feature @@ -164,7 +164,7 @@ in mind the following: provide a compatibility layer to support the old way) -- patches that break backward compatibility have less chance to be merged; -* Do atomic and logically separate commits (use the power of `git rebase` to +* Do atomic and logically separate commits (use the power of ``git rebase`` to have a clean and logical history); * Squash irrelevant commits that are just about fixing coding standards or @@ -199,11 +199,11 @@ Prepare your Patch for Submission When your patch is not about a bug fix (when you add a new feature or change an existing one for instance), it must also include the following: -* An explanation of the changes in the relevant CHANGELOG file(s) (the ``[BC - BREAK]`` or the ``[DEPRECATION]`` prefix must be used when relevant); +* An explanation of the changes in the relevant ``CHANGELOG`` file(s) (the + ``[BC BREAK]`` or the ``[DEPRECATION]`` prefix must be used when relevant); * An explanation on how to upgrade an existing application in the relevant - UPGRADE file(s) if the changes break backward compatibility or if you + ``UPGRADE`` file(s) if the changes break backward compatibility or if you deprecate something that will ultimately break backward compatibility. Step 3: Submit your Patch @@ -254,7 +254,7 @@ You can now make a pull request on the ``symfony/symfony`` Github repository. .. tip:: Take care to point your pull request towards ``symfony:2.2`` if you want - the core team to pull a bugfix based on the 2.2 branch. + the core team to pull a bugfix based on the ``2.2`` branch. To ease the core team work, always include the modified components in your pull request message, like in: @@ -317,10 +317,10 @@ Some answers to the questions trigger some more requirements: documentation and reference it under the "Doc PR" section; * If you answer yes to "BC breaks?", the patch must contain updates to the - relevant CHANGELOG and UPGRADE files; + relevant ``CHANGELOG`` and ``UPGRADE`` files; * If you answer yes to "Deprecations?", the patch must contain updates to the - relevant CHANGELOG and UPGRADE files; + relevant ``CHANGELOG`` and ``UPGRADE`` files; * If you answer no to "Tests pass", you must add an item to a todo-list with the actions that must be done to fix the tests; @@ -394,11 +394,11 @@ type this command, an editor will popup showing a list of commits: pick 7fc64b4 second commit pick 7d33018 third commit -To squash all commits into the first one, remove the word "pick" before the -second and the last commits, and replace it by the word "squash" or just "s". -When you save, Git will start rebasing, and if successful, will ask you to -edit the commit message, which by default is a listing of the commit messages -of all the commits. When you finish, execute the push command. +To squash all commits into the first one, remove the word ``pick`` before the +second and the last commits, and replace it by the word ``squash`` or just + ``s``. When you save, Git will start rebasing, and if successful, will ask + you to edit the commit message, which by default is a listing of the commit + messages of all the commits. When you finish, execute the push command. .. _ProGit: http://git-scm.com/book .. _GitHub: https://github.com/signup/free From 70ed645240cfd7e76d09ce0eb16309856c92a7e0 Mon Sep 17 00:00:00 2001 From: Mathieu Lemoine Date: Sat, 4 Jan 2014 13:34:34 -0500 Subject: [PATCH 0156/1181] [Contributing] Add PSR-1 and 2 links --- contributing/code/patches.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contributing/code/patches.rst b/contributing/code/patches.rst index f4a1c28fde5..c6ec35864d1 100644 --- a/contributing/code/patches.rst +++ b/contributing/code/patches.rst @@ -179,7 +179,7 @@ in mind the following: When submitting pull requests, `fabbot`_ checks your code for common typos and verifies that you are using the PHP coding standards - as defined in PSR-1 and PSR-2. + as defined in `PSR-1`_ and `PSR-2`_. A status is posted below the pull request description with a summary of any problems it detects or any Travis CI build failures. @@ -410,3 +410,5 @@ second and the last commits, and replace it by the word ``squash`` or just .. _`travis-ci.org Getting Started Guide`: http://about.travis-ci.org/docs/user/getting-started/ .. _`documentation repository`: https://github.com/symfony/symfony-docs .. _`fabbot`: http://fabbot.io +.. _`PSR-1`: http://www.php-fig.org/psr/psr-1/ +.. _`PSR-2`: http://www.php-fig.org/psr/psr-2/ From b25ec96eb822a03c466c828dc9838f9a8f766ae5 Mon Sep 17 00:00:00 2001 From: Mathieu Lemoine Date: Sat, 4 Jan 2014 13:35:44 -0500 Subject: [PATCH 0157/1181] [Contributing] Replace mentions of 2.2 for 2.3 As per WouterJ request: https://github.com/symfony/symfony-docs/pull/3421#issuecomment-31585092 --- contributing/code/patches.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/contributing/code/patches.rst b/contributing/code/patches.rst index c6ec35864d1..2f313f87f69 100644 --- a/contributing/code/patches.rst +++ b/contributing/code/patches.rst @@ -107,13 +107,13 @@ Choose the right Branch Before working on a patch, you must determine on which branch you need to work. The branch should be based on the ``master`` branch if you want to add a new feature. But if you want to fix a bug, use the oldest but still maintained -version of Symfony where the bug happens (like ``2.2``). +version of Symfony where the bug happens (like ``2.3``). .. note:: All bug fixes merged into maintenance branches are also merged into more recent branches on a regular basis. For instance, if you submit a patch - for the ``2.2`` branch, the patch will also be applied by the core team on + for the ``2.3`` branch, the patch will also be applied by the core team on the ``master`` branch. Create a Topic Branch @@ -126,18 +126,18 @@ topic branch: $ git checkout -b BRANCH_NAME master -Or, if you want to provide a bugfix for the ``2.2`` branch, first track the remote -``2.2`` branch locally: +Or, if you want to provide a bugfix for the ``2.3`` branch, first track the remote +``2.3`` branch locally: .. code-block:: bash - $ git checkout -t origin/2.2 + $ git checkout -t origin/2.3 -Then create a new branch off the ``2.2`` branch to work on the bugfix: +Then create a new branch off the ``2.3`` branch to work on the bugfix: .. code-block:: bash - $ git checkout -b BRANCH_NAME 2.2 + $ git checkout -b BRANCH_NAME 2.3 .. tip:: @@ -228,7 +228,7 @@ while to finish your changes): .. tip:: - Replace ``master`` with the branch you selected previously (e.g. ``2.2``) + Replace ``master`` with the branch you selected previously (e.g. ``2.3``) if you are working on a bugfix When doing the ``rebase`` command, you might have to fix merge conflicts. @@ -253,8 +253,8 @@ You can now make a pull request on the ``symfony/symfony`` Github repository. .. tip:: - Take care to point your pull request towards ``symfony:2.2`` if you want - the core team to pull a bugfix based on the ``2.2`` branch. + Take care to point your pull request towards ``symfony:2.3`` if you want + the core team to pull a bugfix based on the ``2.3`` branch. To ease the core team work, always include the modified components in your pull request message, like in: From 49a02dc6b68af7cf71c5bde1cb5820429b7b1679 Mon Sep 17 00:00:00 2001 From: Daniel Gomes Date: Sat, 4 Jan 2014 22:39:56 +0000 Subject: [PATCH 0158/1181] Fixed broken urls --- components/console/introduction.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/console/introduction.rst b/components/console/introduction.rst index 4ca2bcfe8c1..0c799f8e84b 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -199,10 +199,10 @@ level. For example:: } .. versionadded:: 2.4 - The :method:`Symfony\\Component\Console\\Output\\Output::isQuiet`, - :method:`Symfony\\Component\Console\\Output\\Output::isVerbose`, - :method:`Symfony\\Component\Console\\Output\\Output::isVeryVerbose` and - :method:`Symfony\\Component\Console\\Output\\Output::isDebug` + The :method:`Symfony\\Component\\Console\\Output\\Output::isQuiet`, + :method:`Symfony\\Component\\Console\\Output\\Output::isVerbose`, + :method:`Symfony\\Component\\Console\\Output\\Output::isVeryVerbose` and + :method:`Symfony\\Component\\Console\\Output\\Output::isDebug` methods were introduced in version 2.4 There are also more semantic methods you can use to test for each of the @@ -225,7 +225,7 @@ verbosity levels:: } When the quiet level is used, all output is suppressed as the default -:method:`Symfony\Component\Console\Output::write ` +:method:`Symfony\Component\Console\Output::write ` method returns without actually printing. .. tip:: From b29ab899a445a2686189a9266e6ec8fea4b3cae4 Mon Sep 17 00:00:00 2001 From: Daniel Gomes Date: Sat, 4 Jan 2014 23:32:19 +0000 Subject: [PATCH 0159/1181] Documented the Change the Default Command in the Console component --- ...tool.rst => changing_default_behavior.rst} | 45 ++++++++++++++++++- components/console/index.rst | 2 +- 2 files changed, 44 insertions(+), 3 deletions(-) rename components/console/{single_command_tool.rst => changing_default_behavior.rst} (62%) diff --git a/components/console/single_command_tool.rst b/components/console/changing_default_behavior.rst similarity index 62% rename from components/console/single_command_tool.rst rename to components/console/changing_default_behavior.rst index 27942df40f2..33ffc6ee1e6 100644 --- a/components/console/single_command_tool.rst +++ b/components/console/changing_default_behavior.rst @@ -1,8 +1,49 @@ .. index:: - single: Console; Single command application + single: Console; Changing the Default Behavior + +Changing the Default Behavior +============================= + +When building a command line tool, you may need to customize it to fit your needs. +Probably you want to change the Default Command that the Application runs or +maybe you just want to run a Single Command instead of have to pass the command +name each time. Fortunately it is possible to do both. + +Changing the Default Command +---------------------------- + +By default the Application will always run the ListCommand. In order to change +the default command you just need to pass the command name you want to run by +default to the :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` +method:: + + #!/usr/bin/env php + add($command); + $application->setDefaultCommand($command->getName()); + $application->run() + +Test the new console command by running the following + +.. code-block:: bash + + $ app/console Fabien + +This will print the following to the command line: + +.. code-block:: text + + Hello Fabien Building a Single Command Application -===================================== +------------------------------------- When building a command line tool, you may not need to provide several commands. In such case, having to pass the command name each time is tedious. Fortunately, diff --git a/components/console/index.rst b/components/console/index.rst index c814942d018..ba15bd2c176 100644 --- a/components/console/index.rst +++ b/components/console/index.rst @@ -6,6 +6,6 @@ Console introduction usage - single_command_tool + changing_default_behavior events helpers/index From b9f8b8d5cbb603ca538889ac29e2e122e78ccfdc Mon Sep 17 00:00:00 2001 From: Philipp Rieber Date: Sun, 5 Jan 2014 13:13:10 +0100 Subject: [PATCH 0160/1181] fix "versionadded" wording --- book/validation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/validation.rst b/book/validation.rst index 4168ae079bb..9d253930917 100644 --- a/book/validation.rst +++ b/book/validation.rst @@ -587,7 +587,7 @@ allows you to add a constraint to any public method whose name starts with as "getters". .. versionadded:: 2.5 - Support for methods starting with ``has`` is new in Symfony 2.5. + Support for methods starting with ``has`` was introduced in Symfony 2.5. The benefit of this technique is that it allows you to validate your object dynamically. For example, suppose you want to make sure that a password field From 11c7174059df940a1a5e75584727c452304355f8 Mon Sep 17 00:00:00 2001 From: Daniel Gomes Date: Sun, 5 Jan 2014 14:42:59 +0000 Subject: [PATCH 0161/1181] Added the version number where the setDefaultCommand was introduced --- components/console/changing_default_behavior.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/console/changing_default_behavior.rst b/components/console/changing_default_behavior.rst index 33ffc6ee1e6..eb44d128a12 100644 --- a/components/console/changing_default_behavior.rst +++ b/components/console/changing_default_behavior.rst @@ -4,6 +4,10 @@ Changing the Default Behavior ============================= +.. versionadded:: 2.5, + The :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` + method was introduced in version 2.5 + When building a command line tool, you may need to customize it to fit your needs. Probably you want to change the Default Command that the Application runs or maybe you just want to run a Single Command instead of have to pass the command From 60e2b3ec4466b3db6450bb76da1d4f6cb0f8c368 Mon Sep 17 00:00:00 2001 From: Daniel Gomes Date: Sun, 5 Jan 2014 14:47:30 +0000 Subject: [PATCH 0162/1181] Added the delete document to avoid broken urls and added a notice that the document was moved to another location --- components/console/single_command_tool.rst | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 components/console/single_command_tool.rst diff --git a/components/console/single_command_tool.rst b/components/console/single_command_tool.rst new file mode 100644 index 00000000000..c4a477ded13 --- /dev/null +++ b/components/console/single_command_tool.rst @@ -0,0 +1,4 @@ +Building a Single Command Application +===================================== + +This Document was moved to :doc:`/components/console/changing_default_behaviour` From af9eac4f97b1918031c02d3dc395997012682e7a Mon Sep 17 00:00:00 2001 From: Daniel Gomes Date: Sun, 5 Jan 2014 14:55:02 +0000 Subject: [PATCH 0163/1181] Changed the code to remove references to Symfony Framework since it's the standalone component --- components/console/changing_default_behavior.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/console/changing_default_behavior.rst b/components/console/changing_default_behavior.rst index eb44d128a12..0dbbb64ed60 100644 --- a/components/console/changing_default_behavior.rst +++ b/components/console/changing_default_behavior.rst @@ -23,9 +23,9 @@ method:: #!/usr/bin/env php Date: Sun, 5 Jan 2014 15:12:09 +0000 Subject: [PATCH 0164/1181] Updated references to the new document --- components/console/introduction.rst | 2 +- components/map.rst.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/console/introduction.rst b/components/console/introduction.rst index 4ca2bcfe8c1..d7217176400 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -525,7 +525,7 @@ Learn More! ----------- * :doc:`/components/console/usage` -* :doc:`/components/console/single_command_tool` +* :doc:`/components/console/changing_default_behavior` .. _Packagist: https://packagist.org/packages/symfony/console .. _ANSICON: https://github.com/adoxa/ansicon/downloads diff --git a/components/map.rst.inc b/components/map.rst.inc index a5f2d0f8db7..842097c5ef2 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -19,7 +19,7 @@ * :doc:`/components/console/introduction` * :doc:`/components/console/usage` - * :doc:`/components/console/single_command_tool` + * :doc:`/components/console/changing_default_behavior` * :doc:`/components/console/events` * :doc:`/components/console/helpers/index` From 012456d9f5a13455c4271d1fdc888600c415ebef Mon Sep 17 00:00:00 2001 From: Daniel Gomes Date: Sun, 5 Jan 2014 15:20:41 +0000 Subject: [PATCH 0165/1181] Moved `versionadded` to the right section --- components/console/changing_default_behavior.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/console/changing_default_behavior.rst b/components/console/changing_default_behavior.rst index 0dbbb64ed60..e89332b4c9d 100644 --- a/components/console/changing_default_behavior.rst +++ b/components/console/changing_default_behavior.rst @@ -4,10 +4,6 @@ Changing the Default Behavior ============================= -.. versionadded:: 2.5, - The :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` - method was introduced in version 2.5 - When building a command line tool, you may need to customize it to fit your needs. Probably you want to change the Default Command that the Application runs or maybe you just want to run a Single Command instead of have to pass the command @@ -16,6 +12,10 @@ name each time. Fortunately it is possible to do both. Changing the Default Command ---------------------------- +.. versionadded:: 2.5, +The :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` + method was introduced in version 2.5 + By default the Application will always run the ListCommand. In order to change the default command you just need to pass the command name you want to run by default to the :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` From c23f34e0f5f9bd6984a2e01aed5d768e1ed82753 Mon Sep 17 00:00:00 2001 From: Daniel Gomes Date: Sun, 5 Jan 2014 22:39:12 +0000 Subject: [PATCH 0166/1181] Applied some suggestions --- .../console/changing_default_behavior.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/components/console/changing_default_behavior.rst b/components/console/changing_default_behavior.rst index e89332b4c9d..244d9ed6af3 100644 --- a/components/console/changing_default_behavior.rst +++ b/components/console/changing_default_behavior.rst @@ -5,21 +5,20 @@ Changing the Default Behavior ============================= When building a command line tool, you may need to customize it to fit your needs. -Probably you want to change the Default Command that the Application runs or -maybe you just want to run a Single Command instead of have to pass the command -name each time. Fortunately it is possible to do both. +Probably you want to change the default command that the Application runs or +maybe you just want to run a single command instead of have to pass the command +name each time. Fortunately, it is possible to do both. Changing the Default Command ---------------------------- .. versionadded:: 2.5, -The :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` - method was introduced in version 2.5 + The :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` + method was introduced in version 2.5. By default the Application will always run the ListCommand. In order to change the default command you just need to pass the command name you want to run by -default to the :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` -method:: +default to the ``setDefaultCommand`` method:: #!/usr/bin/env php Date: Sun, 5 Jan 2014 23:43:24 +0100 Subject: [PATCH 0167/1181] Added info about JsonFileLoader added in 2.4 --- components/translation/introduction.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/translation/introduction.rst b/components/translation/introduction.rst index 2151bebd15e..243a453cdd9 100644 --- a/components/translation/introduction.rst +++ b/components/translation/introduction.rst @@ -62,6 +62,9 @@ The Translation component uses Loader classes to load catalogs. You can load multiple resources for the same locale, which will then be combined into one catalog. +.. versionadded:: 2.4 + The ``JsonFileLoader`` was introduced in Symfony 2.4. + The component comes with some default Loaders and you can create your own Loader too. The default loaders are: @@ -85,6 +88,8 @@ Loader too. The default loaders are: catalogs form QT XML files. * :class:`Symfony\\Component\\Translation\\Loader\\XliffFileLoader` - to load catalogs from Xliff files. +* :class:`Symfony\\Component\\Translation\\Loader\\JsonFileLoader` - to load + catalogs from JSON files. * :class:`Symfony\\Component\\Translation\\Loader\\YamlFileLoader` - to load catalogs from Yaml files (requires the :doc:`Yaml component`). From 732758b850438ed12ab53a84858fb2826423a17b Mon Sep 17 00:00:00 2001 From: Mathieu Lemoine Date: Mon, 6 Jan 2014 08:10:45 -0500 Subject: [PATCH 0168/1181] [Contributing] Fix "When you finish" => "When you are finished" As per @xabbuh suggestion: https://github.com/symfony/symfony-docs/pull/3421#discussion_r8661716 --- contributing/code/patches.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributing/code/patches.rst b/contributing/code/patches.rst index 2f313f87f69..0e38190bb33 100644 --- a/contributing/code/patches.rst +++ b/contributing/code/patches.rst @@ -398,7 +398,7 @@ To squash all commits into the first one, remove the word ``pick`` before the second and the last commits, and replace it by the word ``squash`` or just ``s``. When you save, Git will start rebasing, and if successful, will ask you to edit the commit message, which by default is a listing of the commit - messages of all the commits. When you finish, execute the push command. + messages of all the commits. When you are finished, execute the push command. .. _ProGit: http://git-scm.com/book .. _GitHub: https://github.com/signup/free From 4101d9bf7b448b547d2db890d3d4d33fb0c99433 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 6 Jan 2014 21:46:31 +0000 Subject: [PATCH 0169/1181] Update custom_password_authenticator.rst Fixed TokenInterface use statement causing compile errors --- cookbook/security/custom_password_authenticator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/custom_password_authenticator.rst b/cookbook/security/custom_password_authenticator.rst index 2f4b86c4647..751beef449c 100644 --- a/cookbook/security/custom_password_authenticator.rst +++ b/cookbook/security/custom_password_authenticator.rst @@ -25,7 +25,7 @@ the user:: use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\SimpleFormAuthenticatorInterface; - use Symfony\Component\Security\Core\Authentication\TokenInterface; + use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; From 94fe8dc430f5f70971bb80218df285ddaef2079e Mon Sep 17 00:00:00 2001 From: Marek Kalnik Date: Mon, 6 Jan 2014 23:14:48 +0100 Subject: [PATCH 0170/1181] Add info about callback in options resolver --- components/options_resolver.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index 9a62f8581fa..d14ee678278 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -305,6 +305,26 @@ There is also an method, which you can use if you want to add an allowed value to the previously set allowed values. +If you need to add some more logic to the value validation process you can pass a callable +as an allowed value:: + + // ... + protected function setDefaultOptions(OptionsResolverInterface $resolver) + { + // ... + + $resolver->setAllowedValues(array( + 'transport' => function($value) { + return strpos($value, 'mail') !== false; + } + )); + } + +Note that using this together with addAllowedValues will not work. + +.. versionadded:: 2.5 + The callback support for allowed values was added in Symfony 2.5. + Configure allowed Types ~~~~~~~~~~~~~~~~~~~~~~~ From c0de1cb392b45fad07978122126fd4ab9ad60bac Mon Sep 17 00:00:00 2001 From: Mathieu Lemoine Date: Mon, 6 Jan 2014 14:26:47 -0500 Subject: [PATCH 0171/1181] [Contributing] Replace HEAD~3 by upstream/master As per @cordoval suggestion: https://github.com/symfony/symfony-docs/pull/3421#discussion_r8670868 --- contributing/code/patches.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributing/code/patches.rst b/contributing/code/patches.rst index 0e38190bb33..7f0667ea960 100644 --- a/contributing/code/patches.rst +++ b/contributing/code/patches.rst @@ -382,7 +382,7 @@ convert many commits to one commit. To do this, use the rebase command: .. code-block:: bash - $ git rebase -i HEAD~3 + $ git rebase -i upstream/master $ git push -f origin BRANCH_NAME The number 3 here must equal the amount of commits in your branch. After you From 5e97202fcf5d974964bb540d85bc6e15c2395cc0 Mon Sep 17 00:00:00 2001 From: Daniel Gomes Date: Tue, 7 Jan 2014 15:16:45 +0000 Subject: [PATCH 0172/1181] Applyed suggestions from @fabpot and @stof --- .../console/changing_default_behavior.rst | 116 ------------------ .../console/changing_default_command.rst | 67 ++++++++++ components/console/index.rst | 3 +- components/console/introduction.rst | 3 +- components/console/single_command_tool.rst | 70 ++++++++++- 5 files changed, 140 insertions(+), 119 deletions(-) delete mode 100644 components/console/changing_default_behavior.rst create mode 100644 components/console/changing_default_command.rst diff --git a/components/console/changing_default_behavior.rst b/components/console/changing_default_behavior.rst deleted file mode 100644 index 244d9ed6af3..00000000000 --- a/components/console/changing_default_behavior.rst +++ /dev/null @@ -1,116 +0,0 @@ -.. index:: - single: Console; Changing the Default Behavior - -Changing the Default Behavior -============================= - -When building a command line tool, you may need to customize it to fit your needs. -Probably you want to change the default command that the Application runs or -maybe you just want to run a single command instead of have to pass the command -name each time. Fortunately, it is possible to do both. - -Changing the Default Command ----------------------------- - -.. versionadded:: 2.5, - The :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` - method was introduced in version 2.5. - -By default the Application will always run the ListCommand. In order to change -the default command you just need to pass the command name you want to run by -default to the ``setDefaultCommand`` method:: - - #!/usr/bin/env php - add($command); - $application->setDefaultCommand($command->getName()); - $application->run() - -Test the new console command by running the following - -.. code-block:: bash - - $ app/console Fabien - -This will print the following to the command line: - -.. code-block:: text - - Hello Fabien - -Building a Single Command Application -------------------------------------- - -When building a command line tool, you may not need to provide several commands. -In such case, having to pass the command name each time is tedious. Fortunately, -it is possible to remove this need by extending the application:: - - namespace Acme\Tool; - - use Symfony\Component\Console\Application; - use Symfony\Component\Console\Input\InputInterface; - - class MyApplication extends Application - { - /** - * Gets the name of the command based on input. - * - * @param InputInterface $input The input interface - * - * @return string The command name - */ - protected function getCommandName(InputInterface $input) - { - // This should return the name of your command. - return 'my_command'; - } - - /** - * Gets the default commands that should always be available. - * - * @return array An array of default Command instances - */ - protected function getDefaultCommands() - { - // Keep the core default commands to have the HelpCommand - // which is used when using the --help option - $defaultCommands = parent::getDefaultCommands(); - - $defaultCommands[] = new MyCommand(); - - return $defaultCommands; - } - - /** - * Overridden so that the application doesn't expect the command - * name to be the first argument. - */ - public function getDefinition() - { - $inputDefinition = parent::getDefinition(); - // clear out the normal first argument, which is the command name - $inputDefinition->setArguments(); - - return $inputDefinition; - } - } - -When calling your console script, the ``MyCommand`` command will then always -be used, without having to pass its name. - -Executing the application can also be simplified:: - - #!/usr/bin/env php - run(); diff --git a/components/console/changing_default_command.rst b/components/console/changing_default_command.rst new file mode 100644 index 00000000000..a90e298223a --- /dev/null +++ b/components/console/changing_default_command.rst @@ -0,0 +1,67 @@ +.. index:: + single: Console; Changing the Default Command + +Changing the Default Command +============================ + +.. versionadded:: 2.5, + The :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` + method was introduced in version 2.5. + +By default the Application will always run the ``ListCommand``. In order to change +the default command you just need to pass the command name you want to run by +default to the ``setDefaultCommand`` method:: + + namespace Acme\Command; + + use Symfony\Component\Console\Command\Command; + use Symfony\Component\Console\Input\InputInterface; + use Symfony\Component\Console\Output\OutputInterface; + + class HelloWorldCommand extends Command + { + protected function configure() + { + $this->setName('hello:world') + ->setDescription('Outputs \'Hello World\''); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $output->writeln('Hello World'); + } + } + +Executing the application and changing the default Command:: + + // application.php + + use Acme\Command\HelloWorldCommand; + use Symfony\Component\Console\Application; + + $command = new HelloWorldCommand(); + $application = new Application(); + $application->add($command); + $application->setDefaultCommand($command->getName()); + $application->run(); + +Test the new default console command by running the following + +.. code-block:: bash + + $ php application.php + +This will print the following to the command line: + +.. code-block:: text + + Hello Fabien + +.. tip:: + + The feature was a limitation since you cannot use the Command ``arguments``. + +Learn More! +----------- + +* :doc:`/components/console/single_command_tool` diff --git a/components/console/index.rst b/components/console/index.rst index ba15bd2c176..f974291a8e0 100644 --- a/components/console/index.rst +++ b/components/console/index.rst @@ -6,6 +6,7 @@ Console introduction usage - changing_default_behavior + changing_default_command + single_command_tool events helpers/index diff --git a/components/console/introduction.rst b/components/console/introduction.rst index d7217176400..c742c333f89 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -525,7 +525,8 @@ Learn More! ----------- * :doc:`/components/console/usage` -* :doc:`/components/console/changing_default_behavior` +* :doc:`/components/console/single_command_tool` +* :doc:`/components/console/changing_default_command` .. _Packagist: https://packagist.org/packages/symfony/console .. _ANSICON: https://github.com/adoxa/ansicon/downloads diff --git a/components/console/single_command_tool.rst b/components/console/single_command_tool.rst index c4a477ded13..a5ba82ceca5 100644 --- a/components/console/single_command_tool.rst +++ b/components/console/single_command_tool.rst @@ -1,4 +1,72 @@ +.. index:: +single: Console; Single command application + Building a Single Command Application ===================================== -This Document was moved to :doc:`/components/console/changing_default_behaviour` +When building a command line tool, you may not need to provide several commands. +In such case, having to pass the command name each time is tedious. Fortunately, +it is possible to remove this need by extending the application:: + + namespace Acme\Tool; + + use Symfony\Component\Console\Application; + use Symfony\Component\Console\Input\InputInterface; + + class MyApplication extends Application + { + /** + * Gets the name of the command based on input. + * + * @param InputInterface $input The input interface + * + * @return string The command name + */ + protected function getCommandName(InputInterface $input) + { + // This should return the name of your command. + return 'my_command'; + } + + /** + * Gets the default commands that should always be available. + * + * @return array An array of default Command instances + */ + protected function getDefaultCommands() + { + // Keep the core default commands to have the HelpCommand + // which is used when using the --help option + $defaultCommands = parent::getDefaultCommands(); + + $defaultCommands[] = new MyCommand(); + + return $defaultCommands; + } + + /** + * Overridden so that the application doesn't expect the command + * name to be the first argument. + */ + public function getDefinition() + { + $inputDefinition = parent::getDefinition(); + // clear out the normal first argument, which is the command name + $inputDefinition->setArguments(); + + return $inputDefinition; + } + } + +When calling your console script, the command ``MyCommand`` will then always +be used, without having to pass its name. + +You can also simplify how you execute the application:: + + #!/usr/bin/env php + run(); From fdf48913ed078ac5f232bdbb07d2c6b2e1009b82 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Wed, 8 Jan 2014 22:39:58 +0000 Subject: [PATCH 0173/1181] Documented deprecation of the apache router. --- cookbook/configuration/apache_router.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cookbook/configuration/apache_router.rst b/cookbook/configuration/apache_router.rst index c740979534a..4eca8afe3b3 100644 --- a/cookbook/configuration/apache_router.rst +++ b/cookbook/configuration/apache_router.rst @@ -7,6 +7,12 @@ How to use the Apache Router Symfony2, while fast out of the box, also provides various ways to increase that speed with a little bit of tweaking. One of these ways is by letting Apache handle routes directly, rather than using Symfony2 for this task. +.. note:: + + Apache router was deprecated in Symfony 2.5 and will be removed in Symfony 3.0. + Since the PHP implementation of the Router was improved, performance gains were no longer + significant (while it's very hard to replicate the same behaviour). + Change Router Configuration Parameters -------------------------------------- From a5a56683d02feb140369e9efb415528644dd68d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joan=20Teixid=C3=B3?= Date: Thu, 9 Jan 2014 00:12:34 +0100 Subject: [PATCH 0174/1181] Fix error in namespace when use TokenInterface Change the use statement of TokenInterface to the correct namespace (missing Token folder) --- cookbook/security/custom_password_authenticator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/custom_password_authenticator.rst b/cookbook/security/custom_password_authenticator.rst index 2f4b86c4647..751beef449c 100644 --- a/cookbook/security/custom_password_authenticator.rst +++ b/cookbook/security/custom_password_authenticator.rst @@ -25,7 +25,7 @@ the user:: use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\SimpleFormAuthenticatorInterface; - use Symfony\Component\Security\Core\Authentication\TokenInterface; + use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; From c1b2aad00e47ddd9c02732f24ed2ce3960210e03 Mon Sep 17 00:00:00 2001 From: Daniel Gomes Date: Thu, 9 Jan 2014 09:17:19 +0000 Subject: [PATCH 0175/1181] Applied suggestions from Ryan --- components/console/changing_default_command.rst | 8 ++++---- components/console/single_command_tool.rst | 2 +- components/map.rst.inc | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/components/console/changing_default_command.rst b/components/console/changing_default_command.rst index a90e298223a..a2072c795ba 100644 --- a/components/console/changing_default_command.rst +++ b/components/console/changing_default_command.rst @@ -1,5 +1,5 @@ .. index:: - single: Console; Changing the Default Command + single: Console; Changing the Default Command Changing the Default Command ============================ @@ -8,7 +8,7 @@ Changing the Default Command The :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` method was introduced in version 2.5. -By default the Application will always run the ``ListCommand``. In order to change +will always run the ``ListCommand`` when no command name is passed. In order to change the default command you just need to pass the command name you want to run by default to the ``setDefaultCommand`` method:: @@ -45,7 +45,7 @@ Executing the application and changing the default Command:: $application->setDefaultCommand($command->getName()); $application->run(); -Test the new default console command by running the following +Test the new default console command by running the following: .. code-block:: bash @@ -59,7 +59,7 @@ This will print the following to the command line: .. tip:: - The feature was a limitation since you cannot use the Command ``arguments``. + This feature has a limitation: you cannot use it with any Command arguments. Learn More! ----------- diff --git a/components/console/single_command_tool.rst b/components/console/single_command_tool.rst index a5ba82ceca5..02fc24a565f 100644 --- a/components/console/single_command_tool.rst +++ b/components/console/single_command_tool.rst @@ -1,5 +1,5 @@ .. index:: -single: Console; Single command application + single: Console; Single command application Building a Single Command Application ===================================== diff --git a/components/map.rst.inc b/components/map.rst.inc index 842097c5ef2..7a5c74eeff6 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -19,7 +19,8 @@ * :doc:`/components/console/introduction` * :doc:`/components/console/usage` - * :doc:`/components/console/changing_default_behavior` + * :doc:`/components/console/single_command_tool` + * :doc:`/components/console/changing_default_command` * :doc:`/components/console/events` * :doc:`/components/console/helpers/index` From 4fb6e59b1492a0923a9cd351fcbbaf7604cb51ec Mon Sep 17 00:00:00 2001 From: ghostika Date: Thu, 9 Jan 2014 20:49:57 +0100 Subject: [PATCH 0176/1181] Add host config to the security documentation --- book/security.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/book/security.rst b/book/security.rst index e60e581abc5..b006beb260b 100644 --- a/book/security.rst +++ b/book/security.rst @@ -151,6 +151,9 @@ that looks like the following: Let's look briefly at how security works and how each part of the configuration comes into play. +.. versionadded:: 2.4 + A new property was added to the firewall configuration, where you can make a restriction, called ``host``. + How Security Works: Authentication and Authorization ---------------------------------------------------- From 0244173f3a3b187c3e57a108ab30766652dc9768 Mon Sep 17 00:00:00 2001 From: Ghostika Date: Thu, 9 Jan 2014 21:15:30 +0100 Subject: [PATCH 0177/1181] add host to the config page --- reference/configuration/security.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/reference/configuration/security.rst b/reference/configuration/security.rst index bdaa387acc8..4a6b355782a 100644 --- a/reference/configuration/security.rst +++ b/reference/configuration/security.rst @@ -98,6 +98,8 @@ Each part will be explained in the next section. # Examples: somename: pattern: .* + # restrict the firewall for a specific host + host: admin\.example\.com request_matcher: some.service.id access_denied_url: /foo/error403 access_denied_handler: some.service.id From cc8d19ac8729da4fa0cc0cd1bf4a364e6a1cb722 Mon Sep 17 00:00:00 2001 From: Ghostika Date: Thu, 9 Jan 2014 22:14:46 +0100 Subject: [PATCH 0178/1181] line break --- book/security.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/book/security.rst b/book/security.rst index b006beb260b..68f322823cb 100644 --- a/book/security.rst +++ b/book/security.rst @@ -152,7 +152,8 @@ Let's look briefly at how security works and how each part of the configuration comes into play. .. versionadded:: 2.4 - A new property was added to the firewall configuration, where you can make a restriction, called ``host``. + A new property was added to the firewall configuration, where you can +make a restriction, called ``host``. How Security Works: Authentication and Authorization ---------------------------------------------------- From b64d73f62d732c9f57f937705482d93cb688f0cf Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 9 Jan 2014 23:21:30 +0100 Subject: [PATCH 0179/1181] remove duplicate label --- book/security.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/book/security.rst b/book/security.rst index e60e581abc5..d5bb50f3747 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1098,7 +1098,7 @@ Thanks to the SensioFrameworkExtraBundle, you can also secure your controller us // ... } -For more information, see the +For more information, see the :doc:`FrameworkExtraBundle documentation `. Securing other Services @@ -1733,8 +1733,6 @@ Access Control Now that you have a User and Roles, you can go further than URL-pattern based authorization. -.. _book-security-securing-controller: - Access Control in Controllers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 3334743ab0d21f9c3cd46cbcb2796ec37516015a Mon Sep 17 00:00:00 2001 From: Loick Piera Date: Tue, 7 Jan 2014 19:26:40 +0100 Subject: [PATCH 0180/1181] Change title 'Accessing Public Methods' Change title 'Accessing Public Methods' to 'Accessing Public Properties'. Title 'Accessing Public Properties' more in relation with the content. --- components/expression_language/syntax.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index 4a45f9fbe55..9d401fbffc8 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -28,7 +28,7 @@ Working with Objects When passing objects into an expression, you can use different syntaxes to access properties and call methods on the object. -Accessing Public Methods +Accessing Public Properties ~~~~~~~~~~~~~~~~~~~~~~~~ Public properties on objects can be accessed by using the ``.`` syntax, similar From 52c858695eb50a9b707394c77d707dd2c3769e1b Mon Sep 17 00:00:00 2001 From: Loick Piera Date: Tue, 7 Jan 2014 23:26:58 +0100 Subject: [PATCH 0181/1181] fixe tagline --- components/expression_language/syntax.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index 9d401fbffc8..80a3567362d 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -29,7 +29,7 @@ When passing objects into an expression, you can use different syntaxes to access properties and call methods on the object. Accessing Public Properties -~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~ Public properties on objects can be accessed by using the ``.`` syntax, similar to JavaScript:: From 3e42b84281ac6a17764873b4d450e8869bdfe720 Mon Sep 17 00:00:00 2001 From: Ghostika Date: Sat, 11 Jan 2014 20:26:10 +0100 Subject: [PATCH 0182/1181] Add versionadded tag to security config reference, reference cookbok entry in book --- book/security.rst | 7 ++++--- reference/configuration/security.rst | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/book/security.rst b/book/security.rst index 68f322823cb..389df85d3ff 100644 --- a/book/security.rst +++ b/book/security.rst @@ -152,8 +152,8 @@ Let's look briefly at how security works and how each part of the configuration comes into play. .. versionadded:: 2.4 - A new property was added to the firewall configuration, where you can -make a restriction, called ``host``. + Support for restricting security firewalls to a specific host was added in + Symfony 2.4. How Security Works: Authentication and Authorization ---------------------------------------------------- @@ -1102,7 +1102,7 @@ Thanks to the SensioFrameworkExtraBundle, you can also secure your controller us // ... } -For more information, see the +For more information, see the :doc:`FrameworkExtraBundle documentation `. Securing other Services @@ -2168,6 +2168,7 @@ Learn more from the Cookbook * :doc:`Blacklist users by IP address with a custom voter ` * :doc:`Access Control Lists (ACLs) ` * :doc:`/cookbook/security/remember_me` +* :doc:`How to Restrict Firewalls to a Specific Host ` .. _`FOSUserBundle`: https://github.com/FriendsOfSymfony/FOSUserBundle .. _`implement the \Serializable interface`: http://php.net/manual/en/class.serializable.php diff --git a/reference/configuration/security.rst b/reference/configuration/security.rst index 4a6b355782a..c69a9a987a5 100644 --- a/reference/configuration/security.rst +++ b/reference/configuration/security.rst @@ -13,6 +13,10 @@ Full Default Configuration The following is the full default configuration for the security system. Each part will be explained in the next section. +.. versionadded:: 2.4 + Support for restricting security firewalls to a specific host was added in + Symfony 2.4. + .. configuration-block:: .. code-block:: yaml From 6cba1922f54066a36594a8f352cb506c3064f80f Mon Sep 17 00:00:00 2001 From: Ghostika Date: Sat, 11 Jan 2014 20:52:16 +0100 Subject: [PATCH 0183/1181] remove versionadded from book and fix words --- book/security.rst | 4 ---- cookbook/security/host_restriction.rst | 2 +- reference/configuration/security.rst | 4 ++-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/book/security.rst b/book/security.rst index 389df85d3ff..671e9373dac 100644 --- a/book/security.rst +++ b/book/security.rst @@ -151,10 +151,6 @@ that looks like the following: Let's look briefly at how security works and how each part of the configuration comes into play. -.. versionadded:: 2.4 - Support for restricting security firewalls to a specific host was added in - Symfony 2.4. - How Security Works: Authentication and Authorization ---------------------------------------------------- diff --git a/cookbook/security/host_restriction.rst b/cookbook/security/host_restriction.rst index 232f1cd5ff6..b5b2e529d95 100644 --- a/cookbook/security/host_restriction.rst +++ b/cookbook/security/host_restriction.rst @@ -5,7 +5,7 @@ How to Restrict Firewalls to a Specific Host ============================================ .. versionadded:: 2.4 - Support for restricting security firewalls to a specific host was added in + Support for restricting security firewalls to a specific host was introduced in Symfony 2.4. When using the Security component, you can create firewalls that match certain diff --git a/reference/configuration/security.rst b/reference/configuration/security.rst index c69a9a987a5..6a1d6c6ed67 100644 --- a/reference/configuration/security.rst +++ b/reference/configuration/security.rst @@ -14,7 +14,7 @@ The following is the full default configuration for the security system. Each part will be explained in the next section. .. versionadded:: 2.4 - Support for restricting security firewalls to a specific host was added in + Support for restricting security firewalls to a specific host was introduced in Symfony 2.4. .. configuration-block:: @@ -102,7 +102,7 @@ Each part will be explained in the next section. # Examples: somename: pattern: .* - # restrict the firewall for a specific host + # restrict the firewall to a specific host host: admin\.example\.com request_matcher: some.service.id access_denied_url: /foo/error403 From faa034b3e678dde3d6401c36258fa953f4cb5cb4 Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Sun, 12 Jan 2014 18:58:23 +0100 Subject: [PATCH 0184/1181] [WIP][Valiadtor] - EmailConstraint reference --- reference/constraints/Email.rst | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/reference/constraints/Email.rst b/reference/constraints/Email.rst index 5eacfbda04b..48cf138b9a9 100644 --- a/reference/constraints/Email.rst +++ b/reference/constraints/Email.rst @@ -7,7 +7,8 @@ cast to a string before being validated. +----------------+---------------------------------------------------------------------+ | Applies to | :ref:`property or method ` | +----------------+---------------------------------------------------------------------+ -| Options | - `message`_ | +| Options | - `strict`_ | +| | - `message`_ | | | - `checkMX`_ | | | - `checkHost`_ | +----------------+---------------------------------------------------------------------+ @@ -89,6 +90,15 @@ Basic Usage Options ------- +strict +~~~~~~~ + +**type**: ``boolean`` **default**: ``false`` + +Will validate the email against a simple RegularExpression. +If true, then the library (`egulias/email-validator`)[https://packagist.org/packages/egulias/email-validator] +is required to perform an RFC compilant validation. + message ~~~~~~~ From e4a0e2f0ff892a3ec5ca9a7d45554b57d6b11fa5 Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Sun, 12 Jan 2014 19:07:33 +0100 Subject: [PATCH 0185/1181] Use of Sphinx markup --- reference/constraints/Email.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/constraints/Email.rst b/reference/constraints/Email.rst index 48cf138b9a9..caba8cd7fcc 100644 --- a/reference/constraints/Email.rst +++ b/reference/constraints/Email.rst @@ -96,7 +96,7 @@ strict **type**: ``boolean`` **default**: ``false`` Will validate the email against a simple RegularExpression. -If true, then the library (`egulias/email-validator`)[https://packagist.org/packages/egulias/email-validator] +If true, then the `EmailValidator `_ library is required to perform an RFC compilant validation. message From f0b3b85567f0865a983e1ece7a0780416239597e Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Sun, 12 Jan 2014 19:53:58 +0100 Subject: [PATCH 0186/1181] Version added and clarifications --- reference/constraints/Email.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/reference/constraints/Email.rst b/reference/constraints/Email.rst index caba8cd7fcc..e459115dfa8 100644 --- a/reference/constraints/Email.rst +++ b/reference/constraints/Email.rst @@ -91,11 +91,13 @@ Options ------- strict -~~~~~~~ +~~~~~~ +.. versionadded:: 2.5 + The ``strict`` option was introduced in Symfony 2.5. **type**: ``boolean`` **default**: ``false`` -Will validate the email against a simple RegularExpression. +When false, the email will be validated against a simple RegularExpression. If true, then the `EmailValidator `_ library is required to perform an RFC compilant validation. From 517e4c549372cc81138ca590bf53506817c3402d Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Sun, 12 Jan 2014 20:24:11 +0100 Subject: [PATCH 0187/1181] Link moved and heading updated --- reference/constraints/Email.rst | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/reference/constraints/Email.rst b/reference/constraints/Email.rst index e459115dfa8..518503f583e 100644 --- a/reference/constraints/Email.rst +++ b/reference/constraints/Email.rst @@ -90,16 +90,16 @@ Basic Usage Options ------- -strict -~~~~~~ .. versionadded:: 2.5 The ``strict`` option was introduced in Symfony 2.5. +strict +~~~~~~ + **type**: ``boolean`` **default**: ``false`` -When false, the email will be validated against a simple RegularExpression. -If true, then the `EmailValidator `_ library -is required to perform an RFC compilant validation. +When false, the email will be validated against a simple Regular Expression. +If true, then the `egulias/email-validator`_ library is required to perform an RFC compilant validation. message ~~~~~~~ @@ -124,3 +124,6 @@ checkHost If true, then the :phpfunction:`checkdnsrr` PHP function will be used to check the validity of the MX *or* the A *or* the AAAA record of the host of the given email. + + +.. _EmailValidator: https://packagist.org/packages/egulias/email-validator From cce3b40b6b6be563827010bf991a4c0bdc702ffc Mon Sep 17 00:00:00 2001 From: Daniel Gomes Date: Sun, 12 Jan 2014 20:41:15 +0000 Subject: [PATCH 0188/1181] fixed typo --- components/console/changing_default_command.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/console/changing_default_command.rst b/components/console/changing_default_command.rst index a2072c795ba..d00e60a3d7f 100644 --- a/components/console/changing_default_command.rst +++ b/components/console/changing_default_command.rst @@ -4,7 +4,7 @@ Changing the Default Command ============================ -.. versionadded:: 2.5, +.. versionadded:: 2.5 The :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` method was introduced in version 2.5. From 8beb5704adc38a24d1d9e4581b6740cf8f8f87bd Mon Sep 17 00:00:00 2001 From: Daniel Gomes Date: Sun, 12 Jan 2014 21:50:05 +0000 Subject: [PATCH 0189/1181] Fixed `versionadded` inconsistencies --- cookbook/security/acl_advanced.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/acl_advanced.rst b/cookbook/security/acl_advanced.rst index 01228220bb6..208f72d3b6e 100644 --- a/cookbook/security/acl_advanced.rst +++ b/cookbook/security/acl_advanced.rst @@ -50,7 +50,7 @@ your application. Each role, or user has its own security identity. if for any reason, a user's username was to change, you must ensure its security identity is updated too. The :method:`MutableAclProvider::updateUserSecurityIdentity() ` - method is there to handle the update. + method is there to handle the update, it was introduced in Symfony 2.5. Database Table Structure ------------------------ From aa5aa61593465b80838dd7cc34d5b8d7843fc6e9 Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Sun, 12 Jan 2014 23:47:32 +0100 Subject: [PATCH 0190/1181] Typo and link label --- reference/constraints/Email.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/constraints/Email.rst b/reference/constraints/Email.rst index 518503f583e..d1be0e43dad 100644 --- a/reference/constraints/Email.rst +++ b/reference/constraints/Email.rst @@ -99,7 +99,7 @@ strict **type**: ``boolean`` **default**: ``false`` When false, the email will be validated against a simple Regular Expression. -If true, then the `egulias/email-validator`_ library is required to perform an RFC compilant validation. +If true, then the `EmailValidator`_ library is required to perform an RFC compliant validation. message ~~~~~~~ From 8231230f426e95ff0f2661b33a2555c0b88b27cd Mon Sep 17 00:00:00 2001 From: Marek Kalnik Date: Mon, 13 Jan 2014 20:15:38 +0100 Subject: [PATCH 0191/1181] Fix according to PR comments --- components/options_resolver.rst | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index d14ee678278..56cfa62d4b1 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -305,7 +305,11 @@ There is also an method, which you can use if you want to add an allowed value to the previously set allowed values. -If you need to add some more logic to the value validation process you can pass a callable +.. versionadded:: 2.5 + + The callback support for allowed values was introduced in Symfony 2.5. + +If you need to add some more logic to the value validation process, you can pass a callable as an allowed value:: // ... @@ -315,15 +319,14 @@ as an allowed value:: $resolver->setAllowedValues(array( 'transport' => function($value) { - return strpos($value, 'mail') !== false; - } + return false !== strpos($value, 'mail'); + }, )); } -Note that using this together with addAllowedValues will not work. +.. caution:: -.. versionadded:: 2.5 - The callback support for allowed values was added in Symfony 2.5. + Note that using this together with ``addAllowedValues`` will not work. Configure allowed Types ~~~~~~~~~~~~~~~~~~~~~~~ From a0dd460633842ef7f3e028786d7f503b18613f91 Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Mon, 13 Jan 2014 23:12:35 +0100 Subject: [PATCH 0192/1181] Lowercase and link label --- reference/constraints/Email.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/constraints/Email.rst b/reference/constraints/Email.rst index d1be0e43dad..4b64e3c9632 100644 --- a/reference/constraints/Email.rst +++ b/reference/constraints/Email.rst @@ -98,8 +98,8 @@ strict **type**: ``boolean`` **default**: ``false`` -When false, the email will be validated against a simple Regular Expression. -If true, then the `EmailValidator`_ library is required to perform an RFC compliant validation. +When false, the email will be validated against a simple regular expression. +If true, then the `egulias/email-validator`_ library is required to perform an RFC compliant validation. message ~~~~~~~ @@ -126,4 +126,4 @@ check the validity of the MX *or* the A *or* the AAAA record of the host of the given email. -.. _EmailValidator: https://packagist.org/packages/egulias/email-validator +.. _egulias/email-validator: https://packagist.org/packages/egulias/email-validator From f39686a1d5f077991cc8186dfc5cbb87b8151943 Mon Sep 17 00:00:00 2001 From: skowi Date: Wed, 15 Jan 2014 09:56:06 +0100 Subject: [PATCH 0193/1181] Changed extends to implements --- cookbook/security/api_key_authentication.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index cd2812ebd88..b23a3da9299 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -145,7 +145,7 @@ The ``$userProvider`` might look something like this:: use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; - class ApiKeyUserProvider extends UserProviderInterface + class ApiKeyUserProvider implements UserProviderInterface { public function getUsernameForApiKey($apiKey) { From 18657aabc0c3383c8e72736dc55d141ed60c303f Mon Sep 17 00:00:00 2001 From: Piotr Strugacz Date: Wed, 15 Jan 2014 16:49:35 +0100 Subject: [PATCH 0194/1181] Update custom_password_authenticator.rst Correct me if I am wrong... but because we are passing here ```username``` as first argument to ```UsernamePasswordToken```, when one would like to use method ```getUser()```: ``` ... if (!$this->container->has('security.context')) { throw new \LogicException('The SecurityBundle is not registered in your application.'); } if (null === $token = $this->container->get('security.context')->getToken()) { return null; } if (!is_object($user = $token->getUser())) { return null; } return $user; ... ``` from base ```Controller```, it will fail, to get actually logged user and return null. --- cookbook/security/custom_password_authenticator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/custom_password_authenticator.rst b/cookbook/security/custom_password_authenticator.rst index 751beef449c..890c290eae2 100644 --- a/cookbook/security/custom_password_authenticator.rst +++ b/cookbook/security/custom_password_authenticator.rst @@ -66,7 +66,7 @@ the user:: } return new UsernamePasswordToken( - $user->getUsername(), + $user, $user->getPassword(), $providerKey, $user->getRoles() From c50f0413782ea8d76a785e7aafac90049439a1a9 Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Fri, 17 Jan 2014 00:11:14 +0100 Subject: [PATCH 0195/1181] CS --- reference/constraints/Email.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/reference/constraints/Email.rst b/reference/constraints/Email.rst index 4b64e3c9632..02c736bc6e5 100644 --- a/reference/constraints/Email.rst +++ b/reference/constraints/Email.rst @@ -99,7 +99,8 @@ strict **type**: ``boolean`` **default**: ``false`` When false, the email will be validated against a simple regular expression. -If true, then the `egulias/email-validator`_ library is required to perform an RFC compliant validation. +If true, then the `egulias/email-validator`_ library is required to perform +an RFC compliant validation. message ~~~~~~~ @@ -124,6 +125,4 @@ checkHost If true, then the :phpfunction:`checkdnsrr` PHP function will be used to check the validity of the MX *or* the A *or* the AAAA record of the host of the given email. - - .. _egulias/email-validator: https://packagist.org/packages/egulias/email-validator From 6fd3f93201ec093d20b12f13f035373ac5a0bec0 Mon Sep 17 00:00:00 2001 From: Klaus Silveira Date: Fri, 17 Jan 2014 10:51:53 -0200 Subject: [PATCH 0196/1181] Documenting createAccessDeniedException() method Updating documentation to reflect the changes added in https://github.com/symfony/symfony/pull/9405. --- book/security.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/book/security.rst b/book/security.rst index fa9958dca1e..f9a8e97e887 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1072,12 +1072,11 @@ fine-grained enough in certain cases. When necessary, you can easily force authorization from inside a controller:: // ... - use Symfony\Component\Security\Core\Exception\AccessDeniedException; public function helloAction($name) { if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) { - throw new AccessDeniedException(); + throw $this->createAccessDeniedException('Unable to access this page!'); } // ... @@ -1085,6 +1084,9 @@ authorization from inside a controller:: .. _book-security-securing-controller-annotations: +The ``createAccessDeniedException()`` method creates a special ``AccessDeniedException`` +object, which ultimately triggers a 403 HTTP response inside Symfony. + Thanks to the SensioFrameworkExtraBundle, you can also secure your controller using annotations:: // ... From 53f156c6fd104cb0d0719fcd4d66d5f32b522906 Mon Sep 17 00:00:00 2001 From: Klaus Silveira Date: Fri, 17 Jan 2014 15:07:11 -0200 Subject: [PATCH 0197/1181] Updating references to match doc format --- book/security.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/security.rst b/book/security.rst index f9a8e97e887..8cff1560a0a 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1084,7 +1084,7 @@ authorization from inside a controller:: .. _book-security-securing-controller-annotations: -The ``createAccessDeniedException()`` method creates a special ``AccessDeniedException`` +The :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::createAccessDeniedException()` method creates a special :class:`Symfony\\Component\\Security\\Core\Exception\\AccessDeniedException` object, which ultimately triggers a 403 HTTP response inside Symfony. Thanks to the SensioFrameworkExtraBundle, you can also secure your controller using annotations:: From b1b9090452a6141fa7763f711fde1a99f9e79e71 Mon Sep 17 00:00:00 2001 From: Klaus Silveira Date: Fri, 17 Jan 2014 16:06:35 -0200 Subject: [PATCH 0198/1181] Adding versionadded detail --- book/security.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/book/security.rst b/book/security.rst index 8cff1560a0a..3d0a26dc3b1 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1084,6 +1084,9 @@ authorization from inside a controller:: .. _book-security-securing-controller-annotations: +.. versionadded:: 2.5 + The ``createAccessDeniedException`` method was introduced in Symfony 2.5. + The :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::createAccessDeniedException()` method creates a special :class:`Symfony\\Component\\Security\\Core\Exception\\AccessDeniedException` object, which ultimately triggers a 403 HTTP response inside Symfony. From da6002d65ea8468875306c10eec6e5a115543c1a Mon Sep 17 00:00:00 2001 From: Klaus Silveira Date: Fri, 17 Jan 2014 17:01:57 -0200 Subject: [PATCH 0199/1181] Wrapping line --- book/security.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/book/security.rst b/book/security.rst index 3d0a26dc3b1..9603fb92a15 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1087,7 +1087,8 @@ authorization from inside a controller:: .. versionadded:: 2.5 The ``createAccessDeniedException`` method was introduced in Symfony 2.5. -The :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::createAccessDeniedException()` method creates a special :class:`Symfony\\Component\\Security\\Core\Exception\\AccessDeniedException` +The :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::createAccessDeniedException()` +method creates a special :class:`Symfony\\Component\\Security\\Core\Exception\\AccessDeniedException` object, which ultimately triggers a 403 HTTP response inside Symfony. Thanks to the SensioFrameworkExtraBundle, you can also secure your controller using annotations:: From 257c48348c51a9b5361bb4ea800d643afa3f140f Mon Sep 17 00:00:00 2001 From: Eduardo Gulias Davis Date: Sat, 18 Jan 2014 20:03:36 +0100 Subject: [PATCH 0200/1181] Blank line restored --- reference/constraints/Email.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/reference/constraints/Email.rst b/reference/constraints/Email.rst index 02c736bc6e5..112620da68b 100644 --- a/reference/constraints/Email.rst +++ b/reference/constraints/Email.rst @@ -125,4 +125,5 @@ checkHost If true, then the :phpfunction:`checkdnsrr` PHP function will be used to check the validity of the MX *or* the A *or* the AAAA record of the host of the given email. + .. _egulias/email-validator: https://packagist.org/packages/egulias/email-validator From 8cd63d06953434b2ba9186f800ab4905b1ac6bca Mon Sep 17 00:00:00 2001 From: tamirvs Date: Sat, 18 Jan 2014 22:46:03 +0200 Subject: [PATCH 0201/1181] Added feature doc for named encoders --- book/security.rst | 73 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/book/security.rst b/book/security.rst index fa9958dca1e..48112ff4325 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1466,6 +1466,79 @@ it as base64. In other words, the password has been greatly obfuscated so that the hashed password can't be decoded (i.e. you can't determine the password from the hashed password). +Named encoders +.............. + +.. versionadded:: 2.5 + Named encoders were introduced in Symfony 2.5 + +Another option is to set the encoder dynamically on an instance basis. +In the previous example, you've set the ``sha512`` algorithm for ``Acme\UserBundle\Entity\User``. +This may be secure enough for a regular user, but what if you want your admins to have +a stronger algorithm? Let's say ``bcrypt``. This can be done with named encoders: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + security: + # ... + encoders: + harsh: + algorithm: bcrypt + cost: 15 + + .. code-block:: xml + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + $container->loadFromExtension('security', array( + // ... + 'encoders' => array( + 'harsh' => array( + 'algorithm' => 'bcrypt', + 'cost' => '15' + ), + ), + )); + +Now you've created an encoder named ``harsh``. In order for a ``User`` instance to use it, +It must implement ``EncoderAwareInterface`` and have a method ``getEncoderName`` which returns the +name of the encoder to use:: + + // src/Acme/UserBundle/Entity/User.php + namespace Acme\UserBundle\Entity; + + use Symfony\Component\Security\Core\User\UserInterface; + use Symfony\Component\Security\Core\Encoder\EncoderAwareInterface; + + class User implements UserInterface, EncoderAwareInterface + { + public function getEncoderName() + { + if ($this->isAdmin()) { + return 'harsh'; + } + + return null; // use the default encoder + } + } + Determining the Hashed Password ............................... From b6abafbf9d1a2e3bc76417e7f7886cd6a98f5dc9 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 20 Jan 2014 21:11:15 -0600 Subject: [PATCH 0202/1181] [#3446] Minor tweaks as suggested by @xabbuh --- cookbook/configuration/apache_router.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cookbook/configuration/apache_router.rst b/cookbook/configuration/apache_router.rst index 4eca8afe3b3..c0d0fc9578d 100644 --- a/cookbook/configuration/apache_router.rst +++ b/cookbook/configuration/apache_router.rst @@ -7,11 +7,12 @@ How to use the Apache Router Symfony2, while fast out of the box, also provides various ways to increase that speed with a little bit of tweaking. One of these ways is by letting Apache handle routes directly, rather than using Symfony2 for this task. -.. note:: +.. caution:: - Apache router was deprecated in Symfony 2.5 and will be removed in Symfony 3.0. - Since the PHP implementation of the Router was improved, performance gains were no longer - significant (while it's very hard to replicate the same behaviour). + Apache router was deprecated in Symfony 2.5 and will be removed in Symfony + 3.0. Since the PHP implementation of the Router was improved, performance + gains were no longer significant (while it's very hard to replicate the + same behavior). Change Router Configuration Parameters -------------------------------------- From f1c127386f59d296217fde0997b7bc378620cd15 Mon Sep 17 00:00:00 2001 From: skowi Date: Tue, 21 Jan 2014 08:52:34 +0100 Subject: [PATCH 0203/1181] ApiKeyUserProvider should implements UserProviderInterface --- cookbook/security/api_key_authentication.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index b23a3da9299..3b9fbe2558f 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -414,7 +414,7 @@ of the user to make sure it's not out-of-date. But regardless of your requiremen // src/Acme/HelloBundle/Security/ApiKeyUserProvider.php // ... - class ApiKeyUserProvider extends UserProviderInterface + class ApiKeyUserProvider implements UserProviderInterface { // ... From 0723078dcb42f7f71c4653f42c94af135709cacc Mon Sep 17 00:00:00 2001 From: Andrew M Date: Tue, 21 Jan 2014 22:22:25 +0200 Subject: [PATCH 0204/1181] Fix YAML syntax highlight + remove trailing whitespace --- cookbook/service_container/scopes.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook/service_container/scopes.rst b/cookbook/service_container/scopes.rst index 59d4cd425a4..48e1da77f80 100644 --- a/cookbook/service_container/scopes.rst +++ b/cookbook/service_container/scopes.rst @@ -45,7 +45,7 @@ scope other than ``container`` and ``prototype``. But for the purposes of this entry, imagine there is another scope ``client`` and a service ``client_configuration`` that belongs to it. This is not a common situation, but the idea is that you may enter and exit multiple ``client`` scopes during a request, and each -has its own ``client_configuration`` service. +has its own ``client_configuration`` service. Scopes add a constraint on the dependencies of a service: a service cannot depend on services from a narrower scope. For example, if you create a generic @@ -274,7 +274,7 @@ argument is the ``ClientConfiguration`` object: my_mailer: class: Acme\HelloBundle\Mail\Mailer scope: client - arguments: [@client_configuration] + arguments: ["@client_configuration"] .. code-block:: xml From 3090cf2c68622ffc9c1ef5d544cccb2fe4dcc468 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 22 Jan 2014 17:48:33 +0100 Subject: [PATCH 0205/1181] fix include directive so that the contents are really included --- book/includes/_service_container_my_mailer.rst.inc | 5 ++--- book/service_container.rst | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/book/includes/_service_container_my_mailer.rst.inc b/book/includes/_service_container_my_mailer.rst.inc index efc2eaeac26..675df06f375 100644 --- a/book/includes/_service_container_my_mailer.rst.inc +++ b/book/includes/_service_container_my_mailer.rst.inc @@ -16,8 +16,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd" - > - + > sendmail @@ -33,4 +32,4 @@ $container->setDefinition('my_mailer', new Definition( 'Acme\HelloBundle\Mailer', array('sendmail') - )); \ No newline at end of file + )); diff --git a/book/service_container.rst b/book/service_container.rst index 3dc5698c853..655cf604e4e 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -103,7 +103,7 @@ for you. In order for this to work, you must *teach* the container how to create the ``Mailer`` service. This is done via configuration, which can be specified in YAML, XML or PHP: -.. include includes/_service_container_my_mailer.rst.inc +.. include:: includes/_service_container_my_mailer.rst.inc .. note:: @@ -643,7 +643,7 @@ which has a ``getMailerMethod()`` method on it, which will return a string like ``sendmail`` based on some configuration. Remember that the first argument to the ``my_mailer`` service is the simple string ``sendmail``: -.. include includes/_service_container_my_mailer.rst.inc +.. include:: includes/_service_container_my_mailer.rst.inc But instead of hardcoding this, how could we get this value from the ``getMailerMethod()`` of the new ``mailer_configuration`` service? One way is to use an expression: From d57c7384841fdb2f024245f270551ab1622ac93c Mon Sep 17 00:00:00 2001 From: Andrew M Date: Thu, 23 Jan 2014 21:00:51 +0200 Subject: [PATCH 0206/1181] Fix a typo (missing `) in :doc: link --- components/console/introduction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/console/introduction.rst b/components/console/introduction.rst index d68ac799fc8..da96f538d2b 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -233,7 +233,7 @@ method returns without actually printing. The MonologBridge provides a :class:`Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler` class that allows you to display messages on the console. This is cleaner than wrapping your output calls in conditions. For an example use in - the Symfony Framework, see :doc:/cookbook/logging/monolog_console. + the Symfony Framework, see :doc:`/cookbook/logging/monolog_console`. Using Command Arguments ----------------------- From 064c74040e0b82e33bbcb4e2d176d5d8f495b085 Mon Sep 17 00:00:00 2001 From: Robin van der Vleuten Date: Mon, 27 Jan 2014 15:05:17 +0100 Subject: [PATCH 0207/1181] Fixed small typo in code example --- cookbook/security/api_key_authentication.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index cd2812ebd88..99886a4d003 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -59,7 +59,7 @@ value and then a User object is created:: public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) { $apiKey = $token->getCredentials(); - $username = $this->userProvider->getUsernameForApiKey($apiKey) + $username = $this->userProvider->getUsernameForApiKey($apiKey); if (!$username) { throw new AuthenticationException( From ea5531b4f9b1d72ba52fca9cf6cdfa41557c6ede Mon Sep 17 00:00:00 2001 From: Robin van der Vleuten Date: Mon, 27 Jan 2014 15:11:28 +0100 Subject: [PATCH 0208/1181] An interface should be implemented --- cookbook/security/api_key_authentication.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index 99886a4d003..dd7003ddb68 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -145,7 +145,7 @@ The ``$userProvider`` might look something like this:: use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; - class ApiKeyUserProvider extends UserProviderInterface + class ApiKeyUserProvider implements UserProviderInterface { public function getUsernameForApiKey($apiKey) { From 0c6cfd113ba6328b8d526e4ca886bd3ce324e4a2 Mon Sep 17 00:00:00 2001 From: Robin van der Vleuten Date: Mon, 27 Jan 2014 15:12:54 +0100 Subject: [PATCH 0209/1181] Example creates a class not an interface --- cookbook/security/api_key_authentication.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index dd7003ddb68..3e245e520b4 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -38,7 +38,7 @@ value and then a User object is created:: { protected $userProvider; - public function __construct(ApiKeyUserProviderInterface $userProvider) + public function __construct(ApiKeyUserProvider $userProvider) { $this->userProvider = $userProvider; } From edec44d1aa19f0d3db62be3b0361e95b7ccd948e Mon Sep 17 00:00:00 2001 From: Denis Togbe Date: Tue, 28 Jan 2014 22:59:11 +0100 Subject: [PATCH 0210/1181] [Book][Service Container] Fix syntax highlighting --- book/service_container.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/service_container.rst b/book/service_container.rst index 3dc5698c853..c1e21def2b9 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -874,7 +874,7 @@ Now, just inject the ``request_stack``, which behaves like any normal service: # src/Acme/HelloBundle/Resources/config/services.yml services: newsletter_manager: - class: "Acme\HelloBundle\Newsletter\NewsletterManager" + class: Acme\HelloBundle\Newsletter\NewsletterManager arguments: ["@request_stack"] .. code-block:: xml From 269c1660edae2d5337cc4e25c5eda16d0a1cc32a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 29 Jan 2014 16:57:23 +0100 Subject: [PATCH 0211/1181] describe that the event name and the event dispatcher are passed to event listeners by the event dispatcher --- components/event_dispatcher/introduction.rst | 26 +++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/components/event_dispatcher/introduction.rst b/components/event_dispatcher/introduction.rst index 0ea96b89abc..b037c462898 100644 --- a/components/event_dispatcher/introduction.rst +++ b/components/event_dispatcher/introduction.rst @@ -441,30 +441,31 @@ which returns a boolean value:: EventDispatcher aware Events and Listeners ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The ``EventDispatcher`` always injects a reference to itself in the passed event -object. This means that all listeners have direct access to the -``EventDispatcher`` object that notified the listener via the passed ``Event`` -object's :method:`Symfony\\Component\\EventDispatcher\\Event::getDispatcher` -method. +.. versionadded:: 2.4 + Since Symfony 2.4 the current event name and the ``EventDispatcher`` + itself are passed to the listeners as additional arguments. -This can lead to some advanced applications of the ``EventDispatcher`` including -letting listeners dispatch other events, event chaining or even lazy loading of -more listeners into the dispatcher object. Examples follow: +The ``EventDispatcher`` always passes the dispatched event, the event's name +and a reference to itself to the listeners. This can be used in some advanced +usages of the ``EventDispatcher`` like dispatching other events in listeners, +event chaining or even lazy loading of more listeners into the dispatcher +object as shown in the following examples. Lazy loading listeners:: use Symfony\Component\EventDispatcher\Event; + use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Acme\StoreBundle\Event\StoreSubscriber; class Foo { private $started = false; - public function myLazyListener(Event $event) + public function myLazyListener(Event $event, $eventName, EventDispatcherInterface $dispatcher) { if (false === $this->started) { $subscriber = new StoreSubscriber(); - $event->getDispatcher()->addSubscriber($subscriber); + $dispatcher->addSubscriber($subscriber); } $this->started = true; @@ -476,12 +477,13 @@ Lazy loading listeners:: Dispatching another event from within a listener:: use Symfony\Component\EventDispatcher\Event; + use Symfony\Component\EventDispatcher\EventDispatcherInterface; class Foo { - public function myFooListener(Event $event) + public function myFooListener(Event $event, $eventName, EventDispatcherInterface $dispatcher) { - $event->getDispatcher()->dispatch('log', $event); + $dispatcher->dispatch('log', $event); // ... more code } From 4419aadb12a5395b4d5e1e6aba5686839888f5af Mon Sep 17 00:00:00 2001 From: Andrew M Date: Sun, 2 Feb 2014 12:58:38 +0200 Subject: [PATCH 0212/1181] Remove horizontal scrolling in code block --- components/expression_language/caching.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/expression_language/caching.rst b/components/expression_language/caching.rst index 41c9d2a1c26..3ea35752e2f 100644 --- a/components/expression_language/caching.rst +++ b/components/expression_language/caching.rst @@ -63,7 +63,9 @@ Both ``evaluate()`` and ``compile()`` can handle ``ParsedExpression`` and use Symfony\Component\ExpressionLanguage\SerializedParsedExpression; // ... - $expression = new SerializedParsedExpression(serialize($language->parse('1 + 4'))); + $expression = new SerializedParsedExpression( + serialize($language->parse('1 + 4')) + ); echo $language->evaluate($expression); // prints 5 From b97e79c7772ddd41173f26a07406f7f084cb1c32 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Sun, 2 Feb 2014 18:51:34 +0300 Subject: [PATCH 0213/1181] Added tip for Entity Listeners --- cookbook/doctrine/event_listeners_subscribers.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cookbook/doctrine/event_listeners_subscribers.rst b/cookbook/doctrine/event_listeners_subscribers.rst index fb1274a38a7..4961ae00aa8 100644 --- a/cookbook/doctrine/event_listeners_subscribers.rst +++ b/cookbook/doctrine/event_listeners_subscribers.rst @@ -154,6 +154,12 @@ specific type of entity (e.g. a ``Product`` entity but not a ``BlogPost`` entity), you should check for the entity's class type in your method (as shown above). +.. tip:: + + Starting from version 2.4 Doctrine has a feature called `Entity Listeners`_ + which is a lifecycle listener class used for an entity. You can read about + it in Doctrine documentation. + Creating the Subscriber Class ----------------------------- @@ -211,3 +217,4 @@ interface and have an event method for each event it subscribes to:: For a full reference, see chapter `The Event System`_ in the Doctrine documentation. .. _`The Event System`: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html +.. _`Entity Listeners`: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#entity-listeners From 2fbf17c69cfbfc3afcfb968b77fbfdc363c1fb47 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 2 Feb 2014 21:16:23 -0600 Subject: [PATCH 0214/1181] [#3491] Moving the new named algorithms into their own cookbook entry and making some minor tweaks --- book/security.rst | 74 +----------------- cookbook/map.rst.inc | 1 + cookbook/security/index.rst | 1 + cookbook/security/named_encoders.rst | 111 +++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 71 deletions(-) create mode 100644 cookbook/security/named_encoders.rst diff --git a/book/security.rst b/book/security.rst index 7e40fe7c3be..391856bb3ae 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1434,78 +1434,10 @@ or via some online tool. Supported algorithms for this method depend on your PHP version. A full list is available by calling the PHP function :phpfunction:`hash_algos`. -Named encoders -.............. - -.. versionadded:: 2.5 - Named encoders were introduced in Symfony 2.5 - -Another option is to set the encoder dynamically on an instance basis. -In the previous example, you've set the ``sha512`` algorithm for ``Acme\UserBundle\Entity\User``. -This may be secure enough for a regular user, but what if you want your admins to have -a stronger algorithm? Let's say ``bcrypt``. This can be done with named encoders: - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/security.yml - security: - # ... - encoders: - harsh: - algorithm: bcrypt - cost: 15 - - .. code-block:: xml - - - - - - - - - - - - .. code-block:: php - - // app/config/security.php - $container->loadFromExtension('security', array( - // ... - 'encoders' => array( - 'harsh' => array( - 'algorithm' => 'bcrypt', - 'cost' => '15' - ), - ), - )); - -Now you've created an encoder named ``harsh``. In order for a ``User`` instance to use it, -It must implement ``EncoderAwareInterface`` and have a method ``getEncoderName`` which returns the -name of the encoder to use:: - - // src/Acme/UserBundle/Entity/User.php - namespace Acme\UserBundle\Entity; - - use Symfony\Component\Security\Core\User\UserInterface; - use Symfony\Component\Security\Core\Encoder\EncoderAwareInterface; +.. tip:: - class User implements UserInterface, EncoderAwareInterface - { - public function getEncoderName() - { - if ($this->isAdmin()) { - return 'harsh'; - } - - return null; // use the default encoder - } - } + It's also possible to use different hashing algorithms on a user-by-user + basis. See :doc:`/cookbook/security/named-encoders` for more details. Determining the Hashed Password ............................... diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 6986e4b1ca0..380498f59e0 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -144,6 +144,7 @@ * :doc:`/cookbook/security/custom_authentication_provider` * :doc:`/cookbook/security/target_path` * :doc:`/cookbook/security/csrf_in_login_form` + * :doc:`/cookbook/security/named_encoders` * **Serializer** diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst index 63bd29520b3..59f9af787be 100644 --- a/cookbook/security/index.rst +++ b/cookbook/security/index.rst @@ -20,3 +20,4 @@ Security custom_authentication_provider target_path csrf_in_login_form + named_encoders diff --git a/cookbook/security/named_encoders.rst b/cookbook/security/named_encoders.rst new file mode 100644 index 00000000000..cf881563363 --- /dev/null +++ b/cookbook/security/named_encoders.rst @@ -0,0 +1,111 @@ +.. index:: + single: Security; Named Encoders + +How to Choose the Password Encoder Algorithm Dynamically +======================================================== + +.. versionadded:: 2.5 + Named encoders were introduced in Symfony 2.5 + +Usually, the same password encoder is used for all users by configuring it +to apply to all instances of a specific class: + + # app/config/security.yml + security: + # ... + encoders: + Symfony\Component\Security\Core\User\User: sha512 + + .. code-block:: xml + + + + + + + + .. code-block:: php + + // app/config/security.php + $container->loadFromExtension('security', array( + // ... + 'encoders' => array( + 'Symfony\Component\Security\Core\User\User' => array( + 'algorithm' => 'sha512', + ), + ), + )); + +Another option is to use a "named" encoder, and then select which encoder +you want to use dynamically. + +In the previous example, you've set the ``sha512`` algorithm for ``Acme\UserBundle\Entity\User``. +This may be secure enough for a regular user, but what if you want your admins +to have a stronger algorithm, for example ``bcrypt``. This can be done with +named encoders: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + security: + # ... + encoders: + harsh: + algorithm: bcrypt + cost: 15 + + .. code-block:: xml + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + $container->loadFromExtension('security', array( + // ... + 'encoders' => array( + 'harsh' => array( + 'algorithm' => 'bcrypt', + 'cost' => '15' + ), + ), + )); + +This creates an encoder named ``harsh``. In order for a ``User`` instance +to use it, the class must implement +:class:`Symfony\\Component\\Security\\Core\\Encoder\\EncoderAwareInterface`. +The interface requires one method - ``getEncoderName`` - which should reutrn +the name of the encoder to use:: + + // src/Acme/UserBundle/Entity/User.php + namespace Acme\UserBundle\Entity; + + use Symfony\Component\Security\Core\User\UserInterface; + use Symfony\Component\Security\Core\Encoder\EncoderAwareInterface; + + class User implements UserInterface, EncoderAwareInterface + { + public function getEncoderName() + { + if ($this->isAdmin()) { + return 'harsh'; + } + + return null; // use the default encoder + } + } From b53e1787c418f7176b20fba1a76d1c7fd570634d Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Mon, 3 Feb 2014 13:27:50 +0300 Subject: [PATCH 0215/1181] Fixed typo --- cookbook/doctrine/event_listeners_subscribers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/doctrine/event_listeners_subscribers.rst b/cookbook/doctrine/event_listeners_subscribers.rst index 4961ae00aa8..bd045aab921 100644 --- a/cookbook/doctrine/event_listeners_subscribers.rst +++ b/cookbook/doctrine/event_listeners_subscribers.rst @@ -158,7 +158,7 @@ entity), you should check for the entity's class type in your method Starting from version 2.4 Doctrine has a feature called `Entity Listeners`_ which is a lifecycle listener class used for an entity. You can read about - it in Doctrine documentation. + it in the Doctrine documentation. Creating the Subscriber Class ----------------------------- From 34e69de95ed997846e9c755144105fcc2ff48519 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 3 Feb 2014 21:33:12 -0600 Subject: [PATCH 0216/1181] [#3533] Lots of nice changes thanks to @xabbuh --- cookbook/security/named_encoders.rst | 32 +++++++++++++++++++--------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/cookbook/security/named_encoders.rst b/cookbook/security/named_encoders.rst index cf881563363..fe54738f670 100644 --- a/cookbook/security/named_encoders.rst +++ b/cookbook/security/named_encoders.rst @@ -5,7 +5,7 @@ How to Choose the Password Encoder Algorithm Dynamically ======================================================== .. versionadded:: 2.5 - Named encoders were introduced in Symfony 2.5 + Named encoders were introduced in Symfony 2.5. Usually, the same password encoder is used for all users by configuring it to apply to all instances of a specific class: @@ -19,12 +19,20 @@ to apply to all instances of a specific class: .. code-block:: xml - - - - + + + + + + + .. code-block:: php @@ -33,12 +41,12 @@ to apply to all instances of a specific class: // ... 'encoders' => array( 'Symfony\Component\Security\Core\User\User' => array( - 'algorithm' => 'sha512', + 'algorithm' => 'sha512', ), ), )); -Another option is to use a "named" encoder, and then select which encoder +Another option is to use a "named" encoder and then select which encoder you want to use dynamically. In the previous example, you've set the ``sha512`` algorithm for ``Acme\UserBundle\Entity\User``. @@ -63,7 +71,11 @@ named encoders: + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:srv="http://symfony.com/schema/dic/services" + xsi:schemaLocation="http://symfony.com/schema/dic/services + http://symfony.com/schema/dic/services/services-1.0.xsd" + > From 2ca9bd5e1c6ad44114f6d400853c119cb2b418af Mon Sep 17 00:00:00 2001 From: jochenvdv Date: Tue, 4 Feb 2014 13:53:20 +0100 Subject: [PATCH 0217/1181] Describe retrieval of StopwatchEvent --- components/stopwatch.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/stopwatch.rst b/components/stopwatch.rst index 2598bdb3cd0..034a6d3e928 100644 --- a/components/stopwatch.rst +++ b/components/stopwatch.rst @@ -31,6 +31,8 @@ microtime by yourself. Instead, use the simple // ... some code goes here $event = $stopwatch->stop('eventName'); +The :class:`Symfony\\Component\\Stopwatch\StopwatchEvent` object can be retrieved from :method:`Symfony\\Component\\Stopwatch\\Stopwatch::start`, :method:`Symfony\\Component\\Stopwatch\\Stopwatch::stop`, :method:`Symfony\\Component\\Stopwatch\\Stopwatch::lap` and :method:`Symfony\\Component\\Stopwatch\\Stopwatch::getEvent` + You can also provide a category name to an event:: $stopwatch->start('eventName', 'categoryName'); From 64602c83849b29088bfbf60b46a8fb802bcc9860 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 5 Feb 2014 17:26:24 +0100 Subject: [PATCH 0218/1181] fix referenced documents names --- book/security.rst | 2 +- reference/forms/types/collection.rst | 2 +- reference/forms/types/options/checkbox_empty_data.rst.inc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/book/security.rst b/book/security.rst index 12a98e7bd1f..758bd7b3878 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1437,7 +1437,7 @@ is available by calling the PHP function :phpfunction:`hash_algos`. .. tip:: It's also possible to use different hashing algorithms on a user-by-user - basis. See :doc:`/cookbook/security/named-encoders` for more details. + basis. See :doc:`/cookbook/security/named_encoders` for more details. Determining the Hashed Password ............................... diff --git a/reference/forms/types/collection.rst b/reference/forms/types/collection.rst index 76f91580dc8..f918c6cbf80 100644 --- a/reference/forms/types/collection.rst +++ b/reference/forms/types/collection.rst @@ -379,4 +379,4 @@ error_bubbling .. include:: /reference/forms/types/options/mapped.rst.inc -.. include:: /reference/forms/type/options/cascade_validation.rst.inc +.. include:: /reference/forms/types/options/cascade_validation.rst.inc diff --git a/reference/forms/types/options/checkbox_empty_data.rst.inc b/reference/forms/types/options/checkbox_empty_data.rst.inc index 8143ad364ce..d7a09ba3b7b 100644 --- a/reference/forms/types/options/checkbox_empty_data.rst.inc +++ b/reference/forms/types/options/checkbox_empty_data.rst.inc @@ -6,4 +6,4 @@ empty_data This option determines what value the field will return when the ``empty_value`` choice is selected. In checkbox, the value of ``empty_data`` is overriden by the value returned by -the data transformer (see :doc:`/cookbook/form/data_transformers.rst`). +the data transformer (see :doc:`/cookbook/form/data_transformers`). From 7e3c0e3af0bc730a4ccc732ee6c46fd9d82a99a9 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 5 Feb 2014 17:27:38 +0100 Subject: [PATCH 0219/1181] readd configuration block --- cookbook/security/named_encoders.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cookbook/security/named_encoders.rst b/cookbook/security/named_encoders.rst index fe54738f670..cf9ea3770c2 100644 --- a/cookbook/security/named_encoders.rst +++ b/cookbook/security/named_encoders.rst @@ -10,6 +10,10 @@ How to Choose the Password Encoder Algorithm Dynamically Usually, the same password encoder is used for all users by configuring it to apply to all instances of a specific class: +.. configuration-block:: + + .. code-block:: yaml + # app/config/security.yml security: # ... @@ -117,7 +121,7 @@ the name of the encoder to use:: if ($this->isAdmin()) { return 'harsh'; } - + return null; // use the default encoder } } From 46e0b52f66cb2bebbf769c1590c27108a1e257a0 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 5 Feb 2014 17:28:15 +0100 Subject: [PATCH 0220/1181] remove empty_data from the list of inherited options, it's documented in the overriden options section --- reference/forms/types/checkbox.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/reference/forms/types/checkbox.rst b/reference/forms/types/checkbox.rst index aeefb915ccf..e39c393dae7 100644 --- a/reference/forms/types/checkbox.rst +++ b/reference/forms/types/checkbox.rst @@ -60,8 +60,6 @@ These options inherit from the :doc:`form ` type: .. include:: /reference/forms/types/options/data.rst.inc -.. include:: /reference/forms/types/options/empty_data.rst.inc - .. include:: /reference/forms/types/options/required.rst.inc .. include:: /reference/forms/types/options/label.rst.inc From 400a0c0639b9050de9dcb510fcd0341ac00da407 Mon Sep 17 00:00:00 2001 From: Andrew M Date: Sat, 8 Feb 2014 10:45:45 +0200 Subject: [PATCH 0221/1181] Minimize horizontal scrolling in code block to improve readability --- components/http_foundation/introduction.rst | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index e0371822d19..6e80801df9a 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -289,8 +289,24 @@ PHP callable that is able to create an instance of your ``Request`` class:: use Symfony\Component\HttpFoundation\Request; - Request::setFactory(function (array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { - return SpecialRequest::create($query, $request, $attributes, $cookies, $files, $server, $content); + Request::setFactory(function ( + array $query = array(), + array $request = array(), + array $attributes = array(), + array $cookies = array(), + array $files = array(), + array $server = array(), + $content = null + ) { + return SpecialRequest::create( + $query, + $request, + $attributes, + $cookies, + $files, + $server, + $content + ); }); $request = Request::createFromGlobals(); From 65649aa712cee26d9b8a99b44313def11e42ab71 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Tue, 11 Feb 2014 08:39:44 +0300 Subject: [PATCH 0222/1181] Update event_listeners_subscribers.rst --- cookbook/doctrine/event_listeners_subscribers.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cookbook/doctrine/event_listeners_subscribers.rst b/cookbook/doctrine/event_listeners_subscribers.rst index bd045aab921..bd1f322d0b3 100644 --- a/cookbook/doctrine/event_listeners_subscribers.rst +++ b/cookbook/doctrine/event_listeners_subscribers.rst @@ -156,9 +156,9 @@ entity), you should check for the entity's class type in your method .. tip:: - Starting from version 2.4 Doctrine has a feature called `Entity Listeners`_ - which is a lifecycle listener class used for an entity. You can read about - it in the Doctrine documentation. + In Doctrine 2.4, a feature called Entity Listeners was introduced. + It is a lifecycle listener class used for an entity. You can read + about it in `the Doctrine Documentation`_. Creating the Subscriber Class ----------------------------- @@ -217,4 +217,4 @@ interface and have an event method for each event it subscribes to:: For a full reference, see chapter `The Event System`_ in the Doctrine documentation. .. _`The Event System`: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html -.. _`Entity Listeners`: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#entity-listeners +.. _`the Doctrine Documentation`: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#entity-listeners From 027bc973591065fd4cd05bc316adf0e3611b33db Mon Sep 17 00:00:00 2001 From: Janusz Slota Date: Wed, 12 Feb 2014 16:28:12 +0000 Subject: [PATCH 0223/1181] Callback: [Validator, validate] expects validate to be static Otherwise you'll get: ``` ContextErrorException: Runtime Notice: call_user_func() expects parameter 1 to be a valid callback, non-static method Vendor\Package\Validator::validate() should not be called statically in Symfony/Component/Validator/Constraints/CallbackValidator.php ``` --- reference/constraints/Callback.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/constraints/Callback.rst b/reference/constraints/Callback.rst index e370c46ecf1..36b55e97910 100644 --- a/reference/constraints/Callback.rst +++ b/reference/constraints/Callback.rst @@ -160,7 +160,7 @@ your validation function is ``Vendor\Package\Validator::validate()``:: class Validator { - public function validate($object, ExecutionContextInterface $context) + public static function validate($object, ExecutionContextInterface $context) { // ... } From eefd0ab58faad4bb0284b3859ef5743e0df7b4eb Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 25 Feb 2014 23:24:25 +0100 Subject: [PATCH 0224/1181] add versionadded directive for multiple option --- reference/forms/types/file.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/reference/forms/types/file.rst b/reference/forms/types/file.rst index fa79a02e18e..ed148358262 100644 --- a/reference/forms/types/file.rst +++ b/reference/forms/types/file.rst @@ -86,6 +86,9 @@ Field Options multiple ~~~~~~~~ +.. versionadded:: 2.5 + The ``multiple`` option was introduced in Symfony 2.5. + **type**: ``Boolean`` **default**: ``false`` When set to true, the user will be able to upload multiple files at the same time. From f4afaab4abf5f191e9d2fdd415eccf7c9be75bb8 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 28 Feb 2014 15:21:23 -0500 Subject: [PATCH 0225/1181] Documentation for the new Uuid constraint --- reference/constraints/Uuid.rst | 126 +++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 reference/constraints/Uuid.rst diff --git a/reference/constraints/Uuid.rst b/reference/constraints/Uuid.rst new file mode 100644 index 00000000000..1d315bdd2a8 --- /dev/null +++ b/reference/constraints/Uuid.rst @@ -0,0 +1,126 @@ +Uuid +== + +.. versionadded:: 2.5 + The Uuid constraint was added in Symfony 2.5. + +Validates that a value is a valid `Universally unique identifier (UUID)`_ per `RFC 4122`_. +By default, this will validate the format according to the RFC's guidelines, but this can +be relaxed to accept non-standard UUIDs that other systems (like PostgreSQL) accept. +UUID versions can also be restricted using a whitelist. + ++----------------+---------------------------------------------------------------------+ +| Applies to | :ref:`property or method ` | ++----------------+---------------------------------------------------------------------+ +| Options | - `message`_ | +| | - `strict`_ | +| | - `versions`_ | ++----------------+---------------------------------------------------------------------+ +| Class | :class:`Symfony\\Component\\Validator\\Constraints\\Uuid` | ++----------------+---------------------------------------------------------------------+ +| Validator | :class:`Symfony\\Component\\Validator\\Constraints\\UuidValidator` | ++----------------+---------------------------------------------------------------------+ + +Basic Usage +----------- + +.. configuration-block:: + + .. code-block:: yaml + + # src/UploadsBundle/Resources/config/validation.yml + Acme\UploadsBundle\Entity\File: + properties: + identifier: + - Uuid: ~ + + .. code-block:: php-annotations + + // src/Acme/UploadsBundle/Entity/File.php + namespace Acme\UploadsBundle\Entity; + + use Symfony\Component\Validator\Constraints as Assert; + + class File + { + /** + * @Assert\Uuid + */ + protected $identifier; + } + + .. code-block:: xml + + + + + + + + + + + + + .. code-block:: php + + // src/Acme/UploadsBundle/Entity/File.php + namespace Acme\UploadsBundle\Entity; + + use Symfony\Component\Validator\Mapping\ClassMetadata; + use Symfony\Component\Validator\Constraints as Assert; + + class File + { + public static function loadValidatorMetadata(ClassMetadata $metadata) + { + $metadata->addPropertyConstraint('identifier', new Assert\Uuid()); + } + } + + +Options +------- + +message +~~~~~~~ + +**type**: ``string`` **default**: ``This is not a valid UUID.`` + +This message is shown if the string is not a valid UUID. + +strict +~~~~~~ + +**type**: ``boolean`` **default**: ``true`` + +If this option is set to ``true`` the constraint will check if the UUID is formatted per the +RFC's input format rules: ``216fff40-98d9-11e3-a5e2-0800200c9a66``. Setting this to ``false`` +will allow alternate input formats like:: + + 216f-ff40-98d9-11e3-a5e2-0800-200c-9a66 + {216fff40-98d9-11e3-a5e2-0800200c9a66} + 216fff4098d911e3a5e20800200c9a66 + +versions +~~~~~~~~ + +**type**: ``int[]`` **default**: ``[1,2,3,4,5]`` + +This option can be used to only allow specific `UUID versions`_. Valid versions are 1 - 5. +The following PHP constants can also be used: + +* ``Uuid::V1_MAC`` +* ``Uuid::V2_DCE`` +* ``Uuid::V3_MD5`` +* ``Uuid::V4_RANDOM`` +* ``Uuid::V5_SHA1`` + +All five versions are allowed by default. + +.. _`Universally unique identifier (UUID)`: http://en.wikipedia.org/wiki/Universally_unique_identifier +.. _`RFC 4122`: http://tools.ietf.org/html/rfc4122 +.. _`UUID versions`: http://en.wikipedia.org/wiki/Universally_unique_identifier#Variants_and_versions + From 3ea91372096bd7486fa04e85ad706e6302f0a506 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 28 Feb 2014 15:22:50 -0500 Subject: [PATCH 0226/1181] List the UUID constraint in the reference section --- reference/constraints.rst | 1 + reference/constraints/map.rst.inc | 1 + 2 files changed, 2 insertions(+) diff --git a/reference/constraints.rst b/reference/constraints.rst index 0b209bbf012..ac8ef5ae33c 100644 --- a/reference/constraints.rst +++ b/reference/constraints.rst @@ -18,6 +18,7 @@ Validation Constraints Reference constraints/Url constraints/Regex constraints/Ip + constraints/Uuid constraints/Range diff --git a/reference/constraints/map.rst.inc b/reference/constraints/map.rst.inc index 237329866d4..686ad22bca5 100644 --- a/reference/constraints/map.rst.inc +++ b/reference/constraints/map.rst.inc @@ -20,6 +20,7 @@ String Constraints * :doc:`Url ` * :doc:`Regex ` * :doc:`Ip ` +* :doc:`Uuid` Number Constraints ~~~~~~~~~~~~~~~~~~ From 6f6c03fe6c28994909f7eafebbaaa46f1de07fa2 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 28 Feb 2014 15:43:14 -0500 Subject: [PATCH 0227/1181] Fix formatting issues --- reference/constraints/Uuid.rst | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/reference/constraints/Uuid.rst b/reference/constraints/Uuid.rst index 1d315bdd2a8..4db4fc8ceab 100644 --- a/reference/constraints/Uuid.rst +++ b/reference/constraints/Uuid.rst @@ -1,8 +1,8 @@ Uuid -== +==== .. versionadded:: 2.5 - The Uuid constraint was added in Symfony 2.5. + The Uuid constraint was introduced in Symfony 2.5. Validates that a value is a valid `Universally unique identifier (UUID)`_ per `RFC 4122`_. By default, this will validate the format according to the RFC's guidelines, but this can @@ -97,12 +97,12 @@ strict **type**: ``boolean`` **default**: ``true`` If this option is set to ``true`` the constraint will check if the UUID is formatted per the -RFC's input format rules: ``216fff40-98d9-11e3-a5e2-0800200c9a66``. Setting this to ``false`` -will allow alternate input formats like:: +RFC's input format rules: ``216fff40-98d9-11e3-a5e2-0800200c9a66``. Setting this to ``false`` +will allow alternate input formats like: - 216f-ff40-98d9-11e3-a5e2-0800-200c-9a66 - {216fff40-98d9-11e3-a5e2-0800200c9a66} - 216fff4098d911e3a5e20800200c9a66 +* ``216f-ff40-98d9-11e3-a5e2-0800-200c-9a66`` +* ``{216fff40-98d9-11e3-a5e2-0800200c9a66}`` +* ``216fff4098d911e3a5e20800200c9a66`` versions ~~~~~~~~ @@ -123,4 +123,3 @@ All five versions are allowed by default. .. _`Universally unique identifier (UUID)`: http://en.wikipedia.org/wiki/Universally_unique_identifier .. _`RFC 4122`: http://tools.ietf.org/html/rfc4122 .. _`UUID versions`: http://en.wikipedia.org/wiki/Universally_unique_identifier#Variants_and_versions - From 947ad92a90d9ad2803ce897342e4706f93e61d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Chardonnet?= Date: Sat, 1 Mar 2014 00:45:11 +0100 Subject: [PATCH 0228/1181] [Console] Adding use cases to command as service | Q | A | ------------- | --- | Doc fix? | yes | New docs? | no | Applies to | 2.4+ | Fixed tickets | N/A Command as a service can be useful to give access to services and configuration parameters in the `configure` method. A simple use case: you want to allow the user to set an option's default value in the `app/config/parameters.yml` file. Or the default value needs to be computed by a service (database retrieval for instance). With a `ContainerAwareCommand`, this wouldn't be possible because the `configure` method is called from the constructor, so the container isn't set yet. --- cookbook/console/console_command.rst | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index 6e3721a24ef..455aab090cc 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -71,9 +71,12 @@ Register Commands in the Service Container Support for registering commands in the service container was added in version 2.4. -Instead of putting your command in the ``Command`` directory and having Symfony -auto-discover it for you, you can register commands in the service container -using the ``console.command`` tag: +By default, Symfony will take a look in the ``Command`` directory of you +bundles and automatically register your commands. For the ones implementing +the ``ContainerAwareCommand`` interface, Symfony will even inject the container. + +If you wan to, you can instead register them as services in the container using +the ``console.command`` tag: .. configuration-block:: @@ -111,9 +114,20 @@ using the ``console.command`` tag: .. tip:: - Registering your command as a service gives you more control over its - location and the services that are injected into it. But, there are no - functional advantages, so you don't need to register your command as a service. + Command as a service can be usefull in few situations: + * if you need your commands to be defined somewhere else than ``Command`` + * if you need to access services or configuration parameters in the + ``configure`` method + + For example, Imagine you want to provide a default value for the ``name`` + option. You could hard code a string and pass it as the 4th argument of + ``addArgument``, or you could allow the user to set the default value in the + configuration. + + With a ``ContainerAwareCommand`` you wouldn't be able to retrieve the + configuration parameter, because the ``configure`` method is called in the + command's constructor. The only solution is to inject them through its + constructor. Getting Services from the Service Container ------------------------------------------- From a055140916455563182a2df5fe63acb2c6ad5a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Chardonnet?= Date: Sat, 1 Mar 2014 12:54:18 +0100 Subject: [PATCH 0229/1181] Took @WouterJ's advices into account --- cookbook/console/console_command.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index 455aab090cc..4beba877e89 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -75,7 +75,7 @@ By default, Symfony will take a look in the ``Command`` directory of you bundles and automatically register your commands. For the ones implementing the ``ContainerAwareCommand`` interface, Symfony will even inject the container. -If you wan to, you can instead register them as services in the container using +If you want to, you can instead register them as services in the container using the ``console.command`` tag: .. configuration-block:: @@ -115,11 +115,12 @@ the ``console.command`` tag: .. tip:: Command as a service can be usefull in few situations: - * if you need your commands to be defined somewhere else than ``Command`` - * if you need to access services or configuration parameters in the - ``configure`` method - For example, Imagine you want to provide a default value for the ``name`` + * If you need your commands to be defined somewhere else than ``Command``; + * if you need to access services or configuration parameters in the + ``configure`` method. + + For example, imagine you want to provide a default value for the ``name`` option. You could hard code a string and pass it as the 4th argument of ``addArgument``, or you could allow the user to set the default value in the configuration. From a7b916e42e525c2cb4133d5f05feb0ab6d35e74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Chardonnet?= Date: Sat, 1 Mar 2014 15:17:41 +0100 Subject: [PATCH 0230/1181] Fixed typos spotted by @cordoval --- cookbook/console/console_command.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index 4beba877e89..320c4d0377b 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -71,7 +71,7 @@ Register Commands in the Service Container Support for registering commands in the service container was added in version 2.4. -By default, Symfony will take a look in the ``Command`` directory of you +By default, Symfony will take a look in the ``Command`` directory of your bundles and automatically register your commands. For the ones implementing the ``ContainerAwareCommand`` interface, Symfony will even inject the container. @@ -114,9 +114,10 @@ the ``console.command`` tag: .. tip:: - Command as a service can be usefull in few situations: + Commands as services can be useful in few situations: - * If you need your commands to be defined somewhere else than ``Command``; + * if you need your commands to be defined somewhere else than in the + ``Command`` folder; * if you need to access services or configuration parameters in the ``configure`` method. From cdd534a806ba45020c076dda70d2128be1cb3b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Chardonnet?= Date: Sat, 1 Mar 2014 20:12:46 +0100 Subject: [PATCH 0231/1181] Added @lsmith77 and @dbu use cases --- cookbook/console/console_command.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index 320c4d0377b..3441549e363 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -118,6 +118,11 @@ the ``console.command`` tag: * if you need your commands to be defined somewhere else than in the ``Command`` folder; + * if you need to register the command conditionally (depending on the + environment or presence of some dependencies); + * ou want to reuse the command with a different service or different + configuration, without having to extend the command - you could just + define a second service with the same class; * if you need to access services or configuration parameters in the ``configure`` method. From e13795114c37b5085bf7c57fb79cce6a6cb57571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Chardonnet?= Date: Sat, 1 Mar 2014 23:35:14 +0100 Subject: [PATCH 0232/1181] Created a new article --- components/console/commands_as_services.rst | 118 ++++++++++++++++++++ components/console/index.rst | 1 + cookbook/console/console_command.rst | 74 ------------ 3 files changed, 119 insertions(+), 74 deletions(-) create mode 100644 components/console/commands_as_services.rst diff --git a/components/console/commands_as_services.rst b/components/console/commands_as_services.rst new file mode 100644 index 00000000000..b0bffe5fd1a --- /dev/null +++ b/components/console/commands_as_services.rst @@ -0,0 +1,118 @@ +.. index:: + single: Console; Commands as Services + +How to define Commands as Services +================================== + +.. versionadded:: 2.4 + Support for registering commands in the service container was added in + version 2.4. + +By default, Symfony will take a look in the ``Command`` directory of your +bundles and automatically register your commands. For the ones implementing +the ``ContainerAwareCommand`` interface, Symfony will even inject the container. + +While making life easier, this default implementation has some drawbacks in some +situations: + +* what if you want your command to be defined elsewhere than in the ``Command`` + folder? +* what if you want to register conditionally your command, depending on the + current environment or on the availability of some dependencies? +* what if you need to access dependencies before the ``setContainer`` is called + (for example in the ``configure`` method)? +* what if you want to reuse a command many times, but with different + dependencies or parameters? + +To solve those problems, you can register your command as a service by simply +defining it with the ``console.command`` tag: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + services: + acme_hello.command.my_command: + class: Acme\HelloBundle\Command\MyCommand + tags: + - { name: console.command } + + .. code-block:: xml + + + + + + + + + + + .. code-block:: php + + // app/config/config.php + + $container + ->register('acme_hello.command.my_command', 'Acme\HelloBundle\Command\MyCommand') + ->addTag('console.command') + ; + +Here are some use cases. + +Use dependencies and parameters in configure +-------------------------------------------- + +For example, imagine you want to provide a default value for the ``name`` +argument. You could: + +* hard code a string and pass it as the 4th argument of ``addArgument``; +* allow the user to set the default value in the configuration; +* retrieve the default value from a service (a repository for example). + +With a ``ContainerAwareCommand`` you wouldn't be able to retrieve the +configuration parameter, because the ``configure`` method is called in the +command's constructor. The only solution is to inject them through its +constructor: + + nameRepository = $nameRepository; + } + + protected function configure() + { + $defaultName = $this->nameRepository->findLastOne(); + + $this + ->setName('demo:greet') + ->setDescription('Greet someone') + ->addArgument('name', InputArgument::OPTIONAL, 'Who do you want to greet?', $defaultName) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $name = $input->getArgument('name'); + + $output->writeln($name); + } + } diff --git a/components/console/index.rst b/components/console/index.rst index c814942d018..a4b85f9cba9 100644 --- a/components/console/index.rst +++ b/components/console/index.rst @@ -6,6 +6,7 @@ Console introduction usage + commands_as_services single_command_tool events helpers/index diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index 3441549e363..abd5fddbc94 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -62,80 +62,6 @@ This command will now automatically be available to run: $ app/console demo:greet Fabien -.. _cookbook-console-dic: - -Register Commands in the Service Container ------------------------------------------- - -.. versionadded:: 2.4 - Support for registering commands in the service container was added in - version 2.4. - -By default, Symfony will take a look in the ``Command`` directory of your -bundles and automatically register your commands. For the ones implementing -the ``ContainerAwareCommand`` interface, Symfony will even inject the container. - -If you want to, you can instead register them as services in the container using -the ``console.command`` tag: - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/config.yml - services: - acme_hello.command.my_command: - class: Acme\HelloBundle\Command\MyCommand - tags: - - { name: console.command } - - .. code-block:: xml - - - - - - - - - - - .. code-block:: php - - // app/config/config.php - - $container - ->register('acme_hello.command.my_command', 'Acme\HelloBundle\Command\MyCommand') - ->addTag('console.command') - ; - -.. tip:: - - Commands as services can be useful in few situations: - - * if you need your commands to be defined somewhere else than in the - ``Command`` folder; - * if you need to register the command conditionally (depending on the - environment or presence of some dependencies); - * ou want to reuse the command with a different service or different - configuration, without having to extend the command - you could just - define a second service with the same class; - * if you need to access services or configuration parameters in the - ``configure`` method. - - For example, imagine you want to provide a default value for the ``name`` - option. You could hard code a string and pass it as the 4th argument of - ``addArgument``, or you could allow the user to set the default value in the - configuration. - - With a ``ContainerAwareCommand`` you wouldn't be able to retrieve the - configuration parameter, because the ``configure`` method is called in the - command's constructor. The only solution is to inject them through its - constructor. - Getting Services from the Service Container ------------------------------------------- From 6a7a25fa165b71a84c12350a3977eb549d4c3d2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Chardonnet?= Date: Sun, 2 Mar 2014 11:47:42 +0100 Subject: [PATCH 0233/1181] Fixed @WouterJ's feedback --- components/console/commands_as_services.rst | 53 ++++++++++----------- components/console/introduction.rst | 1 + 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/components/console/commands_as_services.rst b/components/console/commands_as_services.rst index b0bffe5fd1a..3aa217c25ee 100644 --- a/components/console/commands_as_services.rst +++ b/components/console/commands_as_services.rst @@ -1,26 +1,25 @@ .. index:: single: Console; Commands as Services -How to define Commands as Services +How to Define Commands as Services ================================== .. versionadded:: 2.4 - Support for registering commands in the service container was added in + Support for registering commands in the service container was introduced in version 2.4. By default, Symfony will take a look in the ``Command`` directory of your bundles and automatically register your commands. For the ones implementing the ``ContainerAwareCommand`` interface, Symfony will even inject the container. - While making life easier, this default implementation has some drawbacks in some situations: -* what if you want your command to be defined elsewhere than in the ``Command`` - folder? -* what if you want to register conditionally your command, depending on the +* What if you want your command to be defined elsewhere than in the ``Command`` + directory? +* what if you want to conditionally register your command, depending on the current environment or on the availability of some dependencies? -* what if you need to access dependencies before the ``setContainer`` is called - (for example in the ``configure`` method)? +* what if you need to access dependencies before the ``setContainer()`` is + called (for example in the ``configure()`` method)? * what if you want to reuse a command many times, but with different dependencies or parameters? @@ -46,45 +45,41 @@ defining it with the ``console.command`` tag: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - - + + + + + .. code-block:: php // app/config/config.php - $container ->register('acme_hello.command.my_command', 'Acme\HelloBundle\Command\MyCommand') ->addTag('console.command') ; -Here are some use cases. - -Use dependencies and parameters in configure --------------------------------------------- +Use Case: Using Dependencies and Parameters to Set Default Values for Options +----------------------------------------------------------------------------- -For example, imagine you want to provide a default value for the ``name`` -argument. You could: +Imagine you want to provide a default value for the ``name``option. You could +pass one of the following as the 5th argument of ``addOption()``: -* hard code a string and pass it as the 4th argument of ``addArgument``; -* allow the user to set the default value in the configuration; -* retrieve the default value from a service (a repository for example). +* an hardcoded string; +* a value coming from the configuration (allows the user to change it easily); +* a value computed by a service (e.g. a repository). With a ``ContainerAwareCommand`` you wouldn't be able to retrieve the -configuration parameter, because the ``configure`` method is called in the -command's constructor. The only solution is to inject them through its -constructor: +configuration parameter, because the ``configure()`` method is called in the +constructor. The only solution is to inject them through it:: - setName('demo:greet') ->setDescription('Greet someone') - ->addArgument('name', InputArgument::OPTIONAL, 'Who do you want to greet?', $defaultName) + ->addOption('name', '-n', InputOption::VALUE_REQUIRED, 'Who do you want to greet?', $defaultName) ; } protected function execute(InputInterface $input, OutputInterface $output) { - $name = $input->getArgument('name'); + $name = $input->getOption('name'); $output->writeln($name); } diff --git a/components/console/introduction.rst b/components/console/introduction.rst index 98f8b8643be..8ea786629dd 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -527,6 +527,7 @@ Learn More! * :doc:`/components/console/usage` * :doc:`/components/console/single_command_tool` * :doc:`/components/console/events` +* :doc:`/components/console/commands_as_services` .. _Packagist: https://packagist.org/packages/symfony/console .. _ANSICON: https://github.com/adoxa/ansicon/releases From 11bfe506c9c5d175c787d4a1b300f207ddcf2415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Chardonnet?= Date: Sun, 2 Mar 2014 17:27:35 +0100 Subject: [PATCH 0234/1181] Added warning about performances --- components/console/commands_as_services.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/components/console/commands_as_services.rst b/components/console/commands_as_services.rst index 3aa217c25ee..29ba2c715a9 100644 --- a/components/console/commands_as_services.rst +++ b/components/console/commands_as_services.rst @@ -61,8 +61,8 @@ defining it with the ``console.command`` tag: ->addTag('console.command') ; -Use Case: Using Dependencies and Parameters to Set Default Values for Options ------------------------------------------------------------------------------ +Using Dependencies and Parameters to Set Default Values for Options +------------------------------------------------------------------- Imagine you want to provide a default value for the ``name``option. You could pass one of the following as the 5th argument of ``addOption()``: @@ -111,3 +111,9 @@ constructor. The only solution is to inject them through it:: $output->writeln($name); } } + +.. caution:: + + When running the console, every commands are instanciated, which means every + ``configure()`` methods are called. Be careful with database queries, as + this could impact performances. From bd9cd2694ee562f858b969d4382780f992faadc8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 3 Mar 2014 12:24:53 +0100 Subject: [PATCH 0235/1181] added docs for the new Table console helper --- components/console/helpers/index.rst | 1 + components/console/helpers/map.rst.inc | 1 + components/console/helpers/table.rst | 144 +++++++++++++++++++++ components/console/helpers/tablehelper.rst | 7 + 4 files changed, 153 insertions(+) create mode 100644 components/console/helpers/table.rst diff --git a/components/console/helpers/index.rst b/components/console/helpers/index.rst index 1c95bc47057..417ec6caf12 100644 --- a/components/console/helpers/index.rst +++ b/components/console/helpers/index.rst @@ -10,6 +10,7 @@ The Console Helpers dialoghelper formatterhelper progresshelper + table tablehelper The Console component comes with some useful helpers. These helpers contain diff --git a/components/console/helpers/map.rst.inc b/components/console/helpers/map.rst.inc index 60b32c03975..cb046bfb592 100644 --- a/components/console/helpers/map.rst.inc +++ b/components/console/helpers/map.rst.inc @@ -1,4 +1,5 @@ * :doc:`/components/console/helpers/dialoghelper` * :doc:`/components/console/helpers/formatterhelper` * :doc:`/components/console/helpers/progresshelper` +* :doc:`/components/console/helpers/table` * :doc:`/components/console/helpers/tablehelper` diff --git a/components/console/helpers/table.rst b/components/console/helpers/table.rst new file mode 100644 index 00000000000..6fe6848a8e1 --- /dev/null +++ b/components/console/helpers/table.rst @@ -0,0 +1,144 @@ +.. index:: + single: Console Helpers; Table + +Table +===== + +.. versionadded:: 2.5 + The ``Table`` class was introduced in Symfony 2.5 as a replacement for the + :doc:`Table Helper `. + +When building a console application it may be useful to display tabular data: + +.. code-block:: text + + +---------------+--------------------------+------------------+ + | ISBN | Title | Author | + +---------------+--------------------------+------------------+ + | 99921-58-10-7 | Divine Comedy | Dante Alighieri | + | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | + | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | + | 80-902734-1-6 | And Then There Were None | Agatha Christie | + +---------------+--------------------------+------------------+ + +To display a table, use :class:`Symfony\\Component\\Console\\Helper\\Table`, +set the headers, set the rows and then render the table:: + + use Symfony\Component\Helper\Table; + + $table = new Table($output); + $table + ->setHeaders(array('ISBN', 'Title', 'Author')) + ->setRows(array( + array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), + array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), + array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), + array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), + )) + ; + $table->render(); + +You can add a table separator anywhere in the output by passing an instance of +:class:`Symfony\\Component\\Console\\Helper\\TableSeparator` as a row:: + + use Symfony\Component\Helper\TableSeparator; + + $table->setRows(array( + array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), + array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), + new TableSeparator(), + array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), + array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), + )); + +.. code-block:: text + + +---------------+--------------------------+------------------+ + | ISBN | Title | Author | + +---------------+--------------------------+------------------+ + | 99921-58-10-7 | Divine Comedy | Dante Alighieri | + | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | + +---------------+--------------------------+------------------+ + | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | + | 80-902734-1-6 | And Then There Were None | Agatha Christie | + +---------------+--------------------------+------------------+ + +The table style can be changed to any built-in styles via +:method:`Symfony\\Component\\Console\\Helper\\Table::setStyle`:: + + // same as calling nothing + $table->setStyle('default'); + + // changes the default style to compact + $table->setStyle('compact'); + $table->render(); + +This code results in: + +.. code-block:: text + + ISBN Title Author + 99921-58-10-7 Divine Comedy Dante Alighieri + 9971-5-0210-0 A Tale of Two Cities Charles Dickens + 960-425-059-0 The Lord of the Rings J. R. R. Tolkien + 80-902734-1-6 And Then There Were None Agatha Christie + +You can also set the style to ``borderless``:: + + $table->setStyle('borderless'); + $table->render(); + +which outputs: + +.. code-block:: text + + =============== ========================== ================== + ISBN Title Author + =============== ========================== ================== + 99921-58-10-7 Divine Comedy Dante Alighieri + 9971-5-0210-0 A Tale of Two Cities Charles Dickens + 960-425-059-0 The Lord of the Rings J. R. R. Tolkien + 80-902734-1-6 And Then There Were None Agatha Christie + =============== ========================== ================== + +If the built-in styles do not fit your need, define your own:: + +.. code-block:: php + + use Symfony\Component\Helper\TableStyle; + + // by default, this is based on the default style + $style = new TableStyle(); + + // customize the style + $style + ->setHorizontalBorderChar('|') + ->setVerticalBorderChar('-') + ->setCrossingChar(' ') + ; + + // use the style for this table + $table->setStyle($style); + +Here is a full list of things you can customize: + +* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setPaddingChar` +* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setHorizontalBorderChar` +* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setVerticalBorderChar` +* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setCrossingChar` +* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setCellHeaderFormat` +* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setCellRowFormat` +* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setBorderFormat` +* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setPadType` + +.. tip:: + + You can also register a style globally:: + + // register the style under the colorful name + Table::setStyleDefinition('colorful', $style); + + // use it for a table + $table->setStyle('colorful'); + + This method can also be used to override a built-in style. diff --git a/components/console/helpers/tablehelper.rst b/components/console/helpers/tablehelper.rst index 4bc3323ebe6..e42b151b845 100644 --- a/components/console/helpers/tablehelper.rst +++ b/components/console/helpers/tablehelper.rst @@ -7,6 +7,13 @@ Table Helper .. versionadded:: 2.3 The ``table`` helper was added in Symfony 2.3. +.. caution:: + + The Table Helper was deprecated in Symfony 2.5 and will be removed in + Symfony 3.0. You should now use the + :doc:`Table ` class instead which is + more powerful. + When building a console application it may be useful to display tabular data: .. image:: /images/components/console/table.png From 9e2727d628be64d5a1d8a730d2c3c7be9608cf34 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 3 Mar 2014 10:38:50 +0100 Subject: [PATCH 0236/1181] added documentation for the new Symfony 2.5 progress bar --- components/console/helpers/index.rst | 1 + components/console/helpers/map.rst.inc | 1 + components/console/helpers/progressbar.rst | 322 ++++++++++++++++++ components/console/helpers/progresshelper.rst | 11 +- images/components/console/progressbar.gif | Bin 0 -> 29016 bytes 5 files changed, 333 insertions(+), 2 deletions(-) create mode 100644 components/console/helpers/progressbar.rst create mode 100644 images/components/console/progressbar.gif diff --git a/components/console/helpers/index.rst b/components/console/helpers/index.rst index 1c95bc47057..35e9e56d4e3 100644 --- a/components/console/helpers/index.rst +++ b/components/console/helpers/index.rst @@ -9,6 +9,7 @@ The Console Helpers dialoghelper formatterhelper + progressbar progresshelper tablehelper diff --git a/components/console/helpers/map.rst.inc b/components/console/helpers/map.rst.inc index 60b32c03975..034af6fd43b 100644 --- a/components/console/helpers/map.rst.inc +++ b/components/console/helpers/map.rst.inc @@ -1,4 +1,5 @@ * :doc:`/components/console/helpers/dialoghelper` * :doc:`/components/console/helpers/formatterhelper` +* :doc:`/components/console/helpers/progressbar` * :doc:`/components/console/helpers/progresshelper` * :doc:`/components/console/helpers/tablehelper` diff --git a/components/console/helpers/progressbar.rst b/components/console/helpers/progressbar.rst new file mode 100644 index 00000000000..0cd119a0a9b --- /dev/null +++ b/components/console/helpers/progressbar.rst @@ -0,0 +1,322 @@ +.. index:: + single: Console Helpers; Progress Bar + +Progress Bar +============ + +.. versionadded:: 2.5 + The Progress Bar feature was introduced in Symfony 2.5 as a replacement for + the :doc:`Progress Helper `. + +When executing longer-running commands, it may be helpful to show progress +information, which updates as your command runs: + +.. image:: /images/components/console/progressbar.gif + +To display progress details, use the +:class:`Symfony\\Component\\Console\\Helper\\ProgressBar`, pass it a total +number of units, and advance the progress as the command executes:: + + use Symfony\Component\Console\Helper\ProgressBar; + + // create a new progress bar (50 units) + $progress = new ProgressBar($output, 50); + + // start and displays the progress bar + $progress->start(); + + $i = 0; + while ($i++ < 50) { + // ... do some work + + // advance the progress bar 1 unit + $progress->advance(); + + // you can also advance the progress bar by more than 1 unit + // $progress->advance(3); + } + + // ensure that the progress bar is at 100% + $progress->finish(); + +Instead of advancing the bar by a number of steps (with the +:method:`Symfony\\Component\\Console\\Helper\\ProgressBar::advance` method), +you can also set the current progress by calling the +:method:`Symfony\\Component\\Console\\Helper\\ProgressBar::setCurrent` method. + +.. caution:: + + The progress bar only works if your platform supports ANSI codes; on other + platforms, no output is generated. + +If you don't know the number of steps in advance, just omit the steps argument +when creating the :class:`Symfony\\Component\\Console\\Helper\\ProgressBar` +instance:: + + $progress = new ProgressBar($output); + +The progress will then be displayed as a throbber:: + +.. code-block:: text + + # no max steps (displays it like a throbber) + 0 [>---------------------------] + 5 [----->----------------------] + 5 [============================] + + # max steps defined + 0/3 [>---------------------------] 0% + 1/3 [=========>------------------] 33% + 3/3 [============================] 100% + +Whenever your task is finished, don't forget to call +:method:`Symfony\\Component\\Console\\Helper\\ProgressBar::finish` to ensure +that the progress bar display is refreshed with a 100% completion. + +.. note:: + + If you want to output something while the progress bar is running, + call :method:`Symfony\\Component\\Console\\Helper\\ProgressBar::clear` first. + After you're done, call + :method:`Symfony\\Component\\Console\\Helper\\ProgressBar::display` + to show the progress bar again. + +Customizing the Progress Bar +---------------------------- + +Built-in Formats +~~~~~~~~~~~~~~~~ + +By default, the information rendered on a progress bar depends on the current +level of verbosity of the ``OutputInterface`` instance: + +.. code-block:: text + + # OutputInterface::VERBOSITY_NORMAL (CLI with no verbosity flag) + 0/3 [>---------------------------] 0% + 1/3 [=========>------------------] 33% + 3/3 [============================] 100% + + # OutputInterface::VERBOSITY_VERBOSE (-v) + 0/3 [>---------------------------] 0% 1 sec + 1/3 [=========>------------------] 33% 1 sec + 3/3 [============================] 100% 1 sec + + # OutputInterface::VERBOSITY_VERY_VERBOSE (-vv) + 0/3 [>---------------------------] 0% 1 sec + 1/3 [=========>------------------] 33% 1 sec + 3/3 [============================] 100% 1 sec + + # OutputInterface::VERBOSITY_DEBUG (-vvv) + 0/3 [>---------------------------] 0% 1 sec/1 sec 1.0 MB + 1/3 [=========>------------------] 33% 1 sec/1 sec 1.0 MB + 3/3 [============================] 100% 1 sec/1 sec 1.0 MB + +.. note:: + + If you call a command with the quiet flag (``-q``), the progress bar won't + be displayed. + +Instead of relying on the verbosity mode of the current command, you can also +force a format via ``setFormat()``:: + + $bar->setFormat('verbose'); + +The built-in formats are the following: + +* ``normal`` +* ``verbose`` +* ``very_verbose`` +* ``debug`` + +If you don't set the number of steps for your progress bar, use the ``_nomax`` +variants: + +* ``normal_nomax`` +* ``verbose_nomax`` +* ``very_verbose_nomax`` +* ``debug_nomax`` + +Custom Formats +~~~~~~~~~~~~~~ + +Instead of using the built-in formats, you can also set your own:: + + $bar->setFormat('%bar%'); + +This sets the format to only display the progress bar itself: + +.. code-block:: text + + >--------------------------- + =========>------------------ + ============================ + +A progress bar format is a string that contains specific placeholders (a name +enclosed with the ``%`` character); the placeholders are replaced based on the +current progress of the bar. Here is a list of the built-in placeholders: + +* ``current``: The current step; +* ``max``: The maximum number of steps (or 0 if no max is defined); +* ``bar``: The bar itself; +* ``percent``: The percentage of completion (not available if no max is defined); +* ``elapsed``: The time elapsed since the start of the progress bar; +* ``remaining``: The remaining time to complete the task (not available if no max is defined); +* ``estimated``: The estimated time to complete the task (not available if no max is defined); +* ``memory``: The current memory usage; +* ``message``: The current message attached to the progress bar. + +For instance, here is how you could set the format to be the same as the +``debug`` one:: + + $bar->setFormat(' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%'); + +Notice the ``:6s`` part added to some placeholders? That's how you can tweak +the appearance of the bar (formatting and alignment). The part after the colon +(``:``) is used to set the ``sprintf`` format of the string. + +The ``message`` placeholder is a bit special as you must set the value +yourself:: + + $bar->setMessage('Task starts'); + $bar->start(); + + $bar->setMessage('Task in progress...'); + $bar->advance(); + + // ... + + $bar->setMessage('Task is finished'); + $bar->finish(); + +Instead of setting the format for a given instance of a progress bar, you can +also define global formats:: + + ProgressBar::setFormatDefinition('minimal', 'Progress: %percent%%'); + + $bar = new ProgressBar($output, 3); + $bar->setFormat('minimal'); + +This code defines a new ``minimal`` format that you can then use for your +progress bars: + +.. code-block:: text + + Progress: 0% + Progress: 33% + Progress: 100% + +.. tip:: + + It is almost always better to redefine built-in formats instead of creating + new ones as that allows the display to automatically vary based on the + verbosity flag of the command. + +When defining a new style that contains placeholders that are only available +when the maximum number of steps is known, you should create a ``_nomax`` +variant:: + + ProgressBar::setFormatDefinition('minimal', '%percent%% %remaining%'); + ProgressBar::setFormatDefinition('minimal_nomax', '%percent%%'); + + $bar = new ProgressBar($output); + $bar->setFormat('minimal'); + +When displaying the progress bar, the format will automatically be set to +``minimal_nomax`` if the bar does not have a maximum number of steps like in +the example above. + +.. tip:: + + A format can contain any valid ANSI codes and can also use the + Symfony-specific way to set colors:: + + ProgressBar::setFormatDefinition( + 'minimal', + '%percent%\033[32m%\033[0m %remaining%' + ); + +.. note:: + + A format can span more than one line; that's very useful when you want to + display more contextual information alongside the progress bar (see the + example at the beginning of this article). + +Bar Settings +~~~~~~~~~~~~ + +Amongst the placeholders, ``bar`` is a bit special as all the characters used +to display it can be customized:: + + // the finished part of the bar + $progress->setBarCharacter('='); + + // the unfinished part of the bar + $progress->setEmptyBarCharacter(' '); + + // the progress character + $progress->setProgressCharacter('|'); + + // the bar width + $progress->setBarWidth(50); + +.. caution:: + + For performance reasons, be careful if you set the total number of steps + to a high number. For example, if you're iterating over a large number of + items, consider setting the redraw frequency to a higher value by calling + :method:`Symfony\\Component\\Console\\Helper\\ProgressHelper::setRedrawFrequency`, + so it updates on only some iterations:: + + $progress->start($output, 50000); + + // update every 100 iterations + $progress->setRedrawFrequency(100); + + $i = 0; + while ($i++ < 50000) { + // ... do some work + + $progress->advance(); + } + +Custom Placeholders +~~~~~~~~~~~~~~~~~~~ + +If you want to display some information that depends on the progress bar +display that are not available in the list of built-in placeholders, you can +create your own. Let's see how you can create a ``remaining_steps`` placeholder +that displays the number of remaining steps:: + + ProgressBar::setPlaceholderFormatter( + '%remaining_steps%', + function (ProgressBar $bar, OutputInterface $output) { + return $bar->getMaxSteps() - $bar->getStep(); + } + ); + +Custom Messages +~~~~~~~~~~~~~~~ + +The ``%message%`` placeholder allows you to specify a custom message to be +displayed with the progress bar. But if you need more than one, just define +your own:: + + $bar->setMessage('Task starts'); + $bar->setMessage('', 'filename'); + $bar->start(); + + $bar->setMessage('Task is in progress...'); + while ($file = array_pop($files)) { + $bar->setMessage($filename, 'filename'); + $bar->advance(); + } + + $bar->setMessage('Task is finished'); + $bar->setMessage('', 'filename'); + $bar->finish(); + +For the ``filename`` to be part of the progress bar, just add the +``%filename%`` placeholder in your format:: + + $bar->setFormat(" %message%\n %step%/%max%\n Working on %filename%"); diff --git a/components/console/helpers/progresshelper.rst b/components/console/helpers/progresshelper.rst index 9ee76b694cb..3722b3fe213 100644 --- a/components/console/helpers/progresshelper.rst +++ b/components/console/helpers/progresshelper.rst @@ -10,6 +10,13 @@ Progress Helper .. versionadded:: 2.4 The ``clear`` method was added in Symfony 2.4. +.. caution:: + + The Progress Helper was deprecated in Symfony 2.5 and will be removed in + Symfony 3.0. You should now use the + :doc:`Progress Bar ` instead which + is more powerful. + When executing longer-running commands, it may be helpful to show progress information, which updates as your command runs: @@ -25,7 +32,7 @@ pass it a total number of units, and advance the progress as your command execut while ($i++ < 50) { // ... do some work - // advance the progress bar 1 unit + // advances the progress bar 1 unit $progress->advance(); } @@ -79,7 +86,7 @@ To see other available options, check the API documentation for $progress->start($output, 50000); - // update every 100 iterations + // updates every 100 iterations $progress->setRedrawFrequency(100); $i = 0; diff --git a/images/components/console/progressbar.gif b/images/components/console/progressbar.gif new file mode 100644 index 0000000000000000000000000000000000000000..6c80e6e897f670d0a53a1dc115bbe34a71fa1568 GIT binary patch literal 29016 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
ZeTPcbORBHACKVq0VF$~>Ex^4p#$>AvyurY zAfPS-h#l zDl)&xcvEusa7ra3^(hljLqIu(-HZX$&~F`-(=!ZoV)E-7@|!yVK~$KN01$GZ7E?@P z77wu4%BYc1(%QooN53-->^4jzgI$FgV6dw&jny^9DZi^QopoL8{u%(pfi_IzAcKv? z89*Cmn5~0=_yTLVt&Q0>l+8xr_4z;{<}VNjIxzqc?>r53VtTrOAVeMj#QQp#f7>t& z*1!OBaAx#BI%s~HF*(cv3Nj-M*8K2rU(KHq3>%BTnHirQ21+n&GR|a9j^zkg=u z1729kISGF|5L5^S)2R1x?J^1$>`Pujog|zrg}&OkjFqu`5yYoU*z9Z%3avjmEA54o zQYGd4Imcd)Tg?7L1q9OZn=ULkA$Mf=iA%zMrP zw1b~t_t(N@6Iq*&TUA@El`|hq`09z*D?6uOX|PwDkIpgQHo5IobZXbl?SMOn4}I#^ z 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 literal 0 HcmV?d00001 From 2d9647b9e953dbd85fc1d0873eaa163505b97e82 Mon Sep 17 00:00:00 2001 From: florianv Date: Mon, 3 Mar 2014 18:49:17 +0100 Subject: [PATCH 0237/1181] Added documentation for translation:debug --- book/translation.rst | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/book/translation.rst b/book/translation.rst index c27ac70c933..b8c0600b932 100644 --- a/book/translation.rst +++ b/book/translation.rst @@ -649,6 +649,39 @@ The translation of database content should be handled by Doctrine through the `Translatable Extension`_. For more information, see the documentation for that library. +Debugging Translations +---------------------- + +.. versionadded:: 2.5 + The ``translation:debug`` command was introduced in Symfony 2.5. + +When maintaining a bundle, you may use or remove the usage of a translation +message without updating all message catalogues. The ``translation:debug`` +command helps you finding these missing or unused translation messages for a +given locale. It shows you a table with the result when translating the +message in the given locale and the result when the fallback would be used. +On top of that, it also shows you when the translation is the same as the +fallback translation (this could indicate that the message was not correctly +translated). To inspect all messages in the ``en`` locale for the AcmeDemoBundle, run: + +.. code-block:: bash + + $ php app/console translation:debug en AcmeDemoBundle + +By default all domains are inspected, but it is possible to specify a single domain: + +.. code-block:: bash + + $ php app/console translation:debug en AcmeDemoBundle --domain=messages + +You can also display only the unused or only the missing messages, by using +the ``--only-unused`` or ``--only-missing`` switches: + +.. code-block:: bash + + $ php app/console translation:debug en AcmeDemoBundle --only-unused + $ php app/console translation:debug en AcmeDemoBundle --only-missing + Summary ------- From 6adf1603933dded0fe264c4a0f03907250a4f311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gildas=20Qu=C3=A9m=C3=A9ner?= Date: Tue, 31 Dec 2013 11:41:39 +0100 Subject: [PATCH 0238/1181] Added documentation about new requests formats configuration --- cookbook/request/mime_type.rst | 136 ++++++++++++++++++++------------- 1 file changed, 81 insertions(+), 55 deletions(-) diff --git a/cookbook/request/mime_type.rst b/cookbook/request/mime_type.rst index fb57352c189..6879407da8c 100644 --- a/cookbook/request/mime_type.rst +++ b/cookbook/request/mime_type.rst @@ -15,81 +15,107 @@ object. Internally, Symfony contains a map of the most common formats (e.g. easily be added. This document will show how you can add the ``jsonp`` format and corresponding MIME type. -Create a ``kernel.request`` Listener -------------------------------------- +.. versionadded:: 2.5 + The possibility to configure request formats was introduced in Symfony 2.5. -The key to defining a new MIME type is to create a class that will "listen" to -the ``kernel.request`` event dispatched by the Symfony kernel. The -``kernel.request`` event is dispatched early in Symfony's request handling -process and allows you to modify the request object. - -Create the following class, replacing the path with a path to a bundle in your -project:: - - // src/Acme/DemoBundle/RequestListener.php - namespace Acme\DemoBundle; - - use Symfony\Component\HttpKernel\HttpKernelInterface; - use Symfony\Component\HttpKernel\Event\GetResponseEvent; - - class RequestListener - { - public function onKernelRequest(GetResponseEvent $event) - { - $event->getRequest()->setFormat('jsonp', 'application/javascript'); - } - } - -Registering your Listener +Configure your New Format ------------------------- -As with any other listener, you need to add it in one of your configuration -files and register it as a listener by adding the ``kernel.event_listener`` tag: +The FrameworkBundle registers a subscriber that will add formats to incomming requests. + +All you have to do is to configure the ``jsonp`` format: .. configuration-block:: .. code-block:: yaml # app/config/config.yml - services: - acme.demobundle.listener.request: - class: Acme\DemoBundle\RequestListener - tags: - - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest } + framework: + request: + formats: + jsonp: 'application/javascript' .. code-block:: xml - + + - - - - - + xmlns:framework="http://symfony.com/schema/dic/symfony" + xsi:schemaLocation="http://symfony.com/schema/dic/services + http://symfony.com/schema/dic/services/services-1.0.xsd + http://symfony.com/schema/dic/symfony + http://symfony.com/schema/dic/symfony/symfony-1.0.xsd" + > + + + + application/javascript + + + .. code-block:: php - # app/config/config.php - $definition = new Definition('Acme\DemoBundle\RequestListener'); - $definition->addTag('kernel.event_listener', array( - 'event' => 'kernel.request', - 'method' => 'onKernelRequest', + // app/config/config.php + $container->loadFromExtension('framework', array( + 'request' => array( + 'formats' => array( + 'jsonp' => 'application/javascript', + ), + ), )); - $container->setDefinition('acme.demobundle.listener.request', $definition); - -At this point, the ``acme.demobundle.listener.request`` service has been -configured and will be notified when the Symfony kernel dispatches the -``kernel.request`` event. .. tip:: - You can also register the listener in a configuration extension class (see - :ref:`service-container-extension-configuration` for more information). + You can also associate multiple mime types to a format, but please note that + the preferred one must be the first as it will be used as the content type: + + .. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + framework: + request: + formats: + csv: ['text/csv', 'text/plain'] + + .. code-block:: xml + + + + + + + + + text/csv + text/plain + + + + + + .. code-block:: php + + // app/config/config.php + $container->loadFromExtension('framework', array( + 'request' => array( + 'formats' => array( + 'jsonp' => array( + 'text/csv', + 'text/plain', + ), + ), + ), + )); From 6c52b92a1eba95a7cedb62309d20ddb2c29bcbeb Mon Sep 17 00:00:00 2001 From: John Kary Date: Sat, 30 Nov 2013 00:16:42 -0600 Subject: [PATCH 0239/1181] [#3311] Use KernelTestCase instead of WebTestCase for tests needing only a Container --- cookbook/console/console_command.rst | 15 ++++++++++++--- cookbook/testing/doctrine.rst | 9 ++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index 6e3721a24ef..fc903b12650 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -183,14 +183,14 @@ instead of To be able to use the fully set up service container for your console tests you can extend your test from -:class:`Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase`:: +:class:`Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase`:: use Symfony\Component\Console\Tester\CommandTester; use Symfony\Bundle\FrameworkBundle\Console\Application; - use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; + use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Acme\DemoBundle\Command\GreetCommand; - class ListCommandTest extends WebTestCase + class ListCommandTest extends KernelTestCase { public function testExecute() { @@ -214,3 +214,12 @@ you can extend your test from // ... } } + +.. versionadded:: 2.5 + :class:`Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase` was + extracted from :class:`Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase` + in Symfony 2.5, where WebTestCase was made to inherit from KernelTestCase. + The difference being that WebTestCase makes available an instance of + :class:`Symfony\\Bundle\\FrameworkBundle\\Client` via `createClient()`, + while KernelTestCase makes available an instance of + :class:`Symfony\\Component\\HttpKernel\\KernelInterface` via `createKernel()`. diff --git a/cookbook/testing/doctrine.rst b/cookbook/testing/doctrine.rst index ef9467861a3..87779fcda41 100644 --- a/cookbook/testing/doctrine.rst +++ b/cookbook/testing/doctrine.rst @@ -17,15 +17,15 @@ Functional Testing ------------------ If you need to actually execute a query, you will need to boot the kernel -to get a valid connection. In this case, you'll extend the ``WebTestCase``, +to get a valid connection. In this case, you'll extend the ``KernelTestCase``, which makes all of this quite easy:: // src/Acme/StoreBundle/Tests/Entity/ProductRepositoryFunctionalTest.php namespace Acme\StoreBundle\Tests\Entity; - use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; + use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; - class ProductRepositoryFunctionalTest extends WebTestCase + class ProductRepositoryFunctionalTest extends KernelTestCase { /** * @var \Doctrine\ORM\EntityManager @@ -37,8 +37,7 @@ which makes all of this quite easy:: */ public function setUp() { - static::$kernel = static::createKernel(); - static::$kernel->boot(); + self::bootKernel(); $this->em = static::$kernel->getContainer() ->get('doctrine') ->getManager() From 9a938795926cb16e65b9e4e2a817af48cf28ca06 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 5 Oct 2013 10:17:03 +0200 Subject: [PATCH 0240/1181] use DebugClassLoader class from Debug component instead of the one from the Class Loader component --- .../class_loader/debug_class_loader.rst | 14 +++--------- components/debug/class_loader.rst | 22 +++++++++++++++++++ components/debug/index.rst | 8 +++++++ .../{debug.rst => debug/introduction.rst} | 5 ++--- components/index.rst | 2 +- components/map.rst.inc | 5 +++-- .../front_controllers_and_kernel.rst | 4 ++-- 7 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 components/debug/class_loader.rst create mode 100644 components/debug/index.rst rename components/{debug.rst => debug/introduction.rst} (92%) diff --git a/components/class_loader/debug_class_loader.rst b/components/class_loader/debug_class_loader.rst index 7c724fb6a01..c56d7ffe095 100644 --- a/components/class_loader/debug_class_loader.rst +++ b/components/class_loader/debug_class_loader.rst @@ -4,14 +4,6 @@ Debugging a Class Loader ======================== -The :class:`Symfony\\Component\\ClassLoader\\DebugClassLoader` attempts to -throw more helpful exceptions when a class isn't found by the registered -autoloaders. All autoloaders that implement a ``findFile()`` method are replaced -with a ``DebugClassLoader`` wrapper. - -Using the ``DebugClassLoader`` is as easy as calling its static -:method:`Symfony\\Component\\ClassLoader\\DebugClassLoader::enable` method:: - - use Symfony\Component\ClassLoader\DebugClassLoader; - - DebugClassLoader::enable(); +Since Symfony 2.4, the ``DebugClassLoader`` of the Class Loader component is +deprecated. Use the +:doc:`DebugClassLoader provided by the Debug component `. diff --git a/components/debug/class_loader.rst b/components/debug/class_loader.rst new file mode 100644 index 00000000000..090b230baf4 --- /dev/null +++ b/components/debug/class_loader.rst @@ -0,0 +1,22 @@ +.. index:: + single: Class Loader; DebugClassLoader + single: Debug; DebugClassLoader + +Debugging a Class Loader +======================== + +.. versionadded:: 2.4 + The ``DebugClassLoader`` of the Debug component is new in Symfony 2.4. + Previously, it was located in the Class Loader component. + +The :class:`Symfony\\Component\\Debug\\DebugClassLoader` attempts to +throw more helpful exceptions when a class isn't found by the registered +autoloaders. All autoloaders that implement a ``findFile()`` method are replaced +with a ``DebugClassLoader`` wrapper. + +Using the ``DebugClassLoader`` is as easy as calling its static +:method:`Symfony\\Component\\Debug\\DebugClassLoader::enable` method:: + + use Symfony\Component\ClassLoader\DebugClassLoader; + + DebugClassLoader::enable(); diff --git a/components/debug/index.rst b/components/debug/index.rst new file mode 100644 index 00000000000..6797789cb1b --- /dev/null +++ b/components/debug/index.rst @@ -0,0 +1,8 @@ +Debug +===== + +.. toctree:: + :maxdepth: 2 + + introduction + class_loader diff --git a/components/debug.rst b/components/debug/introduction.rst similarity index 92% rename from components/debug.rst rename to components/debug/introduction.rst index 0d20a13ee9a..5691ca58be4 100644 --- a/components/debug.rst +++ b/components/debug/introduction.rst @@ -30,9 +30,8 @@ Enabling them all is as easy as it can get:: Debug::enable(); The :method:`Symfony\\Component\\Debug\\Debug::enable` method registers an -error handler and an exception handler. If the :doc:`ClassLoader component -` is available, a special class loader -is also registered. +error handler, an exception handler and +:doc:`a special class loader `. Read the following sections for more information about the different available tools. diff --git a/components/index.rst b/components/index.rst index b53785bb642..8e167cd2ac9 100644 --- a/components/index.rst +++ b/components/index.rst @@ -9,7 +9,7 @@ The Components config/index console/index css_selector - debug + debug/index dependency_injection/index dom_crawler event_dispatcher/index diff --git a/components/map.rst.inc b/components/map.rst.inc index a5f2d0f8db7..b472a607d3d 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -27,9 +27,10 @@ * :doc:`/components/css_selector` -* **Debug** +* :doc:`/components/debug/index` - * :doc:`/components/debug` + * :doc:`/components/debug/introduction` + * :doc:`/components/debug/class_loader` * :doc:`/components/dependency_injection/index` diff --git a/cookbook/configuration/front_controllers_and_kernel.rst b/cookbook/configuration/front_controllers_and_kernel.rst index c49788f9056..8c4264a2161 100644 --- a/cookbook/configuration/front_controllers_and_kernel.rst +++ b/cookbook/configuration/front_controllers_and_kernel.rst @@ -45,8 +45,8 @@ to `decorate`_ the kernel with additional features. Examples include: * Configuring the autoloader or adding additional autoloading mechanisms; * Adding HTTP level caching by wrapping the kernel with an instance of :ref:`AppCache `; -* Enabling (or skipping) the :doc:`ClassCache ` -* Enabling the :doc:`Debug component `. +* Enabling (or skipping) the :doc:`ClassCache `; +* Enabling the :doc:`Debug Component `. The front controller can be chosen by requesting URLs like: From e8b3320e97336beb0a270484b618a01dc3158f12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Chardonnet?= Date: Sun, 9 Mar 2014 20:10:52 +0100 Subject: [PATCH 0241/1181] Took into account @cordoval's feedback --- components/console/commands_as_services.rst | 22 ++++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/components/console/commands_as_services.rst b/components/console/commands_as_services.rst index 29ba2c715a9..066eb8aab39 100644 --- a/components/console/commands_as_services.rst +++ b/components/console/commands_as_services.rst @@ -14,14 +14,12 @@ the ``ContainerAwareCommand`` interface, Symfony will even inject the container. While making life easier, this default implementation has some drawbacks in some situations: -* What if you want your command to be defined elsewhere than in the ``Command`` - directory? -* what if you want to conditionally register your command, depending on the - current environment or on the availability of some dependencies? -* what if you need to access dependencies before the ``setContainer()`` is - called (for example in the ``configure()`` method)? -* what if you want to reuse a command many times, but with different - dependencies or parameters? +* Define the command elsewhere than in the ``Command`` directory; +* Conditionally register your command, depending on the current environment or + on the availability of some dependencies; +* Access dependencies before the ``setContainer()`` is called (for example in + the ``configure()`` method); +* Reuse a command many times, but with different dependencies or parameters To solve those problems, you can register your command as a service by simply defining it with the ``console.command`` tag: @@ -73,7 +71,7 @@ pass one of the following as the 5th argument of ``addOption()``: With a ``ContainerAwareCommand`` you wouldn't be able to retrieve the configuration parameter, because the ``configure()`` method is called in the -constructor. The only solution is to inject them through it:: +constructor. The only solution is to inject them:: // src/Acme/DemoBundle/Command/GreetCommand.php namespace Acme\DemoBundle\Command; @@ -114,6 +112,6 @@ constructor. The only solution is to inject them through it:: .. caution:: - When running the console, every commands are instanciated, which means every - ``configure()`` methods are called. Be careful with database queries, as - this could impact performances. + When running the console, every command is instantiated, which means every + ``configure()`` method is called. Be careful with database queries, as + they could impact performance. From 92fb4b12cc310b683f99cabf6add192d267a9b9d Mon Sep 17 00:00:00 2001 From: Sam Hudson Date: Tue, 11 Feb 2014 09:37:08 +0000 Subject: [PATCH 0242/1181] added information on AuthenticationFailureHandlerInterface in api keys docs --- cookbook/security/api_key_authentication.rst | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index c412bd234d6..9bf8ebf729a 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -210,6 +210,27 @@ exception in ``refreshUser()``. If you *do* want to store authentication data in the session so that the key doesn't need to be sent on every request, see :ref:`cookbook-security-api-key-session`. +Handling Exceptions +------------------- + +In order for you're ``ApiKeyAuthentication`` to correctly display a 403 http status when either bad credentials, or authentication fails you will need to implement the ``AuthenticationFailureHandlerInterface`` on your Authenticator. This will provide a method ``onAuthenticationFailure`` which you can then return a ``Response`` with. + + // src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php + namespace Acme\HelloBundle\Security; + + use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; + use Symfony\Component\HttpFoundation\Response; + + class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface, AuthenticationFailureHandlerInterface + { + //... + + public function onAuthenticationFailure(Request $request, AuthenticationException $exception) + { + return new Response("Authentication Failed.", 403); + } + } + .. _cookbook-security-api-key-config: Configuration From 698825ffcc88d65539322d0ce053c8440239a038 Mon Sep 17 00:00:00 2001 From: Sam Hudson Date: Tue, 11 Feb 2014 14:10:12 +0000 Subject: [PATCH 0243/1181] fixed line wrapping --- cookbook/security/api_key_authentication.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index 9bf8ebf729a..ccfcc82d13f 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -213,7 +213,11 @@ exception in ``refreshUser()``. Handling Exceptions ------------------- -In order for you're ``ApiKeyAuthentication`` to correctly display a 403 http status when either bad credentials, or authentication fails you will need to implement the ``AuthenticationFailureHandlerInterface`` on your Authenticator. This will provide a method ``onAuthenticationFailure`` which you can then return a ``Response`` with. +In order for you're ``ApiKeyAuthentication`` to correctly display a 403 +http status when either bad credentials, or authentication fails you will +need to implement the ``AuthenticationFailureHandlerInterface`` on your +Authenticator. This will provide a method ``onAuthenticationFailure`` which +you can then return a ``Response`` with. // src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php namespace Acme\HelloBundle\Security; From c5a87fa30dfd9bdd26fc5201421cba7fd964764e Mon Sep 17 00:00:00 2001 From: Sam Hudson Date: Wed, 26 Feb 2014 22:09:05 +0000 Subject: [PATCH 0244/1181] fixed authentication failed header --- cookbook/security/api_key_authentication.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index ccfcc82d13f..46a920bcf83 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -210,11 +210,11 @@ exception in ``refreshUser()``. If you *do* want to store authentication data in the session so that the key doesn't need to be sent on every request, see :ref:`cookbook-security-api-key-session`. -Handling Exceptions -------------------- +Handling Authentication Failure +------------------------------- -In order for you're ``ApiKeyAuthentication`` to correctly display a 403 -http status when either bad credentials, or authentication fails you will +In order for your ``ApiKeyAuthentication`` to correctly display a 403 +http status when either bad credentials, or authentication fails - you will need to implement the ``AuthenticationFailureHandlerInterface`` on your Authenticator. This will provide a method ``onAuthenticationFailure`` which you can then return a ``Response`` with. From 9445676209b39508a55de770482df021857bd998 Mon Sep 17 00:00:00 2001 From: Sam Hudson Date: Wed, 5 Mar 2014 16:46:17 +0000 Subject: [PATCH 0245/1181] recommendations by xabbuh --- .gitignore | 1 + cookbook/security/api_key_authentication.rst | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..e43b0f98895 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index 46a920bcf83..9c659744673 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -213,17 +213,20 @@ exception in ``refreshUser()``. Handling Authentication Failure ------------------------------- -In order for your ``ApiKeyAuthentication`` to correctly display a 403 -http status when either bad credentials, or authentication fails - you will -need to implement the ``AuthenticationFailureHandlerInterface`` on your +In order for you're ``ApiKeyAuthentication`` to correctly display a 403 +http status when either bad credentials or authentication fails you will +need to implement the :class:`Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface` on your Authenticator. This will provide a method ``onAuthenticationFailure`` which -you can then return a ``Response`` with. +you can use to create an error ``Response``. // src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php namespace Acme\HelloBundle\Security; + use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface; + use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\HttpFoundation\Response; + use Symfony\Component\HttpFoundation\Request; class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface, AuthenticationFailureHandlerInterface { From e915162ad48189edb311908b66b34f2084fe0eac Mon Sep 17 00:00:00 2001 From: Sam Hudson Date: Wed, 5 Mar 2014 16:52:04 +0000 Subject: [PATCH 0246/1181] fixed typo --- cookbook/security/api_key_authentication.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index 9c659744673..e27ef087c90 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -213,7 +213,7 @@ exception in ``refreshUser()``. Handling Authentication Failure ------------------------------- -In order for you're ``ApiKeyAuthentication`` to correctly display a 403 +In order for your ``ApiKeyAuthentication`` to correctly display a 403 http status when either bad credentials or authentication fails you will need to implement the :class:`Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface` on your Authenticator. This will provide a method ``onAuthenticationFailure`` which From 881477c7045affd1344a624153c583826f0f7c32 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Mon, 10 Mar 2014 18:00:14 +0100 Subject: [PATCH 0247/1181] Created 2.4 CHANGELOG --- changelog.rst | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/changelog.rst b/changelog.rst index 5c03e5ff7ea..6264bee4693 100644 --- a/changelog.rst +++ b/changelog.rst @@ -13,45 +13,42 @@ documentation. Do you also want to participate in the Symfony Documentation? Take a look at the ":doc:`/contributing/documentation/overview`" article. + January, 2014 ------------- New Documentation ~~~~~~~~~~~~~~~~~ -No changes +- `d52f3f8 `_ #3454 [Security] Add host option (ghostika) +- `6b3c424 `_ #3428 Translation - Added info about JsonFileLoader added in 2.4 (singles) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `e385d28 `_ #3503 file extension correction xfliff to xliff (nixilla) -- `7fe0de3 `_ #3475 Fixed doc for framework.session.cookie_lifetime refrence. (tyomo4ka) -- `8155e4c `_ #3473 Update proxy_examples.rst (AZielinski) +- `fb22fa0 `_ #3456 remove duplicate label (xabbuh) - `c205bc6 `_ #3468 enclose YAML string with double quotes to fix syntax highlighting (xabbuh) - `89963cc `_ #3463 Fix typos in cookbook/testing/database (ifdattic) - `e0a52ec `_ #3460 remove confusing outdated note on interactive rebasing (xabbuh) - `6831b13 `_ #3455 [Contributing][Code] fix indentation so that the text is rendered properly (xabbuh) - `ea5816f `_ #3433 [WIP][Reference][Form Types] Update "radio" form type (bicpi) - `42c80d1 `_ #3448 Overridden tweak (weaverryan) +- `bede4c3 `_ #3447 Fix error in namespace when use TokenInterface (joanteixi) - `d9d7c58 `_ #3444 Fix issue #3442 (ifdattic) +- `a6ad607 `_ #3441 [Expression]Change title 'Accessing Public Methods' (Pyrech) - `9e2e64b `_ #3427 Removed code references to Symfony Standard Distribution (danielcsgomes) +- `3c2c5fc `_ #3435 Update custom_password_authenticator.rst (boardyuk) - `26b8146 `_ #3415 [#3334] the data_class option was not introduced in 2.4 (xabbuh) - `0b2a491 `_ #3414 add missing code-block directive (xabbuh) - `4988118 `_ #3432 [Reference][Form Types] Add "max_length" option in form type (nykopol) - `26a7b1b `_ #3423 [Session Configuration] add clarifying notes on session save handler proxies (cordoval) +- `f2f5e9a `_ #3421 [Contributing] Cleaning the "contributing patch" page a bit (lemoinem) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `1131247 `_ #3508 Add 'in XML' for additional clarity (ifdattic) -- `a650b93 `_ #3506 Nykopol overriden options (weaverryan) -- `ab10035 `_ #3505 replace Akamaï with Akamai (xabbuh) -- `7f56c20 `_ #3501 [Security] Fix markup (tyx) -- `80a90ba `_ #3500 Minimize horizontal scrolling in code blocks (improve readability) (ifdattic) -- `e5bc4ea `_ #3498 Remove second empty data (xabbuh) -- `d084d87 `_ #3485 [Cookbook][Assetic] Fix "javascripts" tag name typo (bicpi) -- `3250aba `_ #3481 Fix code block (minimise horizontal scrolling), typo in yaml (ifdattic) - `f285d93 `_ #3451 some language tweaks (AE, third-person perspective) (xabbuh) +- `b9bbe5d `_ #3499 Fix YAML syntax highlight + remove trailing whitespace (ifdattic) - `2b7e0f6 `_ #3497 Fix highlighting (WouterJ) - `a535ae0 `_ #3471 Fixed `````versionadded````` inconsistencies in Symfony 2.3 (danielcsgomes) - `f077a8e `_ #3465 change wording in versionadded example to be consistent with what we use... (xabbuh) @@ -64,7 +61,7 @@ Minor Documentation Changes - `7c5a914 `_ #3369 Indicate that Group Sequence Providers can use YAML (karptonite) - `1e0311e `_ #3416 add empty_data option where required option is used (xabbuh) - `2be3f52 `_ #3422 [Cookbook][Custom Authentication Provider] add a note of warning for when forbidding anonymous users (cordoval) - +- `e255de9 `_ #3429 [Reference][Form Types] Document "with_minutes" time/datetime option (bicpi) February, 2014 -------------- @@ -76,13 +73,15 @@ New Documentation - `89c6f1d `_ #3439 [Review] Added detailed Backwards Compatibility Promise text (webmozart) - `0029408 `_ #3558 Created Documentation CHANGELOG (WouterJ) - `f6dd678 `_ #3548 Update forms.rst (atmosf3ar) +- `9676f2c `_ #3523 [Components][EventDispatcher] describe that the event name and the event dispatcher are passed to even... (xabbuh) +- `5c367b4 `_ #3517 Fixed OptionsResolver component docs (WouterJ) - `527c8b6 `_ #3496 Added a section about using named assets (vmattila) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `5c367b4 `_ #3517 Fixed OptionsResolver component docs (WouterJ) - `adcbb5d `_ #3615 Fixes to cookbook/doctrine/registration_form.rst (Crushnaut) +- `5c4336a `_ #3570 Callback: [Validator, validate] expects validate to be static (nixilla) - `a21fb26 `_ #3559 Remove reference to copying parameters.yml from Git cookbook (pwaring) - `de71a51 `_ #3551 [Cookbook][Dynamic Form Modification] Fix sample code (rybakit) - `143db2f `_ #3550 Update introduction.rst (taavit) @@ -92,9 +91,15 @@ Fixed Documentation - `d7e8262 `_ #3535 fix form type name. (yositani2002) - `821af3b `_ #3493 Type fix in remove.rst (weaverryan) - `003230f `_ #3530 Update form_customization.rst (dczech) +- `a43f15a `_ #3519 [Book][Service Container] Fix syntax highlighting (iamdto) +- `86e02c6 `_ #3514 Fixed some small typos in code example (RobinvdVleuten) - `696313c `_ #3513 [Component-DI] Fixed typo (saro0h) - `27dcebd `_ #3509 Fix typo: side.bar.twig => sidebar.twig (ifdattic) +- `0dc8c26 `_ #3507 Fix a typo (missing `````) in ``:doc:`` link (ifdattic) +- `272197b `_ #3504 fix include directive so that the contents are really included (xabbuh) - `e385d28 `_ #3503 file extension correction xfliff to xliff (nixilla) +- `6d34aa6 `_ #3478 Update custom_password_authenticator.rst (piotras-s) +- `a171700 `_ #3477 Api key user provider should use "implements" instead of "extends" (skowi) - `7fe0de3 `_ #3475 Fixed doc for framework.session.cookie_lifetime refrence. (tyomo4ka) - `8155e4c `_ #3473 Update proxy_examples.rst (AZielinski) @@ -105,13 +110,16 @@ Minor Documentation Changes - `38def3b `_ #3567 Update checkbox_compound.rst.inc (joshuaadickerson) - `15d8ab8 `_ #3553 Minimize horizontal scrolling in code blocks to improve readability (ifdattic) - `5120863 `_ #3547 Update acl.rst (iqfoundry) +- `b7ac326 `_ #3557 Minimize horizontal scrolling in code block to improve readability (ifdattic) - `d974c77 `_ #3556 Fix PSR error (ifdattic) - `f4bb017 `_ #3555 Wrap variables in {} for safer interpolation (ifdattic) - `5f02bca `_ #3552 Fix typos (ifdattic) - `6e32c47 `_ #3546 Fix README: contributions should be based off 2.3 or higher (colinodell) - `ffa8f76 `_ #3545 Example of getting entity managers directly from the container (colinodell) - `6a2a55b `_ #3579 Fix build errors (xabbuh) +- `dce2e23 `_ #3532 Added tip for Entity Listeners (slavafomin) - `73adf8b `_ #3528 Clarify service parameters usages (WouterJ) +- `f634600 `_ #3531 Remove horizontal scrolling in code block (ifdattic) - `9ba4fa7 `_ #3527 Changes to components domcrawler (ifdattic) - `8973c81 `_ #3526 Changes for Console component (ifdattic) - `6848bed `_ #3538 Rebasing #3518 (weaverryan) @@ -124,4 +132,4 @@ Minor Documentation Changes - `80a90ba `_ #3500 Minimize horizontal scrolling in code blocks (improve readability) (ifdattic) - `e5bc4ea `_ #3498 Remove second empty data (xabbuh) - `d084d87 `_ #3485 [Cookbook][Assetic] Fix "javascripts" tag name typo (bicpi) -- `3250aba `_ #3481 Fix code block (minimise horizontal scrolling), typo in yaml (ifdattic) +- `3250aba `_ #3481 Fix code block (minimise horizontal scrolling), typo in yaml (ifdattic) \ No newline at end of file From 153f97f768e256a97cf0017edfcb31ac038d6393 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Mon, 10 Mar 2014 18:02:10 +0100 Subject: [PATCH 0248/1181] Added 2.5 CHANGELOG --- changelog.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/changelog.rst b/changelog.rst index 6264bee4693..ca2995a01cc 100644 --- a/changelog.rst +++ b/changelog.rst @@ -21,12 +21,16 @@ New Documentation ~~~~~~~~~~~~~~~~~ - `d52f3f8 `_ #3454 [Security] Add host option (ghostika) +- `11e079b `_ #3446 [WCM] Documented deprecation of the apache router. (jakzal) +- `0a0bf4c `_ #3437 Add info about callback in options resolver (marekkalnik) +- `6db5f23 `_ #3426 New Feature: Change the Default Command in the Console component (danielcsgomes) - `6b3c424 `_ #3428 Translation - Added info about JsonFileLoader added in 2.4 (singles) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ - `fb22fa0 `_ #3456 remove duplicate label (xabbuh) +- `a87fe18 `_ #3470 Fixed typo (danielcsgomes) - `c205bc6 `_ #3468 enclose YAML string with double quotes to fix syntax highlighting (xabbuh) - `89963cc `_ #3463 Fix typos in cookbook/testing/database (ifdattic) - `e0a52ec `_ #3460 remove confusing outdated note on interactive rebasing (xabbuh) @@ -50,6 +54,7 @@ Minor Documentation Changes - `f285d93 `_ #3451 some language tweaks (AE, third-person perspective) (xabbuh) - `b9bbe5d `_ #3499 Fix YAML syntax highlight + remove trailing whitespace (ifdattic) - `2b7e0f6 `_ #3497 Fix highlighting (WouterJ) +- `2746067 `_ #3472 Fixed `````versionadded````` inconsistencies in Symfony 2.5+ (danielcsgomes) - `a535ae0 `_ #3471 Fixed `````versionadded````` inconsistencies in Symfony 2.3 (danielcsgomes) - `f077a8e `_ #3465 change wording in versionadded example to be consistent with what we use... (xabbuh) - `f9f7548 `_ #3462 Replace ... with etc (ifdattic) @@ -76,6 +81,8 @@ New Documentation - `9676f2c `_ #3523 [Components][EventDispatcher] describe that the event name and the event dispatcher are passed to even... (xabbuh) - `5c367b4 `_ #3517 Fixed OptionsResolver component docs (WouterJ) - `527c8b6 `_ #3496 Added a section about using named assets (vmattila) +- `8ccfe85 `_ #3491 Added doc for named encoders (tamirvs) +- `46377b2 `_ #3486 Documenting createAccessDeniedException() method (klaussilveira) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ @@ -86,6 +93,7 @@ Fixed Documentation - `de71a51 `_ #3551 [Cookbook][Dynamic Form Modification] Fix sample code (rybakit) - `143db2f `_ #3550 Update introduction.rst (taavit) - `384538b `_ #3549 Fixed createPropertyAccessorBuilder usage (antonbabenko) +- `642e776 `_ #3544 Fix build errors (xabbuh) - `d275302 `_ #3541 Update generic_event.rst (Lumbendil) - `819949c `_ #3537 Add missing variable assignment (colinodell) - `d7e8262 `_ #3535 fix form type name. (yositani2002) @@ -119,6 +127,7 @@ Minor Documentation Changes - `6a2a55b `_ #3579 Fix build errors (xabbuh) - `dce2e23 `_ #3532 Added tip for Entity Listeners (slavafomin) - `73adf8b `_ #3528 Clarify service parameters usages (WouterJ) +- `7e75b64 `_ #3533 Moving the new named algorithms into their own cookbook entry (weaverryan) - `f634600 `_ #3531 Remove horizontal scrolling in code block (ifdattic) - `9ba4fa7 `_ #3527 Changes to components domcrawler (ifdattic) - `8973c81 `_ #3526 Changes for Console component (ifdattic) From 1cc59256438b373c7c062fec5c9144bf95c051f5 Mon Sep 17 00:00:00 2001 From: Luis Cordova Date: Sun, 2 Mar 2014 21:22:59 -0500 Subject: [PATCH 0249/1181] add parenthesis in the example to correct precendence --- components/expression_language/syntax.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index 80a3567362d..e8cf7b859aa 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -176,7 +176,10 @@ Comparison Operators To test if a string does *not* match a regex, use the logical ``not`` operator in combination with the ``matches`` operator:: - $language->evaluate('not "foo" matches "/bar/"'); // returns true + $language->evaluate('not ("foo" matches "/bar/")'); // returns true + + You must use parenthesis because the unary operator ``not`` has precedence + over the binary operator ``matches``. Examples:: From 7eb30516357f36b02e9f8c5c18c62f7f8ac62036 Mon Sep 17 00:00:00 2001 From: Rick van Laarhoven Date: Wed, 12 Mar 2014 17:31:36 +0100 Subject: [PATCH 0250/1181] Fixed syntax highlighting --- cookbook/security/voters_data_permission.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cookbook/security/voters_data_permission.rst b/cookbook/security/voters_data_permission.rst index 0e5055261e1..0afab373a4b 100644 --- a/cookbook/security/voters_data_permission.rst +++ b/cookbook/security/voters_data_permission.rst @@ -54,7 +54,9 @@ Creating the Custom Voter ------------------------- The goal is to create a voter that checks if a user has access to view or -edit a particular object. Here's an example implementation:: +edit a particular object. Here's an example implementation + +.. code-block:: php // src/Acme/DemoBundle/Security/Authorization/Voter/PostVoter.php namespace Acme\DemoBundle\Security\Authorization\Voter; From 484b7b95f2f309df8f4c00afc2042ae8aaacb424 Mon Sep 17 00:00:00 2001 From: Rick van Laarhoven Date: Wed, 12 Mar 2014 17:42:11 +0100 Subject: [PATCH 0251/1181] Added : --- cookbook/security/voters_data_permission.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/voters_data_permission.rst b/cookbook/security/voters_data_permission.rst index 0afab373a4b..e27a86669be 100644 --- a/cookbook/security/voters_data_permission.rst +++ b/cookbook/security/voters_data_permission.rst @@ -54,7 +54,7 @@ Creating the Custom Voter ------------------------- The goal is to create a voter that checks if a user has access to view or -edit a particular object. Here's an example implementation +edit a particular object. Here's an example implementation: .. code-block:: php From 38b2955966776d2836106bd1650e820b87e4b748 Mon Sep 17 00:00:00 2001 From: florianv Date: Thu, 13 Mar 2014 03:08:32 +0100 Subject: [PATCH 0252/1181] Improved the documentation with examples and images --- book/translation.rst | 134 ++++++++++++++++++++++++++-- images/book/translation/debug_1.png | Bin 0 -> 22689 bytes images/book/translation/debug_2.png | Bin 0 -> 22534 bytes images/book/translation/debug_3.png | Bin 0 -> 22381 bytes images/book/translation/debug_4.png | Bin 0 -> 22236 bytes 5 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 images/book/translation/debug_1.png create mode 100644 images/book/translation/debug_2.png create mode 100644 images/book/translation/debug_3.png create mode 100644 images/book/translation/debug_4.png diff --git a/book/translation.rst b/book/translation.rst index d3a6e010ff6..2356f239f6c 100644 --- a/book/translation.rst +++ b/book/translation.rst @@ -657,16 +657,140 @@ Debugging Translations When maintaining a bundle, you may use or remove the usage of a translation message without updating all message catalogues. The ``translation:debug`` -command helps you finding these missing or unused translation messages for a +command helps you to find these missing or unused translation messages for a given locale. It shows you a table with the result when translating the message in the given locale and the result when the fallback would be used. On top of that, it also shows you when the translation is the same as the fallback translation (this could indicate that the message was not correctly -translated). To inspect all messages in the ``en`` locale for the AcmeDemoBundle, run: +translated). + +Thanks to the messages extractors, the command will detect the translation +tag or filter usages in Twig templates: + +.. code-block:: jinja + + {% trans %}Symfony2 is great{% endtrans %} + + {{ 'Symfony2 is great'|trans }} + +It will also detect the following translator usages in PHP templates: + +.. code-block:: php + + $view['translator']->trans("Symfony2 is great"); + + $view['translator']->trans(‘Symfony2 is great’); + +Supposing your application default_locale is French ``fr`` and you have enabled +the translator in your configuration with English ``en`` as fallback locale. + +See :ref:`book-translation-configuration` and :ref:`book-translation-fallback` for details +about how to configure these. + +You are working on the AcmeDemoBundle and the translation file for the ``messages`` domain +in the ``fr`` locale contains: + +.. configuration-block:: + + .. code-block:: xml + + + + + + + + Symfony2 is great + J'aime Symfony2 + + + + + + .. code-block:: php + + // messages.fr.php + return array( + 'Symfony2 is great' => 'J\'aime Symfony2', + ); + + .. code-block:: yaml + + # messages.fr.yml + Symfony2 is great: J'aime Symfony2 + +and for the ``en`` locale: + +.. configuration-block:: + + .. code-block:: xml + + + + + + + + Symfony2 is great + Symfony2 is great + + + + + + .. code-block:: php + + // messages.en.php + return array( + 'Symfony2 is great' => 'Symfony2 is great', + ); + + .. code-block:: yaml + + # messages.en.yml + Symfony2 is great: Symfony2 is great + +To inspect all messages in the ``fr`` locale for the AcmeDemoBundle, run: .. code-block:: bash - $ php app/console translation:debug en AcmeDemoBundle + $ php app/console translation:debug fr AcmeDemoBundle + +You will get this output: + +.. image:: /images/book/translation/debug_1.png + :align: center + +It indicates the message with id ``Symfony2 is great`` is unused because it is translated +but we don’t use it in any template yet. + +Now, if you translate the message in one of your templates, you will get this output: + +.. image:: /images/book/translation/debug_2.png + :align: center + +The state is empty which means the message is translated in the ``fr`` locale and used in one or more templates. +Moreover, we see the translation is different than the ``en`` one. + +If you delete the message ``Symfony2 is great`` from your translation file for the ``fr`` locale +and run the command, you will get: + +.. image:: /images/book/translation/debug_3.png + :align: center + +The state indicates the message is missing because it is not translated in the ``fr`` locale +but it is still used in the template. +Moreover, we see the message in the ``fr`` locale equals to the message in the ``en`` locale. +This is a special case because the untranslated message id equals its translation in the ``en`` locale. + +If you copy the content of the translation file in the ``en`` locale, to the translation file +in the ``fr`` locale and run the command, you will get: + +.. image:: /images/book/translation/debug_4.png + :align: center + +We observe the translations of the message are identical in the ``fr`` and ``en`` locales +which means this message was probably copied from French to English or vice versa (which is the case). By default all domains are inspected, but it is possible to specify a single domain: @@ -674,8 +798,8 @@ By default all domains are inspected, but it is possible to specify a single dom $ php app/console translation:debug en AcmeDemoBundle --domain=messages -You can also display only the unused or only the missing messages, by using -the ``--only-unused`` or ``--only-missing`` switches: +When bundles have a lot of messages, it is useful to display only the unused +or only the missing messages, by using the ``--only-unused`` or ``--only-missing`` switches: .. code-block:: bash diff --git a/images/book/translation/debug_1.png b/images/book/translation/debug_1.png new file mode 100644 index 0000000000000000000000000000000000000000..8f175f4d7fffb76a5834a22b37580c5b8213f2d0 GIT binary patch literal 22689 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 literal 0 HcmV?d00001 diff --git a/images/book/translation/debug_2.png b/images/book/translation/debug_2.png new file mode 100644 index 0000000000000000000000000000000000000000..04a57fa41d45ef6bfa7ed755518b5ee1a2178a71 GIT binary patch literal 22534 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 D9@U|- literal 0 HcmV?d00001 diff --git a/images/book/translation/debug_3.png b/images/book/translation/debug_3.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed595e097b7b714b93be70d134cef71ac8b7c9a GIT binary patch literal 22381 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�D7=5gk)_W3TkefbFJrdOqir!n0*vrq9t+X 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 literal 0 HcmV?d00001 From b6ac4540c0b95f1bcdd47c26db126336cd0535f2 Mon Sep 17 00:00:00 2001 From: florianv Date: Thu, 13 Mar 2014 16:21:09 +0100 Subject: [PATCH 0253/1181] Fixed the issues --- book/translation.rst | 47 ++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/book/translation.rst b/book/translation.rst index 2356f239f6c..0c7e13e77ae 100644 --- a/book/translation.rst +++ b/book/translation.rst @@ -673,28 +673,38 @@ tag or filter usages in Twig templates: {{ 'Symfony2 is great'|trans }} + {{ 'Symfony2 is great'|transchoice(1) }} + + {% transchoice 1 %}Symfony2 is great{% endtranschoice %} + It will also detect the following translator usages in PHP templates: .. code-block:: php $view['translator']->trans("Symfony2 is great"); - $view['translator']->trans(‘Symfony2 is great’); + $view['translator']->trans('Symfony2 is great'); + +.. caution:: -Supposing your application default_locale is French ``fr`` and you have enabled -the translator in your configuration with English ``en`` as fallback locale. + The extractors are not able to inspect the messages translated outside templates which means + that translator usages in form labels or inside your controllers won't be detected. + Dynamic translations involving variables or expressions are not detected in templates, + which means this example won't be analyzed: -See :ref:`book-translation-configuration` and :ref:`book-translation-fallback` for details -about how to configure these. + .. code-block:: jinja + {% set message = 'Symfony2 is great' %} + {{ message|trans }} -You are working on the AcmeDemoBundle and the translation file for the ``messages`` domain -in the ``fr`` locale contains: +Suppose your application's default_locale is ``fr`` and you have configured ``en`` as the fallback locale +(see :ref:`book-translation-configuration` and :ref:`book-translation-fallback` for how to configure these). +And suppose you've already setup some translations for the ``fr`` locale inside an AcmeDemoBundle: .. configuration-block:: .. code-block:: xml - + @@ -709,14 +719,14 @@ in the ``fr`` locale contains: .. code-block:: php - // messages.fr.php + // src/Acme/AcmeDemoBundle/Resources/translations/messages.fr.php return array( 'Symfony2 is great' => 'J\'aime Symfony2', ); .. code-block:: yaml - # messages.fr.yml + # src/Acme/AcmeDemoBundle/Resources/translations/messages.fr.yml Symfony2 is great: J'aime Symfony2 and for the ``en`` locale: @@ -725,7 +735,7 @@ and for the ``en`` locale: .. code-block:: xml - + @@ -740,14 +750,14 @@ and for the ``en`` locale: .. code-block:: php - // messages.en.php + // src/Acme/AcmeDemoBundle/Resources/translations/messages.en.php return array( 'Symfony2 is great' => 'Symfony2 is great', ); .. code-block:: yaml - # messages.en.yml + # src/Acme/AcmeDemoBundle/Resources/translations/messages.en.yml Symfony2 is great: Symfony2 is great To inspect all messages in the ``fr`` locale for the AcmeDemoBundle, run: @@ -761,8 +771,8 @@ You will get this output: .. image:: /images/book/translation/debug_1.png :align: center -It indicates the message with id ``Symfony2 is great`` is unused because it is translated -but we don’t use it in any template yet. +It indicates that the message ``Symfony2 is great`` is unused because it is translated, +but you haven't used it anywhere yet. Now, if you translate the message in one of your templates, you will get this output: @@ -770,7 +780,6 @@ Now, if you translate the message in one of your templates, you will get this ou :align: center The state is empty which means the message is translated in the ``fr`` locale and used in one or more templates. -Moreover, we see the translation is different than the ``en`` one. If you delete the message ``Symfony2 is great`` from your translation file for the ``fr`` locale and run the command, you will get: @@ -780,7 +789,7 @@ and run the command, you will get: The state indicates the message is missing because it is not translated in the ``fr`` locale but it is still used in the template. -Moreover, we see the message in the ``fr`` locale equals to the message in the ``en`` locale. +Moreover, the message in the ``fr`` locale equals to the message in the ``en`` locale. This is a special case because the untranslated message id equals its translation in the ``en`` locale. If you copy the content of the translation file in the ``en`` locale, to the translation file @@ -789,8 +798,8 @@ in the ``fr`` locale and run the command, you will get: .. image:: /images/book/translation/debug_4.png :align: center -We observe the translations of the message are identical in the ``fr`` and ``en`` locales -which means this message was probably copied from French to English or vice versa (which is the case). +You can see that the translations of the message are identical in the ``fr`` and ``en`` locales +which means this message was probably copied from French to English and maybe you forgot to translate it. By default all domains are inspected, but it is possible to specify a single domain: From 3ace4d6d36292eb9b43fd3fd3c0eab638ceafcae Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 13 Mar 2014 22:33:53 +0100 Subject: [PATCH 0254/1181] add missing code block directive --- cookbook/security/api_key_authentication.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index e27ef087c90..c027012052b 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -214,11 +214,13 @@ Handling Authentication Failure ------------------------------- In order for your ``ApiKeyAuthentication`` to correctly display a 403 -http status when either bad credentials or authentication fails you will -need to implement the :class:`Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface` on your -Authenticator. This will provide a method ``onAuthenticationFailure`` which +http status when either bad credentials or authentication fails you will +need to implement the :class:`Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface` on your +Authenticator. This will provide a method ``onAuthenticationFailure`` which you can use to create an error ``Response``. +.. code-block:: php + // src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php namespace Acme\HelloBundle\Security; From 37278d8b693408ab603a5070f73b67fb594b4b3e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 13 Mar 2014 22:40:18 +0100 Subject: [PATCH 0255/1181] remove unnecessary code block directive --- components/console/helpers/table.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/console/helpers/table.rst b/components/console/helpers/table.rst index 6fe6848a8e1..7729ecce6eb 100644 --- a/components/console/helpers/table.rst +++ b/components/console/helpers/table.rst @@ -103,8 +103,6 @@ which outputs: If the built-in styles do not fit your need, define your own:: -.. code-block:: php - use Symfony\Component\Helper\TableStyle; // by default, this is based on the default style From 17166bd4107bdf64a5a4c177751b9deb004c9d6a Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Wed, 12 Mar 2014 12:27:02 +0100 Subject: [PATCH 0256/1181] First shot of a documentation of the new PSR-4 class loader. --- components/class_loader/index.rst | 1 + components/class_loader/psr4_class_loader.rst | 63 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 components/class_loader/psr4_class_loader.rst diff --git a/components/class_loader/index.rst b/components/class_loader/index.rst index 4916933d6fa..de8da86c7c6 100644 --- a/components/class_loader/index.rst +++ b/components/class_loader/index.rst @@ -6,6 +6,7 @@ ClassLoader introduction class_loader + psr4_class_loader map_class_loader cache_class_loader debug_class_loader diff --git a/components/class_loader/psr4_class_loader.rst b/components/class_loader/psr4_class_loader.rst new file mode 100644 index 00000000000..d98362267c1 --- /dev/null +++ b/components/class_loader/psr4_class_loader.rst @@ -0,0 +1,63 @@ +.. index:: + single: ClassLoader; PSR-4 Class Loader + +The PSR-4 Class Loader +====================== + +Libraries that follow the `PSR-4`_ standard can be loaded with the ``Psr4ClassLoader``. + +.. note:: + + If you manage your dependencies via Composer, you get a PSR-4 compatible + autoloader out of the box. Use this loader in environments where Composer + is not available. + +.. tip:: + All Symfony Components follow PSR-4. + +Usage +----- + +The following example demonstrates, how you can use the +:class:`Symfony\\Component\\ClassLoader\\Psr4ClassLoader` autoloader to use +Symfony's Yaml component. Let's imagine, you downloaded both components – +ClassLoader and Yaml – as ZIP packages and unpacked them to a libs directory. + +The directory structure will look like this: + +.. code-block:: text + + / + +- libs + | +- ClassLoader + | | +- Psr4ClassLoader.php + | | +- … + | +- Yaml + | +- Yaml.php + | +- … + +- config.yml + +- test.php + +In ``demo.php``, to parse the file ``config.yml``, you can use the following +code. + +.. code-block:: php + + use Symfony\Component\ClassLoader\Psr4ClassLoader; + use Symfony\Component\Yaml\Yaml; + + require __DIR__ . '/lib/ClassLoader/Psr4ClassLoader.php'; + + $loader = new Psr4ClassLoader(); + $loader->addPrefix('Symfony\\Component\\Yaml\\', __DIR__ . '/lib/Yaml'); + $loader->register(); + + $data = Yaml::parse(__DIR__ . '/demo.yml'); + +First of all, we've loaded our class loader manually using ``require`` since we +don't have an autoload mechanism, yet. With the ``addPrefix()`` call, we told +the class loader where to look for classes with the namespace prefix +``Symfony\Component\Yaml\``. After registering the autoloader, the Yaml +component is ready to use. + +.. _PSR-4: http://www.php-fig.org/psr/psr-4/ From 6f2a1a34f01b9338f9f302dff83a4a3eb3e54ff6 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sun, 16 Mar 2014 23:50:58 +0100 Subject: [PATCH 0257/1181] Adjustments from comments be @WouterJ --- components/class_loader/psr4_class_loader.rst | 52 ++++++++++--------- components/map.rst.inc | 1 + 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/components/class_loader/psr4_class_loader.rst b/components/class_loader/psr4_class_loader.rst index d98362267c1..f7ada1df22c 100644 --- a/components/class_loader/psr4_class_loader.rst +++ b/components/class_loader/psr4_class_loader.rst @@ -6,6 +6,10 @@ The PSR-4 Class Loader Libraries that follow the `PSR-4`_ standard can be loaded with the ``Psr4ClassLoader``. +.. versionadded:: 2.5 + The :class:`Symfony\\Component\\ClassLoader\\Psr4ClassLoader` was + introduced in Symfony 2.5. + .. note:: If you manage your dependencies via Composer, you get a PSR-4 compatible @@ -13,51 +17,51 @@ Libraries that follow the `PSR-4`_ standard can be loaded with the ``Psr4ClassLo is not available. .. tip:: + All Symfony Components follow PSR-4. Usage ----- -The following example demonstrates, how you can use the +The following example demonstrates how you can use the :class:`Symfony\\Component\\ClassLoader\\Psr4ClassLoader` autoloader to use -Symfony's Yaml component. Let's imagine, you downloaded both components – -ClassLoader and Yaml – as ZIP packages and unpacked them to a libs directory. - +Symfony's Yaml component. Imagine, you downloaded both the ``ClassLoader`` and +``Yaml`` component as ZIP packages and unpacked them to a ``libs`` directory. The directory structure will look like this: .. code-block:: text - / - +- libs - | +- ClassLoader - | | +- Psr4ClassLoader.php - | | +- … - | +- Yaml - | +- Yaml.php - | +- … - +- config.yml - +- test.php + libs/ + ClassLoader/ + Psr4ClassLoader.php + ... + Yaml/ + Yaml.php + ... + config.yml + test.php -In ``demo.php``, to parse the file ``config.yml``, you can use the following -code. +In ``demo.php`` you are going to parse the ``config.yml`` file. To do that, you +first need to configure the ``Psr4ClassLoader``: .. code-block:: php use Symfony\Component\ClassLoader\Psr4ClassLoader; use Symfony\Component\Yaml\Yaml; - require __DIR__ . '/lib/ClassLoader/Psr4ClassLoader.php'; + require __DIR__.'/lib/ClassLoader/Psr4ClassLoader.php'; $loader = new Psr4ClassLoader(); - $loader->addPrefix('Symfony\\Component\\Yaml\\', __DIR__ . '/lib/Yaml'); + $loader->addPrefix('Symfony\\Component\\Yaml\\', __DIR__.'/lib/Yaml'); $loader->register(); - $data = Yaml::parse(__DIR__ . '/demo.yml'); + $data = Yaml::parse(__DIR__.'/demo.yml'); -First of all, we've loaded our class loader manually using ``require`` since we -don't have an autoload mechanism, yet. With the ``addPrefix()`` call, we told -the class loader where to look for classes with the namespace prefix -``Symfony\Component\Yaml\``. After registering the autoloader, the Yaml -component is ready to use. +First of all, the class loader is loaded manually using a ``require`` +statement, since there is no autoload mechanism yet. With the +:method:`Symfony\Component\ClassLoader\Psr4ClassLoader::addPrefix` call, you +tell the class loader where to look for classes with the +``Symfony\Component\Yaml\`` namespace prefix. After registering the autoloader, +the Yaml component is ready to use. .. _PSR-4: http://www.php-fig.org/psr/psr-4/ diff --git a/components/map.rst.inc b/components/map.rst.inc index 17e6146f2d8..c3b88b548a9 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -4,6 +4,7 @@ * :doc:`/components/class_loader/introduction` * :doc:`/components/class_loader/class_loader` + * :doc:`/components/class_loader/psr4_class_loader` * :doc:`/components/class_loader/map_class_loader` * :doc:`/components/class_loader/cache_class_loader` * :doc:`/components/class_loader/debug_class_loader` From a05da41b86f713f4acf5dd8f9b721ea160c7fce8 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 17 Mar 2014 09:05:44 +0100 Subject: [PATCH 0258/1181] Minor corrections. --- components/class_loader/psr4_class_loader.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/class_loader/psr4_class_loader.rst b/components/class_loader/psr4_class_loader.rst index f7ada1df22c..f10799c5a98 100644 --- a/components/class_loader/psr4_class_loader.rst +++ b/components/class_loader/psr4_class_loader.rst @@ -39,7 +39,7 @@ The directory structure will look like this: Yaml.php ... config.yml - test.php + demo.php In ``demo.php`` you are going to parse the ``config.yml`` file. To do that, you first need to configure the ``Psr4ClassLoader``: @@ -55,13 +55,13 @@ first need to configure the ``Psr4ClassLoader``: $loader->addPrefix('Symfony\\Component\\Yaml\\', __DIR__.'/lib/Yaml'); $loader->register(); - $data = Yaml::parse(__DIR__.'/demo.yml'); + $data = Yaml::parse(__DIR__.'/config.yml'); First of all, the class loader is loaded manually using a ``require`` statement, since there is no autoload mechanism yet. With the :method:`Symfony\Component\ClassLoader\Psr4ClassLoader::addPrefix` call, you tell the class loader where to look for classes with the ``Symfony\Component\Yaml\`` namespace prefix. After registering the autoloader, -the Yaml component is ready to use. +the Yaml component is ready to be used. .. _PSR-4: http://www.php-fig.org/psr/psr-4/ From 16fead486a71751ceefeb78237a05dc0dda7fdec Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 17 Mar 2014 09:35:36 +0100 Subject: [PATCH 0259/1181] Adjustments from comments by @bicpi --- components/class_loader/psr4_class_loader.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/class_loader/psr4_class_loader.rst b/components/class_loader/psr4_class_loader.rst index f10799c5a98..973c8ec3656 100644 --- a/components/class_loader/psr4_class_loader.rst +++ b/components/class_loader/psr4_class_loader.rst @@ -18,15 +18,15 @@ Libraries that follow the `PSR-4`_ standard can be loaded with the ``Psr4ClassLo .. tip:: - All Symfony Components follow PSR-4. + All Symfony components follow PSR-4. Usage ----- The following example demonstrates how you can use the :class:`Symfony\\Component\\ClassLoader\\Psr4ClassLoader` autoloader to use -Symfony's Yaml component. Imagine, you downloaded both the ``ClassLoader`` and -``Yaml`` component as ZIP packages and unpacked them to a ``libs`` directory. +Symfony's Yaml component. Imagine, you downloaded both the ClassLoader and +Yaml component as ZIP packages and unpacked them to a ``libs`` directory. The directory structure will look like this: .. code-block:: text From cb2be4ab4df34a6aa02726c665e566d9ed31a849 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 17 Mar 2014 13:29:40 +0100 Subject: [PATCH 0260/1181] Moved versionadded block to the top. --- components/class_loader/psr4_class_loader.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/class_loader/psr4_class_loader.rst b/components/class_loader/psr4_class_loader.rst index 973c8ec3656..489db8a351d 100644 --- a/components/class_loader/psr4_class_loader.rst +++ b/components/class_loader/psr4_class_loader.rst @@ -4,12 +4,12 @@ The PSR-4 Class Loader ====================== -Libraries that follow the `PSR-4`_ standard can be loaded with the ``Psr4ClassLoader``. - .. versionadded:: 2.5 The :class:`Symfony\\Component\\ClassLoader\\Psr4ClassLoader` was introduced in Symfony 2.5. +Libraries that follow the `PSR-4`_ standard can be loaded with the ``Psr4ClassLoader``. + .. note:: If you manage your dependencies via Composer, you get a PSR-4 compatible From 4dde2caa50d6877fc2e49ad83e29d172e6ae5f8e Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 12 Mar 2014 10:01:36 +0100 Subject: [PATCH 0261/1181] [Process] Add doc for Process::disableOutput and Process::enableOutput --- components/process.rst | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/components/process.rst b/components/process.rst index 5340f21d1fd..6ad44519b0c 100644 --- a/components/process.rst +++ b/components/process.rst @@ -281,6 +281,34 @@ You can access the `pid`_ of a running process with the you may have to prefix your commands with `exec`_. Please read `Symfony Issue#5759`_ to understand why this is happening. +Disabling Output +---------------- + +.. versionadded:: 2.5 + The :method:`Symfony\\Component\\Process\\Process::disableOutput` and + :method:`Symfony\\Component\\Process\\Process::enableOutput` methods were + introduced in Symfony 2.5. + +As standard output and error output are always fetched from the underlying process, +it might be convenient to disable output in some cases to save memory. +Use :method:`Symfony\\Component\\Process\\Process::disableOutput` and +:method:`Symfony\\Component\\Process\\Process::enableOutput` to toggle this feature:: + + use Symfony\Component\Process\Process; + + $process = new Process('/usr/bin/php worker.php'); + $process->disableOutput(); + $process->run(); + +.. caution:: + + You can not enable or disable the output while the process is running. + + If you disable the output, you cannot access ``getOutput``, + ``getIncrementalOutput``, ``getErrorOutput`` or ``getIncrementalErrorOutput``. + Moreover, you could not pass a callback to the ``start``, ``run`` or ``mustRun`` + methods or use ``setIdleTimeout``. + .. _`Symfony Issue#5759`: https://github.com/symfony/symfony/issues/5759 .. _`PHP Bug#39992`: https://bugs.php.net/bug.php?id=39992 .. _`exec`: http://en.wikipedia.org/wiki/Exec_(operating_system) From bd947c7fb104596295ce7ad628768b48e94bca96 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Fri, 14 Mar 2014 14:54:16 +0100 Subject: [PATCH 0262/1181] [TwigBundle] Add documentation about generating absolute URL with the asset function --- book/templating.rst | 16 ++ .../templating/helpers/assetshelper.rst | 17 +++ reference/twig_reference.rst | 142 +++++++++--------- 3 files changed, 104 insertions(+), 71 deletions(-) diff --git a/book/templating.rst b/book/templating.rst index 6e1090f7d71..e9cfdfaf086 100644 --- a/book/templating.rst +++ b/book/templating.rst @@ -991,6 +991,22 @@ assets won't be cached when deployed. For example, ``/images/logo.png`` might look like ``/images/logo.png?v2``. For more information, see the :ref:`ref-framework-assets-version` configuration option. +.. versionadded:: 2.5 + Absolute URLs for assets were introduced in Symfony 2.5. + +If you need absolute URLs for assets, you can set the third argument (or the +``absolute`` argument) to ``true``: + +.. configuration-block:: + + .. code-block:: html+jinja + + Symfony! + + .. code-block:: html+php + + Symfony! + .. index:: single: Templating; Including stylesheets and JavaScripts single: Stylesheets; Including stylesheets diff --git a/components/templating/helpers/assetshelper.rst b/components/templating/helpers/assetshelper.rst index 57ef49f0802..6151d2b4784 100644 --- a/components/templating/helpers/assetshelper.rst +++ b/components/templating/helpers/assetshelper.rst @@ -47,6 +47,23 @@ You can also specify a URL to use in the second parameter of the constructor:: Now URLs are rendered like ``http://cdn.example.com/images/logo.png``. +.. versionadded:: 2.5 + Absolute URLs for assets were introduced in Symfony 2.5. + +You can also use the third argument of the helper to force an absolute URL: + +.. code-block:: html+php + + + + +.. note:: + + If you already set a URL in the constructor, using the third argument of + ``getUrl`` will not affect the generated URL. + Versioning ---------- diff --git a/reference/twig_reference.rst b/reference/twig_reference.rst index a791f8c8d21..02e48fb8bfa 100644 --- a/reference/twig_reference.rst +++ b/reference/twig_reference.rst @@ -20,77 +20,77 @@ Functions .. versionadded:: 2.4 The ``expression`` function was introduced in Symfony 2.4. -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| Function Syntax | Usage | -+====================================================+============================================================================================+ -| ``render(uri, options = {})`` | This will render the fragment for the given controller or URL | -| ``render(controller('B:C:a', {params}))`` | For more information, see :ref:`templating-embedding-controller`. | -| ``render(path('route', {params}))`` | | -| ``render(url('route', {params}))`` | | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``render_esi(controller('B:C:a', {params}))`` | This will generate an ESI tag when possible or fallback to the ``render`` | -| ``render_esi(url('route', {params}))`` | behavior otherwise. For more information, see :ref:`templating-embedding-controller`. | -| ``render_esi(path('route', {params}))`` | | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``render_hinclude(controller(...))`` | This will generates an Hinclude tag for the given controller or URL. | -| ``render_hinclude(url('route', {params}))`` | For more information, see :ref:`templating-embedding-controller`. | -| ``render_hinclude(path('route', {params}))`` | | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``controller(attributes = {}, query = {})`` | Used along with the ``render`` tag to refer to the controller that you want to render. | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``asset(path, packageName = null)`` | Get the public path of the asset, more information in | -| | ":ref:`book-templating-assets`". | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``asset_version(packageName = null)`` | Get the current version of the package, more information in | -| | ":ref:`book-templating-assets`". | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form(view, variables = {})`` | This will render the HTML of a complete form, more information in | -| | in :ref:`the Twig Form reference`. | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_start(view, variables = {})`` | This will render the HTML start tag of a form, more information in | -| | in :ref:`the Twig Form reference`. | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_end(view, variables = {})`` | This will render the HTML end tag of a form together with all fields that | -| | have not been rendered yet, more information | -| | in :ref:`the Twig Form reference`. | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_enctype(view)`` | This will render the required ``enctype="multipart/form-data"`` attribute | -| | if the form contains at least one file upload field, more information in | -| | in :ref:`the Twig Form reference `. | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_widget(view, variables = {})`` | This will render a complete form or a specific HTML widget of a field, | -| | more information in :ref:`the Twig Form reference `. | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_errors(view)`` | This will render any errors for the given field or the "global" errors, | -| | more information in :ref:`the Twig Form reference `. | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_label(view, label = null, variables = {})`` | This will render the label for the given field, more information in | -| | :ref:`the Twig Form reference `. | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_row(view, variables = {})`` | This will render the row (the field's label, errors and widget) of the given | -| | field, more information in :ref:`the Twig Form reference `. | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_rest(view, variables = {})`` | This will render all fields that have not yet been rendered, more | -| | information in :ref:`the Twig Form reference `. | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``csrf_token(intention)`` | This will render a CSRF token. Use this function if you want CSRF protection without | -| | creating a form | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``is_granted(role, object = null, field = null)`` | This will return ``true`` if the current user has the required role, more | -| | information in ":ref:`book-security-template`" | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``logout_path(key)`` | This will generate the relative logout URL for the given firewall | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``logout_url(key)`` | Equal to ``logout_path(...)`` but this will generate an absolute URL | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``path(name, parameters = {})`` | Get a relative URL for the given route, more information in | -| | ":ref:`book-templating-pages`". | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``url(name, parameters = {})`` | Equal to ``path(...)`` but it generates an absolute URL | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``expression(expression)`` | Creates an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` in Twig. See | -| | ":ref:`Template Expressions `". | -+----------------------------------------------------+--------------------------------------------------------------------------------------------+ ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| Function Syntax | Usage | ++=======================================================+============================================================================================+ +| ``render(uri, options = {})`` | This will render the fragment for the given controller or URL | +| ``render(controller('B:C:a', {params}))`` | For more information, see :ref:`templating-embedding-controller`. | +| ``render(path('route', {params}))`` | | +| ``render(url('route', {params}))`` | | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``render_esi(controller('B:C:a', {params}))`` | This will generate an ESI tag when possible or fallback to the ``render`` | +| ``render_esi(url('route', {params}))`` | behavior otherwise. For more information, see :ref:`templating-embedding-controller`. | +| ``render_esi(path('route', {params}))`` | | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``render_hinclude(controller(...))`` | This will generates an Hinclude tag for the given controller or URL. | +| ``render_hinclude(url('route', {params}))`` | For more information, see :ref:`templating-embedding-controller`. | +| ``render_hinclude(path('route', {params}))`` | | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``controller(attributes = {}, query = {})`` | Used along with the ``render`` tag to refer to the controller that you want to render. | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``asset(path, packageName = null, absolute = false)`` | Get the public path of the asset, more information in | +| | ":ref:`book-templating-assets`". | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``asset_version(packageName = null)`` | Get the current version of the package, more information in | +| | ":ref:`book-templating-assets`". | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form(view, variables = {})`` | This will render the HTML of a complete form, more information in | +| | in :ref:`the Twig Form reference`. | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_start(view, variables = {})`` | This will render the HTML start tag of a form, more information in | +| | in :ref:`the Twig Form reference`. | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_end(view, variables = {})`` | This will render the HTML end tag of a form together with all fields that | +| | have not been rendered yet, more information | +| | in :ref:`the Twig Form reference`. | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_enctype(view)`` | This will render the required ``enctype="multipart/form-data"`` attribute | +| | if the form contains at least one file upload field, more information in | +| | in :ref:`the Twig Form reference `. | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_widget(view, variables = {})`` | This will render a complete form or a specific HTML widget of a field, | +| | more information in :ref:`the Twig Form reference `. | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_errors(view)`` | This will render any errors for the given field or the "global" errors, | +| | more information in :ref:`the Twig Form reference `. | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_label(view, label = null, variables = {})`` | This will render the label for the given field, more information in | +| | :ref:`the Twig Form reference `. | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_row(view, variables = {})`` | This will render the row (the field's label, errors and widget) of the given | +| | field, more information in :ref:`the Twig Form reference `. | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_rest(view, variables = {})`` | This will render all fields that have not yet been rendered, more | +| | information in :ref:`the Twig Form reference `. | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``csrf_token(intention)`` | This will render a CSRF token. Use this function if you want CSRF protection without | +| | creating a form | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``is_granted(role, object = null, field = null)`` | This will return ``true`` if the current user has the required role, more | +| | information in ":ref:`book-security-template`" | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``logout_path(key)`` | This will generate the relative logout URL for the given firewall | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``logout_url(key)`` | Equal to ``logout_path(...)`` but this will generate an absolute URL | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``path(name, parameters = {})`` | Get a relative URL for the given route, more information in | +| | ":ref:`book-templating-pages`". | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``url(name, parameters = {})`` | Equal to ``path(...)`` but it generates an absolute URL | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``expression(expression)`` | Creates an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` in Twig. See | +| | ":ref:`Template Expressions `". | ++-------------------------------------------------------+--------------------------------------------------------------------------------------------+ Filters ------- From a6a074c8378cbf01c1162357bce32ad3522dcefd Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 18 Mar 2014 19:35:36 +0100 Subject: [PATCH 0263/1181] fixing a code block --- book/translation.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/book/translation.rst b/book/translation.rst index 0c7e13e77ae..d398a7d9cfa 100644 --- a/book/translation.rst +++ b/book/translation.rst @@ -693,8 +693,9 @@ It will also detect the following translator usages in PHP templates: which means this example won't be analyzed: .. code-block:: jinja - {% set message = 'Symfony2 is great' %} - {{ message|trans }} + + {% set message = 'Symfony2 is great' %} + {{ message|trans }} Suppose your application's default_locale is ``fr`` and you have configured ``en`` as the fallback locale (see :ref:`book-translation-configuration` and :ref:`book-translation-fallback` for how to configure these). From eafbab1a5f29bbd865fd9e0ab54d9e8a1f705591 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Tue, 18 Mar 2014 22:48:17 +0100 Subject: [PATCH 0264/1181] Enhanced Firewall Restrictions docs Squashed commits: [2081fc4] Enhanced Firewall Restrictions docs for PR symfony/symfony#10404 [8f065bc] Add redirect to new page [b42e80f] fixed typos [cc6b07d] tiny update --- book/security.rst | 7 +- cookbook/map.rst.inc | 2 +- cookbook/security/firewall_restriction.rst | 193 +++++++++++++++++++++ cookbook/security/host_restriction.rst | 70 +------- reference/configuration/security.rst | 6 + 5 files changed, 209 insertions(+), 69 deletions(-) create mode 100644 cookbook/security/firewall_restriction.rst diff --git a/book/security.rst b/book/security.rst index a2fea0592b9..07310c0225f 100644 --- a/book/security.rst +++ b/book/security.rst @@ -181,6 +181,11 @@ firewall is activated does *not* mean, however, that the HTTP authentication username and password box is displayed for every URL. For example, any user can access ``/foo`` without being prompted to authenticate. +.. tip:: + + You can also match a request against other details of the request (e.g. host, method). For more + information and examples read :doc:`/cookbook/security/firewall_restriction`. + .. image:: /images/book/security_anonymous_user_access.png :align: center @@ -2139,7 +2144,7 @@ Learn more from the Cookbook * :doc:`Blacklist users by IP address with a custom voter ` * :doc:`Access Control Lists (ACLs) ` * :doc:`/cookbook/security/remember_me` -* :doc:`How to Restrict Firewalls to a Specific Host ` +* :doc:`How to Restrict Firewalls to a Specific Request ` .. _`FOSUserBundle`: https://github.com/FriendsOfSymfony/FOSUserBundle .. _`implement the \Serializable interface`: http://php.net/manual/en/class.serializable.php diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 6c23641e2e3..dd9295c9515 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -138,7 +138,7 @@ * :doc:`/cookbook/security/acl` * :doc:`/cookbook/security/acl_advanced` * :doc:`/cookbook/security/force_https` - * :doc:`/cookbook/security/host_restriction` + * :doc:`/cookbook/security/firewall_restriction` * :doc:`/cookbook/security/form_login` * :doc:`/cookbook/security/securing_services` * :doc:`/cookbook/security/custom_provider` diff --git a/cookbook/security/firewall_restriction.rst b/cookbook/security/firewall_restriction.rst new file mode 100644 index 00000000000..db3568e5f2b --- /dev/null +++ b/cookbook/security/firewall_restriction.rst @@ -0,0 +1,193 @@ +.. index:: + single: Security; Restrict Security Firewalls to a Request + +How to Restrict Firewalls to a Specific Request +=============================================== + +When using the Security component, you can create firewalls that match certain request options. +In most cases, matching against the URL is sufficient, but in special cases you can further +restrict the initialization of a firewall against other options of the request. + +.. note:: + + You can use any of these restrictions individually or mix them together to get + your desired firewall configuration. + +Restricting by Pattern +---------------------- + +This is the default restriction and restricts a firewall to only be initialized if the request URL +matches the configured ``pattern``. + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + + # ... + security: + firewalls: + secured_area: + pattern: ^/admin + # ... + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + + // ... + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'pattern' => '^/admin', + // ... + ), + ), + )); + +The ``pattern`` is a regular expression. In this example, the firewall will only be +activated if the URL starts (due to the ``^`` regex character) with ``/admin`. If +the URL does not match this pattern, the firewall will not be activated and subsequent +firewalls will have the opportunity to be matched for this request. + +Restricting by Host +------------------- + +.. versionadded:: 2.4 + Support for restricting security firewalls to a specific host was introduced in + Symfony 2.4. + +If matching against the ``pattern`` only is not enough, the request can also be matched against +``host``. When the configuration option ``host`` is set, the firewall will be restricted to +only initialize if the host from the request matches against the configuration. + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + + # ... + security: + firewalls: + secured_area: + host: ^admin\.example\.com$ + # ... + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + + // ... + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'host' => '^admin\.example\.com$', + // ... + ), + ), + )); + +The ``host`` (like the ``pattern``) is a regular expression. In this example, +the firewall will only be activated if the host is equal exactly (due to +the ``^`` and ``$`` regex characters) to the hostname ``admin.example.com``. +If the hostname does not match this pattern, the firewall will not be activated +and subsequent firewalls will have the opportunity to be matched for this +request. + +Restricting by HTTP Methods +--------------------------- + +.. versionadded:: 2.5 + Support for restricting security firewalls to specific HTTP methods was introduced in + Symfony 2.5. + +The configuration option ``methods`` restricts the initialization of the firewall to +the provided HTTP methods. + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + + # ... + security: + firewalls: + secured_area: + methods: [GET, POST] + # ... + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + + // ... + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'methods' => array('GET', 'POST'), + // ... + ), + ), + )); + +In this example, the firewall will only be activated if the HTTP method of the +request is either ``GET`` or ``POST``. If the method is not in the array of the +allowed methods, the firewall will not be activated and subsequent firewalls will again +have the opportunity to be matched for this request. diff --git a/cookbook/security/host_restriction.rst b/cookbook/security/host_restriction.rst index b5b2e529d95..0ee0d334e30 100644 --- a/cookbook/security/host_restriction.rst +++ b/cookbook/security/host_restriction.rst @@ -1,70 +1,6 @@ -.. index:: - single: Security; Restrict Security Firewalls to a Host - How to Restrict Firewalls to a Specific Host ============================================ -.. versionadded:: 2.4 - Support for restricting security firewalls to a specific host was introduced in - Symfony 2.4. - -When using the Security component, you can create firewalls that match certain -URL patterns and therefore are activated for all pages whose URL matches -that pattern. Additionally, you can restrict the initialization of a firewall -to a host using the ``host`` key: - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/security.yml - - # ... - - security: - firewalls: - secured_area: - pattern: ^/ - host: ^admin\.example\.com$ - http_basic: true - - .. code-block:: xml - - - - - - - - - - - - - - .. code-block:: php - - // app/config/security.php - - // ... - - $container->loadFromExtension('security', array( - 'firewalls' => array( - 'secured_area' => array( - 'pattern' => '^/', - 'host' => '^admin\.example\.com$', - 'http_basic' => true, - ), - ), - )); - -The ``host`` (like the ``pattern``) is a regular expression. In this example, -the firewall will only be activated if the host is equal exactly (due to -the ``^`` and ``$`` regex characters) to the hostname ``admin.example.com``. -If the hostname does not match this pattern, the firewall will not be activated -and subsequent firewalls will have the opportunity to be matched for this -request. +As of Symfony 2.5, more possibilities to restrict firewalls have been added. +You can read everything about all the possibilities (including ``host``) +in ":doc:`/cookbook/security/firewall_restriction`". diff --git a/reference/configuration/security.rst b/reference/configuration/security.rst index accbbd97cbd..a5a643d334c 100644 --- a/reference/configuration/security.rst +++ b/reference/configuration/security.rst @@ -17,6 +17,10 @@ Each part will be explained in the next section. Support for restricting security firewalls to a specific host was introduced in Symfony 2.4. +.. versionadded:: 2.5 + Support for restricting security firewalls to specific http methods was introduced in + Symfony 2.5. + .. configuration-block:: .. code-block:: yaml @@ -104,6 +108,8 @@ Each part will be explained in the next section. pattern: .* # restrict the firewall to a specific host host: admin\.example\.com + # restrict the firewall to specific http methods + methods: [GET, POST] request_matcher: some.service.id access_denied_url: /foo/error403 access_denied_handler: some.service.id From 9889dbe00be1e046168bdb0001f7f80f15d766b5 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Tue, 18 Mar 2014 22:48:17 +0100 Subject: [PATCH 0265/1181] Enhanced Firewall Restrictions docs Squashed commits: [2081fc4] Enhanced Firewall Restrictions docs for PR symfony/symfony#10404 [8f065bc] Add redirect to new page [b42e80f] fixed typos [cc6b07d] tiny update --- book/security.rst | 7 +- cookbook/map.rst.inc | 2 +- cookbook/security/firewall_restriction.rst | 193 +++++++++++++++++++++ cookbook/security/host_restriction.rst | 68 +------- 4 files changed, 201 insertions(+), 69 deletions(-) create mode 100644 cookbook/security/firewall_restriction.rst diff --git a/book/security.rst b/book/security.rst index 4287795aa53..ed29b44504e 100644 --- a/book/security.rst +++ b/book/security.rst @@ -181,6 +181,11 @@ firewall is activated does *not* mean, however, that the HTTP authentication username and password box is displayed for every URL. For example, any user can access ``/foo`` without being prompted to authenticate. +.. tip:: + + You can also match a request against other details of the request (e.g. host, method). For more + information and examples read :doc:`/cookbook/security/firewall_restriction`. + .. image:: /images/book/security_anonymous_user_access.png :align: center @@ -2135,7 +2140,7 @@ Learn more from the Cookbook * :doc:`Blacklist users by IP address with a custom voter ` * :doc:`Access Control Lists (ACLs) ` * :doc:`/cookbook/security/remember_me` -* :doc:`How to Restrict Firewalls to a Specific Host ` +* :doc:`How to Restrict Firewalls to a Specific Request ` .. _`FOSUserBundle`: https://github.com/FriendsOfSymfony/FOSUserBundle .. _`implement the \Serializable interface`: http://php.net/manual/en/class.serializable.php diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 67b2ebe2d1b..caf5374d5cb 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -139,7 +139,7 @@ * :doc:`/cookbook/security/acl` * :doc:`/cookbook/security/acl_advanced` * :doc:`/cookbook/security/force_https` - * :doc:`/cookbook/security/host_restriction` + * :doc:`/cookbook/security/firewall_restriction` * :doc:`/cookbook/security/form_login` * :doc:`/cookbook/security/securing_services` * :doc:`/cookbook/security/custom_provider` diff --git a/cookbook/security/firewall_restriction.rst b/cookbook/security/firewall_restriction.rst new file mode 100644 index 00000000000..db3568e5f2b --- /dev/null +++ b/cookbook/security/firewall_restriction.rst @@ -0,0 +1,193 @@ +.. index:: + single: Security; Restrict Security Firewalls to a Request + +How to Restrict Firewalls to a Specific Request +=============================================== + +When using the Security component, you can create firewalls that match certain request options. +In most cases, matching against the URL is sufficient, but in special cases you can further +restrict the initialization of a firewall against other options of the request. + +.. note:: + + You can use any of these restrictions individually or mix them together to get + your desired firewall configuration. + +Restricting by Pattern +---------------------- + +This is the default restriction and restricts a firewall to only be initialized if the request URL +matches the configured ``pattern``. + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + + # ... + security: + firewalls: + secured_area: + pattern: ^/admin + # ... + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + + // ... + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'pattern' => '^/admin', + // ... + ), + ), + )); + +The ``pattern`` is a regular expression. In this example, the firewall will only be +activated if the URL starts (due to the ``^`` regex character) with ``/admin`. If +the URL does not match this pattern, the firewall will not be activated and subsequent +firewalls will have the opportunity to be matched for this request. + +Restricting by Host +------------------- + +.. versionadded:: 2.4 + Support for restricting security firewalls to a specific host was introduced in + Symfony 2.4. + +If matching against the ``pattern`` only is not enough, the request can also be matched against +``host``. When the configuration option ``host`` is set, the firewall will be restricted to +only initialize if the host from the request matches against the configuration. + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + + # ... + security: + firewalls: + secured_area: + host: ^admin\.example\.com$ + # ... + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + + // ... + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'host' => '^admin\.example\.com$', + // ... + ), + ), + )); + +The ``host`` (like the ``pattern``) is a regular expression. In this example, +the firewall will only be activated if the host is equal exactly (due to +the ``^`` and ``$`` regex characters) to the hostname ``admin.example.com``. +If the hostname does not match this pattern, the firewall will not be activated +and subsequent firewalls will have the opportunity to be matched for this +request. + +Restricting by HTTP Methods +--------------------------- + +.. versionadded:: 2.5 + Support for restricting security firewalls to specific HTTP methods was introduced in + Symfony 2.5. + +The configuration option ``methods`` restricts the initialization of the firewall to +the provided HTTP methods. + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + + # ... + security: + firewalls: + secured_area: + methods: [GET, POST] + # ... + + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + + // ... + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'methods' => array('GET', 'POST'), + // ... + ), + ), + )); + +In this example, the firewall will only be activated if the HTTP method of the +request is either ``GET`` or ``POST``. If the method is not in the array of the +allowed methods, the firewall will not be activated and subsequent firewalls will again +have the opportunity to be matched for this request. diff --git a/cookbook/security/host_restriction.rst b/cookbook/security/host_restriction.rst index b5b2e529d95..2dea53f155e 100644 --- a/cookbook/security/host_restriction.rst +++ b/cookbook/security/host_restriction.rst @@ -1,70 +1,4 @@ -.. index:: - single: Security; Restrict Security Firewalls to a Host - How to Restrict Firewalls to a Specific Host ============================================ -.. versionadded:: 2.4 - Support for restricting security firewalls to a specific host was introduced in - Symfony 2.4. - -When using the Security component, you can create firewalls that match certain -URL patterns and therefore are activated for all pages whose URL matches -that pattern. Additionally, you can restrict the initialization of a firewall -to a host using the ``host`` key: - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/security.yml - - # ... - - security: - firewalls: - secured_area: - pattern: ^/ - host: ^admin\.example\.com$ - http_basic: true - - .. code-block:: xml - - - - - - - - - - - - - - .. code-block:: php - - // app/config/security.php - - // ... - - $container->loadFromExtension('security', array( - 'firewalls' => array( - 'secured_area' => array( - 'pattern' => '^/', - 'host' => '^admin\.example\.com$', - 'http_basic' => true, - ), - ), - )); - -The ``host`` (like the ``pattern``) is a regular expression. In this example, -the firewall will only be activated if the host is equal exactly (due to -the ``^`` and ``$`` regex characters) to the hostname ``admin.example.com``. -If the hostname does not match this pattern, the firewall will not be activated -and subsequent firewalls will have the opportunity to be matched for this -request. +This entry has moved to ":doc:`/cookbook/security/firewall_restriction`". From be46c76e18dc982762eb070053c37558ab68d5da Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 19 Mar 2014 07:45:34 -0500 Subject: [PATCH 0266/1181] After backporting something from master (2.5), removing the 2.5-specific features --- book/security.rst | 4 +- cookbook/security/firewall_restriction.rst | 60 ---------------------- 2 files changed, 2 insertions(+), 62 deletions(-) diff --git a/book/security.rst b/book/security.rst index ed29b44504e..fc525f2c410 100644 --- a/book/security.rst +++ b/book/security.rst @@ -183,8 +183,8 @@ can access ``/foo`` without being prompted to authenticate. .. tip:: - You can also match a request against other details of the request (e.g. host, method). For more - information and examples read :doc:`/cookbook/security/firewall_restriction`. + You can also match a request against other details of the request (e.g. host). + For more information and examples read :doc:`/cookbook/security/firewall_restriction`. .. image:: /images/book/security_anonymous_user_access.png :align: center diff --git a/cookbook/security/firewall_restriction.rst b/cookbook/security/firewall_restriction.rst index db3568e5f2b..b5ae292159d 100644 --- a/cookbook/security/firewall_restriction.rst +++ b/cookbook/security/firewall_restriction.rst @@ -131,63 +131,3 @@ the ``^`` and ``$`` regex characters) to the hostname ``admin.example.com``. If the hostname does not match this pattern, the firewall will not be activated and subsequent firewalls will have the opportunity to be matched for this request. - -Restricting by HTTP Methods ---------------------------- - -.. versionadded:: 2.5 - Support for restricting security firewalls to specific HTTP methods was introduced in - Symfony 2.5. - -The configuration option ``methods`` restricts the initialization of the firewall to -the provided HTTP methods. - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/security.yml - - # ... - security: - firewalls: - secured_area: - methods: [GET, POST] - # ... - - .. code-block:: xml - - - - - - - - - - - - - - .. code-block:: php - - // app/config/security.php - - // ... - $container->loadFromExtension('security', array( - 'firewalls' => array( - 'secured_area' => array( - 'methods' => array('GET', 'POST'), - // ... - ), - ), - )); - -In this example, the firewall will only be activated if the HTTP method of the -request is either ``GET`` or ``POST``. If the method is not in the array of the -allowed methods, the firewall will not be activated and subsequent firewalls will again -have the opportunity to be matched for this request. From 0816a077ef60ec625132e1465cf6c08c9c8b9d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 19 Mar 2014 17:26:51 +0100 Subject: [PATCH 0267/1181] [Console] Change Command namespaces --- components/console/changing_default_command.rst | 4 ++-- components/console/introduction.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/console/changing_default_command.rst b/components/console/changing_default_command.rst index d00e60a3d7f..6c8d2689a97 100644 --- a/components/console/changing_default_command.rst +++ b/components/console/changing_default_command.rst @@ -12,7 +12,7 @@ will always run the ``ListCommand`` when no command name is passed. In order to the default command you just need to pass the command name you want to run by default to the ``setDefaultCommand`` method:: - namespace Acme\Command; + namespace Acme\Console\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -36,7 +36,7 @@ Executing the application and changing the default Command:: // application.php - use Acme\Command\HelloWorldCommand; + use Acme\Console\Command\HelloWorldCommand; use Symfony\Component\Console\Application; $command = new HelloWorldCommand(); diff --git a/components/console/introduction.rst b/components/console/introduction.rst index 3801b5d7ebb..6f2d43a196b 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -35,7 +35,7 @@ Creating a basic Command To make a console command that greets you from the command line, create ``GreetCommand.php`` and add the following to it:: - namespace Acme\Command; + namespace Acme\Console\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -88,7 +88,7 @@ an ``Application`` and adds commands to it:: Date: Thu, 20 Mar 2014 22:54:24 +0100 Subject: [PATCH 0268/1181] add firewall restriction document to security toctree --- cookbook/security/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst index 9cd886b686a..15a2668d1fe 100644 --- a/cookbook/security/index.rst +++ b/cookbook/security/index.rst @@ -13,6 +13,7 @@ Security acl_advanced force_https host_restriction + firewall_restriction form_login securing_services custom_provider From 70b55b54abb0a3865fc9f175fffef0750573f701 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 20 Mar 2014 22:55:00 +0100 Subject: [PATCH 0269/1181] fix literal --- cookbook/security/firewall_restriction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/firewall_restriction.rst b/cookbook/security/firewall_restriction.rst index db3568e5f2b..4cc7e0f7617 100644 --- a/cookbook/security/firewall_restriction.rst +++ b/cookbook/security/firewall_restriction.rst @@ -65,7 +65,7 @@ matches the configured ``pattern``. )); The ``pattern`` is a regular expression. In this example, the firewall will only be -activated if the URL starts (due to the ``^`` regex character) with ``/admin`. If +activated if the URL starts (due to the ``^`` regex character) with ``/admin``. If the URL does not match this pattern, the firewall will not be activated and subsequent firewalls will have the opportunity to be matched for this request. From c8fe61046bf9c3dafbd51cad78552c0787c04880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Chardonnet?= Date: Sat, 22 Mar 2014 18:18:32 +0100 Subject: [PATCH 0270/1181] Moved back and listened to @weaverryan Moved the article from components to the cookbook. --- components/console/index.rst | 1 - components/console/introduction.rst | 1 - .../console/commands_as_services.rst | 53 ++++++++++--------- cookbook/console/console_command.rst | 9 ++++ cookbook/console/index.rst | 1 + 5 files changed, 39 insertions(+), 26 deletions(-) rename {components => cookbook}/console/commands_as_services.rst (64%) diff --git a/components/console/index.rst b/components/console/index.rst index a4b85f9cba9..c814942d018 100644 --- a/components/console/index.rst +++ b/components/console/index.rst @@ -6,7 +6,6 @@ Console introduction usage - commands_as_services single_command_tool events helpers/index diff --git a/components/console/introduction.rst b/components/console/introduction.rst index 8ea786629dd..98f8b8643be 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -527,7 +527,6 @@ Learn More! * :doc:`/components/console/usage` * :doc:`/components/console/single_command_tool` * :doc:`/components/console/events` -* :doc:`/components/console/commands_as_services` .. _Packagist: https://packagist.org/packages/symfony/console .. _ANSICON: https://github.com/adoxa/ansicon/releases diff --git a/components/console/commands_as_services.rst b/cookbook/console/commands_as_services.rst similarity index 64% rename from components/console/commands_as_services.rst rename to cookbook/console/commands_as_services.rst index 066eb8aab39..c6001e246bf 100644 --- a/components/console/commands_as_services.rst +++ b/cookbook/console/commands_as_services.rst @@ -8,21 +8,22 @@ How to Define Commands as Services Support for registering commands in the service container was introduced in version 2.4. -By default, Symfony will take a look in the ``Command`` directory of your -bundles and automatically register your commands. For the ones implementing -the ``ContainerAwareCommand`` interface, Symfony will even inject the container. -While making life easier, this default implementation has some drawbacks in some -situations: - -* Define the command elsewhere than in the ``Command`` directory; -* Conditionally register your command, depending on the current environment or - on the availability of some dependencies; -* Access dependencies before the ``setContainer()`` is called (for example in - the ``configure()`` method); -* Reuse a command many times, but with different dependencies or parameters - -To solve those problems, you can register your command as a service by simply -defining it with the ``console.command`` tag: +By default, Symfony will take a look in the ``Command`` directory of each +bundle and automatically register your commands. If a command extends the +:class:`Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerAwareCommand`, +Symfony will even inject the container. +While making life easier, this has some limitations: + +* Your command must live in the ``Command`` directory; +* There's no way to conditionally register your service based on the environment + or availability of some dependencies; +* You can't access the container in the ``configure()`` method (because + ``setContainer`` hasn't been called yet); +* You can't use the same class to create many commands (i.e. each with + different configuration). + +To solve these problems, you can register your command as a service and tag it +with ``console.command``: .. configuration-block:: @@ -62,16 +63,17 @@ defining it with the ``console.command`` tag: Using Dependencies and Parameters to Set Default Values for Options ------------------------------------------------------------------- -Imagine you want to provide a default value for the ``name``option. You could +Imagine you want to provide a default value for the ``name`` option. You could pass one of the following as the 5th argument of ``addOption()``: -* an hardcoded string; -* a value coming from the configuration (allows the user to change it easily); +* a hardcoded string; +* a container parameter (e.g. something from parameters.yml); * a value computed by a service (e.g. a repository). -With a ``ContainerAwareCommand`` you wouldn't be able to retrieve the -configuration parameter, because the ``configure()`` method is called in the -constructor. The only solution is to inject them:: +By extending ``ContainerAwareCommand``, only the first is possible, because you +can't access the container inside the ``configure()`` method. Instead, inject +any parameter or service you need into the constructor. For example, suppose you +have some ``NameRepository`` service that you'll use to get your default value:: // src/Acme/DemoBundle/Command/GreetCommand.php namespace Acme\DemoBundle\Command; @@ -110,8 +112,11 @@ constructor. The only solution is to inject them:: } } +Now, just update the arguments of your service configuration like normal to +inject the ``NameRepository``. Great, you now have a dynamic default value! + .. caution:: - When running the console, every command is instantiated, which means every - ``configure()`` method is called. Be careful with database queries, as - they could impact performance. + Be careful not to actually do any work in ``configure`` (e.g. make database + queries), as your code will be run, even if you're using the console to + execute a different command. diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index abd5fddbc94..ab509787773 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -62,6 +62,15 @@ This command will now automatically be available to run: $ app/console demo:greet Fabien +.. _cookbook-console-dic: + +Register Commands in the Service Container +------------------------------------------- + +Just like controllers, commands can be declared as services. See the +:doc:`dedicated cookbook entry ` +for details. + Getting Services from the Service Container ------------------------------------------- diff --git a/cookbook/console/index.rst b/cookbook/console/index.rst index 878d1fc862a..6f1f939d772 100644 --- a/cookbook/console/index.rst +++ b/cookbook/console/index.rst @@ -8,3 +8,4 @@ Console usage sending_emails logging + commands_as_services From 15628e64971b776cfdc3c3113ac619e4b4a16058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 19 Mar 2014 16:00:26 +0100 Subject: [PATCH 0271/1181] [Console] Added standalone PSR-3 compliant logger --- components/console/index.rst | 1 + components/console/logger.rst | 108 +++++++++++++++++++++++++++ cookbook/logging/monolog_console.rst | 5 ++ 3 files changed, 114 insertions(+) create mode 100644 components/console/logger.rst diff --git a/components/console/index.rst b/components/console/index.rst index f974291a8e0..b449eff094b 100644 --- a/components/console/index.rst +++ b/components/console/index.rst @@ -9,4 +9,5 @@ Console changing_default_command single_command_tool events + logger helpers/index diff --git a/components/console/logger.rst b/components/console/logger.rst new file mode 100644 index 00000000000..84a41ad2b6c --- /dev/null +++ b/components/console/logger.rst @@ -0,0 +1,108 @@ +.. index:: + single: Console; Logger + +Using the Logger +================ + +.. versionadded:: 2.5 + The :class:`Symfony\\Component\\Console\\Logger\\ConsoleLogger` was + introduced in Symfony 2.5. + +The Console component comes with a standalone logger complying with the +`PSR-3_` standard. +Depending of the verbosity setting, log messages will be sent to the +:class:`Symfony\\Component\\Console\\Output\\OutputInterface` instance +passed as a parameter to the constructor. + +The logger does not have any external dependency except ``php-fig/log``. +This is useful for console applications and commands needing a lightweight +PSR-3 compliant logger:: + + namespace Acme; + + use Psr\Log\LoggerInterface; + + class MyDependency + { + private $logger; + + public function __construct(LoggerInterface $logger) + { + $this->logger = $logger; + } + + public function doStuff() + { + $this->logger->info('I love Tony Vairelles\' hairdresser.'); + } + } + +You can rely on the logger to use this dependency inside a command:: + + namespace Acme\Console\Command; + + use Acme\MyDependency; + use Symfony\Component\Console\Command\Command; + use Symfony\Component\Console\Input\InputInterface; + use Symfony\Component\Console\Output\OutputInterface; + use Symfony\Component\Console\Logger\ConsoleLogger; + + class MyCommand extends Command + { + protected function configure() + { + $this + ->setName('my:command') + ->setDescription( + 'Use an external dependency requiring a PSR-3 logger' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $logger = new ConsoleLogger($output); + + $myDependency = MyDependency($logger); + $myDependency->doStuff(); + } + } + +The dependency will use the instance of +``Symfony\\Component\\Console\\Logger\\ConsoleLogger`` as logger. +Log messages emitted will be displayed on the console output. + +Verbosity +--------- + +Depending on the verbosity level that the command is run, messages may or +may not be sent to the ``Symfony\\Component\\Console\\Output\\OutputInterface`` instance. + +By default, the console logger behaves like the +:doc:`Monolog's Console Handler `. +The association between the log level and the verbosity can be configured +through the second parameter of the :class:`Symfony\\Component\\Console\\ConsoleLogger` +constructor:: + + // ... + $verbosityLevelMap = array( + LogLevel::NOTICE => OutputInterface::VERBOSITY_NORMAL, + LogLevel::INFO => OutputInterface::VERBOSITY_NORMAL, + ); + $logger = new ConsoleLogger($output, $verbosityLevelMap); + +Color +----- + +The logger outputs the log messages formatted with a color reflecting their +level. This behavior is configurable through the third parameter of the +constructor:: + + // ... + private $formatLevelMap = array( + LogLevel::CRITICAL => self::INFO, + LogLevel::DEBUG => self::ERROR, + ); + $logger = new ConsoleLogger($output, array(), $formatLevelMap); + +.. _PSR-3: http://www.php-fig.org/psr/psr-3/ \ No newline at end of file diff --git a/cookbook/logging/monolog_console.rst b/cookbook/logging/monolog_console.rst index 7945193022e..ec72197c4c9 100644 --- a/cookbook/logging/monolog_console.rst +++ b/cookbook/logging/monolog_console.rst @@ -12,6 +12,11 @@ It is possible to use the console to print messages for certain :class:`Symfony\\Component\\Console\\Output\\OutputInterface` instance that is passed when a command gets executed. +.. seealso:: + Alternatively, you can use the + :doc:`standalone PSR-3 logger ` provided with + the console component. + When a lot of logging has to happen, it's cumbersome to print information depending on the verbosity settings (``-v``, ``-vv``, ``-vvv``) because the calls need to be wrapped in conditions. The code quickly gets verbose or dirty. From 8187776b02e7d249f0a0a37d08ec031dd07824cd Mon Sep 17 00:00:00 2001 From: WouterJ Date: Mon, 24 Mar 2014 22:45:23 +0100 Subject: [PATCH 0272/1181] was added -> was introduced --- book/controller.rst | 4 ++-- book/from_flat_php_to_symfony2.rst | 2 +- book/http_cache.rst | 2 +- book/http_fundamentals.rst | 2 +- book/internals.rst | 2 +- book/testing.rst | 2 +- components/console/helpers/progresshelper.rst | 2 +- components/console/helpers/tablehelper.rst | 2 +- components/debug/class_loader.rst | 4 ++-- components/dom_crawler.rst | 2 +- components/event_dispatcher/introduction.rst | 2 +- components/filesystem.rst | 4 ++-- components/http_foundation/introduction.rst | 6 +++--- components/process.rst | 2 +- cookbook/console/console_command.rst | 4 ++-- cookbook/security/api_key_authentication.rst | 2 +- cookbook/security/custom_authentication_provider.rst | 2 +- cookbook/security/custom_password_authenticator.rst | 2 +- cookbook/service_container/event_listener.rst | 2 +- cookbook/session/limit_metadata_writes.rst | 2 +- cookbook/testing/insulating_clients.rst | 2 +- reference/constraints/Image.rst | 2 +- reference/dic_tags.rst | 4 ++-- reference/forms/twig_reference.rst | 2 +- reference/twig_reference.rst | 2 +- 25 files changed, 32 insertions(+), 32 deletions(-) diff --git a/book/controller.rst b/book/controller.rst index 1831dc75218..ece7dc2f3c5 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -398,7 +398,7 @@ itself. via the ``container`` property. .. versionadded:: 2.4 - The ``ContainerAwareTrait`` is new in Symfony 2.4. + The ``ContainerAwareTrait`` was introduced in Symfony 2.4. .. note:: @@ -766,7 +766,7 @@ headers and content that's sent back to the client:: $response->headers->set('Content-Type', 'application/json'); .. versionadded:: 2.4 - Support for HTTP status code constants was added in Symfony 2.4. + Support for HTTP status code constants was introduced in Symfony 2.4. .. tip:: diff --git a/book/from_flat_php_to_symfony2.rst b/book/from_flat_php_to_symfony2.rst index 19ad8485ae1..b970b6cc4b8 100644 --- a/book/from_flat_php_to_symfony2.rst +++ b/book/from_flat_php_to_symfony2.rst @@ -481,7 +481,7 @@ the HTTP response being returned. Use them to improve the blog: $response->send(); .. versionadded:: 2.4 - Support for HTTP status code constants was added in Symfony 2.4. + Support for HTTP status code constants was introduced in Symfony 2.4. The controllers are now responsible for returning a ``Response`` object. To make this easier, you can add a new ``render_template()`` function, which, diff --git a/book/http_cache.rst b/book/http_cache.rst index 585a8b3368f..29367ac5be4 100644 --- a/book/http_cache.rst +++ b/book/http_cache.rst @@ -1082,7 +1082,7 @@ Here is how you can configure the Symfony2 reverse proxy to support the } .. versionadded:: 2.4 - Support for HTTP status code constants was added in Symfony 2.4. + Support for HTTP status code constants was introduced in Symfony 2.4. .. caution:: diff --git a/book/http_fundamentals.rst b/book/http_fundamentals.rst index 2fcfdb6c386..1f67ae3868f 100644 --- a/book/http_fundamentals.rst +++ b/book/http_fundamentals.rst @@ -285,7 +285,7 @@ interface to construct the response that needs to be returned to the client:: $response->send(); .. versionadded:: 2.4 - Support for HTTP status code constants was added in Symfony 2.4. + Support for HTTP status code constants was introduced in Symfony 2.4. If Symfony offered nothing else, you would already have a toolkit for easily accessing request information and an object-oriented interface for creating diff --git a/book/internals.rst b/book/internals.rst index a6b5ece9aaa..cf204094287 100644 --- a/book/internals.rst +++ b/book/internals.rst @@ -427,7 +427,7 @@ and set a new ``Exception`` object, or do nothing:: ); .. versionadded:: 2.4 - Support for HTTP status code constants was added in Symfony 2.4. + Support for HTTP status code constants was introduced in Symfony 2.4. .. seealso:: diff --git a/book/testing.rst b/book/testing.rst index aa432dcc884..2a9408825b5 100644 --- a/book/testing.rst +++ b/book/testing.rst @@ -311,7 +311,7 @@ document:: $this->assertTrue($client->getResponse()->isRedirect()); .. versionadded:: 2.4 - Support for HTTP status code constants was added with Symfony 2.4. + Support for HTTP status code constants was introduced in Symfony 2.4. .. index:: single: Tests; Client diff --git a/components/console/helpers/progresshelper.rst b/components/console/helpers/progresshelper.rst index ccd5d381afd..41e25b96b63 100644 --- a/components/console/helpers/progresshelper.rst +++ b/components/console/helpers/progresshelper.rst @@ -11,7 +11,7 @@ Progress Helper The ``setCurrent`` method was added in Symfony 2.3. .. versionadded:: 2.4 - The ``clear`` method was added in Symfony 2.4. + The ``clear`` method was introduced in Symfony 2.4. When executing longer-running commands, it may be helpful to show progress information, which updates as your command runs: diff --git a/components/console/helpers/tablehelper.rst b/components/console/helpers/tablehelper.rst index 305448845ba..f5f918481fe 100644 --- a/components/console/helpers/tablehelper.rst +++ b/components/console/helpers/tablehelper.rst @@ -33,7 +33,7 @@ Customize Table Layout using Named Layouts ------------------------------------------ .. versionadded:: 2.4 - The ``TableHelper::LAYOUT_COMPACT`` layout was added in Symfony 2.4. + The ``TableHelper::LAYOUT_COMPACT`` layout was introduced in Symfony 2.4. The Table helper ships with three preconfigured table layouts: diff --git a/components/debug/class_loader.rst b/components/debug/class_loader.rst index 090b230baf4..34a06bce3e7 100644 --- a/components/debug/class_loader.rst +++ b/components/debug/class_loader.rst @@ -6,8 +6,8 @@ Debugging a Class Loader ======================== .. versionadded:: 2.4 - The ``DebugClassLoader`` of the Debug component is new in Symfony 2.4. - Previously, it was located in the Class Loader component. + The ``DebugClassLoader`` of the Debug component was introduced in Symfony 2.4. + Previously, it was located in the ClassLoader component. The :class:`Symfony\\Component\\Debug\\DebugClassLoader` attempts to throw more helpful exceptions when a class isn't found by the registered diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index 6a3a6b70ce1..2d17126b89f 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -449,7 +449,7 @@ Selecting Invalid Choice Values .. versionadded:: 2.4 The :method:`Symfony\\Component\\DomCrawler\\Form::disableValidation` - method was added in Symfony 2.4. + method was introduced in Symfony 2.4. By default, choice fields (select, radio) have internal validation activated to prevent you from setting invalid values. If you want to be able to set diff --git a/components/event_dispatcher/introduction.rst b/components/event_dispatcher/introduction.rst index b037c462898..c8adf4908c1 100644 --- a/components/event_dispatcher/introduction.rst +++ b/components/event_dispatcher/introduction.rst @@ -442,7 +442,7 @@ EventDispatcher aware Events and Listeners ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.4 - Since Symfony 2.4 the current event name and the ``EventDispatcher`` + Since Symfony 2.4, the current event name and the ``EventDispatcher`` itself are passed to the listeners as additional arguments. The ``EventDispatcher`` always passes the dispatched event, the event's name diff --git a/components/filesystem.rst b/components/filesystem.rst index a88308d5cd1..210aa6cdc34 100644 --- a/components/filesystem.rst +++ b/components/filesystem.rst @@ -32,8 +32,8 @@ endpoint for filesystem operations:: } .. versionadded:: 2.4 - The ``IOExceptionInterface`` and its ``getPath`` method are new in Symfony - 2.4. Prior to 2.4, you would catch the ``IOException`` class. + The ``IOExceptionInterface`` and its ``getPath`` method were introduced in + Symfony 2.4. Prior to 2.4, you would catch the ``IOException`` class. .. note:: diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index 884aa375f42..dc5fa29b931 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -254,7 +254,7 @@ by using the following methods: returns the list of accepted charsets ordered by descending quality; .. versionadded:: 2.4 - The ``getEncodings()`` method was added in Symfony 2.4. + The ``getEncodings()`` method was introduced in Symfony 2.4. .. versionadded:: 2.2 The :class:`Symfony\\Component\\HttpFoundation\\AcceptHeader` class is new in Symfony 2.2. @@ -289,7 +289,7 @@ Overriding the Request .. versionadded:: 2.4 The :method:`Symfony\\Component\\HttpFoundation\\Request::setFactory` - method was added in Symfony 2.4. + method was introduced in Symfony 2.4. The ``Request`` class should not be overridden as it is a data object that represents an HTTP message. But when moving from a legacy system, adding @@ -339,7 +339,7 @@ code, and an array of HTTP headers:: ); .. versionadded:: 2.4 - Support for HTTP status code constants was added in Symfony 2.4. + Support for HTTP status code constants was introduced in Symfony 2.4. These information can also be manipulated after the Response object creation:: diff --git a/components/process.rst b/components/process.rst index 7680dc7adfa..cc2d2319224 100644 --- a/components/process.rst +++ b/components/process.rst @@ -46,7 +46,7 @@ and :method:`Symfony\\Component\\Process\\Process::getIncrementalErrorOutput` methods returns the new outputs since the last call. .. versionadded:: 2.4 - The ``clearOutput()`` and ``clearErrorOutput()`` methods were added in Symfony 2.4. + The ``clearOutput()`` and ``clearErrorOutput()`` methods were introduced in Symfony 2.4. The :method:`Symfony\\Component\\Process\\Process::clearOutput` method clears the contents of the output and diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index ab509787773..8f6de9dd0d6 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -128,8 +128,8 @@ instead of .. versionadded:: 2.4 Since Symfony 2.4, the ``CommandTester`` automatically detects the name of - the command to execute. Thus, you don't need to pass it via the ``command`` - key anymore. + the command to execute. Prior to Symfony 2.4, you need to pass it via the + ``command`` key. .. note:: diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index c027012052b..a5c9f409200 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -12,7 +12,7 @@ The API Key Authenticator ------------------------- .. versionadded:: 2.4 - The ``SimplePreAuthenticatorInterface`` interface was added in Symfony 2.4. + The ``SimplePreAuthenticatorInterface`` interface was introduced in Symfony 2.4. Authenticating a user based on the Request information should be done via a pre-authentication mechanism. The :class:`Symfony\\Component\\Security\\Core\\Authentication\\SimplePreAuthenticatorInterface` diff --git a/cookbook/security/custom_authentication_provider.rst b/cookbook/security/custom_authentication_provider.rst index a3480dfbd14..4a8fb4862b8 100644 --- a/cookbook/security/custom_authentication_provider.rst +++ b/cookbook/security/custom_authentication_provider.rst @@ -175,7 +175,7 @@ set an authenticated token in the security context if successful. } .. versionadded:: 2.4 - Support for HTTP status code constants was added in Symfony 2.4. + Support for HTTP status code constants was introduced in Symfony 2.4. This listener checks the request for the expected ``X-WSSE`` header, matches the value returned for the expected WSSE information, creates a token using diff --git a/cookbook/security/custom_password_authenticator.rst b/cookbook/security/custom_password_authenticator.rst index 890c290eae2..288d0e65a6f 100644 --- a/cookbook/security/custom_password_authenticator.rst +++ b/cookbook/security/custom_password_authenticator.rst @@ -13,7 +13,7 @@ The Password Authenticator -------------------------- .. versionadded:: 2.4 - The ``SimpleFormAuthenticatorInterface`` interface was added in Symfony 2.4. + The ``SimpleFormAuthenticatorInterface`` interface was introduced in Symfony 2.4. First, create a new class that implements :class:`Symfony\\Component\\Security\\Core\\Authentication\\SimpleFormAuthenticatorInterface`. diff --git a/cookbook/service_container/event_listener.rst b/cookbook/service_container/event_listener.rst index 2e22ca66ecc..0676ca4479a 100644 --- a/cookbook/service_container/event_listener.rst +++ b/cookbook/service_container/event_listener.rst @@ -52,7 +52,7 @@ event is just one of the core kernel events:: } .. versionadded:: 2.4 - Support for HTTP status code constants was added in Symfony 2.4. + Support for HTTP status code constants was introduced in Symfony 2.4. .. tip:: diff --git a/cookbook/session/limit_metadata_writes.rst b/cookbook/session/limit_metadata_writes.rst index 78d3923c69b..4a96cec7843 100644 --- a/cookbook/session/limit_metadata_writes.rst +++ b/cookbook/session/limit_metadata_writes.rst @@ -5,7 +5,7 @@ Limit Session Metadata Writes ============================= .. versionadded:: 2.4 - The ability to limit session metadata writes was added in Symfony 2.4. + The ability to limit session metadata writes was introduced in Symfony 2.4. The default behavior of PHP session is to persist the session regardless of whether the session data has changed or not. In Symfony, each time the session diff --git a/cookbook/testing/insulating_clients.rst b/cookbook/testing/insulating_clients.rst index 5e908e2e98c..80a54c7d65c 100644 --- a/cookbook/testing/insulating_clients.rst +++ b/cookbook/testing/insulating_clients.rst @@ -19,7 +19,7 @@ chat for instance), create several clients:: $this->assertRegExp('/Hello/', $sally->getResponse()->getContent()); .. versionadded:: 2.4 - Support for HTTP status code constants was added in Symfony 2.4. + Support for HTTP status code constants was introduced in Symfony 2.4. This works except when your code maintains a global state or if it depends on a third-party library that has some kind of global state. In such a case, you diff --git a/reference/constraints/Image.rst b/reference/constraints/Image.rst index ca7b43b1bdd..cca9a6df0ff 100644 --- a/reference/constraints/Image.rst +++ b/reference/constraints/Image.rst @@ -9,7 +9,7 @@ Additionally it has options so you can validate against the width and height of the image. .. versionadded:: 2.4 - As of Symfony 2.4 you can also validate against the image aspect ratio + As of Symfony 2.4, you can also validate against the image aspect ratio (defined as ``width / height``) and selectively allow square, landscape and portrait image orientations. diff --git a/reference/dic_tags.rst b/reference/dic_tags.rst index a7b6856a061..4adaf16dc63 100644 --- a/reference/dic_tags.rst +++ b/reference/dic_tags.rst @@ -247,8 +247,8 @@ console.command --------------- .. versionadded:: 2.4 - Support for registering commands in the service container was added in - version 2.4. + Support for registering commands in the service container was introduced in + Symfony 2.4. **Purpose**: Add a command to the application diff --git a/reference/forms/twig_reference.rst b/reference/forms/twig_reference.rst index 85f9a818f53..0bd5d8d6771 100644 --- a/reference/forms/twig_reference.rst +++ b/reference/forms/twig_reference.rst @@ -317,7 +317,7 @@ object: The ``method`` and ``action`` variables were introduced in Symfony 2.3. .. versionadded:: 2.4 - The ``submitted`` variable was added in Symfony 2.4. + The ``submitted`` variable was introduced in Symfony 2.4. +------------------------+-------------------------------------------------------------------------------------+ | Variable | Usage | diff --git a/reference/twig_reference.rst b/reference/twig_reference.rst index 17961dd06f4..1d2e6ac26d1 100644 --- a/reference/twig_reference.rst +++ b/reference/twig_reference.rst @@ -141,7 +141,7 @@ Tags ---- .. versionadded:: 2.4 - The stopwatch tag was added in Symfony 2.4. + The stopwatch tag was introduced in Symfony 2.4. +---------------------------------------------------+--------------------------------------------------------------------+ | Tag Syntax | Usage | From 78d4a0f2f77de5e86383d90613610f793dea5e37 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Mon, 24 Mar 2014 22:48:03 +0100 Subject: [PATCH 0273/1181] More consistency stuff --- book/service_container.rst | 2 +- components/console/introduction.rst | 2 +- cookbook/console/commands_as_services.rst | 2 +- cookbook/logging/channels_handlers.rst | 6 +++--- cookbook/logging/monolog_regex_based_excludes.rst | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/book/service_container.rst b/book/service_container.rst index 39fd36a68fe..1dd19f0dac8 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -836,7 +836,7 @@ Injecting the Request ~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.4 - The ``request_stack`` service was introduced in version 2.4. + The ``request_stack`` service was introduced in Symfony 2.4. As of Symfony 2.4, instead of injecting the ``request`` service, you should inject the ``request_stack`` service and access the ``Request`` by calling diff --git a/components/console/introduction.rst b/components/console/introduction.rst index 669159db3ff..24d103df9c4 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -203,7 +203,7 @@ level. For example:: :method:`Symfony\\Component\\Console\\Output\\Output::isVerbose`, :method:`Symfony\\Component\\Console\\Output\\Output::isVeryVerbose` and :method:`Symfony\\Component\\Console\\Output\\Output::isDebug` - methods were introduced in version 2.4 + methods were introduced in Symfony 2.4 There are also more semantic methods you can use to test for each of the verbosity levels:: diff --git a/cookbook/console/commands_as_services.rst b/cookbook/console/commands_as_services.rst index c6001e246bf..09bfe12d77b 100644 --- a/cookbook/console/commands_as_services.rst +++ b/cookbook/console/commands_as_services.rst @@ -6,7 +6,7 @@ How to Define Commands as Services .. versionadded:: 2.4 Support for registering commands in the service container was introduced in - version 2.4. + Symfony 2.4. By default, Symfony will take a look in the ``Command`` directory of each bundle and automatically register your commands. If a command extends the diff --git a/cookbook/logging/channels_handlers.rst b/cookbook/logging/channels_handlers.rst index 9bf24ee2331..9cee5557af3 100644 --- a/cookbook/logging/channels_handlers.rst +++ b/cookbook/logging/channels_handlers.rst @@ -114,9 +114,9 @@ specified. Configure Additional Channels without Tagged Services ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. versionadded:: 2.3 - This feature was introduced to the MonologBundle in version 2.4, which - was first packaged with Symfony at version 2.4. +.. versionadded:: 2.4 + This feature was introduced to the MonologBundle 2.4, which was first + packaged with Symfony 2.4. With MonologBundle 2.4 you can configure additional channels without the need to tag your services: diff --git a/cookbook/logging/monolog_regex_based_excludes.rst b/cookbook/logging/monolog_regex_based_excludes.rst index 71bc77a2a12..1ad549f9334 100644 --- a/cookbook/logging/monolog_regex_based_excludes.rst +++ b/cookbook/logging/monolog_regex_based_excludes.rst @@ -7,8 +7,8 @@ How to Configure Monolog to Exclude 404 Errors from the Log =========================================================== .. versionadded:: 2.4 - This feature was introduced to the MonologBundle in version 2.4, which - was first packaged with Symfony at version 2.4. + This feature was introduced to the MonologBundle 2.4, which was first + packaged with Symfony 2.4. Sometimes your logs become flooded with unwanted 404 HTTP errors, for example, when an attacker scans your app for some well-known application paths (e.g. From ac484f41e609177d8f3db0358096c2731e527e16 Mon Sep 17 00:00:00 2001 From: jochenvdv Date: Tue, 25 Mar 2014 16:09:59 +0100 Subject: [PATCH 0274/1181] Made suggested tweaks --- components/stopwatch.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/components/stopwatch.rst b/components/stopwatch.rst index 034a6d3e928..b056af59e6e 100644 --- a/components/stopwatch.rst +++ b/components/stopwatch.rst @@ -31,7 +31,14 @@ microtime by yourself. Instead, use the simple // ... some code goes here $event = $stopwatch->stop('eventName'); -The :class:`Symfony\\Component\\Stopwatch\StopwatchEvent` object can be retrieved from :method:`Symfony\\Component\\Stopwatch\\Stopwatch::start`, :method:`Symfony\\Component\\Stopwatch\\Stopwatch::stop`, :method:`Symfony\\Component\\Stopwatch\\Stopwatch::lap` and :method:`Symfony\\Component\\Stopwatch\\Stopwatch::getEvent` +.. versionadded:: 2.5 + The ``getEvent()`` method was introduced + +The :class:`Symfony\\Component\\Stopwatch\StopwatchEvent` object can be retrieved from the +:method:`Symfony\\Component\\Stopwatch\\Stopwatch::start`, +:method:`Symfony\\Component\\Stopwatch\\Stopwatch::stop`, +:method:`Symfony\\Component\\Stopwatch\\Stopwatch::lap` and +:method:`Symfony\\Component\\Stopwatch\\Stopwatch::getEvent` methods. You can also provide a category name to an event:: From 295f10993545c3b9a33e0eb383fe7ade4713538d Mon Sep 17 00:00:00 2001 From: jochenvdv Date: Tue, 25 Mar 2014 16:18:54 +0100 Subject: [PATCH 0275/1181] Add reason for getEvent() --- components/stopwatch.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/stopwatch.rst b/components/stopwatch.rst index b056af59e6e..4bc306b8338 100644 --- a/components/stopwatch.rst +++ b/components/stopwatch.rst @@ -38,7 +38,8 @@ The :class:`Symfony\\Component\\Stopwatch\StopwatchEvent` object can be retrieve :method:`Symfony\\Component\\Stopwatch\\Stopwatch::start`, :method:`Symfony\\Component\\Stopwatch\\Stopwatch::stop`, :method:`Symfony\\Component\\Stopwatch\\Stopwatch::lap` and -:method:`Symfony\\Component\\Stopwatch\\Stopwatch::getEvent` methods. +:method:`Symfony\\Component\\Stopwatch\\Stopwatch::getEvent` methods. +The latter should be used when you need to retrieve the duration of an event while it is still running. You can also provide a category name to an event:: From 0ee15d3ad6821a4e1eacdd397d18d77505e78700 Mon Sep 17 00:00:00 2001 From: jochenvdv Date: Tue, 25 Mar 2014 16:46:49 +0100 Subject: [PATCH 0276/1181] Fix versionadded --- components/stopwatch.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/stopwatch.rst b/components/stopwatch.rst index 4bc306b8338..324539f3cf6 100644 --- a/components/stopwatch.rst +++ b/components/stopwatch.rst @@ -32,7 +32,7 @@ microtime by yourself. Instead, use the simple $event = $stopwatch->stop('eventName'); .. versionadded:: 2.5 - The ``getEvent()`` method was introduced + The ``getEvent()`` method was introduced in Symfony 2.5 The :class:`Symfony\\Component\\Stopwatch\StopwatchEvent` object can be retrieved from the :method:`Symfony\\Component\\Stopwatch\\Stopwatch::start`, From 239b1b686d16624c7404fe8375dbcfd564938c54 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 25 Mar 2014 16:53:59 +0100 Subject: [PATCH 0277/1181] Some markup fixes --- components/options_resolver.rst | 1 - cookbook/console/console_command.rst | 11 ++++++----- reference/forms/types/collection.rst | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index ced1cb0c2b0..af240abaefd 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -328,7 +328,6 @@ method, which you can use if you want to add an allowed value to the previously configured allowed values. .. versionadded:: 2.5 - The callback support for allowed values was introduced in Symfony 2.5. If you need to add some more logic to the value validation process, you can pass a callable diff --git a/cookbook/console/console_command.rst b/cookbook/console/console_command.rst index 30ea6f0d9cf..da5c18e01eb 100644 --- a/cookbook/console/console_command.rst +++ b/cookbook/console/console_command.rst @@ -174,8 +174,9 @@ you can extend your test from .. versionadded:: 2.5 :class:`Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase` was extracted from :class:`Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase` - in Symfony 2.5, where WebTestCase was made to inherit from KernelTestCase. - The difference being that WebTestCase makes available an instance of - :class:`Symfony\\Bundle\\FrameworkBundle\\Client` via `createClient()`, - while KernelTestCase makes available an instance of - :class:`Symfony\\Component\\HttpKernel\\KernelInterface` via `createKernel()`. + in Symfony 2.5. ``WebTestCase`` inherits from ``KernelTestCase``. The + ``WebTestCase`` creates an instance of + :class:`Symfony\\Bundle\\FrameworkBundle\\Client` via ``createClient()``, + while ``KernelTestCase`` creates an instance of + :class:`Symfony\\Component\\HttpKernel\\KernelInterface` via + ``createKernel()``. diff --git a/reference/forms/types/collection.rst b/reference/forms/types/collection.rst index 42018725f2d..ad487018e20 100644 --- a/reference/forms/types/collection.rst +++ b/reference/forms/types/collection.rst @@ -341,7 +341,7 @@ delete_empty ~~~~~~~~~~~~ .. versionadded:: 2.5 - The delete_empty option was introduced in Symfony 2.5. + The ``delete_empty`` option was introduced in Symfony 2.5. **type**: ``Boolean`` **default**: ``false`` From b3372cf73ac0c17d0ca5cee2f317bb0d362b06b5 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 25 Mar 2014 16:54:45 +0100 Subject: [PATCH 0278/1181] Made versionadded consistent --- components/console/changing_default_command.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/console/changing_default_command.rst b/components/console/changing_default_command.rst index 6c8d2689a97..1c191ba8571 100644 --- a/components/console/changing_default_command.rst +++ b/components/console/changing_default_command.rst @@ -6,7 +6,7 @@ Changing the Default Command .. versionadded:: 2.5 The :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` - method was introduced in version 2.5. + method was introduced in Symfony 2.5. will always run the ``ListCommand`` when no command name is passed. In order to change the default command you just need to pass the command name you want to run by From dd165898d2ea89718ee6fc1232f3eb44243f003f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 26 Mar 2014 10:35:55 +0100 Subject: [PATCH 0279/1181] add logger chapter to the component's map --- components/map.rst.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/components/map.rst.inc b/components/map.rst.inc index c3b88b548a9..9eb981425e3 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -23,6 +23,7 @@ * :doc:`/components/console/single_command_tool` * :doc:`/components/console/changing_default_command` * :doc:`/components/console/events` + * :doc:`/components/console/logger` * :doc:`/components/console/helpers/index` * **CssSelector** From 9b0911b2a4b44950d030d8039210a7c3d2c57392 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 26 Mar 2014 10:39:42 +0100 Subject: [PATCH 0280/1181] fix grammer mistake --- components/console/logger.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/components/console/logger.rst b/components/console/logger.rst index 84a41ad2b6c..6c54564963e 100644 --- a/components/console/logger.rst +++ b/components/console/logger.rst @@ -9,10 +9,9 @@ Using the Logger introduced in Symfony 2.5. The Console component comes with a standalone logger complying with the -`PSR-3_` standard. -Depending of the verbosity setting, log messages will be sent to the -:class:`Symfony\\Component\\Console\\Output\\OutputInterface` instance -passed as a parameter to the constructor. +`PSR-3_` standard. Depending on the verbosity setting, log messages will +be sent to the :class:`Symfony\\Component\\Console\\Output\\OutputInterface` +instance passed as a parameter to the constructor. The logger does not have any external dependency except ``php-fig/log``. This is useful for console applications and commands needing a lightweight @@ -76,7 +75,8 @@ Verbosity --------- Depending on the verbosity level that the command is run, messages may or -may not be sent to the ``Symfony\\Component\\Console\\Output\\OutputInterface`` instance. +may not be sent to the ``Symfony\\Component\\Console\\Output\\OutputInterface`` +instance. By default, the console logger behaves like the :doc:`Monolog's Console Handler `. @@ -105,4 +105,4 @@ constructor:: ); $logger = new ConsoleLogger($output, array(), $formatLevelMap); -.. _PSR-3: http://www.php-fig.org/psr/psr-3/ \ No newline at end of file +.. _PSR-3: http://www.php-fig.org/psr/psr-3/ From 3bbccf70bf27d0f32fa00fb395ff06a1b151450e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 26 Mar 2014 10:40:03 +0100 Subject: [PATCH 0281/1181] fix PSR-3 link as mentioned by @max-voloshin --- components/console/logger.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/console/logger.rst b/components/console/logger.rst index 6c54564963e..35b72704044 100644 --- a/components/console/logger.rst +++ b/components/console/logger.rst @@ -9,7 +9,7 @@ Using the Logger introduced in Symfony 2.5. The Console component comes with a standalone logger complying with the -`PSR-3_` standard. Depending on the verbosity setting, log messages will +`PSR-3`_ standard. Depending on the verbosity setting, log messages will be sent to the :class:`Symfony\\Component\\Console\\Output\\OutputInterface` instance passed as a parameter to the constructor. From 83adc87e176ed9b194c06b727d4092ffb51737b5 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 26 Mar 2014 10:43:37 +0100 Subject: [PATCH 0282/1181] fix class roles --- components/console/logger.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/console/logger.rst b/components/console/logger.rst index 35b72704044..71b8452b1d3 100644 --- a/components/console/logger.rst +++ b/components/console/logger.rst @@ -68,14 +68,14 @@ You can rely on the logger to use this dependency inside a command:: } The dependency will use the instance of -``Symfony\\Component\\Console\\Logger\\ConsoleLogger`` as logger. +:class:`Symfony\\Component\\Console\\Logger\\ConsoleLogger` as logger. Log messages emitted will be displayed on the console output. Verbosity --------- Depending on the verbosity level that the command is run, messages may or -may not be sent to the ``Symfony\\Component\\Console\\Output\\OutputInterface`` +may not be sent to the :class:`Symfony\\Component\\Console\\Output\\OutputInterface` instance. By default, the console logger behaves like the From 610eb6b3910d6f7db3ecf787b2c86ef7a4d8e9b0 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 26 Mar 2014 10:46:38 +0100 Subject: [PATCH 0283/1181] code fixes as mentioned by @dirkluijk --- components/console/logger.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/console/logger.rst b/components/console/logger.rst index 71b8452b1d3..43951c63130 100644 --- a/components/console/logger.rst +++ b/components/console/logger.rst @@ -62,7 +62,7 @@ You can rely on the logger to use this dependency inside a command:: { $logger = new ConsoleLogger($output); - $myDependency = MyDependency($logger); + $myDependency = new MyDependency($logger); $myDependency->doStuff(); } } @@ -99,7 +99,7 @@ level. This behavior is configurable through the third parameter of the constructor:: // ... - private $formatLevelMap = array( + $formatLevelMap = array( LogLevel::CRITICAL => self::INFO, LogLevel::DEBUG => self::ERROR, ); From 3580b7b6a5f3513e2c2f70de30bcb9bf11f2cbdc Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 26 Mar 2014 13:11:39 +0100 Subject: [PATCH 0284/1181] add "Commands as Services" chapter to the cookbook's map --- cookbook/map.rst.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 67b2ebe2d1b..c8a00ce6a3e 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -37,6 +37,7 @@ * :doc:`/cookbook/console/usage` * :doc:`/cookbook/console/sending_emails` * :doc:`/cookbook/console/logging` + * :doc:`/cookbook/console/commands_as_services` * :doc:`/cookbook/controller/index` From bb8e3ed3ee2ebd141acb5c572efcdfbecf5d5b2d Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 28 Mar 2014 17:33:52 +0100 Subject: [PATCH 0285/1181] Added documentation for the new PropertyAccessor::isReadable() and isWritable() methods --- components/property_access/introduction.rst | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/components/property_access/introduction.rst b/components/property_access/introduction.rst index 07177d15b5f..2fabbf2119b 100644 --- a/components/property_access/introduction.rst +++ b/components/property_access/introduction.rst @@ -309,6 +309,39 @@ see `Enable other Features`_. echo $person->getWouter(); // array(...) +Checking Property Paths +----------------------- + +.. versionadded:: 2.5 + The methods + :method:`PropertyAccessor::isReadable` + and + :method:`PropertyAccessor::isWritable` + methods were added in Symfony 2.5. + +When you want to check whether :method:`PropertyAccessor::getValue` +can safely be called without actually calling that method, you can use +:method:`PropertyAccessor::isReadable` +instead:: + + $person = new Person(); + + if ($accessor->isReadable($person, 'firstName') { + // ... + } + +The same is possible for :method:`PropertyAccessor::setValue`: +Call the +:method:`PropertyAccessor::isWritable` +method to find out whether a property path can be updated. In the third +argument, you should pass the value that you want to write:: + + $person = new Person(); + + if ($accessor->isWritable($person, 'firstName', 'Wouter') { + // ... + } + Mixing Objects and Arrays ------------------------- From f6af2510347c02aaffab6877ca1ed8e566aa862d Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Mon, 31 Mar 2014 15:46:59 +0200 Subject: [PATCH 0286/1181] [Templating] Add documentation about generating versioned URLs --- book/templating.rst | 19 +++ .../templating/helpers/assetshelper.rst | 12 ++ reference/twig_reference.rst | 142 +++++++++--------- 3 files changed, 102 insertions(+), 71 deletions(-) diff --git a/book/templating.rst b/book/templating.rst index e9cfdfaf086..a91c4b5ba81 100644 --- a/book/templating.rst +++ b/book/templating.rst @@ -1007,6 +1007,25 @@ If you need absolute URLs for assets, you can set the third argument (or the Symfony! +.. versionadded:: 2.5 + Versioned URLs for assets were introduced in Symfony 2.5. + +If you need versioned URLs for assets, you can set the fourth argument (or the +``version`` argument) to the desired version: + +.. configuration-block:: + + .. code-block:: html+jinja + + Symfony! + + .. code-block:: html+php + + Symfony! + +If you dont give a version or pass ``null``, the default package version will +be used. If you pass ``false``, versioned URL will be deactivated. + .. index:: single: Templating; Including stylesheets and JavaScripts single: Stylesheets; Including stylesheets diff --git a/components/templating/helpers/assetshelper.rst b/components/templating/helpers/assetshelper.rst index 6151d2b4784..6f096d35c52 100644 --- a/components/templating/helpers/assetshelper.rst +++ b/components/templating/helpers/assetshelper.rst @@ -80,6 +80,18 @@ is used in :phpfunction:`sprintf`. The first argument is the path and the second is the version. For instance, ``%s?v=%s`` will be rendered as ``/images/logo.png?v=328rad75``. +.. versionadded:: 2.5 + On-demand versioned URLs for assets were introduced in Symfony 2.5. + +You can also generate a versioned URL using the fourth argument of the helper: + +.. code-block:: html+php + + + + Multiple Packages ----------------- diff --git a/reference/twig_reference.rst b/reference/twig_reference.rst index 23c39471555..00e709fd335 100644 --- a/reference/twig_reference.rst +++ b/reference/twig_reference.rst @@ -20,77 +20,77 @@ Functions .. versionadded:: 2.4 The ``expression`` function was introduced in Symfony 2.4. -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| Function Syntax | Usage | -+=======================================================+============================================================================================+ -| ``render(uri, options = {})`` | This will render the fragment for the given controller or URL | -| ``render(controller('B:C:a', {params}))`` | For more information, see :ref:`templating-embedding-controller`. | -| ``render(path('route', {params}))`` | | -| ``render(url('route', {params}))`` | | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``render_esi(controller('B:C:a', {params}))`` | This will generate an ESI tag when possible or fallback to the ``render`` | -| ``render_esi(url('route', {params}))`` | behavior otherwise. For more information, see :ref:`templating-embedding-controller`. | -| ``render_esi(path('route', {params}))`` | | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``render_hinclude(controller(...))`` | This will generates an Hinclude tag for the given controller or URL. | -| ``render_hinclude(url('route', {params}))`` | For more information, see :ref:`templating-embedding-controller`. | -| ``render_hinclude(path('route', {params}))`` | | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``controller(attributes = {}, query = {})`` | Used along with the ``render`` tag to refer to the controller that you want to render. | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``asset(path, packageName = null, absolute = false)`` | Get the public path of the asset, more information in | -| | ":ref:`book-templating-assets`". | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``asset_version(packageName = null)`` | Get the current version of the package, more information in | -| | ":ref:`book-templating-assets`". | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form(view, variables = {})`` | This will render the HTML of a complete form, more information in | -| | in :ref:`the Twig Form reference`. | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_start(view, variables = {})`` | This will render the HTML start tag of a form, more information in | -| | in :ref:`the Twig Form reference`. | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_end(view, variables = {})`` | This will render the HTML end tag of a form together with all fields that | -| | have not been rendered yet, more information | -| | in :ref:`the Twig Form reference`. | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_enctype(view)`` | This will render the required ``enctype="multipart/form-data"`` attribute | -| | if the form contains at least one file upload field, more information in | -| | in :ref:`the Twig Form reference `. | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_widget(view, variables = {})`` | This will render a complete form or a specific HTML widget of a field, | -| | more information in :ref:`the Twig Form reference `. | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_errors(view)`` | This will render any errors for the given field or the "global" errors, | -| | more information in :ref:`the Twig Form reference `. | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_label(view, label = null, variables = {})`` | This will render the label for the given field, more information in | -| | :ref:`the Twig Form reference `. | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_row(view, variables = {})`` | This will render the row (the field's label, errors and widget) of the given | -| | field, more information in :ref:`the Twig Form reference `. | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``form_rest(view, variables = {})`` | This will render all fields that have not yet been rendered, more | -| | information in :ref:`the Twig Form reference `. | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``csrf_token(intention)`` | This will render a CSRF token. Use this function if you want CSRF protection without | -| | creating a form | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``is_granted(role, object = null, field = null)`` | This will return ``true`` if the current user has the required role, more | -| | information in ":ref:`book-security-template`" | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``logout_path(key)`` | This will generate the relative logout URL for the given firewall | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``logout_url(key)`` | Equal to ``logout_path(...)`` but this will generate an absolute URL | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``path(name, parameters = {})`` | Get a relative URL for the given route, more information in | -| | ":ref:`book-templating-pages`". | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``url(name, parameters = {})`` | Equal to ``path(...)`` but it generates an absolute URL | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| ``expression(expression)`` | Creates an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` in Twig. See | -| | ":ref:`Template Expressions `". | -+-------------------------------------------------------+--------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| Function Syntax | Usage | ++=======================================================================+============================================================================================+ +| ``render(uri, options = {})`` | This will render the fragment for the given controller or URL | +| ``render(controller('B:C:a', {params}))`` | For more information, see :ref:`templating-embedding-controller`. | +| ``render(path('route', {params}))`` | | +| ``render(url('route', {params}))`` | | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``render_esi(controller('B:C:a', {params}))`` | This will generate an ESI tag when possible or fallback to the ``render`` | +| ``render_esi(url('route', {params}))`` | behavior otherwise. For more information, see :ref:`templating-embedding-controller`. | +| ``render_esi(path('route', {params}))`` | | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``render_hinclude(controller(...))`` | This will generates an Hinclude tag for the given controller or URL. | +| ``render_hinclude(url('route', {params}))`` | For more information, see :ref:`templating-embedding-controller`. | +| ``render_hinclude(path('route', {params}))`` | | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``controller(attributes = {}, query = {})`` | Used along with the ``render`` tag to refer to the controller that you want to render. | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``asset(path, packageName = null, absolute = false, version = null)`` | Get the public path of the asset, more information in | +| | ":ref:`book-templating-assets`". | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``asset_version(packageName = null)`` | Get the current version of the package, more information in | +| | ":ref:`book-templating-assets`". | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form(view, variables = {})`` | This will render the HTML of a complete form, more information in | +| | in :ref:`the Twig Form reference`. | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_start(view, variables = {})`` | This will render the HTML start tag of a form, more information in | +| | in :ref:`the Twig Form reference`. | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_end(view, variables = {})`` | This will render the HTML end tag of a form together with all fields that | +| | have not been rendered yet, more information | +| | in :ref:`the Twig Form reference`. | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_enctype(view)`` | This will render the required ``enctype="multipart/form-data"`` attribute | +| | if the form contains at least one file upload field, more information in | +| | in :ref:`the Twig Form reference `. | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_widget(view, variables = {})`` | This will render a complete form or a specific HTML widget of a field, | +| | more information in :ref:`the Twig Form reference `. | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_errors(view)`` | This will render any errors for the given field or the "global" errors, | +| | more information in :ref:`the Twig Form reference `. | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_label(view, label = null, variables = {})`` | This will render the label for the given field, more information in | +| | :ref:`the Twig Form reference `. | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_row(view, variables = {})`` | This will render the row (the field's label, errors and widget) of the given | +| | field, more information in :ref:`the Twig Form reference `. | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``form_rest(view, variables = {})`` | This will render all fields that have not yet been rendered, more | +| | information in :ref:`the Twig Form reference `. | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``csrf_token(intention)`` | This will render a CSRF token. Use this function if you want CSRF protection without | +| | creating a form | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``is_granted(role, object = null, field = null)`` | This will return ``true`` if the current user has the required role, more | +| | information in ":ref:`book-security-template`" | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``logout_path(key)`` | This will generate the relative logout URL for the given firewall | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``logout_url(key)`` | Equal to ``logout_path(...)`` but this will generate an absolute URL | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``path(name, parameters = {})`` | Get a relative URL for the given route, more information in | +| | ":ref:`book-templating-pages`". | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``url(name, parameters = {})`` | Equal to ``path(...)`` but it generates an absolute URL | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| ``expression(expression)`` | Creates an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` in Twig. See | +| | ":ref:`Template Expressions `". | ++-----------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ Filters ------- From 899bc4ef35493a83c0f0ad471d372f191ea7434f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 3 Apr 2014 15:44:52 +0200 Subject: [PATCH 0287/1181] fix literal --- cookbook/security/firewall_restriction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/firewall_restriction.rst b/cookbook/security/firewall_restriction.rst index b5ae292159d..e5379cbc310 100644 --- a/cookbook/security/firewall_restriction.rst +++ b/cookbook/security/firewall_restriction.rst @@ -65,7 +65,7 @@ matches the configured ``pattern``. )); The ``pattern`` is a regular expression. In this example, the firewall will only be -activated if the URL starts (due to the ``^`` regex character) with ``/admin`. If +activated if the URL starts (due to the ``^`` regex character) with ``/admin``. If the URL does not match this pattern, the firewall will not be activated and subsequent firewalls will have the opportunity to be matched for this request. From 456da2802373c6a6be0f719210ee791c5cf9e3ed Mon Sep 17 00:00:00 2001 From: Stefano Sala Date: Sat, 11 Jan 2014 10:41:56 +0100 Subject: [PATCH 0288/1181] [Form] Deprecated max_length and pattern options --- book/forms.rst | 6 +++--- reference/forms/twig_reference.rst | 6 ++++-- reference/forms/types/email.rst | 2 +- reference/forms/types/form.rst | 4 ++-- reference/forms/types/options/max_length.rst.inc | 12 +++++++++--- reference/forms/types/options/pattern.rst.inc | 5 +++++ reference/forms/types/password.rst | 2 +- reference/forms/types/search.rst | 2 +- reference/forms/types/text.rst | 2 +- reference/forms/types/textarea.rst | 2 +- reference/forms/types/url.rst | 2 +- 11 files changed, 29 insertions(+), 16 deletions(-) diff --git a/book/forms.rst b/book/forms.rst index c21c44f6d68..0f318b3be0c 100644 --- a/book/forms.rst +++ b/book/forms.rst @@ -707,8 +707,8 @@ the correct values of a number of field options. (i.e. is the field ``nullable``). This is very useful, as your client-side validation will automatically match your validation rules. -* ``max_length``: If the field is some sort of text field, then the ``max_length`` - option can be guessed from the validation constraints (if ``Length`` or +* ``maxlength``: If the field is some sort of text field, then the ``maxlength`` + option attribute can be guessed from the validation constraints (if ``Length`` or ``Range`` is used) or from the Doctrine metadata (via the field's length). .. note:: @@ -719,7 +719,7 @@ the correct values of a number of field options. If you'd like to change one of the guessed values, you can override it by passing the option in the options field array:: - ->add('task', null, array('max_length' => 4)) + ->add('task', null, array('attr' => array('maxlength' => 4))) .. index:: single: Forms; Rendering in a template diff --git a/reference/forms/twig_reference.rst b/reference/forms/twig_reference.rst index 0bd5d8d6771..fc19dc08b11 100644 --- a/reference/forms/twig_reference.rst +++ b/reference/forms/twig_reference.rst @@ -350,9 +350,11 @@ object: | ``required`` | If ``true``, a ``required`` attribute is added to the field to activate HTML5 | | | validation. Additionally, a ``required`` class is added to the label. | +------------------------+-------------------------------------------------------------------------------------+ -| ``max_length`` | Adds a ``maxlength`` HTML attribute to the element. | +| ``max_length`` | Adds a ``maxlength`` HTML attribute to the element. (deprecated as of 2.5, to be | +| | removed in 3.0, use ``attr["maxlength"]`` instead) | +------------------------+-------------------------------------------------------------------------------------+ -| ``pattern`` | Adds a ``pattern`` HTML attribute to the element. | +| ``pattern`` | Adds a ``pattern`` HTML attribute to the element. (deprecated as of 2.5, to be | +| | removed in 3.0, use ``attr["pattern"]`` instead) | +------------------------+-------------------------------------------------------------------------------------+ | ``label`` | The string label that will be rendered. | +------------------------+-------------------------------------------------------------------------------------+ diff --git a/reference/forms/types/email.rst b/reference/forms/types/email.rst index 33908563a9a..e03177a47e1 100644 --- a/reference/forms/types/email.rst +++ b/reference/forms/types/email.rst @@ -10,7 +10,7 @@ The ``email`` field is a text field that is rendered using the HTML5 +-------------+---------------------------------------------------------------------+ | Rendered as | ``input`` ``email`` field (a text box) | +-------------+---------------------------------------------------------------------+ -| Inherited | - `max_length`_ | +| Inherited | - `max_length`_ (deprecated as of 2.5) | | options | - `empty_data`_ | | | - `required`_ | | | - `label`_ | diff --git a/reference/forms/types/form.rst b/reference/forms/types/form.rst index 38416d12aa9..8aedffb86f7 100644 --- a/reference/forms/types/form.rst +++ b/reference/forms/types/form.rst @@ -20,7 +20,7 @@ on all types for which ``form`` is the parent type. | | - `trim`_ | | | - `mapped`_ | | | - `property_path`_ | -| | - `max_length`_ | +| | - `max_length`_ (deprecated as of 2.5) | | | - `by_reference`_ | | | - `error_bubbling`_ | | | - `inherit_data`_ | @@ -29,7 +29,7 @@ on all types for which ``form`` is the parent type. | | - `invalid_message_parameters`_ | | | - `extra_fields_message`_ | | | - `post_max_size_message`_ | -| | - `pattern`_ | +| | - `pattern`_ (deprecated as of 2.5) | +-----------+--------------------------------------------------------------------+ | Inherited | - `block_name`_ | | options | - `disabled`_ | diff --git a/reference/forms/types/options/max_length.rst.inc b/reference/forms/types/options/max_length.rst.inc index d20d44e1199..85874698d15 100644 --- a/reference/forms/types/options/max_length.rst.inc +++ b/reference/forms/types/options/max_length.rst.inc @@ -1,10 +1,16 @@ +.. caution:: + + The ``max_length`` option has been deprecated and will be removed in 3.0. + Instead, use the ``attr`` option by setting it to an array with a ``maxlength`` key. + max_length ~~~~~~~~~~ **type**: ``integer`` **default**: ``null`` -If this option is not null, an attribute ``maxlength`` is added, which -is used by some browsers to limit the amount of text in a field. +If this option is not null, an attribute ``maxlength`` is added, which +is used by some browsers to limit the amount of text in a field. -This is just a browser validation, so data must still be validated +This is just a browser validation, so data must still be validated server-side. + diff --git a/reference/forms/types/options/pattern.rst.inc b/reference/forms/types/options/pattern.rst.inc index d1ff3aea732..65c3870961a 100644 --- a/reference/forms/types/options/pattern.rst.inc +++ b/reference/forms/types/options/pattern.rst.inc @@ -1,3 +1,8 @@ +.. caution:: + + The ``pattern`` option has been deprecated and will be removed in 3.0. + Instead, use the ``attr`` option by setting it to an array with a ``pattern`` key. + pattern ~~~~~~~ diff --git a/reference/forms/types/password.rst b/reference/forms/types/password.rst index 12ed8b17d77..fa9df3f3b12 100644 --- a/reference/forms/types/password.rst +++ b/reference/forms/types/password.rst @@ -11,7 +11,7 @@ The ``password`` field renders an input password text box. +-------------+------------------------------------------------------------------------+ | Options | - `always_empty`_ | +-------------+------------------------------------------------------------------------+ -| Inherited | - `max_length`_ | +| Inherited | - `max_length`_ (deprecated as of 2.5) | | options | - `empty_data`_ | | | - `required`_ | | | - `label`_ | diff --git a/reference/forms/types/search.rst b/reference/forms/types/search.rst index 9ff7b9d8393..cc1ceeccb8d 100644 --- a/reference/forms/types/search.rst +++ b/reference/forms/types/search.rst @@ -12,7 +12,7 @@ Read about the input search field at `DiveIntoHTML5.info`_ +-------------+----------------------------------------------------------------------+ | Rendered as | ``input search`` field | +-------------+----------------------------------------------------------------------+ -| Inherited | - `max_length`_ | +| Inherited | - `max_length`_ (deprecated as of 2.5) | | options | - `empty_data`_ | | | - `required`_ | | | - `label`_ | diff --git a/reference/forms/types/text.rst b/reference/forms/types/text.rst index 675b1f800ae..c61de693ab9 100644 --- a/reference/forms/types/text.rst +++ b/reference/forms/types/text.rst @@ -9,7 +9,7 @@ The text field represents the most basic input text field. +-------------+--------------------------------------------------------------------+ | Rendered as | ``input`` ``text`` field | +-------------+--------------------------------------------------------------------+ -| Inherited | - `max_length`_ | +| Inherited | - `max_length`_ (deprecated as of 2.5) | | options | - `empty_data`_ | | | - `required`_ | | | - `label`_ | diff --git a/reference/forms/types/textarea.rst b/reference/forms/types/textarea.rst index da27d4e9efb..0963abadbad 100644 --- a/reference/forms/types/textarea.rst +++ b/reference/forms/types/textarea.rst @@ -9,7 +9,7 @@ Renders a ``textarea`` HTML element. +-------------+------------------------------------------------------------------------+ | Rendered as | ``textarea`` tag | +-------------+------------------------------------------------------------------------+ -| Inherited | - `max_length`_ | +| Inherited | - `max_length`_ (deprecated as of 2.5) | | options | - `empty_data`_ | | | - `required`_ | | | - `label`_ | diff --git a/reference/forms/types/url.rst b/reference/forms/types/url.rst index 44a68d68218..ecd29752cb0 100644 --- a/reference/forms/types/url.rst +++ b/reference/forms/types/url.rst @@ -13,7 +13,7 @@ have a protocol. +-------------+-------------------------------------------------------------------+ | Options | - `default_protocol`_ | +-------------+-------------------------------------------------------------------+ -| Inherited | - `max_length`_ | +| Inherited | - `max_length`_ (deprecated as of 2.5) | | options | - `empty_data`_ | | | - `required`_ | | | - `label`_ | From 612ab9b3af1715ed5b6c5b9837a7e463d4072bf6 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 3 Apr 2014 15:48:13 +0200 Subject: [PATCH 0289/1181] add missing toctree entry for the firewall restriction article --- cookbook/security/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/cookbook/security/index.rst b/cookbook/security/index.rst index 40b0edd297c..ebb0ae4db6a 100644 --- a/cookbook/security/index.rst +++ b/cookbook/security/index.rst @@ -12,6 +12,7 @@ Security acl acl_advanced force_https + firewall_restriction host_restriction form_login securing_services From efbe0f3b04de19385f7e50d0a63f0a25c8e22e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gildas=20Qu=C3=A9m=C3=A9ner?= Date: Thu, 3 Apr 2014 16:43:52 +0200 Subject: [PATCH 0290/1181] Fixed a typo --- cookbook/request/mime_type.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/request/mime_type.rst b/cookbook/request/mime_type.rst index 6879407da8c..11851c02031 100644 --- a/cookbook/request/mime_type.rst +++ b/cookbook/request/mime_type.rst @@ -21,7 +21,7 @@ and corresponding MIME type. Configure your New Format ------------------------- -The FrameworkBundle registers a subscriber that will add formats to incomming requests. +The FrameworkBundle registers a subscriber that will add formats to incoming requests. All you have to do is to configure the ``jsonp`` format: From f02fb35775fcc8e23628cdc8ada87d9c6a40d29b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 7 Apr 2014 22:56:39 +0200 Subject: [PATCH 0291/1181] [Book][Internals] add description for the kernel.finish_request event --- book/internals.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/book/internals.rst b/book/internals.rst index cf204094287..2a63680c766 100644 --- a/book/internals.rst +++ b/book/internals.rst @@ -364,6 +364,19 @@ The FrameworkBundle registers several listeners: Read more on the :ref:`kernel.response event `. +.. index:: + single: Event; kernel.finish_request + +``kernel.finish_request`` Event +............................... + +*Event Class*: :class:`Symfony\\Component\\HttpKernel\\Event\\FinishRequestEvent` + +The purpose of this event is to to handle tasks that should be performed after +the request has been handled but that do not need to modify the response. +Event listeners for the ``kernel.finish_request`` event are called in both +successful and exception cases. + .. index:: single: Event; kernel.terminate From 0127bd24ccd3face99a94de0aa96f96deac7a47e Mon Sep 17 00:00:00 2001 From: bfgasparin Date: Mon, 7 Apr 2014 19:28:54 -0300 Subject: [PATCH 0292/1181] Updated event_listener.rst Updated event_listener.rst to use the new KernelEvent::isMasterRequest method --- cookbook/service_container/event_listener.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/service_container/event_listener.rst b/cookbook/service_container/event_listener.rst index 0676ca4479a..0aa7da76fd5 100644 --- a/cookbook/service_container/event_listener.rst +++ b/cookbook/service_container/event_listener.rst @@ -115,7 +115,7 @@ done as follow:: { public function onKernelRequest(GetResponseEvent $event) { - if (HttpKernel::MASTER_REQUEST != $event->getRequestType()) { + if (false === $event->isMasterRequest()) { // don't do anything if it's not the master request return; } From 8e8b8a00d04222aafe6e27c394998673ba2194ac Mon Sep 17 00:00:00 2001 From: bfgasparin Date: Tue, 8 Apr 2014 17:15:42 -0300 Subject: [PATCH 0293/1181] Added Versionadded directive to event_listener.rst Added missing Versionadded directive to event_listener.rst --- cookbook/service_container/event_listener.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cookbook/service_container/event_listener.rst b/cookbook/service_container/event_listener.rst index 0aa7da76fd5..c37edc0a0ce 100644 --- a/cookbook/service_container/event_listener.rst +++ b/cookbook/service_container/event_listener.rst @@ -124,6 +124,10 @@ done as follow:: } } +.. versionadded:: 2.4 + The ``isMasterRequest()`` method was introduced in Symfony 2.4. + Prior, the ``getRequestType()`` method must be used. + .. tip:: Two types of request are available in the :class:`Symfony\\Component\\HttpKernel\\HttpKernelInterface` From a6b17a00297b1315604459883429f9953ce708c4 Mon Sep 17 00:00:00 2001 From: Bruno Ferme Gasparin Date: Thu, 10 Apr 2014 02:25:04 -0300 Subject: [PATCH 0294/1181] Added KernelEvent::isMasterRequest method reference --- book/internals.rst | 13 ++++++++++--- components/http_kernel/introduction.rst | 10 +++++++--- cookbook/service_container/event_listener.rst | 10 +++++----- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/book/internals.rst b/book/internals.rst index cf204094287..829120a3047 100644 --- a/book/internals.rst +++ b/book/internals.rst @@ -208,6 +208,10 @@ processing must only occur on the master request). Events ~~~~~~ +.. versionadded:: 2.4 + The ``isMasterRequest()`` method was introduced in Symfony 2.4. + Prior, the ``getRequestType()`` method must be used. + Each event thrown by the Kernel is a subclass of :class:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent`. This means that each event has access to the same basic information: @@ -216,22 +220,25 @@ each event has access to the same basic information: - returns the *type* of the request (``HttpKernelInterface::MASTER_REQUEST`` or ``HttpKernelInterface::SUB_REQUEST``); +* :method:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent::isMasterRequest` + - checks if it is a master request; + * :method:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent::getKernel` - returns the Kernel handling the request; * :method:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent::getRequest` - returns the current ``Request`` being handled. -``getRequestType()`` +``IsMasterRequest()`` .................... -The ``getRequestType()`` method allows listeners to know the type of the +The ``isMasterRequest()`` method allows listeners to check the type of the request. For instance, if a listener must only be active for master requests, add the following code at the beginning of your listener method:: use Symfony\Component\HttpKernel\HttpKernelInterface; - if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { + if (!$event->isMasterRequest()) { // return immediately return; } diff --git a/components/http_kernel/introduction.rst b/components/http_kernel/introduction.rst index 5ab8e5c729b..d486630fc3b 100644 --- a/components/http_kernel/introduction.rst +++ b/components/http_kernel/introduction.rst @@ -665,12 +665,16 @@ argument as follows:: $response = $kernel->handle($request, HttpKernelInterface::SUB_REQUEST); // do something with this response +.. versionadded:: 2.4 + The ``isMasterRequest()`` method was introduced in Symfony 2.4. + Prior, the ``getRequestType()`` method must be used. + This creates another full request-response cycle where this new ``Request`` is transformed into a ``Response``. The only difference internally is that some listeners (e.g. security) may only act upon the master request. Each listener is passed some sub-class of :class:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent`, -whose :method:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent::getRequestType` -can be used to figure out if the current request is a "master" or "sub" request. +whose :method:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent::isMasterRequest` +can be used to check if the current request is a "master" or "sub" request. For example, a listener that only needs to act on the master request may look like this:: @@ -680,7 +684,7 @@ look like this:: public function onKernelRequest(GetResponseEvent $event) { - if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { + if (!$event->isMasterRequest()) { return; } diff --git a/cookbook/service_container/event_listener.rst b/cookbook/service_container/event_listener.rst index c37edc0a0ce..4e61fdbff92 100644 --- a/cookbook/service_container/event_listener.rst +++ b/cookbook/service_container/event_listener.rst @@ -100,6 +100,10 @@ using a special "tag": Request events, checking types ------------------------------ +.. versionadded:: 2.4 + The ``isMasterRequest()`` method was introduced in Symfony 2.4. + Prior, the ``getRequestType()`` method must be used. + A single page can make several requests (one master request, and then multiple sub-requests), which is why when working with the ``KernelEvents::REQUEST`` event, you might need to check the type of the request. This can be easily @@ -115,7 +119,7 @@ done as follow:: { public function onKernelRequest(GetResponseEvent $event) { - if (false === $event->isMasterRequest()) { + if (!$event->isMasterRequest()) { // don't do anything if it's not the master request return; } @@ -124,10 +128,6 @@ done as follow:: } } -.. versionadded:: 2.4 - The ``isMasterRequest()`` method was introduced in Symfony 2.4. - Prior, the ``getRequestType()`` method must be used. - .. tip:: Two types of request are available in the :class:`Symfony\\Component\\HttpKernel\\HttpKernelInterface` From f4ee337449ca7c19d1ebd09083e99e1a91bd5e38 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Thu, 3 Apr 2014 14:41:33 +0200 Subject: [PATCH 0295/1181] [Console] Add documentation for QuestionHelper --- components/console/helpers/dialoghelper.rst | 9 + components/console/helpers/index.rst | 1 + components/console/helpers/map.rst.inc | 1 + components/console/helpers/questionhelper.rst | 263 ++++++++++++++++++ 4 files changed, 274 insertions(+) create mode 100644 components/console/helpers/questionhelper.rst diff --git a/components/console/helpers/dialoghelper.rst b/components/console/helpers/dialoghelper.rst index 334b53ef86f..c84724d66b2 100644 --- a/components/console/helpers/dialoghelper.rst +++ b/components/console/helpers/dialoghelper.rst @@ -4,6 +4,13 @@ Dialog Helper ============= +.. caution:: + + The Dialog Helper was deprecated in Symfony 2.5 and will be removed in + Symfony 3.0. You should now use the + :doc:`Question Helper ` instead, + which is simpler to use. + The :class:`Symfony\\Component\\Console\\Helper\\DialogHelper` provides functions to ask the user for more information. It is included in the default helper set, which you can get by calling @@ -149,6 +156,8 @@ You can also ask and validate a hidden response:: if (trim($value) == '') { throw new \Exception('The password can not be empty'); } + + return $value; }; $password = $dialog->askHiddenResponseAndValidate( diff --git a/components/console/helpers/index.rst b/components/console/helpers/index.rst index 357b4bc071d..d632eeeb66a 100644 --- a/components/console/helpers/index.rst +++ b/components/console/helpers/index.rst @@ -11,6 +11,7 @@ The Console Helpers formatterhelper progressbar progresshelper + questionhelper table tablehelper diff --git a/components/console/helpers/map.rst.inc b/components/console/helpers/map.rst.inc index ff746b14a78..b9a1114cfc2 100644 --- a/components/console/helpers/map.rst.inc +++ b/components/console/helpers/map.rst.inc @@ -2,5 +2,6 @@ * :doc:`/components/console/helpers/formatterhelper` * :doc:`/components/console/helpers/progressbar` * :doc:`/components/console/helpers/progresshelper` +* :doc:`/components/console/helpers/questionhelper` * :doc:`/components/console/helpers/table` * :doc:`/components/console/helpers/tablehelper` diff --git a/components/console/helpers/questionhelper.rst b/components/console/helpers/questionhelper.rst new file mode 100644 index 00000000000..0f1031392c1 --- /dev/null +++ b/components/console/helpers/questionhelper.rst @@ -0,0 +1,263 @@ +.. index:: + single: Console Helpers; Question Helper + +Question Helper +=============== + +.. versionadded:: 2.5 + The Question Helper was introduced in Symfony 2.5. + +The :class:`Symfony\\Component\\Console\\Helper\\QuestionHelper` provides +functions to ask the user for more information. It is included in the default +helper set, which you can get by calling +:method:`Symfony\\Component\\Console\\Command\\Command::getHelperSet`:: + + $helper = $this->getHelperSet()->get('question'); + +The Question Helper has a single method +:method:`Symfony\\Component\\Console\\Command\\Command::ask` that needs an +:class:`Symfony\\Component\\Console\\Output\\InputInterface` instance as the +first argument, an :class:`Symfony\\Component\\Console\\Output\\OutputInterface` +instance as the second argument and a +:class:`Symfony\\Component\\Console\\Question\\Question` as last argument. + +Asking the User for Confirmation +-------------------------------- + +Suppose you want to confirm an action before actually executing it. Add +the following to your command:: + + use Symfony\Component\Console\Question\ConfirmationQuestion; + // ... + + $helper = $this->getHelperSet()->get('question'); + $question = new ConfirmationQuestion('Continue with this action?', false); + + if (!$helper->ask($input, $output, $question)) { + return; + } + +In this case, the user will be asked "Continue with this action?". If the user +answers with ``y`` it returns ``true`` or ``false`` if they answer with ``n``. +The second argument to +:method:`Symfony\\Component\\Console\\Question\\ConfirmationQuestion::__construct` +is the default value to return if the user doesn't enter any input. Any other +input will ask the same question again. + +Asking the User for Information +------------------------------- + +You can also ask a question with more than a simple yes/no answer. For instance, +if you want to know a bundle name, you can add this to your command:: + + use Symfony\Component\Console\Question\Question; + // ... + + $question = new Question('Please enter the name of the bundle', 'AcmeDemoBundle'); + + $bundle = $helper->ask($input, $output, $question); + +The user will be asked "Please enter the name of the bundle". They can type +some name which will be returned by the +:method:`Symfony\\Component\\Console\\Helper\\QuestionHelper::ask` method. +If they leave it empty, the default value (``AcmeDemoBundle`` here) is returned. + +Let the User Choose from a List of Answers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you have a predefined set of answers the user can choose from, you +could use a :class:`Symfony\\Component\\Console\\Question\\ChoiceQuestion` +which makes sure that the user can only enter a valid string +from a predefined list:: + + use Symfony\Component\Console\Question\ChoiceQuestion; + // ... + + $helper = $app->getHelperSet()->get('question'); + $question = new ChoiceQuestion( + 'Please select your favorite color (defaults to red)', + array('red', 'blue', 'yellow'), + 'red' + ); + $question->setErrorMessage('Color %s is invalid.'); + + $color = $helper->ask($input, $output, $question); + $output->writeln('You have just selected: '.$color); + + // ... do something with the color + +The option which should be selected by default is provided with the third +argument of the constructor. The default is ``null``, which means that no +option is the default one. + +If the user enters an invalid string, an error message is shown and the user +is asked to provide the answer another time, until they enter a valid string +or reach the maximum number of attempts. The default value for the maximum number +of attempts is ``null``, which means infinite number attempts. You can define +your own error message using +:method:`Symfony\\Component\\Console\\Question\\ChoiceQuestion::setErrorMessage`. + +Multiple Choices +................ + +Sometimes, multiple answers can be given. The ``ChoiceQuestion`` provides this +feature using comma separated values. This is disabled by default, to enable +this use :method:`Symfony\\Component\\Console\\Question\\ChoiceQuestion::setMultiselect`:: + + use Symfony\Component\Console\Question\ChoiceQuestion; + // ... + + $helper = $app->getHelperSet()->get('question'); + $question = new ChoiceQuestion( + 'Please select your favorite color (defaults to red)', + array('red', 'blue', 'yellow'), + 'red' + ); + $question->setMultiselect(true); + + $colors = $helper->ask($input, $output, $question); + $output->writeln('You have just selected: ' . implode(', ', $colors)); + +Now, when the user enters ``1,2``, the result will be: +``You have just selected: blue, yellow``. + +Autocompletion +~~~~~~~~~~~~~~ + +You can also specify an array of potential answers for a given question. These +will be autocompleted as the user types:: + + use Symfony\Component\Console\Question\Question; + // ... + + $bundles = array('AcmeDemoBundle', 'AcmeBlogBundle', 'AcmeStoreBundle'); + $question = new Question('Please enter the name of a bundle', 'FooBundle'); + $question->setAutocompleterValues($bundles); + + $name = $helper->ask($input, $output, $question); + +Hiding the User's Response +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can also ask a question and hide the response. This is particularly +convenient for passwords:: + + use Symfony\Component\Console\Question\Question; + // ... + + $question = new Question('What is the database password?'); + $question->setHidden(true); + $question->setHiddenFallback(false); + + $password = $helper->ask($input, $output, $question); + +.. caution:: + + When you ask for a hidden response, Symfony will use either a binary, change + stty mode or use another trick to hide the response. If none is available, + it will fallback and allow the response to be visible unless you set this + behavior to ``false`` using + :method:`Symfony\\Component\\Console\\Question\\Question::setHiddenFallback` + like in the example above. In this case, a ``RuntimeException`` + would be thrown. + +Validating the Answer +--------------------- + +You can even validate the answer. For instance, in a previous example you asked +for the bundle name. Following the Symfony naming conventions, it should +be suffixed with ``Bundle``. You can validate that by using the +:method:`Symfony\\Component\\Console\\Question\\Question::setValidator` +method:: + + use Symfony\Component\Console\Question\Question; + // ... + + $question = new Question('Please enter the name of the bundle', 'AcmeDemoBundle'); + $question->setValidator(function ($answer) { + if ('Bundle' !== substr($answer, -6)) { + throw new \RuntimeException( + 'The name of the bundle should be suffixed with \'Bundle\'' + ); + } + return $answer; + }); + $question->setMaxAttempts(2); + + $name = $helper->ask($input, $output, $question); + +The ``$validator`` is a callback which handles the validation. It should +throw an exception if there is something wrong. The exception message is displayed +in the console, so it is a good practice to put some useful information in it. The +callback function should also return the value of the user's input if the validation +was successful. + +You can set the max number of times to ask with the +:method:`Symfony\\Component\\Console\\Question\\Question::setMaxAttempts` method. +If you reach this max number it will use the default value. Using ``null`` means +the amount of attempts is infinite. The user will be asked as long as they provide an +invalid answer and will only be able to proceed if their input is valid. + +Validating a Hidden Response +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can also use a validator with a hidden question:: + + use Symfony\Component\Console\Question\Question; + // ... + + $helper = $this->getHelperSet()->get('question'); + + $question = new Question('Please enter your password'); + $question->setValidator(function ($value) { + if (trim($value) == '') { + throw new \Exception('The password can not be empty'); + } + + return $value; + }); + $question->setHidden(true); + $question->setMaxAttempts(20); + + $password = $helper->ask($input, $output, $question); + + +Testing a Command that Expects Input +------------------------------------ + +If you want to write a unit test for a command which expects some kind of input +from the command line, you need to set the helper input stream:: + + use Symfony\Component\Console\Helper\QuestionHelper; + use Symfony\Component\Console\Helper\HelperSet; + use Symfony\Component\Console\Tester\CommandTester; + + // ... + public function testExecute() + { + // ... + $commandTester = new CommandTester($command); + + $helper = $command->getHelper('question'); + $helper->setInputStream($this->getInputStream('Test\\n')); + // Equals to a user inputting "Test" and hitting ENTER + // If you need to enter a confirmation, "yes\n" will work + + $commandTester->execute(array('command' => $command->getName())); + + // $this->assertRegExp('/.../', $commandTester->getDisplay()); + } + + protected function getInputStream($input) + { + $stream = fopen('php://memory', 'r+', false); + fputs($stream, $input); + rewind($stream); + + return $stream; + } + +By setting the input stream of the ``QuestionHelper``, you imitate what the +console would do internally with all user input through the cli. This way +you can test any user interaction (even complex ones) by passing an appropriate +input stream. From 1705231f31b0120ab40f0a7dfb1cb1fc834dc7cc Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Thu, 3 Apr 2014 15:53:10 +0200 Subject: [PATCH 0296/1181] [Console] Add Process Helper documentation --- components/console/helpers/index.rst | 1 + components/console/helpers/map.rst.inc | 1 + components/console/helpers/processhelper.rst | 56 ++++++++++++++++++ .../console/process-helper-debug.png | Bin 0 -> 28822 bytes .../console/process-helper-error-debug.png | Bin 0 -> 19108 bytes .../console/process-helper-verbose.png | Bin 0 -> 14289 bytes 6 files changed, 58 insertions(+) create mode 100644 components/console/helpers/processhelper.rst create mode 100644 images/components/console/process-helper-debug.png create mode 100644 images/components/console/process-helper-error-debug.png create mode 100644 images/components/console/process-helper-verbose.png diff --git a/components/console/helpers/index.rst b/components/console/helpers/index.rst index 357b4bc071d..7fcfe78fd4b 100644 --- a/components/console/helpers/index.rst +++ b/components/console/helpers/index.rst @@ -9,6 +9,7 @@ The Console Helpers dialoghelper formatterhelper + processhelper progressbar progresshelper table diff --git a/components/console/helpers/map.rst.inc b/components/console/helpers/map.rst.inc index ff746b14a78..fbf2e8e8602 100644 --- a/components/console/helpers/map.rst.inc +++ b/components/console/helpers/map.rst.inc @@ -1,5 +1,6 @@ * :doc:`/components/console/helpers/dialoghelper` * :doc:`/components/console/helpers/formatterhelper` +* :doc:`/components/console/helpers/processhelper` * :doc:`/components/console/helpers/progressbar` * :doc:`/components/console/helpers/progresshelper` * :doc:`/components/console/helpers/table` diff --git a/components/console/helpers/processhelper.rst b/components/console/helpers/processhelper.rst new file mode 100644 index 00000000000..f9fd141ffcd --- /dev/null +++ b/components/console/helpers/processhelper.rst @@ -0,0 +1,56 @@ +.. index:: + single: Console Helpers; Process Helper + +Process Helper +============== + +.. versionadded:: 2.5 + The Process Helper was introduced in Symfony 2.5. + +The Process Helper shows processes as they're running and reports +useful information about process status. + +To display process details, use the :class:`Symfony\\Component\\Console\\Helper\\ProcessHelper` +and run your command with verbosity. For example, running the following code with +a very verbose verbosity (e.g. -vv):: + + use Symfony\Component\Process\ProcessBuilder; + + $helper = $this->getHelperSet()->get('process'); + $process = ProcessBuilder::create(array('figlet', 'Symfony'))->getProcess(); + + $helper->run($output, $process); + +will result in this output: + +.. image:: /images/components/console/process-helper-verbose.png + +It will result in more detailed output with debug verbosity (e.g. -vvv): + +.. image:: /images/components/console/process-helper-debug.png + +In case the process fails, debugging is easier: + +.. image:: /images/components/console/process-helper-error-debug.png + +There are three ways to use the process helper: using a command line string, an array +of arguments that would be escaped or a :class:`Symfony\\Component\\Process\\Process` +object. + +You can display a customized error message using the third argument of the +:method:`Symfony\\Component\\Console\\Helper\\ProcessHelper::run` method:: + + $helper->run($output, $process, 'The process failed :('); + +A custom process callback can be passed as fourth argument, refer to the +:doc:`Process Component ` for callback documentation:: + + use Symfony\Component\Process\Process; + + $helper->run($output, $process, 'The process failed :(', function ($type, $data) { + if (Process::ERR === $type) { + // do something with the stderr output + } else { + // do something with the stdout + } + }); diff --git a/images/components/console/process-helper-debug.png b/images/components/console/process-helper-debug.png new file mode 100644 index 0000000000000000000000000000000000000000..282e1336389762bb88f5fa6d61d4669066c483de GIT binary patch literal 28822 zcmce-bx>SS@Gpu63j}vxEZE|1!QI{6-JKAe;1V2y2lwC*Jh;0BcXxkF^0nW6_tvX= zf84D@)$W`#Ju`i}r$7DaAxvIY3=tj|9t;c&Q9@i;5ey7s0SpYB0~P|*vcKD94+i#D z&_YN^UP4HSSl-dj)WX^X3``ucOwCPQX%_GKSR8@`4uA}fV*pgRPH2UOP7x#sB#U7% zgoVPmp(@iS_{L$cTuZ%P3>m|P?4X5S?}A=OMODXPpMB2F{`TS0;^kqPXJ?81^*cl(57sQi&v*>#b-<@PG{wo=2pEBnZ1*TXFkulkKR7rro@UK1rhQcC zwTeloH;o zh=HI8W;w#wy69XY;vM)`FYs?wP!J-RV3g=*kE8~e;aw;shh%6HCa@KPb9z)L#8FNJ zYbYKbN+>hJ$kxoyn3M;0>cl^>!`~wtBd$Gbf6M-gNlh2C18@56`H{c5MVq`hX`e}m zS1KnoLd;D^xgL>IDfj)5pnE&5kv4577c5btBF@bQW*8F_oWVf5j5_isOE{ju)ljJH zaacU?U(zPBieq5kF{zLh?>0InI=^*;rx_fedEyBKuimM zCJvdI@g6Z+5WAJe+pLO=5!xURtpXTF5iOJ)VDI!n79!t2+^J3-Rq%|OD2OR@!aD3W zN?L>?5pYhT?g0&3w2rnd=)bRVAL>SvKqg8`7)fp@ygtSdIPMe%XQ(mpkx-Bn__knO z{<-H|d-_q7E6mZs7OE!=&{Fo5%E10GMNovaC$|ZOy$0Io+g&&d+URDGgR%@2?+M8p zL1OgVuflYY1%hniT21>+W9`0D9Iyi58pLnx8Jq*U;5zmpgGvl z^zL4v_|9+8;p5Jn(-Mrb@mtfNl}&x}XPm7P5qQ!~j3+s{b+2_|hc6rw>6B5ZEB&wA?SO;teFNF~1|zbPZHp&0&_}KHzYF z%IF?3Dw`uXB$)|o?c`gB8tHU#Fj~ST3i4X};Leg6D%V+a>fM5^7YOW`U01oaZNcOZ z)9beTWpnG)5&|X|@C(H>5U?f^h+HL%8!JH-$|?L_;e#@YSJ<1&@(L6iVXQO%ym;+6 zIj)>L90`h8L8h#9A$pS8cXa5yKC}DKFY&D#th#N~>%K}S!%QZ_2OQt$#OAO2Asi+bi6|dr%lJb1p{Nr505_-j~>^5ni zG|zy0lPlLN-2%4B;JrR+V^iiG=2@m2COPI4Mm;NY^JFV`tBBbc%b`j2k}AE8^j@LJ zceDgwcxeJzWAlyaOpf$ftB)&nYv!%3T#30Ob$;p&l$&N5^6R(n*mD9n74T8a=nLbN z1{()FvWv@NQV@b&|@ha`E!h%Cria#p*@s zwdBM`Wq=xXO}hCjjIC^h9W~n`XO13&?lA7`9z-EH?+|b)2*10}tr)0fgi2L+|K4f(G2u+Nw*te{)bjbu4A~pvfAl(qqpmNW4h+(%UOy<6Wo zpFK~zTQ(InjWw05p);j3ZQW+ume@uZx=C5B*VlB{FxD)sHm~0O&QgbO#W`5rd(KYd zLIb1;o5n4vQ9UWODODItF2i5MfG6SqPbfS zVZB>@(wy3Yp6d?+9{fBcJOWLzF;VyEn8KnKAWOl|wKcN8!qHWkF zoYXc`;R=&$JolO&T4%B^SZXB*3}%7M%HOWn3< zOSa8U%Y99LJ1d*d^IeldYgMzklamw7%T571bU>X7jtX+!ofeCgjuofYXivY>v(xvN zoWCxTDst_jPUu&o#@TXva_b{~56zA#PZ!r`w?}W}ZeGUQ>3+}(Aj@N%QjL+yqc`xL zTEytcyN(@y#p;ml2>;d9aU$p~Xd1#2jGB#-ou5r-z-1s|aL`2X3fUXe!aT8S>n6IKwg3I z@Mc*5bpMH>pwfWS0!2hBgI8yda+k7&r4KHEj?>0VbClg+we-2bC+DF%E{vUWUOJU; z@6ouczcD^qW;~rV*^wdROJ-af%~L$Fsyz8_f9Swm%sAa!lyVe4Ea-66Fs>fob;q+w z>Gq-Xp(xt+(nO7nI53HzJSkjK9iUGNK}sv{vN+xkvS+bqL%$)H{Lp(WIVdxv>v zXXwSnfAZ5gv>j#vt+l#wi}^}U->Rs$mQv??g@mR1k(=h>)%aDZb~}y3CimraV1CX7 zf{CmNhDp{J*d*=Sj=PXL{!6-H?S<+gqxpiZ%dP4yb~UKdIgN51UF~Q0t+~XylG_qV zwN?#YldC)U`tV_^WUBM&C3i%Effr-HnzaXVN6t?N(FWOOC$p zy7px(aRdEm?#phDTfAz$@^9*n)p!^@<*%BTPaYO{7NU6H`nc~Ybmlfk2SsPSD4g~c zUW>@h$x&yf@|7Li?{O^PtaxnAvyU!h4QAcACO#HD?F3_e2O>RT+|K47!z~{HF@O)c zbRIURo_%=r>@vI#yzf@FTaSFy?pJ<2jl9z(8u69ByRCIwpzJNI%R1s?_YQk@tN>P2 z$kEHgDtm!LT)CT4{3sy+J5;W9Yk>H%d70IyOsM|CiDF>=RpFA~{-rU3=_@bPAuN=5 zDh%=@Y$Y5kO`yiEtW7%_B)FRkfn{iR`6p>LEQ}xO@U^TStFt!?*dNEiPBq47XPc`k zPA=GL)!HG)l2`p^a$Aa+H>17bpDY4mpd=% z?d6CqUBG`9^haC2 zTS4mLgXaPMqk2AgYHAW~Ffaiy3E>aQ?%;>52;S(^%P)SWrfz7cs;IEDUlq`#!7-$! z1_1h6nhbT4_wv@(3J*f&XPrhKEdnUeWYM9!LcoG8k{N#3DdpNAMXQbwO$hWX!P+I| zK>65aC{$S5`Q^sP(Ge53>(u%FLsMXu&sHL@)5wkY=uOM0cAM8Ww;5~)43q%a|K_Sr z0n2sfvzwcFoBL~lm8r`!@c1Jb?CT{^fU3`2XS9p;``2qj6Y@vyIC=my_lG}{h>hTW z5cJPwi}d{^npg++2Z2OV?57N3Fo@SHrV8p;l=0zMj?v!@^ibA&hURfcwO3hI2WKX| znUwW3$m4V#e3yjDK&V6PV{DeiFN;d&$7jChR75|c*;Opty{WD04~pkQ-3lLmO6tfC zkk1otG`1MtYkwj02({O3nWEA*m#j{F(@WKlnazm|1`fL7p@td&Za&c&-T()$S_;li z6w-$NBD4wq7n0U{|1WYshf)qh1y{FIle(u1A@5l7sYoF1Hl)@|3SHt5x~H*>B;F*F z8ymTgBxj|x!*e?)LAI+AZV zqnai2iuj~tv&T4i^_;ZQz7HbriBM`Qy%|PKR81ILf@u5+tDqP|_Jl1()B$E{ab;Y}y*J^I?@5*j$&KID^@Jy@q!W1`?oRLfm_2?hZ#lH%M z8h<55DO!5}{rKD)38j1c#ghN~_$q8b z|GtTWgZic^s5J46=PrUSx-zf|Lw$`VV)*DqWm>sNgyZ4OYE!hmh;@BO>4oVRtM5O9 zCiI0L*!V=pS%`^#+c$9!ENI4$Ivls`XW8xFw0e@5onGSUj&5Jcf z54*z_7vFy%t8J9PQ!|G8$4w|VnCtBE zor@+1Z)irX>eB(9?K*r^%QhQkGNoD+XzO(ptVU^ameI8IT(jm-SE4A!=+pVTbzKPn z1i8@^RRJrt{n;IHR?GR2pBsHgx$h&4zdZmlH~C-6ceDj$LX7glqK0uU!Dh>nHFLbl zo-6G=i*`PLl+ey}9>{F>}JT{3yZ3CpErzSPZ-5<|byusTY?| z(|ovn^XkjU4AMU&-8RdsB2ZVUg&XBv^f9hPph$m??%6}mz2MUGOsB*|AmJiVn<5ao zT()I~9(DUBDhfC`UMx=2;26a(`0ntnH8U}Cs?|iTe;qJvc5Ou%P-Sc2V~u*&L&W?E z(9TYuOv`W6dMrK6w_C6n3V-gxbmV=>)vB+S%HrD@93jYZy3={P7M3tbb)k1i{P0z? z8EB~bJVw~a)({=s47BvvtdQ#a7DA<^YYcoMD%$H)@Gc^y=nDy@N$t*<%L#gSrxI0< z@%G{lr+e%3lFL}s=3==={87PmXn)BN&RoC|t71^^b4ln1K>Y2(djteddocxOxD=j4>C zUvHj!Pd;-Q_Qk&v$GiDm4pTSVT7^y%+61 zYk$Ic{&c;#$~L9&EPK3l6Rftw|5EnNIflSe?Qk5<;i)~JZ~E{#?dymL=TloK?d~s6 zXm0y!#eLBpM$twk=Qi;)_v6u(ZT`=MNrupqPY=uGEn0QrXHeYUS`WS<8Ij`VqS!kc2%3nycu^U#8i^_o{#gR z{YdYF09wpEeJ_wYJiUItFZptW=KQxC*K%!xdX}HHbGw#~-*I{-(kM>cZGpN}?d%%f z6s}&?;;S;v6RNbKV6-9cJrQS}?XxCt7x|2PZhC#>e2%WSDF2o1wwVwee{{Fel1+o( zDp`lWVyo(Sc{_8TGA%z2aXGF5z#xKj{5OJJN>WT@DSc+(es6MHkQ>} z?0J|dwG4){N;f}~2eVO+Xx`c9GxZbbVY>r|diwqM`a#ZnIyc7y*K#NA&bOn*DWLQ<+zo@QR?`9j?YqyNfnip~a&qExj_>@V+SnmgP+ z;J8w1Esb@s@*{1Hi}V0Zb?!UWhOS?-miUA$1bLWCp41P$L?CkxE)wmZ2!AOz4X;41 zPKs&%tfw}djnW>#@D^zuJC8i}YhA}$=hw45AmJymZVx_??MA4mJyDSi+0ng0SdH%j zZ5t~vP=3%CVegiRruDmyNk3BEJQQ z!&5rA&hw*OpBJWu76gRKtQ4q;-%vifh7AM98v!9eHcg%AkzMTZzK<8vVs$}Eqq|jJ zX_*`4PeJ%N6VZ4a176Ob+c{HX=*t_OPj@Uw8tLM0>F)TFxUNiU#XKX$1Ab#BY>Kg> z`PeblsL!j2x*fF2KYpCTs+m}p~_EzA5I|1tBR zX6t#8NEvPND2-Fdw>%BjqieAsie#~5A@7?n5 zvet8wdTyTN?B0H*Np_htgn>x%-kLc1UJ}10WM@_pJ4O z<%j7iAsdkm8{YQ(=Q~LL+Bj*-F9i1H_9~-me2oTAvJhG})2% zTC=KebVY-kNQLjftg;fl)0*@uc~1)8a&QF!k|fI8Jy}VvxRXORc~KN?z2j?&?0_+O zPQ6wrq!p`$70CWZJiHSng1CQnA^-#meIkJhTtdmQ@Dtz3>^#vYJ5l&IH2V{K1z~{>^D90@|u~>zy zr3wul<&ZCmY)4Du3H@c-SW0*<5y=ZsET#*9Q_8KDZSFZbE!aqcWEg)|FBBnAv|BgLD#LMM>694 z9;*Q>w*l-ZFeJ7 z`b;7HZtM(8+wYkMz?r{`b8h<#lQ;d6Kr#4kmkXxqA_T#SpBV8WuNmf!UgeUvwPFRx z*DA;*Dt<=1T|`thK=Aw}Ixl!v=0qKM{J_ON^*H3?JdOFK(#Ix=zXOHa;BX@UYGpFK zuQI6Je!?NeE?=Qw@zyrL6ZUA?J9 z#0S3=^JnJHpB?Z^0OgeZyu_NzCZ}6IH)L+8;GMUmatrPTU|$>Xt4f=lx9z_ZOk8@Q z3>V_al0wO#caabg$h(?dM>A z4f%KQ(Or&7ZUe@*p~~IzG#mw5L6Of_KA%DfJ2|FYE`8SNpKo(X>I=-vce?c&6|bHX zoY!pp#7J3?mov?4fG7!LrIR%+cO^%>lIC&!ci|fY6;NSt4?GW8Fk9V?C}Pp;Q*Rw! z{p_bE#2dddn6tB{>Cc2j_a6gmH)W3ep(ve3&GpJsYPx;QAf}(%V0|z*r=fFR97bKY zbbc79)kL$0ao6o0bRbe5w-1LsW92 zH&YUt@`a}`fY!jJ4R*EL?^$1e*}F9pp}AII7IUqZZ8#U6s&R4xGc{&RyA z2^1G0;KYpo)VoT>id{c)({r}7B%J`26f?#eBedse@JoHZS_Je`>b8z)wq;do4_YZlj#Q- zfWRNOggLiqEv#(pi8x~F++w;^@qTnT>(py4tcN1|q;yHn&3WE=t@zL+m67%ZR@K@V zG^iQ=RVvxah`sLFQiVGWA@}|SA(v;|@x6-fuXl67lW=%G|n;dDP8*S){74+K^@F7fX zXUO`hS?o-})NW-S64RP>F5+@W-M9SF%lq8L=1-LM0%fCW%jGWkMA@>A7$x^A%0>@u z13(d-zV=@9{+={tHuonWMEljOcDW#$#(K+{Nzt@a31M>lv-GOQ+n=A!eCpboR&DrG zem$sYD)m1RZZ!z{rew9L7$k+XkpOl0K_Z+9;N}oPyiErb19#llj%BJ^7Rk%`_|xbq zicG!9%#M1CDZG!CqvSWLqbng@My_2QdA73KS5z(eHa6p{9Y*X!^*TM^jLQd+jVyo8ez251H& z%>Hj)7g3q~@xB>2E;plYT?g)>Loi_ZLpby=Y6=YYCzO578*Yeys3|P8vEy*Nw(8G_ zRV{amd^OtS=%0Q=GEfh)Phh5Es2?!6{(u_Lt6L`qb0b4iM~42LU4jM^hXQW^gnfno zo3{dkZ~$>#s4%pl|CO>7D=Z%*`#V6sChQ!r&aODM4$@o56stn?x-qHs65L3=<1E7e zj3e+v>?_(aEOXlmTUFrNBXJ>$TzsW(+-boVC5F}S`cOI<@##7nKE<+wDs3f=ck%Ol zf$3U18Cz?aSwFAs(fHKKj0eAbTXaJx6Vu+fgJES>n5I)&dJ}2Jv;zFZMg%#N>k>J_Y2Jdce}G)IsWCt9{Yxp#eY54~4q)pS<1bda#I+1D$fAwC>u z^2w*)>wYg|AOQ83FN3tfLaA@+nipO|t~F&Gl`~X@k{*gek2d(6$j5dzh^{9* zuif45sw}~1Qg2lht_Y*T&1#0{N<#!FE$@3sSVO*z5DdscC&NG zR|RQ^f%6FS_qu=TL!31OHh-`wAR;uzrtxX^6{LE7)y_cTY?0s*mC~%c+0+@18iSiK z-a>p!xs$%+U%w8W+kyF)ryApdgB+p=jjjHDdNRrAf>}iT_7_Q zI-JN@zwEc2UK)hlM8?FyBR47%3cAi2#BiwRKWP@or;TaA(~6?nHM-vElC?XthctR* zZd`eI(oG!qbW)J#Drna!d0vZp4CDot==RIxS$*F|G0_bS$JeB2$*l-y`Dfq2L}l2C zih1ME!SfuJwGg}m#q1>2?6<8mhy0U=VOi@T+-G0Dmt@D`nSCC1A{%3+FhL^WV?%nA z_(EbjQW6_nQS$C^b#Y2f@f){cyJ+qS=GqfTcF-zxuUBO-qMq;Y!J$Od zzLKQN3SG3!kEsWT*=G$$5Oaq}D~iXJ_gx-ygtS^kXcQVb)uED*3FMCBYDT1$cn=ZA z5$@2PKZV?t%tEfeLJ-T{k}EoAkhc>#Q6PGR6oqm(mC)#Z?VQ%ke@0cY6=n($8}aeI zFKtC2uL9Glt@^+ROSVqcixTn#55*-X;DZ`$-Bx|kq$t&8la>F4xAM*J{N*+J!Gkl) z%?K+5S^w)_3_@VXp*WV`Apf>YeG<^VirE=R{m(PZpn^bhb}-jJ=7@>C$%Is0o`;c#b%^YXJXUwCOtGP%l=x||N5 zn(87=uTiJK{c9;>rgE{xv=>f*y8`EM&Yc7Xy|arHUl`I?cP+Xn$x5@xT8g&NhwACD zJH{wR%Fp;z3b&|NrPFr=_X@VE2A zgKnbo3%L~;4Hh~jlyUXzXQm8UgKi`{bDus z411r#h)Ogj77I38oveF{tc$F-%fMWr+CuPHpp-WMmz&jl#?le4jua;f%>ISc72T#z zuDUTOP%L4A;0TWo#zpiOFoR7_CU{TSg-IjxzebhGW@b}<$k0`Z>a=MCk=A0YW7?z> z;<`g^#ef(DnixSCSh5t*G|3>voQUr0ch0S+u#2xv*0_M$Yz`WT>q1S@9PmvWv|TFuz+`B-IV(~LRVAT}4|c?2I!G+Z-GO7f9bO3^7ptEF_@KXYXr(qL&j4 zYLPmAsE?KAi!txIRPCJ3LrnE$_GUW)PKyY9B52Mkj6 z_z(CtA3sim=Ab2melI|50k!TX_S4@c2N%;3!0uB!GGTe_@94s{c}j7HO=mH^67R;! zEl4RIpUBQ|9#^=z8AaBP0h~j!p+SDQe%{}~tJU@f*?!(TkY4wgRV&e%i;oT_}` zJ+D_TkBMTZO2sC{1gq9XC=*an1c?r9WnAqj)tUIZZ0qL2vZ?n?Ej$Ps;ecK+x6nJ6 z55&;0$xdS80S)?uFWquBT~41KetmI$8ETeytJ(PBY)fgZiqUxR% z-Y_sHGEr`RWN#7wt5?Q$xajUftoGHeSH-j@3$vmstCQ-qe&+?FP4$_X8{I?m21yCI zp0}ffJpcI-ypI;;x^u)0Rqa(WEG;6I zQ7qlzyq8?a%h;PNM+$fKAfnz@+id%am&@XUyw?Ml2(U4e>?~#uiPznO$HP9n)~3*V z+DE=3F>->5x1R@TU}KlDzO301QDh8rW0HRPX*W@m52b!ulEe-YY03&6E9w-A4K2fx zv(`+nB;zLY{^-!NWZ|!vT(bE)CV!Ed2o6|^4JJr)L!vzvy*{#GTK=%X3vaXR9A7|9 z(K%8+ZQ=cnQFg^W`gL{_4H>;|{^h*kLS6|=fDsOljks)HCO*`0^2igHUM====8Jp6 zjM_WY4W7v8SO=@2W`H9ew`CxKD6Ulk8>^+8eZ)^nr2^M$=fSk*zoR?wG^`*Ku*1ji zGh^FmJO|;7w=H{O9U65;7*t1C_5jx}_rKL5>8lp6sEYn*vCGrgn<_{0KU$>Tl|{$i zvG9(FNXzAe6Jpb|Xp!|4U%A%soP(qJD@`FjfJ^qMrZ~t3|2ql$_%RU_`PC)Rn*KrU z(x4Q}5CXUOpQKJ*0t6otS+WuS#uz_d(=v*$+3wBlzPoy?Zm)DEndPHQk; z1W7#Ya+mJ)i6T80eRma#i;524PvLK=BN|<7*>U6NtRE@%ua%U;Jj}`vP*J!#rRxcF zzqbBnB|hF{x8BtL$Lu{d!BWrP*67fe}ge9R3dI|UNJ_FxpvBGqun`OP#dm^jhES!+cF$6eXbFF+KEC> zphbL%BP^%(?cGA}NE?)T9ix@Ymu1IADwEOk*j>MUpoEjyNZsO~T}#iN)palHG7nmo z_L@||5aq><+{HJVFZAi0L+p;7UVTjy1QOYdlJ^b?fn6W>qD=5@H#(gckXE;p!x?&(iN=bfHe zcA_Fm>(vI@TdB&F?7XrXXD^mSt5i54G7fbH=RZiMCMDRR`np^o-x*7Ii=Lo7)kn7=Xm(NeHPj2FKJvB~oIiwxxZD0K)3oS33vHun5r{_xalw{)8 z{`RWapx=$q=jz*`dD6<+?LXOfK1W)y1U<||Sn4JQLK2lY~cYRd3e zydIF5@N_8-V#N*ATVF}?JQ8;(SttAhj7PPfJL(M6Ch{H2xymhqxz^4YSBN52UI-r< zUt)9m$jfIzS-Vk7jo|UEx=5w#f|XceR-B&KuQjHUTG#x{p#ufA36{m{{>h!`;$yTI zYle~@=hoh)Fr_bSb&b&ec-JR4d2#%Lm43m|`$L>)pEs8Z>XQmOm+Pi*ayLO{I(c*Y zL>AyA-2mt@nllU%M{6%t?K4GrSx_*Ef8We|cpM>H8L$b4dt2z6z#(8m*iPT0@7<~%Gm%Q%4{!==%Yofy(|9cM|C@UWsHL=Rz6S((`qB_p_`NFGRA!J5Q zudtAq#3K>Ll;aO9RM+MzPB30U z!2+uIK^?3`((Efb&gUv)=azFtDQ2IX9V_h7*n!}i_#ubVv!bS=MwPQoytRAppLIL- zeHvGQHNJV?i`KVUtaG=uTrM1sRAY-)V7t+&M<64&SRp_mrKLbMcC7zeRy#jeY2H6F z6mBuxLYO~10wsiq{B!+jlBk2)+T*HcDoh`dsFs!x5I5}eZWRqR)d++yf6x}ST4h=v z{-6c)L{28P?p(u}N=sXT-0dfaAcYRB@!m5|sJ;ydc^0>4l1lZ7^95Eno=EV9{L7}u z&ijHOXJW<^5_UyKEB&OQCUdzM!CR8>$#8*f0tbTicfyryv!hy5+3vFl#%tJj*=A0w zPspgCw44Brhr0`@9I3_*M7Ja*St+Sep@@@Wy3N)ZdpPzdu;O4&rh4#Jdyi#TBET6h zJ{Nt~f0D5j1-+NI^K7D?5c5lJydi-FAVUhReG1*zLSG%ggu?qju`v-%3=)SQ)n)kZ zR$Zi4M=F0C!TAk*Z88VMe68ObQuUiBY8QZdS07heFIDZ${L+m)Cfq{QDgg=1_b^NK zpOH(>Pt6v^jW7e#dof*U-9}UEszx7{Cqry?Jt_co@KBOvCtmVlFqJW!ff_UdEC*_gNhbk`OQ-3Tj>k}p*%5Ps znv+V69Diq#-Ha9HiVC5I6|x)^8}~fi)snl3K`m2(W8)JNd3T=3TqNgo zODKXXrQ^CyXf$~ibkXgJ*B*Fxm3z{vYSn)xt(GEp-bqLA_h>Oekloz(e;}OZGHYDI-K?OQ3*rctk{l)m)732RgqKulj^N^znQ?o906gRH z@tJ;=$6G3DGA-qlRXV5x<#?L5`bSViSqp(W(e#@z7uIuC9y>qQZH-rT z$s^bsrj}IM4kBc&1scbF`l}tHZKWgP=qs5`u1AG0TerqCeac){y!PvB4vh4pOQ=v> zUG)Xx`ly;%Q&w-Rx%`T=3ym)l$HjPfrEDLD9Ghth=rwKw4#LEuD8q^~06VyP3+8@9 zmi<|>-irLOD0M#Qd63{64~nx4#f6{8;DZ=4U7{(M`k6q#{F&n8aD>x^@MB> zLvH-v4FjNtyz|{3Y=3cPKj9(l#i|XH$0h!15I2F?UfnIZw8U594D7#&`HYpfZ8L#n zrOTN%@S|ypZA(YPdvSjBo$qBme`%>*WxCscz-ir~kIxufrYZqj*c>R^m#Lu4c2!;C zck28Ge1|*MTz_=PzwXmTIzqC*L2elFwMJ>DNwxtnbnCg;jT$^Dnj{U#q%e3QTa%$H z)NixtfDLAIaE-hv;-XW#E8pIhGkrjIw9Rn)65{1cy4WRis~;OfrzK0qOCp%knzC9` z&rBJ;xru>^i0?W$_keWrxV*kcLwkV-Ta?UTNM+48x60t=fSPibn*&D-rhH zt9B#D4Nhy*7(QLPy=@^appI0r^KHUsPb{W9N)QkBIXNfUPkHo*J+E)jd<=*0ZG1uQ zF#U%kD}(;XN!{l~pjkvsWtC2Ip*wlbGntB2C8rw@lB)hoRQY9k%c?$>8`_D^6~4 ziHkUD^j9Exl_U9iM3Roas7&U`%B3iAH%V;pGO;NSt&k-MJl0y0ptK@|zBiIkizksYfO8n~t^a)}2IIdgdViZZ%zrp^vU4ry8%O_Lx4lP{yfy#`WhcRq8)= z88mu_C-oJ-gTBh9AuOJT9Mk*o)MB;g#|H1D&m@|u&^atV#xC9koihMa2;9~$5uO1J3e=43{g#)lhJ$SX5l}gaJO^{hI^ZB#=!jBVZkhe(y)sF%JRU6WGQld5= zwJG6P4!Lvg0n1*!&D4sNX`(KmU91~rSL2s_Le^3%oq-de4bvV;Vu@I=Mgd}b8O1*k zNP#+KS^t&Jnk?o=5au+2gg&19YeCo;B6rYhk~MCx&&AeHuoXoR)a`sOr_mnNE!JM= z1E-=_%OLa{l|E4(sOzi<uE@8`vZJ6`vc~T!K*j zjc?YE!&b)O&!@SE!favhK^ttG*w?Bvge^AfkuCN}S?d~(5V9}8T0COVTM^7V5>sBy zxmEp6+z|Gmp2>1VY~5Ax8edgS#7Q@wZnL-_>(Xp0NWu`N+w%N2>cg++1DImBWd8Y; zyXjmbmOxUF;*3$vIeb-9i29pdYZL7T-X1`XkQj)^#5(_videbZe96BMs}@+c;B{VZ zDhB0NcK$}xBmH?3Nje=WH_XlIGNR&2X}^}hy^v&OAqG@n196*aZbb-EUmh3h(dy&S zMo5a9VT|KVD3(wZDXmp!z{y|n)&9Xz$$TNv+7$Z%E5b>6A_-e4C3>=~s~|7CE@%2c z^1#+LcLH)erU8xbh?}h+-c9b=R(NnO_e-#Q#z=>-4YD{L1l~S-3I8*^UHX;1h+#w* zCmEx5HmfYeA4IjruZTNfV4Jz)?$f++C1xX(u!lr?q)Th9D2dmj!d=%Njau%RZ!}HO zSDbkLFfd&dD>NABw$6gR{sF4s`8-x}OEl8{wru|DgUQ@$Y26J1=HR(O$wfSP%dK*+l#_=>06=pLPL<%0F8WKD|*V*cJZo+EK^B&5iKw4e~ z&)$iC_Tq!gBfS?Ig!EYNW+quS1b}DG0m}$;?a8=HFMeur(3pg{V=wPELpQB-H@1i! zgUI!0(_TrRwNGu}^TLK?!P8n0IEB3ila65*m8W6Aq3t5^o8HFVDC^>}lWQBIPg z%>BxG;<-{-=`rz9^pY!?zLaJu-6U>JdY@bk@3HUi`02K--x1C1A-UDKns#z_-t|SOGTUM&Bh`nDzrnNBCI%VhjVuo9pRmARvR#qNIrE|= z&e7=C_tI8>_hjRR_l_`PawLK)gv|KYq_9Q$M&_H=Puy{D0yfzlE+e)+AFD#DB@S)- z;O)qy;4yg|B#A+QN{&Xb5x%!U8aENtdGTb=(Oxe@70>eQ3hTho)E}H=)VS!*tl$^y zR!s}%rPix!M8NF3)0OtAcJ*deH%LmF*sqhsG2~FVmRZ){%977I16Et^q=GoB)eLKT zS~Y1#NHnUO^9Hj|=w^#)1N+~lqeac7%=e(Qi&_y0; zwE%!BE%4vcW`xdt?SJZ?`qo3DYI3dRNdfLr(=%nPjTL#Gb;1$c&YE8M`3R%m9z3`4 z#S}(K_LxK^>X@B+dH2h0z(@Z9iWH}Uh5r;nakPJ*brDMAXzqPb&iGQ|t>$z=S>po> z;y<|uyLkCykJc!>E5(0)p`(n;L?%ICqoI&a(-zT7@@hD}sEgdY%~?XiQKr@5a7vC3 zhdUu)-jDL$Y3r{?zh_CRJIYY78w%PRi%9@g*&Bok>-rR$P9xfk%my6LpYY@8jS{rE znN5~*Pv%umS-fh3Uk}b`o_zjk$|czdhi7wRPH_V|HyAHO%NrWK(}LrOj*(D==b zM97n=)uJi%efXW&)!VnT8*1hToq&V&R?K2)5|xc@9+C&rJeyUm8pKiOq1!vr`lT=} zic#DQ!PcsYgnu<<{$OH?FIM$iQ~kBf%)Pt|x@DVgnT4Eg#>TC!6E_D7H~+1u+E9AU zI=aThZIf@M1?tW73d;|ek82e5kk{1}`IXVvp+23Pr?e?1Ij<)aFc5!I)`l7=;ByoU z)82Tc3fI3i862nT(D8ZfjO~r8^eCX@fQ-o(0>>Udg%1QzjSWa4dwI`tO?wH7){7Gm za7l(sc=(HAk?_g9w$I;{V=STv3^wjJ_zKLzMMs}Ko0s0-{EEJdM(3q>X#KKBL$Hy7 z;n+uc=FL(Fq3yHWK1-aGDlzkA0w#`%M>#@KtWUUSVkp9fsQ zT`Sxtx~&F#_3Jb3D`BiH-mr^gTJGEU300ZmQ&h4<0BUyM9d?oxMxM;w?b)z-xqAY}OR(6Yi?U@rXda9(=J~u@lux%nKJSsR(8E z=bKrmaU9=_3kbv;Cc{A&qop;SBDCH~cqw|b2i1>D* z>=<0qS$vCzJ0<-1uG@00_wxB>$(Z+q6VT9(dPGcF5!@mx18L6 z1Id^6u9QjnjLw7RZEIerR`rt#?@A>Utptdc-iYg>s-6nS9|$sVJSAmH|F$^C`2N4J zbt3;pNB+asQO)lWVn}CgohR_&m;QJ>!tPBD^p6(MKlb=?ql*s!kXtWqnrv4brL<*Kh|-g<d%T&{$ig3MQ?^{A%M3Jsdn-nIu1%7R+o3lLAPA1Wz60!GD5-F=t z%a9yf30YxFBS_zxNt?Uu{-Z9OjY2JTEzw#t9}TvRr)Vf^5;TC0A*%&(!&!sID{`ou z)feub4o3(}Leu!B6kHvX(^dra=eON1o=xMKHU`Kw5o4vrUld*&y3!C2eiUm8J%8;` zs$iqDQPm#tPli+~3Fcy9-P?CJ8^D)I%)4Jxi-l11xcd=PtF`1&9sF~E`%gu6A zU)Lui&JgBu5(9=bw}X~(OG2SXxqe#eAI+A&!Kw%S3_MpuJ-fTRv=r9>u!?#%_+inY zTsYX$6JjbHdVi71ggJ;%uTX~La%WX2awjXr+}!d|f&FV5#nu-r)v z{Sj5{sy(jIT%6Bk#H_1#5!f}bc!Gvw?t6m;&T%A9uo%alvV%|E#8YO<0js3pfAN>K zw0jmLsT-}+p5 zN91sN@(_80FjYwF7+ze$q(2@v!GUQyrj|Q!Ya3&d%T#fHL{QDwu8V8^Zi%Bq#!d#% zFl%PoLFd#u{zm1+bMv2*DLUT#B8`}$Q4v{5Jy}v8d}SJ4oIc1hxXlDaADd)}39mMl zPc#eDu}(gt-yE4?iX3w;J-^@xQpijxk55J!Qg>qgfgBzu-|d z1ZgIAgcM8bk84z09w0muah@~+_j|zgiiA=G*!SetBW|m?0CgOy-DLz)`ClJ3X7hJ% zvOQkR4Q5PR%dP*L%MK$AO!xGk#yV~|R!kfq=l1@_mk4;vanxtZ&}hnhpl?fQ-|U++ zM48Rv|7?vslAqTWSzWwVuT3_MPsf)x=NPSH*%nt7i1U*Cr4^F>l$oOOWND?E6>U>- zhKU$BZI^;JFo`9V9WdN5a<(ycl$5Q;s(Ebs2&*_Hr;b|qJj?ima(-PA78rpK32-}B z($jC;YK0cnwe-(yxZC7S6u)wc&y8EcI z;*RKEN+iA3zQ2*S_+X`2HXMr#8~5ck6S$s!vL0WlQc-<32Q#VOhi#|r&{&HSRf2}V z?-%MjRkG#O!v`a||DHDZm<&G<7Dg_=z+LimJExi#zNzE2^vl>0KU?1NP{63m$Q*~p zhZ#oof}nurWxV((mTO}7@vRpw97W)~m&AD&0TkC34~8&t)xIpInOOXS;*!B;?HR(E z(=uVuvU2z$nvItoeyw;m)(w<%+Pa2v#>8a)?|!XSr8|_-A*9E*rVt zO@o|$7(xcPG`z%V7%@(M3$CFUWAP+}B!IU%h6)wpav3pA2^-(euP=D?gN;0&$<%`( zWKDxeKY{{JP83-W^|?1-CyNt9dW8=xwbz&od)FTsLRN>BwC6i0UJc<$Kf^|W(R`2o zBm~&&D91z;&>X6-Urvh(alhpKgS1$rf^W^rnWJ1{l-BBnuPlfv3E?tYUz0vOeoL8R z0H{L2G*D!~(72}F-TN;R*rhs(&1HR>FXz4oOVrk;OQ`gQL=YNZnXrmlr!Xy+FEE6Xp@e#e|^2fAVGe)DS*TcZg7N_@}e(i2H9}DiOHw0#@c2WYor8#G0?R zo-WCJ=?`>Hh`}Gt@rn2A|CNspM20G)K!fKu3O{$}%NPwlyIwglBB+fA2#Y>S+Pe$> z?g&D$n!Ej&RLphN=jL-kjca@VEe3hG(5OxfZpy6z5Qsl{*K-2QrRfCxnxKx$c#Yn4 z4L(3rRJ8gdDncz`gqjhY5OUG8Ijfpv(ojLP2iIgc8H#|f%z_Od3>H6r8_w@$lls*= zFXBhELUUaDJp1DjF!~prNuiFW8h=tX7|wRLz*?*444JHzO~P-(~0D4MzH{4Z`T}dLGqGx$hLs_m$&vW2gOUHo^6V z&WjD;dF|;aGDBI0njH7v?sVl>q_xA4PuItK$i<&yJwAyTv_bycr9SHbYwPhLz?zc| z0O%#)JfZ=kC7|K1$7Uah;_l$s`%vLyv=aGukq+CB}n#^wJJ0Ftb=7K}Xz z#4sfMLs!vkVI(`tCZ9i^V$H~zb&hu+e9UuHiP&%e?-10=CE6bp*y1Gm=l}aN59ez>JZ;R)KyULmHSvmoXuxua5pWz3)@s3>mTYHRoygScd5Z6)UQCjh6mSyEoz_*V+`<-Or>D%~0@i@@2ti#)-d? z5=ee;Q2{3?MJT2DH-oSV8lLNu@b`}<8Bl_xX?}!*mZ4wU7;=8$k@5lDYF^Z zT+5a8a-=cb4I`D&{wUN)e%8!4qRR+z*DqVkKDiTX-cK(E8)lP!LuU=%6^$v$@>DMg z-}&=>udE5=$}sGIME7v{oy_7pyi9u^95e$}qAoL5`?qI8aGay^_NNzn{(~?7_(rQD z0fjJd1T$^=p7JkCN+)dXA9q@-<(_|c25g{#P_F*=VpYPMD^q8CWVesO)Xj1}Yc@EJ z`%k(y_77?bX2XM&jQiL3Qdxuh7Jqw|jR6Rb z3pBFCBkoxgvkO56f{cjWi65iFaTSlpw&R}YpsgH(P}c@ZGJyc2du8eutw4a0dWb?= zpn5yg-?bz}@YGlY`jb^j+jp2^o7@!JS9c*}31L&2qb!8?Oy#eMzL_?S!Eaz`e0s)gI)5W0q0+#n z#bd8N$b9p(94k;TWLf``?WSHPbO8CCB2c_acvFynA1JWk)8!(%c`Z*YuvscnXdGbP z6byv{1=VC6Bv?0FZi*am^I(d4cm~95{JM%*fPey>yTlPU74cI9_;UtA+56r%v)`}! zdP^<~#_IgzykIZIm$P!%a*7F^ zmE&A50WU>}i@u^)g1r_4>7+++A6u} zQe=sUWA32m=-u)1h<%QG+P|p167R(rt*cZ)N5!QT3zSAl<#E+hfxmb=ynx zBX{=CK7iDD6t&pfQrEx;AY66J_GsFnI`zypYHd!bEhGCN2@9qmBH0g-e{uWqP?kxC z@E3*Ftg;bGAgSCv6a^1-uUNB8FWQ)GiZyfkR=tiBSsHc%mV=A8d)^dPj*C%Rv-KwJ z>(FZuOMWdfMtcy^`a5lAJH^JNQz`EFOvTFpxef%Iu0j^5g8V!{^zDq4qI8&NN2`LH zQfqI6*BdpheGKvsy)S#k-e%#wThUNFeR|Ys1$JE6AzF%CacYHbhc87F!x)3H`|0bP z=sQwVPSE^H8K3Hi2eS?b6S$Y8ApEJ$e~NCId@(FDqjE2dw)Fw|S`K`};N~EGA8-%o zA|ZmeUN~G6aRFZ-)M4voiGWWnbE{SL)U|JUvqsucmRIAoFT77D_qFs{>(Rpo4%#wX zH!5|;0^_?wRCH%6I&`BSAKKch%nJ@4$3nx@mPTDn1FT!*d?e(G=r`WUj9e~aq4J{C zEf*K{>t*bMcwhg{ZAIy)ETU~pFLF_gBfq1#z|Trp?%tD-cX8X&U(L)!>SN8;9hd9{ zY>c7uWc~2xpQmikKJJ*Y>nsI0A{(^N%g1$P_2dSM2|Wluizt_2e)>Lx*cRkx$%$6}P3BVD?^AnLT3i z<-BYS8t6GAU@CivL@M&ZU~o9R_uSFu5E;D#i4Ky`1@l06FMm5@qG>x+x3_f6zBIa< za`XhgX=;)jAg~ntz7J&!o@X`r3f@QOz@ga*`z7j*0K7&fS#>TVrioyVBT%ihDf1Dtc)AO8)Kv0&N z9kVI##7PWpE6AX-Q6tO1PABLV+9OJ686^P&w?OsW^DBM|d7@UWQMg}vy?;zEqPk9! zln?(VDnnQ%KOp<+W9zfW5-f_5DcE=HKJ>bFtyGx9RJXWBSXFOJtGcE)mvD*$8C`(e zB{T^f&Q|o(=9%R4+Y5I!Cnc6zoSKzfWHDG$O?=NHTqV5g!`hd13+*Rda~5S*gO2vL zbBu1g@YLWI3CNmNpM;%Ffenh|7@cpy_)_7tvoPcI9fw>mipTIpI=ISL$cvhiS>p?+ z-c)r%Zdfr}jM{~?MuR01t&}H(MOigl58tA4SZ14(j*3&eAPt@}5~4VYy}zOEoO0IK zNlQqx6lSwjcX4Yky4WFcX=8*bS61k-65@Kq6uqGoYbqFg&n{mQyCgzhO6I}Y2 zq`)Ob<;?ctTU02Wg}VzC>3jPVMc1IH37nQP!d;Mb)hUYm28v*TAo5qw6DE>X*~6}h zH=GOIrYNm%ZPi+XNt4uz71vAlK@1L1C6^``%hq`DQ5mVY+_LF9=vlVd@x?PJ_G#2Y z8&qDF==LdH*Avl-HR95k;brq_niFBx)WWg>eS)p!j8Q;+?^ z5tWhFF0m>tPJ?OL+agiT57>7k%8d* z_-XT%!l{;OtH!vi-6lw|r!=;L{(R)q75JHM7H5H1*s2*0Dc#jz?u(k0xrMy^haZ1h zeHL_XhC4X%^3D!7mJp`!uA7!5h5~ut{M7025XP*^-44mD-!Mo&4Yb*+)XtVFMpnP| zEe*9Ba#8+pb++MGAioNuT`4_j0)JuhO>>s)#XD+vL9(p*&N2D*x94jcwtL}8a;a$x z#7gRt@ZN&1ON6wi+2k@~G=4I1MxlpQ%kfdq&wEm+l6Fx#q`zkdHT-T&t(7HY-|ToHHvh5 z>)_+Tlv+WJ($s!#&3UB^l0Dy*y*3MMBBh>0Y0;71`bEfd*>=5!uIngqaFvXxQYTVU)*B~P=mn`Pt z8j`nV91H8)j=G4<0TT}ui6XWb3)ujn(V`Y9^8xN&;vDyeFwR_ehS1g6^5rNKyW4w7IDK6ZbvM|Vo*yCRyuCt$S3reun`$%ujQ^6i)R~T$*>lxzv zZI!TjNO-t;C&G+6+3;LOtb@z!M0eWT_+(r$WzvxGitV;Sc|Y?`u$V)x#e?C#FNGJ5 zSUUI@qQrBKu?UtE>=Q%YWf_Jh3tLQlsLqypiItc`6|ITO6i7L2$xqONjTAAmw^tetaPzL>|H?vz_zI|M>s z!~9H7^2spCrJ#Fn50r^(gkKKYRZ@9(Jad97sE(K=WG?&k2(zjoV*owvg8FQCP)`I# zUi@gYKPnyr>oL6R*{&go_ApZZC;pW`^}#d4GgOCmv8#eHAV^aoSc~e|O!mRTbCR+z zf^gieiPHET3DI{QAnzsgdu1GO;MUj(dE?^EXBrTRwsJ1Iq5l(?^^U;LF~Ln5#@8KJ zlxodaSw~h=ll+@sEJ1`-QPDLD2MOF2u&ct0xh>*ht5DO#J<&jLr$C0XQ)ifQq^ZgQ z57~}`QlSg3lCzdj>U8?9k{k39GmIZME~!6GYN{jR+d(g*b7OYafDZg9BMHPf zZ_tEARGBOK@fMg^Fh{R%UI^TJ;hx|29i+SJC?Vr%qN{3apT0&Czc4aVd7`?dec`Xm z!<~glNE~Mk$i#e|Ad_PWM;?SVp>T=`Z z)2mT^m^R|pwCmSUA5>GHJ;i59it+Q=5pSB3P25o59(%MD zT*D7%sSamfvGTR|d)F2mfJQ&G(sjuAxqxjC0sr7orb>CYh1&@X6i;dRvquqXcQg$V z8J{TSgDV6OHbywGU40tBH1>%NnLWAB`a)b}jlU#_oXN2@ygIJT!_R#myp_(@Ex`JE zKLjn4<8XP9F$4Ebw`IODuSlx5QEb^#etn4q;zdBclzXWw@BVCvHQ@;P$q@4nDocEg z&Pm0)$mS`jv98!84rbeGNP)w>^`w26D+fKl{d(?C-+F1PSWXE|SLOqjl`BD6WjvnB zH|myy!66)HnWUsPIi@}u#IQkqhkFlc>xdv7I1Vrwge_m5>H$A(MlC5ArCaBuL`JC| z8q$2m^@UFvZWTpg22Hj>zGAWjDcm6#%yYxe!}6N_NwXsan{yeOP(E^py2oO}=v}Si z@N9a)7g{t@OX5EC{m@J^X|Fg={tf<@+}awIfq6^zzBT&7#e96O7D>MAlGP3gmbv9G7K=C6x0E8Sp4 z-zHG05IrC`cOS>0&1*bh5h~IGofYvWc02qb^UOQOp_h26(a0g~iJDZB*j2^%CI%AA@UX!<5<_;%f-*d}vy^b>$^IJ8lEEAL)61HoTWP9K1f(*fX zH9Op@SvQbGbSlc0!@4-j#60Rd)hf*&sh}((bvg1veAraE;Cu2(Bct4m9j8PtVPxV#oE?!$!_*1_!*)B7)DJ^^97cO5tBbr#v9+Yo(s= zWL&G3edK;>WH(HAI#0y27~#V2N2~czQz=sOWC3A0QEo;qD4QuHdvH($cDhS2Pgg8o z8eyQiksfP%)hpOy>Rb@(A#ikHB3VXEi zL)({V2Sywlol7qCwF*OfzrDsZhEJTQ%{xt{7}t2B@*GAASzn;SErhih=j$;cjxpfV zd`?<+>@|*9c6Psle*boYN{MlG=zj0mz-SXaiCH-aJtci-!vRZ0U&LG)#B9l!E4!Ec z2-3$s33g4KSi`41mGSa^yPxwaZ?Fii!y+o*$>Bhsv82;v`(c$4!KQN501KJg*QP}y zi)ZVlpYLHjjVK*ZsI3F}tWUp+UiG|%eI(L8Lz1?q7M9bai|^eLT~&ISQwt?b{5g^f zkm%xHF!B?HjZFE40oup{-3j3G7?P0mybU66onK8i1rP=rK0wN*Za&( zLsD-(DWdj7_2lOTg5QWof9k^d;9)TF(>v2qg*^)c4=VF%Q|_@IEglLg+8y16ryZ7q zGbBDOU6o|c%=@26)ak`v#=rRieIS~Ei3gR;M!3wW5XEBpBl$5Phx36I@8HvjzX2+S i3Vitg{RhI}J7#>cs0d{sC+PZreSksA(&dsb{r>|9X!;)j literal 0 HcmV?d00001 diff --git a/images/components/console/process-helper-error-debug.png b/images/components/console/process-helper-error-debug.png new file mode 100644 index 0000000000000000000000000000000000000000..8d1145478f2e3a0d6c0ee2074ea50883bd7c5107 GIT binary patch literal 19108 zcmZtt19WBG(gq5L9ox2T+jhsc?T&3H9d|nF*tTukww>Jc`QE(e{QtcfV`r>gYgW~) znpHK|d}{45d08u7MG&;M!ki-Z6G(1PYdLh=$qLiq9y zwkGCQ#sC1~FlDN)YDx=O@8{w`1Q0~&VIL*zIzzx!9mzZp}Yl*0>K=*)AS3FWNU;CwL|}0MhD# znz+#xfCdv#D7T6HpO6%19wWi{eOaFoI#I!)b_MM187{LIR?>YH`YofCOFx`mTm$OG zweUeYw_`bkl<`M}9^nCo5Qb5L0BTKoHKnN%l^TKdwLuX>FUcTHi|BERz}6zYt%|NC zBH;jkc>?~a0s#_11t3GddL`6H4evo9I3-4sFb1y>T+}5;z>jvs*+Ou4S3;Nsy>88vu+3kdGOjZl!BDR3;nO=)9U#YupA zRC0L5r=70p?mxYN8Kpll`QY&;lJ}x>_rbygCgMYLzu7l6;!^`&i34Y4QozIrqPJ1~ zFs&kH0M*Y!s-TM}jS>18VCN_x3zY8{?pUXWD0oGQ7sQw~Z58$yEiJ;HM08D{<_-#8 zw2ibc=y$CC9O_DyNGwW-8%1Iuygf-DIOP}yVW2+kiz`S-2VJl&|K4}4HTNpY8RlSb z1JajH)LQn7T;J|ARZxVmFSi+itp?Qa&r>)v(!_3%y|N5B&jrCZL44%LU&1uN1%j;N zn$5?}lO5ht?BM)>>iFLV08Q+K!-ollynv8u-PBK~eyIzuQ^dKg*MQifYYa&9E4-z~cc4E75)x?6%B7;Ou3)wjjWrnblNFt}kdLLVL2&`@g>fT^#P z9&8l!ru(&up88wFfMS&sHB^GWq!nsCJXOzd)!ia$Ddr0Xmw#sOxMA5M&MCosSX(#m zHpqClv%TReCSH)|mVg^`R;XNe&E=0)blpI@zJ+a-N1IkuzA)Wh+fD07$JP)4!GKK! zlR%;^kwEw=VazxQ@=y+83IzdW1kbQ?mC4HnX^y$&RL4yV35hWAoAu~#%pP;v3kfEz$oJBrZU|JMd z&{}L+m|HN`fm)zgw9H1AXsdV@&zF?v+vK0;;+D`VX6Lj^d!>5>JR9G+-02js&IBI~ zNE?|j9WX60J}}BLT`=fcnwkBybhC_Hh_x7ynWQof+qA@6Cwd}quRqJY=y>LFMf2ej6cogb{ zdSo@nk$>}3%8sUyK#RbYz!mF(xj{Rn+%gv{KfO$|phc`fq(M_oY(j=k-L_dLf1RO? z6}PKqU*yWceZ&pSjm;e|1OpBVlN7h!ZE;;+HKc6@uN?0W-8|jgMxl?;M=sz7{wV%{ zUXVa$mzU7=%PQ3)aXO%MuVP)o4S!kX|-APVLfvlwk5|%b^kRRl`|C`RoEP6NzM0*QtMKs z(vF()n)Ax3hOlai`l6~P(~)|Z%CUyB>NXp(hMVe#vGK^v*8M+VqW$RuEWmD z`%Vk$1MZPGKnLFrRB7*N1ydwbPRgwo>=v5J@5<@cuvdF+(pPO-9M=Y#eGb-l-{a%X0ynbsTw4ru7KE7&VYbPih0*Sppo+hRO?F0U>rZaFq@QYvz7qc3PTqNiAM z`*ItiyiZNf$u3v67xpI}D zbX^Gk5Hty44o1vD$jQ&4(dX2c&_C(H4NMO)4O$3v6>Ah5jWmnQ6A=|F4{b#;#wLj@ zjy}fS;V`-Xxo`H}N$~dhP>kW8A^c}>)#DVjxKXMl{;;hD2zfn#onklRw#@QvguK$t! zI`^~|Zq|1XRH~;a;FUwW%&n`qOxdBrOMOjOOzpu(})@Iye~paQ2(=zXr8MEugki zGio(k|2?oF`a@Hxn?fOR^?CfEWo#p1L#o48{j}L_ZJRFt_cWBTtTBplb~1R1)??RG zNFCoT&6w75^{C-e!QSm&^&XolNa><_xwekhyW8GkQeDYoiKJ?qI*;+)6J$g9nB`B) zM9by*{?amC(>i6*iEowXQW+`_*H3K8f#co>INZ z%akX@;bpgFBAVG&QtK}FWEI)P4OljGEAQ?hR$?pTkC|h0S#xtOkuEePU6zR~nJr}J z?bT#Xa&I~VZJPI2_ep0VZ^LgB-m)K0`+kSOGGJ}6=R8KvW>e@tDqBlVGaVD3d}lhw%b+N4c8J1h7&Xza_)zpp;n zd!|}f#ncdM!0o`ayW6dsv@|Uj)9!FHT#cGfmteEqNOLPWt3PxZ$Xw;3^Pze!dpK|P zto6))s5@8XruUG)YgxN^S>|4j=7IKdJ5uP*ZHWnr$^KBd94NdOkz16b%u3@eJGVPx zU&dH>-&8EqXf$MyscTeM5O%$UlczJEKFPd(okBx4!fkz-nNV;j!m| zTiT}(ry67}i~GjH!!o+>6u_nW)WSkbRmH^(YprSr@Z`@8pZVO@ zBBtG#ACPYr3^S3_g^Zfyt$jPm71`*wXu!k zrw(2=Mpo|sjQ@Y#`LD+R;Z*-GCj&F%|8oA%oqssF>HZqwhgMdyAY5ETB?~fQq~cS}K*O*;KI>g(Kf~tCR@lyX7{t1Bi%VNlE7V0s=|=G-9k^ zI#@ZVn#gd!aNlJZ;_P^3d^xSTU$*>s;HX(xssQW+hQJ3T_63OrK;#D!2l$^aJ$}Bj zw0YLYD?+8U<-jShRfzibU!$N&fSz-d(W#;SWs0Q%nFJk5P7~yc`$rNq1<;{CbkT8d z_m_e})K7|$luSMCgm*DGg zUOu`b4>dSHasJWiM<9uhg0_2%b=M#R7L!7__%P$BRfNyDffnGhM z2>&Rw3%#{Q$FJa5&8QGY%`EhB0Q?9@=~LpvX}F|73&1Nze2S+$VpsK9V1K`=Fp&I4 zcPldJ&_W<~+yKZs`5yanNXvr6Xi54jOYgtyC?4}^Kxo=d4jV9^n>Gg)m#pi@$6Shf z-;DjnWYPPSc=18I8AoU((j4Kh8V{RFcBGn>=~Ns^Jc;38#N(Ic%J>^T>5GvcNC6^m4hpgS zianO1*aSeennoD=mBTBU1a zID7Sw=jyvKrOQxg9=hL`(+&{_^Pn8=v@*HHl3WWxq_tFmTWi~csiydtqdrni>}4b| z)sc>%&RL@}fB@Oh$%f3uBm2(3b3k3YW#Fatqg|4}=elzB?}JJlR4bYbO-63JO4)~%rs<6#d{=9@uV zouF-YG20N99{~Eu?Y(51%yZ3mJNKESQog2 zL-H(Nkt`sIPlMK*QG&&VNQ()ks$0Hs#njdspSLs9Nyl=c9#7SPq2nPaAIyL4%vUT+ z>pVQ||3F2siTDUBkm*F(2-2anncv|{wW$zpMBOHORRdJkzE8FK@ng~TR{!C^(QD1x z;k>yOYZrs@G@c?o3gRn8jp+PpzZpoH9(~YL<(=YWgOwMi`v+?2ac|*+1)}jHChOp{ z-YTIT4zL!<0_KJ*_X3f5FMA3~|G~S-PF6@FhG)N1dYB5e$FDY8D5qZ9i`h7siDY}y zz}+8zsmqEa5nxc|99humqIBP-VKC(W%5i8WAoDx_z#2}}MqVe?Dm%bn$LeC&6;XjB zMZ3fA<9;@rLWu;<&4iphcSBAh3QibC9|3OUAG>n3fsm&U+2%=xPWKp{v>3&p6aR`t z0y1yHKf?n(&H``sjI5?4XbGRPE6#2+5ZsEnAZHS!q+5^+RyIw}vk)3}nnxHWkGv=m z?+~9H?>0_}OvTXoDt`2d5P5t48PA24CrVqUG2doEOQDjF85u)v^F_D7)pMm_L(Zoi zlU#f{PyCq3Tc)7|Reu;RlI)yxmHb=ODE(@+;EgS-arJv>^K<>Naz2*)@u>pX*#tS6 zXGjx&4%&e1`M(lyFAyK^8jBI{PWxtFj??Wr97`YkA&ICBc9TAhj~in6_D>b+w8M{0 zhWZU;@m$flF1uH1(C$spHtC@SA;Xy>IyDimASqtcL)k{^b^dJls}D*mqkvbq)kpSl z;^0_{-56_5uRX&s{s*C(2H+w|049ClR}wwK4@N=>x|QX%)BqpayvH#*O-pd`jW^4O zDGWx>%HR-ywso&p7)-C<9tbc&3D;M>900;C0VHF?+MH5y$i7$L-TmpJZo#2#H>9eR zvZ&KT|C(?mK`a9r$U80fL)gO+i)MEu^Bi#x#_PsY`JlOa`$OR+F!h;l6eI=B$|(}4 zwcD1Bl2?+N%ljt$vR5!4jATAmhSbV*-u}9f_rXy>~FAHkl{t|U`wvIM_|CW zrmCGZAN@AHyE7B6VE5CzTTP&KCiKFlLy!zDx<5Wzmpr$v1@z%ZHSFG&ZjNx6+t4Ry zF=qY$TYdt3r@QphpIx$(A69FeRkfgVp`7x_dJa(29-!pJta#GYfwjPB$4a}wt&M{f zZf;58Uqx{apqzM)E~4QT2p35V%{$%xop}^LUlaaYOxcBY>^mLOe&|;q9Kwqma$Dd_#{F7m0EAD9Z>M4Xzmd=OcRP1|Gd%jL zF#lg-nXV+``Qlk51VF}_+aeNlEJm~oiFn8?7r%)?)`kTrR1)EbA&#`)fD!6tE_z&-`@4GK9r@JG6X z^RQs!lcU=?&sCzfq6Bv<->_vxrVc*ACY+U*ow-*fUjg>!Z8bK z=i}6*hpWlf0;-PCuM|JF80t6jIK;yn04IiIa|>*}c}I!GR25tQNcq zSW8}-(Ie=vsazZmyxfUR*@uAmuMdV-n-Fixs^{XkE*sX?gqNagdMsjka)`Vp!r%Y} zt3E~xos4!jK<^qc304P1HxHMg%S2#T9ocB_v9>&Uj8)F-Bi$Dk!_iV*@X4)q?;$IG zrlEB%_s7{O-*x<-Pw-^1CUoM(PSJH#6mru9>1t_zQ%^6ZLPyJIMMY^?YHyFkfHTWA z^XReoiS8tMLF|?`mN1b{x8pfHVg$#;KCNtE>3+fbu7p)2m8a3nx@WoxB@b?8uHN;n z&J|QlX3-idiF>}RHSU>>MUM|2X4y-AS=A+x~$@=1vpESczO73p%;$U_?9 z<{ekYDy<88eJJ9)ZL7^OxUW*hYE3P}u04%zoBi4>0``Wp-rd>BVA3u{oT5o-^fYns zP+X@xAw56s;9Lqh{94%lN|jWBIt`1ZYej~XX_34(wkZ{PapRxxQa^|%SztS%yMEP* zbV^pUVSN|miT1NCkBhYtte*Yjx!F;KH#mpI@WPGSRu5D0^a5hjC-Uru*8w&emd3T@ zDanhe-jNhr?hWhMk|{m*tFD_8)=AWIle-bB151x=Vqi$pQEd%2rm+>aus!Qk`W4g|Wiv{JnOQ`#f|aWy_KLBe<4Iq|IZhBgLB-#gEBZQCs~%g0TRf-?9vva4sWE16I7@NsRhm z-^VU@rM8~0NrBv%h{rZS7doAp5=-!GL+H9e{r)-`6Tu~98idnzm8XHW7A;`(CiD(v zWvcaLon)FM>j7$pVe%j~AMmzIMOqB{te% znkazNcmXOVRl?sjE;|o@KBn3Y$NZb&xm6-8Ctj2>!SrjDxGERgAC5p{P|m#zL`C7U z<_FsA4p*&h$4P8^x!wHt{2t@ufi-H%lh+$?#;`851>Z)C3tjjWij00ui3h~Fg0oBR zy4qj6ygkbGd5Us#i`DZw$i2z#iE7@@mTOYh(I!$S-hQw*Fmp3YwdIKRttDGqYh*!p`q1MGD;B8y~HyvYGkal%ALIr)JMW zhrv~%mnWt3XXQw0M}pABMCIvrMt`m_b}VmsE_?762{Ao3_~8uA?iA|dZ_syv4-L(& z&aPh0n083Zy^A{G>eKiz=DxP}n?;PKqU~Xmjr-A+7R=)X+B8*MI*9>4Pn8d$cqI)O z&7slbL8p*W4shzY% zl&U}&lvD18MMY!jY`r!M@eMV1K01@^kVb^(U3|Th6Zq=hOSKFRP3gKX)}b2a5gB%@ z*Y2ZSM#?Hl!Hmoeq!V5@2;@zcL!B z2~FEI&*04Vej*A9L-NjjZtftX&bzTLYZ7j_5-Uf~m-+CjIo2Ck47WAn?@~pKD)nzZ zx{*1gs|KN7AwSPt2(`V=(U)Ev+S;^_m%}GxWrh7$rG8$(M~TpVnPrkB@s}@+2hW|>P%XMg)wJ+1Fb^4#(K3P2Uc7D z!uHS6R*i~x@5D`o-3imj6BE!&7^VpJ+>&{DURq*rLx?wmKml?5X|&*uago!x>rEIs zN}_DItQbG}ABxuoWd!8ZR7oiePFe%7?10SsqC&(lHK? zwbi3s*7}=JJOAoNCc;!2_3B1?&qBkc7-L>5CCWK3Ee4R7J`mzI1?o4Ul^Zj=o#S1m zg;OFxi&0{)xd@AOQO8L#Xo|P%SeA+L4&6%cO|ElbUXqk9DJ#YBP%pCivL9;&M~ZZ! zoSe7Bs(_0`S#)GjdK&EDIwE@kZ7EGmnXB)aGIY(J3?zg7RB}F(;(5idaxkx%@64*U zKPvkX;-z#m^17JzfC?3(kxzFC@)itrdbDfyWV?{B@g_MXyL6=eL8>GFy6&YNpE3p2 z?Rw(Yh?=`GFqnvMiG*l|6obijsRxb@$`%0bOsj5}&gsZRjVmtW{kRX#cBAfPjLp^7 z{fDs|?U1=a!n$h1L#S1w;raF4GP99m1c#ACv0Ec-Ydh#7Nu9=^aIkce*~SRo)O*2E zgikwlx4vSv%-pzqi4xDs!xY0FFL}9oN2rDRY~{&0gvCzsj}3sf{81)b#h1n61zS(w za`@j*w|%CZ++#=wx9NOYk(oLj(zEt9b;~*5Yp(V@XO0vw2RV-;Jj61^^3D~m zaOlm^_4rUM82B!*@+(P6CxLl`zR(4lPuD&VeZbDaOd<;6amG&f6*r?=Tnp-3X_IQMUW^Vo>aHLP*As3|h*dyK_cZm3bxF-N77 zjzyH{{P;L)F^zjr(Oi06(-gJxxL#@-*wjUxTj%sCenmVnU#gSs9;Yp0pa>x0tlbV< zvn@}h+TIGcbvJkj^3-wPdF$DaBZ`pfuzyb+t~U6X=c*t+iN-i9jo#}uE0yDIytyHw z%4_PE=RO&yx!c3LPaaR@VOdlac!e`3Nvw{bQu-!idumydL2^E|{pXMSQ&DTj>&$b- zMwUX}s+~0DG=jly(a`UsP1SPADjv28?W#VN%NMkV`dHK5>yZOxxiK$=VxlO!e*aS! zZ-+||<#5X>Dx1e6k3VK(*^EBpx05)o33V2}C*X8Q))-!Ca{M-72lx_{hqhN@XPw!*yZGy3PpUpi6g6u~585s`!{m^LOS0 zpF`Io3(GbuS?}WT5}R`Htgn;?A5d&wrX#oASt;rI`GvU&7|W=I*NSjW|BgMp|EY7{Scdnk8BE0ONG=lQJjn|-M=^T)Ql z(7d~xL+N<3q3ZW19@Vlq{6*5))wTjsvmmjeTs`T1!BH31wpW1{7?kN575bCl6%z%d zWw=&ni&v8C`;Ss2e}HfG(SOb!!$5-B{glBBwq3bi4vTr%a0cWJk+W>OZ)#;+mAjLS zJ874|Sf+2csV-RY>_w=MFDyJymRMXtUuY7`)m_0chw53KO(kpXv?q;P*E`89YjfJ+VvXFE8 zksd)d6kt_rfw(~swNU=!UR*qfhvvd2v&Kv$bY%k;M`@TV?ss0_!-eH4tdSgleVw-KjuOPN zR=C2uG`qnTVr0j7M@#ajTwRMr;KD%! zBoz$$7YGw!F(mjG2xI-*4Xei#@ce?dprQU!A}sm^3IA!pp<8|S&@il6{O|FQu)V(n)u7uF44}|cmdOWU$RB)GNg^ zx~=rwPN6>N4D=)WuBo2O@$6qmhF8kGizMcduV1tE1*uN?1c*X$`jP!8T#BS30Ep3c zOYJu+{fMNi0Yqbh%u~8ctuN&R9HO)tr7^O;Ji!m7{ufpQ>4Xc1a%e^I7!2Fre7#)K z-_trHJ>rHWYwptX>yC@HRVtTN2WRtvooFM=s+OV*yZUc8bI<^&s2N`}F4JxU?pH$2 zYs-mV$t<0q5t%OB!zyGop2Ipaz!0c{^XFkwg8sk#Pa`Zp=E7VD`tY(|QATE=7&;x_ zjZ+0#QQ6;Bw+Y(u1)XwVkfJ#L33%R-f1bv=;hE%cg3};rGO5du8YcZ0J_>+{{sZLO zAZXJwB52S`iZ4Wq5s-)*#y{@N|m8-h;JtgYP(% z2kg|(w2?{oz!+Rmq_&}qkV2(;Dbiy`(n0@(;wQ8W1Y|BNX1tEJd+B-kE_K=IqG1HK z>IDZA;$1BjT+qYxUk^w8^)P+PtQm?37h8{InPl2;sV$Rg7K`34T8ubkqOV-S_p>6H z)TIp_&fS{Y>>QhOEuK;U`v0?w{tv{bu*wUl-->2_WFOLU{oMglX6)Aq+Mn+y^#9k_ z0crecGYUAB$0=JKiIxnVmRP^S-pRF%uHarF?{&dv@^qt8UoYg>0A%6>6`@;$|GPRUAWqdu7m;+Mkd8}H8BcrW zF8Yc8O}FP%{^B^>4xY?qy*9 z-W3(hNWUsZjtIaf@~)DthWW*%F8E2I zE+S_}`l>UNgr9Y0vRIB9=8KE^v&@PoDLLSkK_B(o4Xc>0Q?^JCl1wACvSqvHzPTv;M1_OnMRM=w-wUNhzCBG(I%$U zQ-c#}QK(@;KR`nHglr{4rbIhVS;kHz`0>X#KECy~m^s{Xmq2SsFz=|=n1>4XxstHh zfYW#c2?oLv@Vs6B*>}Wt4oL3WJ{EDdya7-#xE?Ma|AH8n&v%30ykf;{I4QAP`~6Zw zXy7`rXu2AQHvG6Mf~M;ABC(IT0bENVV@`7&BkFP{xh28A!PjRVFYm&R1Z!%UwRBsM z=T8u{S+%Kxx2_*)9Vkm`WTh)*TW*4cQa5D;0^>})BsVzY{ick6VlKlr&a~VTlvt8z zc?>}^#SBR$a`2mDUn76kFD&JeiQ6z4(o-=uJg!AA8S`NBUD9hU>a4BlDIt|W4=rNS zmqg|V0+#Mghj%WG^R2kE8F^HepK+k~%ubJdU#4TO#S1+j4h75dXIc zL1hjYi3>GD8>GInne)wK4AwBbQ+R@qPihE8T01tv2bwPphk~$w(c$-iDW{80`;J(X zs0O3H(;yO=u}R%(njtZb{BGCL?G2Oz!DLmrSgV@BX83Jbe-nE&cdSGUKI+Q7Lh`ma z6gXKlmRPaV&nA2w0sXixhnhntFth%tV?xGg5mTdL-e`vTlwGYsKsg=J7>-n3)0ahZ zWxhf1+34z$_mGGKxEIg>9kKRpY<%LK8z`Js0BpD315wlD4(*^nn2RJ}7!=H85Dn%sul1{?BG*amlvzGW)T~wJE2$x9dy#SWICB?$yeK^50;Cjuu zHXwQ8cD6BNc+i!5kFkY#E+l(N0-pp;nCAGLb5Zhzp7ejV&0~M^ZrR2Qu*sr=Nbp42 zoHa_E%57A3La5qKw2Q717=-E6=*qBhD{YWqoe41Wfa4j=14*Ayzp!_BnW!&P@$8ZFCr2mZEh}Zuc*Vg&ycR*2 zEYLv50Ak-p(r7rD)QpsaKz<|Q-^lGf5*c{`;ELntf=r))LNM*AwIJFn;^;smgnD`0 z);d_I#OI0GPh_zpB$ZUJaR%n+jc5w8L7up}amh(Dm z)pPQWQg@PA;mHCW@GQQ@hTF&JYrrF@tZSGK#E^Vm(51SBGpI6kdk|gVi%llZVr^n3>J^?h5ysoJ7~f zq@`^BnR^D=!O=o7_TYgk+jR{hw^+-d=>WZnhhP_cDK?gTtT?HP^_w z{H-3_ut|W(htw(EO>&19RJ>E`R zGdyxEpHlUhBrx;Du4SCsD~Z$VKe~R`^ooa9FhuW;Qi#aI%zsmJve?@RNyzP$ztCe& z`20~1{s@tC!fvqQ01aLymeq{Y=B-CcHmqoGgM6EY0ps8=kH~^M5>#i{Tx$LTs}ZGE zvY(BL_UlRT44!FJWGRCvz=;xXuR}@Nbwv93WTvh;5+^?fDXcQu{gG6y2Wi1uG9`mW zEqlly7Zye>{cs0HB7e4aiICzH?P%?431gPFc({qAhJ|SB(GTW zxu8P>k>9KWkS<$ejrmWT9Bu}#v`JdrB^2a!4tIuNIrU8ks2^71 z*ZUo<+z6fpNB;MLcns>|KhNCCsDFD}3go!5!oB81oVvbmEc7y%j-wTUAFDtW*1^Fk zwS)o883{GKs$GlwE)~Bb9Ei%whDX|Do+!82a89C;#gPp;Rkb`QaSM@P8_~-!KZMvf zuf4l_g1#%|GjG%{8Z3QBR$Dy(Cg5E*rScPbEZ$=+G9y+++60(weT?$69W`1-GvQo1 z1hKAd&HHf$u!c3)&n?*lyOOi+l1X}&oslq6X1Kx{Kw(t zOUEuj$V?2wA<+urXP1tTHIv7?J!&CN2mZQUBpm-JiZemCxw{~ti=DDtHmqtLCOBd& zXPw}1c(m)85aXu#*MZoX-lMY2Sk-s(ZKHG62@IHgMAoM>VVr~TAL;~weMEI!!m{a) z9amS}b06?&YwZ(n{t9&K89Py0ekMs`h%Vu&8d)^;$x~!SYX=(_dtRJx!bEIC;x-B% z1Q>N zZ^D;Ql+@xmMdXrgLR&gR5(moMss~a^Fe#=ED;Z{sNErlgnb0gWFU@0rWg`a<{BcBV zt*|akPGUO`@PCJ(c%RQhQ0VNguP!&%s$`%RTe|*-iJRh%(d-&r$2(|bG8P}0mOa?$ zE9IJG^;vbJqvj!^sQW&#Z)eHPm&^)KsKbz1FDp;<_TqCtGW! z-S~63|Ar;^`8u{vVU%2yV{g_sI2@geHtT6wvF|VCaVAqxQzu7MMORmX6v4ufuk$l& zcRZ32eLVm}5F4|K^lk652(~IK-~Tg6NJ$!g0>= z;@Rs*HdUXGu9yEHs@zdF%`6DEm32$vTRRuKSZJogJ$_61C6z~3}tgmB`#Vz5ft)r?E9 z5$g=H4X#D#guUy`FXbhM--CAWKWET-@Biz^iA-RFI*ma^rLso{?@pjTZsAn8mwm&khzLdxhb=jNL+F+S0h;q7p6dT?e^MpHVy^)Jl_w39^Qwzt*V3S~9 z3AgiD#AB4DPyq|^e;+e*rChQ5ebB8amjC!xlC5pVS?a+E^ue{wr+#Wd9&J|9^r9Xp2b*qm$X0wOch*R%zmN)gs*&amLQbF?lZwtFAR8RYNN7svE6YsH9g`PkbN*^w-WV@GYdv$p^pEi?*BoP28e{4;WVD?&=r9Krm+iN4&o8 zSM6wIq|e`RP;~DMa3aDTb}8`TFF*L|lA=h);47$$!bpau{2=^%w3*@r5g*#7Ki^O~ z2^mO@;_qnH(6))nd-bc)NO!RG97sw1jc7p6FfT>DDR*K$mqi(#h ztr^&W^r#MNUq*sw(k_L%8j-!&RVxzOX&Z3+6MJ6Cn0}Xfh02I};~{r}x?F)uIqG8a zed~p7z|93&WHesI$piJ!c>!fHYBuTy!lT-&#_13;5x_HSkp#t4Dv?_J0}O^j_1jR$ zOP|ij+V?nFuF?(zp z$DA~M9{!Q^9o>9p0J0&_N5&2ADG1X3JYt;Ifi<(__5;#LM2?z7qTe)PT(1gIUQt!L za=zt{`rRMKAQjezq}oG)9{mAx)1OSmO@qkN@-Cz}0y!#$o><|fD3ZD5C6zx1H>QE? z^Cch??84S95~|Nf_YQXWc247`GwGH}nP%A!XYiN`!1pe(n7b(3;ONNxKFwP%G`Z=z5{+0$wq9_&;dKi*y-{SUMx4 z{h8|Vd?F_y8ajhTMyr&I9MikXL##0esErZO>&KeyqX#{(^0cA+;$tWFw5KKNR9L!5lKB zhGef2wRmvPm5-F}SMuGE2uM;@M3_5F&lUN%c>lXGuiej)qZEr;EA?%{Y0XpBJZ=o( zA$m^2 z3RTj@r&pxk8Ux0eRB?}fVqLKvh%W@kB9PxBR!LdN$TDK5E5?T-MzFcKCADpE>@bEL zQI@>kk+#mr6sC~O`ym4J|?AcSzBExZg3ypQI$uXH^RT&slUT9Vf;~4INAVVrY&6iMoojoE8 z%B!^+V(Y*16f`1|{ZoN-uVcK-?oXQ#CLT{u_-QLOI0`!Uoot!@Gjx%hl8~Rod8eUd zIzbL;;YoP~7u{R4XN;#-s`I?r6M)@9X0>lesf@p$TMxq(6VK7W}nkgWP+n2^T7^ zmSE4Z>2EIqaWt`6`{dV36{g~DUg$p~t8>0-smF@33Q5ng4{$2P%=|AJT(cYZP;FVO z>b4WK+1H6FOV%TVt5728Ev6OM?|JE(@YlRz^(Q}t$W*Wo^(purzJ*WQY%uhRdX0(C z2}=nTSp!)UCa4z6s!xtN{UISt*IlZ^LLn|mhV9M!!*raYnZ}twBN+OF^R9en|BseX z;{8yVsynUIfrg6Qa;v=+?Au!|?-28!SsTyB!SA@-DT2Hg#jJFhi218s5{pOoKZL=e z3J*98c+-igOol`Yt_!{n^_8spSFJmxY4JOLrADI^?VSMi_DnJAvm~+(xA0#5bdaaqRHN@xd_bFn?qQI69jBe;T>>XeRVH0N`?K$07}}N_mu79HuT}EbnB- zhL&2UkTq{wBAZ&N<$5)mlxY*2w^k^Rxs>QJd4(QBqZ%1zU6beRjW-~0Xd_s92p z&hMP>IluGyeZP|EZGjJ+Oz6DUN#RI#NhP<$e0_(waPy=;r=QXT#is7W@f&CfuyeAs zsOGi^{!mo;-pON#mjW>{ynheCUVnLmPjnEiwN|Izw<)mMf5B4W>8vE>P+mq&m;bw7?BI1P*w)R`HowOx3cmF17;Az($F>22*!K$imb%Cw-@aDjcTiZ^t@o=EtMjr zJ2ul=3)`{^q-VBQ4X3HQ^ZoB8bXb-8tpzUCenT;KM6~>|0tJb#RO3JrI!ZEeeq;BN z%hA@yKV=#esbTDd9%a;|ZUVQtiFDvM@sJhM6=3GD^9PSqxxPDpM6g(B(2dQ0b$@sA z`Nfdf99$=1_Wt$CsW&`f->HL~_^a!|xIm)I$MV>HUXf+g1$;Qa{@ILJZNu^ue$lpJ zFI{h0#4p8qX-VL$yp9A^(RJ&+oWG{C3I_MAU3$1+BhGMY@SyU{dJzvQfe^vcZ9ZBy zl+~_9)G%oW&|IK6%pzN4VJ|4tCS7eo%7QmiYb1a$kZ>ssb0N>{0kMFVZsKy*Bg{r( z&dDbnP9O19JmaWm$$Fmyq4Ki#3CPg-%;Ej~u*+DS4X;@5fcY~wCEjy45&N4FlfNug zy)@fgm_K^2tFTw9Gi-FpTQq`ahPaxwEqm08Gzm5YeGl$*6PmDvNQ#?_wGZkl%2S*) zj?8KA@uyr`y{*YXvN7s3HzP4tbMK3-enU3^SJbO+>{CZo-W2chHl2m{cHZt*3stlm zkExJFW4&0+oFmoEFDOrT5rS(wr775=iMB_2`kB2B>3)e)t&PWzpcV}g7;u2C@q72O z`C=A>l=}I5`IV1QXIQSq$^oJ>;!hRT%lPikDS8ICY7C;i(2d(ZiZSO?OwS&=UZU|L z>4uN0bdm&vk46<&oOr%iG4WLc?9$m()fC>jx}RV_ih;{}M){;BjSCcS^&CBHUHaO1 zPT8RXQN=xrnVlOd=u$mct))6Q3$uRN=SUezb1tFv%uj7~)=XDq$%iRY1s6I&%LUh-oacUvE6~!%HoY`*g7){BA)5R zP10F;@_4Bap5p{7ugfPZ)9}6+7t8>7AQEQLNCt0>R}-XdJlpOxF}VctEdsDXpGgnbGe?o5?RTJkQkHZe_VD?fgP{Z= zYW1s_1?x(-Zs_fjmTm(h0gyAKe{tNN{0N40y(p2f0L)uew%DZN6CoFXyS58u>4#r? ztKNgZdee$4%A8b4)>HwETLW~L*D>wTE##@q(^ zBeRf0v8WLFf_5V(s*Z7=HR>ymFn_5MY=^VzwxTS1PP>^oiJusUT9_I>tapv;17GfQ z3A_spTes(i((2?*xMiq&2NSnWfSKq=`VBNDvf%~Wn<|aHcvPUu?_h(|G+kAg+gM0} z;SX?f$kEt6aLjj10JKHNjmUZl`_B|xfEbz(=bb+xKEO?5R~@sQTjn4qNe5FUvY3W< z<~e@^{BPgZ*>Rmo|n2A*Ym QS79}f`_V2ur+}ot0sK-87XSbN literal 0 HcmV?d00001 diff --git a/images/components/console/process-helper-verbose.png b/images/components/console/process-helper-verbose.png new file mode 100644 index 0000000000000000000000000000000000000000..c4c912e14331dc53482e25571d1f16ad4018765a GIT binary patch literal 14289 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 literal 0 HcmV?d00001 From c0fdca7ab1b7a5ab30415a7a4d5ae1236a89427b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Andrieu?= Date: Thu, 10 Apr 2014 15:58:42 +0200 Subject: [PATCH 0297/1181] [Expression Langage] be consistent in "print/print out" uses --- components/expression_language/syntax.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index e8cf7b859aa..49dd43b42cd 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -49,7 +49,7 @@ to JavaScript:: ) ); -This will print ``Honeycrisp``. +This will print out ``Honeycrisp``. Calling Methods ~~~~~~~~~~~~~~~ @@ -79,7 +79,7 @@ JavaScript:: ) ); -This will print ``Hi Hi Hi!``. +This will print out ``Hi Hi Hi!``. .. _component-expression-functions: @@ -97,7 +97,7 @@ constant:: 'constant("DB_USER")' ); -This will print ``root``. +This will print out ``root``. .. tip:: @@ -121,7 +121,7 @@ array keys, similar to JavaScript:: ) ); -This will print ``42``. +This will print out ``42``. Supported Operators ------------------- From 4fc3b6acd768a9c54249b10fa7746fb80b69b506 Mon Sep 17 00:00:00 2001 From: bfgasparin Date: Thu, 10 Apr 2014 17:22:26 -0300 Subject: [PATCH 0298/1181] Fixed internals.rst syntax --- book/internals.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/internals.rst b/book/internals.rst index 829120a3047..250242b7277 100644 --- a/book/internals.rst +++ b/book/internals.rst @@ -229,8 +229,8 @@ each event has access to the same basic information: * :method:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent::getRequest` - returns the current ``Request`` being handled. -``IsMasterRequest()`` -.................... +``isMasterRequest()`` +..................... The ``isMasterRequest()`` method allows listeners to check the type of the request. For instance, if a listener must only be active for master requests, From 319bf2935113d28840007e49b5702b0c2f683156 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 12 Apr 2014 10:38:34 -0400 Subject: [PATCH 0299/1181] [#3729] Making minor changes thansk to @WouterJ and @xabbuh. --- components/property_access/introduction.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/components/property_access/introduction.rst b/components/property_access/introduction.rst index 2fabbf2119b..7b1193cb9fa 100644 --- a/components/property_access/introduction.rst +++ b/components/property_access/introduction.rst @@ -314,12 +314,13 @@ Checking Property Paths .. versionadded:: 2.5 The methods - :method:`PropertyAccessor::isReadable` + :method:`PropertyAccessor::isReadable ` and - :method:`PropertyAccessor::isWritable` - methods were added in Symfony 2.5. + :method:`PropertyAccessor::isWritable ` + methods were introduced in Symfony 2.5. -When you want to check whether :method:`PropertyAccessor::getValue` +When you want to check whether +:method:`PropertyAccessor::getValue` can safely be called without actually calling that method, you can use :method:`PropertyAccessor::isReadable` instead:: From fb9fe9971ebcf414a819f129c53c6ff7407967b5 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 12 Apr 2014 10:38:43 -0400 Subject: [PATCH 0300/1181] [#3729] Removing 3rd argument to isWritable - this doesn't exist in the final merged item --- components/property_access/introduction.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/property_access/introduction.rst b/components/property_access/introduction.rst index 7b1193cb9fa..dfd457f7d4d 100644 --- a/components/property_access/introduction.rst +++ b/components/property_access/introduction.rst @@ -334,12 +334,11 @@ instead:: The same is possible for :method:`PropertyAccessor::setValue`: Call the :method:`PropertyAccessor::isWritable` -method to find out whether a property path can be updated. In the third -argument, you should pass the value that you want to write:: +method to find out whether a property path can be updated:: $person = new Person(); - if ($accessor->isWritable($person, 'firstName', 'Wouter') { + if ($accessor->isWritable($person, 'firstName') { // ... } From 552c780925cbc36a1896813250e1f6057be69f4f Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 12 Apr 2014 11:35:28 -0400 Subject: [PATCH 0301/1181] Revert "[Console] Add Process Helper documentation" This reverts commit 1705231f31b0120ab40f0a7dfb1cb1fc834dc7cc. --- components/console/helpers/index.rst | 1 - components/console/helpers/map.rst.inc | 1 - components/console/helpers/processhelper.rst | 56 ------------------ .../console/process-helper-debug.png | Bin 28822 -> 0 bytes .../console/process-helper-error-debug.png | Bin 19108 -> 0 bytes .../console/process-helper-verbose.png | Bin 14289 -> 0 bytes 6 files changed, 58 deletions(-) delete mode 100644 components/console/helpers/processhelper.rst delete mode 100644 images/components/console/process-helper-debug.png delete mode 100644 images/components/console/process-helper-error-debug.png delete mode 100644 images/components/console/process-helper-verbose.png diff --git a/components/console/helpers/index.rst b/components/console/helpers/index.rst index 7fcfe78fd4b..357b4bc071d 100644 --- a/components/console/helpers/index.rst +++ b/components/console/helpers/index.rst @@ -9,7 +9,6 @@ The Console Helpers dialoghelper formatterhelper - processhelper progressbar progresshelper table diff --git a/components/console/helpers/map.rst.inc b/components/console/helpers/map.rst.inc index fbf2e8e8602..ff746b14a78 100644 --- a/components/console/helpers/map.rst.inc +++ b/components/console/helpers/map.rst.inc @@ -1,6 +1,5 @@ * :doc:`/components/console/helpers/dialoghelper` * :doc:`/components/console/helpers/formatterhelper` -* :doc:`/components/console/helpers/processhelper` * :doc:`/components/console/helpers/progressbar` * :doc:`/components/console/helpers/progresshelper` * :doc:`/components/console/helpers/table` diff --git a/components/console/helpers/processhelper.rst b/components/console/helpers/processhelper.rst deleted file mode 100644 index f9fd141ffcd..00000000000 --- a/components/console/helpers/processhelper.rst +++ /dev/null @@ -1,56 +0,0 @@ -.. index:: - single: Console Helpers; Process Helper - -Process Helper -============== - -.. versionadded:: 2.5 - The Process Helper was introduced in Symfony 2.5. - -The Process Helper shows processes as they're running and reports -useful information about process status. - -To display process details, use the :class:`Symfony\\Component\\Console\\Helper\\ProcessHelper` -and run your command with verbosity. For example, running the following code with -a very verbose verbosity (e.g. -vv):: - - use Symfony\Component\Process\ProcessBuilder; - - $helper = $this->getHelperSet()->get('process'); - $process = ProcessBuilder::create(array('figlet', 'Symfony'))->getProcess(); - - $helper->run($output, $process); - -will result in this output: - -.. image:: /images/components/console/process-helper-verbose.png - -It will result in more detailed output with debug verbosity (e.g. -vvv): - -.. image:: /images/components/console/process-helper-debug.png - -In case the process fails, debugging is easier: - -.. image:: /images/components/console/process-helper-error-debug.png - -There are three ways to use the process helper: using a command line string, an array -of arguments that would be escaped or a :class:`Symfony\\Component\\Process\\Process` -object. - -You can display a customized error message using the third argument of the -:method:`Symfony\\Component\\Console\\Helper\\ProcessHelper::run` method:: - - $helper->run($output, $process, 'The process failed :('); - -A custom process callback can be passed as fourth argument, refer to the -:doc:`Process Component ` for callback documentation:: - - use Symfony\Component\Process\Process; - - $helper->run($output, $process, 'The process failed :(', function ($type, $data) { - if (Process::ERR === $type) { - // do something with the stderr output - } else { - // do something with the stdout - } - }); diff --git a/images/components/console/process-helper-debug.png b/images/components/console/process-helper-debug.png deleted file mode 100644 index 282e1336389762bb88f5fa6d61d4669066c483de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28822 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 diff --git a/images/components/console/process-helper-error-debug.png b/images/components/console/process-helper-error-debug.png deleted file mode 100644 index 8d1145478f2e3a0d6c0ee2074ea50883bd7c5107..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19108 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 QS79}f`_V2ur+}ot0sK-87XSbN diff --git a/images/components/console/process-helper-verbose.png b/images/components/console/process-helper-verbose.png deleted file mode 100644 index c4c912e14331dc53482e25571d1f16ad4018765a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14289 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 From eef3313d69a5ce5f231c91cf3cfedd9cac0d8e7c Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 12 Apr 2014 11:47:27 -0400 Subject: [PATCH 0302/1181] [#3752] Adding the question helper to the helper list and marking dialog as deprecated --- components/console/introduction.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/console/introduction.rst b/components/console/introduction.rst index 801ac379344..963c07bb30f 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -402,10 +402,11 @@ Console Helpers The console component also contains a set of "helpers" - different small tools capable of helping you with different tasks: -* :doc:`/components/console/helpers/dialoghelper`: interactively ask the user for information +* :doc:`/components/console/helpers/questionhelper`: interactively ask the user for information * :doc:`/components/console/helpers/formatterhelper`: customize the output colorization * :doc:`/components/console/helpers/progresshelper`: shows a progress bar * :doc:`/components/console/helpers/tablehelper`: displays tabular data as a table +* :doc:`/components/console/helpers/dialoghelper`: (deprecated) interactively ask the user for information Testing Commands ---------------- From 98288fcf789197b5c7a26a6a44ccbdabc911690f Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sun, 13 Apr 2014 12:43:31 +0200 Subject: [PATCH 0303/1181] Updated changelog for March --- changelog.rst | 118 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/changelog.rst b/changelog.rst index ca2995a01cc..0187663a180 100644 --- a/changelog.rst +++ b/changelog.rst @@ -141,4 +141,120 @@ Minor Documentation Changes - `80a90ba `_ #3500 Minimize horizontal scrolling in code blocks (improve readability) (ifdattic) - `e5bc4ea `_ #3498 Remove second empty data (xabbuh) - `d084d87 `_ #3485 [Cookbook][Assetic] Fix "javascripts" tag name typo (bicpi) -- `3250aba `_ #3481 Fix code block (minimise horizontal scrolling), typo in yaml (ifdattic) \ No newline at end of file +- `3250aba `_ #3481 Fix code block (minimise horizontal scrolling), typo in yaml (ifdattic) + +March, 2014 +----------- + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `3b640aa `_ #3644 made some small addition about our BC promise and semantic versioning (fabpot) +- `2d1ecd9 `_ #3525 Update file_uploads.rst (juanmf) +- `b1e8f56 `_ #3368 The host parameter has to be in defaults, not requirements (MarieMinasyan) +- `b34fb64 `_ #3619 [Validator] Uuid constraint reference (colinodell) +- `d7027c0 `_ #3418 [Validation] Add "hasser" support (bicpi) +- `4fd5fc1 `_ #3539 [Stopwatch] Describe retrieval of StopwatchEvent (jochenvdv) +- `1908a15 `_ #3696 [Console] Added standalone PSR-3 compliant logger (dunglas) +- `c75b1a7 `_ #3621 [Console] Command as service (gnugat) +- `00a462a `_ minor #3658 Fix PSR coding standards error (ifdattic) +- `acf255d `_ #3328 [WIP] Travis integration (WouterJ) +- `450146e `_ #3681 Enhanced Firewall Restrictions docs (danez) +- `3e7028d `_ #3659 [Internals] Complete notification description for kernel.terminate (bicpi) +- `db3cde7 `_ #3124 Add note about the property attribute (Property Accessor) (raziel057) +- `5965ec8 `_ #3420 [Cookbook][Configuration] add configuration cookbook handlig parameters in Configurator class (cordoval) +- `dcf8e6e `_ #3402 Added documentation about new requests formats configuration (gquemener) +- `a1050eb `_ #3411 [Cookbook][Dynamic Form Modification] Add AJAX sample (bicpi) +- `842fd30 `_ #3683 [TwigBundle] Add documentation about generating absolute URL with the asset function (romainneutron) +- `fc1576a `_ #3664 [Process] Add doc for ``Process::disableOutput`` and ``Process::enableOutput`` (romainneutron) +- `3731e2e `_ #3686 Documentation of the new PSR-4 class loader. (derrabus) +- `5b915c2 `_ #3629 Added documentation for translation:debug (florianv) +- `6951460 `_ #3601 Added documentation for missing ctype extension (slavafomin) +- `df63740 `_ #3627 added docs for the new Table console helper (fabpot) +- `96bd81b `_ #3626 added documentation for the new Symfony 2.5 progress bar (fabpot) +- `b02c16a `_ #3565 added information on AuthenticationFailureHandlerInterface (samsamm777) +- `2657ee7 `_ #3597 Document how to create a custom type guesser (WouterJ) +- `5ad1599 `_ #3577 Development of custom error pages is impractical if you need to set kernel.debug=false (mpdude) +- `3f4b319 `_ #3610 [HttpFoundation] Add doc for ``Request::getContent()`` method (bicpi) +- `56bc266 `_ #3589 Finishing the Templating component docs (WouterJ) +- `d881181 `_ #3588 Documented all form variables (WouterJ) +- `5cda1c7 `_ #3311 Use KernelTestCase instead of WebTestCase for testing code only requiring the Container (johnkary) +- `e96e12d `_ #3234 [Cookbook] New cookbok: How to use the Cloud to send Emails (bicpi) +- `d5d64ce `_ #3436 [Reference][Form Types] Add missing docs for "action" and "method" option (bicpi) +- `3df34af `_ #3490 Tweaking Doctrine book chapter (WouterJ) +- `b9608a7 `_ #3594 New Data Voter Article (continuation) (weaverryan) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `cad38ae `_ #3721 tweaks to the Console logger (xabbuh) +- `06c56c1 `_ #3709 [Components][Security] Fix #3708 (bicpi) +- `aadc61d `_ #3707 make method supportsClass() in custom voter compatible with the interface's documentation (xabbuh) +- `65150f9 `_ #3637 Update render_without_controller.rst (94noni) +- `9fcccc7 `_ #3634 Fix goal of “framework.profiler.only_exceptions“ option which profile on each exceptions on controller (not only 500) (stephpy) +- `9dd8d96 `_ #3689 Fix cache warmer description (WouterJ) +- `6221f35 `_ #3671 miss extends keyword in define BlogController class (ghanbari) +- `4ce7a15 `_ #3543 Fix the definition of customizing form's global errors. (mtrojanowski) +- `5d4a3a4 `_ #3343 [Testing] Fix phpunit test dir paths (bicpi) +- `badaae7 `_ #3622 [Components][Routing] Fix addPrefix() sample code (bicpi) +- `de0a5e1 `_ #3665 [Cookbook][Test] fix sample code (inalgnu) +- `4ef746a `_ #3614 [Internals] Fix Profiler:find() arguments (bicpi) +- `0c41762 `_ #3600 [Security][Authentication] Fix instructions for creating password encoders (bicpi) +- `0ab1f24 `_ #3593 Clarified Default and ClassName groups (WouterJ) +- `178984b `_ #3648 [Routing] Remove outdated tip about sticky locale (bicpi) +- `fc28453 `_ #3039 use DebugClassLoader class from Decomponent instead of the one from ... (xabbuh) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `abca098 `_ #3726 Minor tweaks after merging #3644 by @stof and @xabbuh (weaverryan) +- `d16be31 `_ #3725 Minor tweaks related to #3368 (weaverryan) +- `aa9bb25 `_ #3636 Update security.rst (nomack84) +- `78425c6 `_ #3722 add "Commands as Services" chapter to the cookbook's map (xabbuh) +- `9f26da8 `_ #3720 [#3539] A backport of a sentence - the parts that apply to 2.3 (weaverryan) +- `4b611d6 `_ #3717 [master] Fixed versionadded blocks (WouterJ) +- `5a3ba1b `_ #3715 change variable name to a better fitting one (xabbuh) +- `499eb6c `_ #3714 [2.4] Versionadded consistency (WouterJ) +- `e7580c0 `_ #3713 Updated versionadded directives to use "introduced" (WouterJ) +- `e15afe0 `_ #3711 Simplified the Travis configuration (stof) +- `db1cda5 `_ #3700 [Cookbook][Security] Firewall restrictions tweaks (xabbuh) +- `5035837 `_ #3706 Add support for nginx (guiditoito) +- `00a462a `_ #3658 Fix PSR coding standards error (ifdattic) +- `868de1e `_ #3698 Dynamic form modification cookbook: Fix inclusion of code (michaelperrin) +- `15a9d25 `_ #3697 [Console] Change Command namespaces (dunglas) +- `41b2eb8 `_ #3693 Tweak to Absolute URL generation (weaverryan) +- `bd473db `_ #3563 Add another tip to setup permissions (tony-co) +- `67129b1 `_ #3611 [Reference][Forms] add an introductory table containing all options of the basic form type (xabbuh) +- `fd8f7ae `_ #3694 fix the referenced documents names (xabbuh) +- `d617011 `_ #3657 Fix typos, remove trailing whitespace. (ifdattic) +- `1b4f6a6 `_ #3656 Minimize horizontal scrolling, add missing characters, remove trailing whitespace. (ifdattic) +- `7c0c5d1 `_ #3653 Http cache validation rewording (weaverryan) +- `0fb2c5f `_ #3651 [Reference][Forms] remove the label_attr option which is not available in the button type (xabbuh) +- `69ac21b `_ #3642 Fixed some typos and formatting issues (javiereguiluz) +- `93c35d0 `_ #3641 Added some examples to the "services as parameters" section (javiereguiluz) +- `12a6676 `_ #3640 [minor] fixed one typo and one formatting issue (javiereguiluz) +- `9967b0c `_ #3638 [#3116] Fixing wrong table name - singular is used elsewhere (weaverryan) +- `4fbf1cd `_ #3635 [QuickTour] close opened literals (xabbuh) +- `27b3410 `_ #3692 [Book][Translations] fixing a code block (xabbuh) +- `2192c32 `_ #3650 Fixing some build errors (xabbuh) +- `fa3f531 `_ #3677 [Reference][Forms] Remove variables section from tables (xabbuh) +- `cd6d1de `_ #3676 remove unnecessary code block directive (xabbuh) +- `07822b8 `_ #3675 add missing code block directive (xabbuh) +- `739f43f `_ #3669 Fixed syntax highlighting (rvanlaarhoven) +- `1f384bc `_ #3631 Added documentation for message option of the ``True`` constraint (naitsirch) +- `f6a41b9 `_ #3630 Minor tweaks to form action/method (weaverryan) +- `ae755e0 `_ #3628 Added anchor for permissions (WouterJ) +- `6380113 `_ #3667 Update index.rst (NAYZO) +- `97ef2f7 `_ #3566 Changes ACL permission setting hints (MicheleOnGit) +- `9f7d742 `_ #3654 [Cookbook][Security] Fix VoterInterface signature (bicpi) +- `0a65b6f `_ #3608 [Reference][Forms] add versionadded directive for multiple option of file type (xabbuh) +- `e34204e `_ #3605 Fixed a plural issue (benjaminpaap) +- `e7d5a45 `_ #3599 [CHANGELOG] fix reference to contributing docs (xabbuh) +- `3582bf1 `_ #3598 add changelog to hidden toctree (xabbuh) +- `58b7f96 `_ #3596 [HTTP Cache] Validation model: Fix header name (bicpi) +- `6d1378e `_ #3592 Added a tip about hardcoding URLs in functional tests (javiereguiluz) +- `04cf9f8 `_ #3595 Collection of fixes and improvements (bicpi) +- `2ed0943 `_ #3645 Adjusted the BC rules to be consistent (stof) +- `664a0be `_ #3633 Added missing PHP syntax coloration (DerekRoth) +- `1714a31 `_ #3585 Use consistent method chaining in BlogBundle sample application (ockcyp) +- `cb61f4f `_ #3581 Add missing hyphen in HTTP Fundamentals page (ockcyp) From 512ae2c512580a30e84a19a2155e4c8648f836c3 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sun, 13 Apr 2014 12:41:19 +0200 Subject: [PATCH 0304/1181] Updated changelog for March --- changelog.rst | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/changelog.rst b/changelog.rst index 6264bee4693..bb3f4e54a2c 100644 --- a/changelog.rst +++ b/changelog.rst @@ -132,4 +132,99 @@ Minor Documentation Changes - `80a90ba `_ #3500 Minimize horizontal scrolling in code blocks (improve readability) (ifdattic) - `e5bc4ea `_ #3498 Remove second empty data (xabbuh) - `d084d87 `_ #3485 [Cookbook][Assetic] Fix "javascripts" tag name typo (bicpi) -- `3250aba `_ #3481 Fix code block (minimise horizontal scrolling), typo in yaml (ifdattic) \ No newline at end of file +- `3250aba `_ #3481 Fix code block (minimise horizontal scrolling), typo in yaml (ifdattic) + +March, 2014 +----------- + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `3b640aa `_ #3644 made some small addition about our BC promise and semantic versioning (fabpot) +- `2d1ecd9 `_ #3525 Update file_uploads.rst (juanmf) +- `b1e8f56 `_ #3368 The host parameter has to be in defaults, not requirements (MarieMinasyan) +- `c75b1a7 `_ #3621 [Console] Command as service (gnugat) +- `00a462a `_ minor #3658 Fix PSR coding standards error (ifdattic) +- `acf255d `_ #3328 [WIP] Travis integration (WouterJ) +- `3e7028d `_ #3659 [Internals] Complete notification description for kernel.terminate (bicpi) +- `db3cde7 `_ #3124 Add note about the property attribute (Property Accessor) (raziel057) +- `5965ec8 `_ #3420 [Cookbook][Configuration] add configuration cookbook handlig parameters in Configurator class (cordoval) +- `a1050eb `_ #3411 [Cookbook][Dynamic Form Modification] Add AJAX sample (bicpi) +- `6951460 `_ #3601 Added documentation for missing ctype extension (slavafomin) +- `b02c16a `_ #3565 added information on AuthenticationFailureHandlerInterface (samsamm777) +- `2657ee7 `_ #3597 Document how to create a custom type guesser (WouterJ) +- `5ad1599 `_ #3577 Development of custom error pages is impractical if you need to set kernel.debug=false (mpdude) +- `3f4b319 `_ #3610 [HttpFoundation] Add doc for ``Request::getContent()`` method (bicpi) +- `56bc266 `_ #3589 Finishing the Templating component docs (WouterJ) +- `d881181 `_ #3588 Documented all form variables (WouterJ) +- `e96e12d `_ #3234 [Cookbook] New cookbok: How to use the Cloud to send Emails (bicpi) +- `d5d64ce `_ #3436 [Reference][Form Types] Add missing docs for "action" and "method" option (bicpi) +- `3df34af `_ #3490 Tweaking Doctrine book chapter (WouterJ) +- `b9608a7 `_ #3594 New Data Voter Article (continuation) (weaverryan) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `06c56c1 `_ #3709 [Components][Security] Fix #3708 (bicpi) +- `aadc61d `_ #3707 make method supportsClass() in custom voter compatible with the interface's documentation (xabbuh) +- `65150f9 `_ #3637 Update render_without_controller.rst (94noni) +- `9fcccc7 `_ #3634 Fix goal of “framework.profiler.only_exceptions“ option which profile on each exceptions on controller (not only 500) (stephpy) +- `9dd8d96 `_ #3689 Fix cache warmer description (WouterJ) +- `6221f35 `_ #3671 miss extends keyword in define BlogController class (ghanbari) +- `4ce7a15 `_ #3543 Fix the definition of customizing form's global errors. (mtrojanowski) +- `5d4a3a4 `_ #3343 [Testing] Fix phpunit test dir paths (bicpi) +- `badaae7 `_ #3622 [Components][Routing] Fix addPrefix() sample code (bicpi) +- `de0a5e1 `_ #3665 [Cookbook][Test] fix sample code (inalgnu) +- `4ef746a `_ #3614 [Internals] Fix Profiler:find() arguments (bicpi) +- `0c41762 `_ #3600 [Security][Authentication] Fix instructions for creating password encoders (bicpi) +- `0ab1f24 `_ #3593 Clarified Default and ClassName groups (WouterJ) +- `178984b `_ #3648 [Routing] Remove outdated tip about sticky locale (bicpi) +- `fc28453 `_ #3039 use DebugClassLoader class from Decomponent instead of the one from ... (xabbuh) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `abca098 `_ #3726 Minor tweaks after merging #3644 by @stof and @xabbuh (weaverryan) +- `d16be31 `_ #3725 Minor tweaks related to #3368 (weaverryan) +- `aa9bb25 `_ #3636 Update security.rst (nomack84) +- `78425c6 `_ #3722 add "Commands as Services" chapter to the cookbook's map (xabbuh) +- `9f26da8 `_ #3720 [#3539] A backport of a sentence - the parts that apply to 2.3 (weaverryan) +- `5a3ba1b `_ #3715 change variable name to a better fitting one (xabbuh) +- `499eb6c `_ #3714 [2.4] Versionadded consistency (WouterJ) +- `e7580c0 `_ #3713 Updated versionadded directives to use "introduced" (WouterJ) +- `e15afe0 `_ #3711 Simplified the Travis configuration (stof) +- `5035837 `_ #3706 Add support for nginx (guiditoito) +- `00a462a `_ #3658 Fix PSR coding standards error (ifdattic) +- `868de1e `_ #3698 Dynamic form modification cookbook: Fix inclusion of code (michaelperrin) +- `41b2eb8 `_ #3693 Tweak to Absolute URL generation (weaverryan) +- `bd473db `_ #3563 Add another tip to setup permissions (tony-co) +- `67129b1 `_ #3611 [Reference][Forms] add an introductory table containing all options of the basic form type (xabbuh) +- `fd8f7ae `_ #3694 fix the referenced documents names (xabbuh) +- `d617011 `_ #3657 Fix typos, remove trailing whitespace. (ifdattic) +- `1b4f6a6 `_ #3656 Minimize horizontal scrolling, add missing characters, remove trailing whitespace. (ifdattic) +- `7c0c5d1 `_ #3653 Http cache validation rewording (weaverryan) +- `0fb2c5f `_ #3651 [Reference][Forms] remove the label_attr option which is not available in the button type (xabbuh) +- `69ac21b `_ #3642 Fixed some typos and formatting issues (javiereguiluz) +- `93c35d0 `_ #3641 Added some examples to the "services as parameters" section (javiereguiluz) +- `12a6676 `_ #3640 [minor] fixed one typo and one formatting issue (javiereguiluz) +- `9967b0c `_ #3638 [#3116] Fixing wrong table name - singular is used elsewhere (weaverryan) +- `4fbf1cd `_ #3635 [QuickTour] close opened literals (xabbuh) +- `2192c32 `_ #3650 Fixing some build errors (xabbuh) +- `fa3f531 `_ #3677 [Reference][Forms] Remove variables section from tables (xabbuh) +- `07822b8 `_ #3675 add missing code block directive (xabbuh) +- `1f384bc `_ #3631 Added documentation for message option of the ``True`` constraint (naitsirch) +- `f6a41b9 `_ #3630 Minor tweaks to form action/method (weaverryan) +- `ae755e0 `_ #3628 Added anchor for permissions (WouterJ) +- `6380113 `_ #3667 Update index.rst (NAYZO) +- `97ef2f7 `_ #3566 Changes ACL permission setting hints (MicheleOnGit) +- `9f7d742 `_ #3654 [Cookbook][Security] Fix VoterInterface signature (bicpi) +- `e34204e `_ #3605 Fixed a plural issue (benjaminpaap) +- `e7d5a45 `_ #3599 [CHANGELOG] fix reference to contributing docs (xabbuh) +- `3582bf1 `_ #3598 add changelog to hidden toctree (xabbuh) +- `58b7f96 `_ #3596 [HTTP Cache] Validation model: Fix header name (bicpi) +- `6d1378e `_ #3592 Added a tip about hardcoding URLs in functional tests (javiereguiluz) +- `04cf9f8 `_ #3595 Collection of fixes and improvements (bicpi) +- `2ed0943 `_ #3645 Adjusted the BC rules to be consistent (stof) +- `664a0be `_ #3633 Added missing PHP syntax coloration (DerekRoth) +- `1714a31 `_ #3585 Use consistent method chaining in BlogBundle sample application (ockcyp) +- `cb61f4f `_ #3581 Add missing hyphen in HTTP Fundamentals page (ockcyp) From 14a78d3750fcab5e7931272ee2b6bd93b9274132 Mon Sep 17 00:00:00 2001 From: Stacy Horton Date: Thu, 17 Apr 2014 16:17:37 +1000 Subject: [PATCH 0305/1181] Fixed broken link in "Handling Authentication Failure" --- cookbook/security/api_key_authentication.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index a5c9f409200..1965847c009 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -215,7 +215,7 @@ Handling Authentication Failure In order for your ``ApiKeyAuthentication`` to correctly display a 403 http status when either bad credentials or authentication fails you will -need to implement the :class:`Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface` on your +need to implement the :class:`Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationFailureHandlerInterface` on your Authenticator. This will provide a method ``onAuthenticationFailure`` which you can use to create an error ``Response``. From ea07ef15bc766477ff2781bdcf84ae23b7019a1f Mon Sep 17 00:00:00 2001 From: mimol91 Date: Sat, 12 Apr 2014 17:04:33 +0200 Subject: [PATCH 0306/1181] Update commands_as_services.rst Missing parent construct --- cookbook/console/commands_as_services.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cookbook/console/commands_as_services.rst b/cookbook/console/commands_as_services.rst index 09bfe12d77b..60f22824686 100644 --- a/cookbook/console/commands_as_services.rst +++ b/cookbook/console/commands_as_services.rst @@ -90,6 +90,8 @@ have some ``NameRepository`` service that you'll use to get your default value:: public function __construct(NameRepository $nameRepository) { + parent::__construct(); + $this->nameRepository = $nameRepository; } From 27360b6897735be6a5f791d1215f379327e8ef60 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 5 May 2014 18:39:44 +0200 Subject: [PATCH 0307/1181] fix the wording in versionadded directives --- components/debug/introduction.rst | 4 ++-- components/process.rst | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/components/debug/introduction.rst b/components/debug/introduction.rst index 5691ca58be4..8f3fc17102e 100644 --- a/components/debug/introduction.rst +++ b/components/debug/introduction.rst @@ -8,8 +8,8 @@ The Debug Component The Debug component provides tools to ease debugging PHP code. .. versionadded:: 2.3 - The Debug component is new to Symfony 2.3. Previously, the classes were - located in the HttpKernel component. + The Debug component was introduced in Symfony 2.3. Previously, the classes + were located in the HttpKernel component. Installation ------------ diff --git a/components/process.rst b/components/process.rst index 9c93207ff18..1170c54a479 100644 --- a/components/process.rst +++ b/components/process.rst @@ -219,7 +219,8 @@ Process Idle Timeout -------------------- .. versionadded:: 2.4 - The :method:`Symfony\\Component\\Process\\Process::setIdleTimeout` method was added in Symfony 2.4. + The :method:`Symfony\\Component\\Process\\Process::setIdleTimeout` method + was introduced in Symfony 2.4. In contrast to the timeout of the previous paragraph, the idle timeout only considers the time since the last output was produced by the process:: From 560e010de144488f308a2b17f804ff833e8252bc Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 6 May 2014 07:56:24 -0500 Subject: [PATCH 0308/1181] Adding more details to be clear that you can set asset version globally or locally on an asset --- book/templating.rst | 29 ++++++++++--------- .../templating/helpers/assetshelper.rst | 3 +- reference/configuration/framework.rst | 4 +++ 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/book/templating.rst b/book/templating.rst index d2a3301a8b8..7c3c31aa7a8 100644 --- a/book/templating.rst +++ b/book/templating.rst @@ -991,40 +991,43 @@ assets won't be cached when deployed. For example, ``/images/logo.png`` might look like ``/images/logo.png?v2``. For more information, see the :ref:`ref-framework-assets-version` configuration option. +.. _` + .. versionadded:: 2.5 - Absolute URLs for assets were introduced in Symfony 2.5. + Setting versioned URLs on an asset-by-asset basis were introduced in Symfony 2.5. -If you need absolute URLs for assets, you can set the third argument (or the -``absolute`` argument) to ``true``: +If you need to set a version for a specific asset, you can set the fourth +argument (or the ``version`` argument) to the desired version: .. configuration-block:: .. code-block:: html+jinja - Symfony! + Symfony! .. code-block:: html+php - Symfony! + Symfony! + +If you dont give a version or pass ``null``, the default package version +(from :ref:`ref-framework-assets-version`) wil be used. If you pass ``false``, +versioned URL will be deactivated for this asset. .. versionadded:: 2.5 - Versioned URLs for assets were introduced in Symfony 2.5. + Absolute URLs for assets were introduced in Symfony 2.5. -If you need versioned URLs for assets, you can set the fourth argument (or the -``version`` argument) to the desired version: +If you need absolute URLs for assets, you can set the third argument (or the +``absolute`` argument) to ``true``: .. configuration-block:: .. code-block:: html+jinja - Symfony! + Symfony! .. code-block:: html+php - Symfony! - -If you dont give a version or pass ``null``, the default package version will -be used. If you pass ``false``, versioned URL will be deactivated. + Symfony! .. index:: single: Templating; Including stylesheets and JavaScripts diff --git a/components/templating/helpers/assetshelper.rst b/components/templating/helpers/assetshelper.rst index 6f096d35c52..8e8dbf857bc 100644 --- a/components/templating/helpers/assetshelper.rst +++ b/components/templating/helpers/assetshelper.rst @@ -83,7 +83,8 @@ second is the version. For instance, ``%s?v=%s`` will be rendered as .. versionadded:: 2.5 On-demand versioned URLs for assets were introduced in Symfony 2.5. -You can also generate a versioned URL using the fourth argument of the helper: +You can also generate a versioned URL on an asset-by-asset basis using the +fourth argument of the helper: .. code-block:: html+php diff --git a/reference/configuration/framework.rst b/reference/configuration/framework.rst index 79c62088a62..a57f578887d 100644 --- a/reference/configuration/framework.rst +++ b/reference/configuration/framework.rst @@ -369,6 +369,10 @@ Now, the same asset will be rendered as ``/images/logo.png?v2`` If you use this feature, you **must** manually increment the ``assets_version`` value before each deployment so that the query parameters change. +It's also possible to set the version value on an asset-by-asset basis (instead +of using the global version - e.g. ``v2`` - set here). See +:ref:`Versioning by Asset ` for details. + You can also control how the query string works via the `assets_version_format`_ option. From 66dffb04dfb23b505ab854f49647e7e8463c981a Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 6 May 2014 16:37:54 +0200 Subject: [PATCH 0309/1181] Added April changelog --- changelog.rst | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/changelog.rst b/changelog.rst index bb3f4e54a2c..3de4a85fa59 100644 --- a/changelog.rst +++ b/changelog.rst @@ -228,3 +228,56 @@ Minor Documentation Changes - `664a0be `_ #3633 Added missing PHP syntax coloration (DerekRoth) - `1714a31 `_ #3585 Use consistent method chaining in BlogBundle sample application (ockcyp) - `cb61f4f `_ #3581 Add missing hyphen in HTTP Fundamentals page (ockcyp) + + +April, 2014 +----------- + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `322972e `_ #3803 [Book][Validation] configuration examples for the GroupSequenceProvider (xabbuh) +- `d4ca16a `_ #3743 Improve examples in parent services (WouterJ) +- `70a3893 `_ #3774 [Book][Internals] add description for the kernel.finish_request event (xabbuh) +- `d611e77 `_ #3701 [Serializer] add documentation for serializer callbacks (cordoval) +- `80c645c `_ #3719 Fixed event listeners priority (tony-co) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `f801e2e `_ #3805 Add missing autocomplete argument in askAndValidate method (ifdattic) +- `a81d367 `_ #3786 replaceArguments should be setArguments (RobinvdVleuten) +- `33b64e1 `_ #3788 Fix link for StopwatchEvent class (rpg600) +- `2ebabfb `_ #3792 Update commands_as_services.rst (mimol91) +- `529d4ce `_ #3761 buildViewBottomUp has been renamed to finishView (Nyholm) +- `d743139 `_ #3768 the Locale component does not have elements tagged with @api (xabbuh) +- `2b8e44d `_ #3747 Fix Image constraint class and validator link (weaverryan) +- `fa362ca `_ #3741 correct RuntimeException reference (shieldo) +- `d92545e `_ #3734 [book] [testing] fixed the path of the phpunit.xml file (javiereguiluz) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `136f98c `_ #3784 [Expression Langage] be consistent in "print/print out" uses (mickaelandrieu) +- `1094a13 `_ #3807 Added some exceptions to the method order in CS (stof) +- `55442b5 `_ #3800 Fixed another blockquote rendering issue (WouterJ) +- `969fd71 `_ #3785 ensure that destination directories don't exist before creating them (xabbuh) +- `79322ff `_ #3799 Fix list to not render in a block quote (WouterJ) +- `1a6f730 `_ #3793 language tweak for the tip introduced in #3743 (xabbuh) +- `dda9e88 `_ #3778 Adding information on internal reverse proxy (tcz) +- `d36bbd9 `_ #3765 [WIP] make headlines consistent with our standards (xabbuh) +- `daa81a0 `_ #3766 [Book] add note about services and the service container in the form cha... (xabbuh) +- `4529858 `_ #3767 [Book] link to the bc promise in the stable API description (xabbuh) +- `a5471b3 `_ #3775 Fixed variable naming (peterrehm) +- `703c2a6 `_ #3772 [Cookbook][Sessions] some language improvements (xabbuh) +- `3d30b56 `_ #3773 modify Symfony CMF configuration values in the build process so that the... (xabbuh) +- `cfd6d7c `_ #3758 [Book][Routing] Fixed typo on PHP version of a route definition (saro0h) +- `6bd134c `_ #3754 ignore more files and directories which are created when building the documentation (xabbuh) +- `610462e `_ #3755 [Cookbook][Security] Firewall resitrction tweaks, fix markup, add to toc (xabbuh) +- `0a21718 `_ #3695 Firewall backport (weaverryan) +- `54d6a9e `_ #3736 [book] Misc. routing fixes (javiereguiluz) +- `f149dcf `_ #3739 [book] [forms] misc. fixes and tweaks (javiereguiluz) +- `ce582ec `_ #3735 [book] [controller] fixed the code of a session sample code (javiereguiluz) +- `499ba5c `_ #3733 [book] [validation] fixed typos (javiereguiluz) +- `4d0ff8f `_ #3732 Update routing.rst. Explain using url() v. path(). (ackerman) +- `44c6273 `_ #3727 Added a note about inlined private services (javiereguiluz) \ No newline at end of file From 513a389cb9aa45bc676016c15f4f156f172f6b31 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 6 May 2014 16:38:43 +0200 Subject: [PATCH 0310/1181] [#3797] Reordered changelog --- changelog.rst | 292 +++++++++++++++++++++++++------------------------- 1 file changed, 145 insertions(+), 147 deletions(-) diff --git a/changelog.rst b/changelog.rst index 3de4a85fa59..bc667a30c9c 100644 --- a/changelog.rst +++ b/changelog.rst @@ -13,126 +13,57 @@ documentation. Do you also want to participate in the Symfony Documentation? Take a look at the ":doc:`/contributing/documentation/overview`" article. - -January, 2014 -------------- - -New Documentation -~~~~~~~~~~~~~~~~~ - -- `d52f3f8 `_ #3454 [Security] Add host option (ghostika) -- `6b3c424 `_ #3428 Translation - Added info about JsonFileLoader added in 2.4 (singles) - -Fixed Documentation -~~~~~~~~~~~~~~~~~~~ - -- `fb22fa0 `_ #3456 remove duplicate label (xabbuh) -- `c205bc6 `_ #3468 enclose YAML string with double quotes to fix syntax highlighting (xabbuh) -- `89963cc `_ #3463 Fix typos in cookbook/testing/database (ifdattic) -- `e0a52ec `_ #3460 remove confusing outdated note on interactive rebasing (xabbuh) -- `6831b13 `_ #3455 [Contributing][Code] fix indentation so that the text is rendered properly (xabbuh) -- `ea5816f `_ #3433 [WIP][Reference][Form Types] Update "radio" form type (bicpi) -- `42c80d1 `_ #3448 Overridden tweak (weaverryan) -- `bede4c3 `_ #3447 Fix error in namespace when use TokenInterface (joanteixi) -- `d9d7c58 `_ #3444 Fix issue #3442 (ifdattic) -- `a6ad607 `_ #3441 [Expression]Change title 'Accessing Public Methods' (Pyrech) -- `9e2e64b `_ #3427 Removed code references to Symfony Standard Distribution (danielcsgomes) -- `3c2c5fc `_ #3435 Update custom_password_authenticator.rst (boardyuk) -- `26b8146 `_ #3415 [#3334] the data_class option was not introduced in 2.4 (xabbuh) -- `0b2a491 `_ #3414 add missing code-block directive (xabbuh) -- `4988118 `_ #3432 [Reference][Form Types] Add "max_length" option in form type (nykopol) -- `26a7b1b `_ #3423 [Session Configuration] add clarifying notes on session save handler proxies (cordoval) -- `f2f5e9a `_ #3421 [Contributing] Cleaning the "contributing patch" page a bit (lemoinem) - -Minor Documentation Changes -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- `f285d93 `_ #3451 some language tweaks (AE, third-person perspective) (xabbuh) -- `b9bbe5d `_ #3499 Fix YAML syntax highlight + remove trailing whitespace (ifdattic) -- `2b7e0f6 `_ #3497 Fix highlighting (WouterJ) -- `a535ae0 `_ #3471 Fixed `````versionadded````` inconsistencies in Symfony 2.3 (danielcsgomes) -- `f077a8e `_ #3465 change wording in versionadded example to be consistent with what we use... (xabbuh) -- `f9f7548 `_ #3462 Replace ... with etc (ifdattic) -- `65efcc4 `_ #3445 [Reference][Form Types] Add missing (but existing) options to "form" type (bicpi) -- `1d1b91d `_ #3431 [Config] add cautionary note on ini file loader limitation (cordoval) -- `f2eaf9b `_ #3419 doctrine file upload example uses dir -- caution added (cordoval) -- `72b53ad `_ #3404 [#3276] Trying to further clarify the session storage directory details (weaverryan) -- `67b7bbd `_ #3413 [Cookbook][Bundles] improve explanation of code block for bundle removal (cordoval) -- `7c5a914 `_ #3369 Indicate that Group Sequence Providers can use YAML (karptonite) -- `1e0311e `_ #3416 add empty_data option where required option is used (xabbuh) -- `2be3f52 `_ #3422 [Cookbook][Custom Authentication Provider] add a note of warning for when forbidding anonymous users (cordoval) -- `e255de9 `_ #3429 [Reference][Form Types] Document "with_minutes" time/datetime option (bicpi) - -February, 2014 --------------- +April, 2014 +----------- New Documentation ~~~~~~~~~~~~~~~~~ -- `9dcf467 `_ #3613 Javiereguiluz revamped quick tour (weaverryan) -- `89c6f1d `_ #3439 [Review] Added detailed Backwards Compatibility Promise text (webmozart) -- `0029408 `_ #3558 Created Documentation CHANGELOG (WouterJ) -- `f6dd678 `_ #3548 Update forms.rst (atmosf3ar) -- `9676f2c `_ #3523 [Components][EventDispatcher] describe that the event name and the event dispatcher are passed to even... (xabbuh) -- `5c367b4 `_ #3517 Fixed OptionsResolver component docs (WouterJ) -- `527c8b6 `_ #3496 Added a section about using named assets (vmattila) +- `322972e `_ #3803 [Book][Validation] configuration examples for the GroupSequenceProvider (xabbuh) +- `d4ca16a `_ #3743 Improve examples in parent services (WouterJ) +- `70a3893 `_ #3774 [Book][Internals] add description for the kernel.finish_request event (xabbuh) +- `d611e77 `_ #3701 [Serializer] add documentation for serializer callbacks (cordoval) +- `80c645c `_ #3719 Fixed event listeners priority (tony-co) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `adcbb5d `_ #3615 Fixes to cookbook/doctrine/registration_form.rst (Crushnaut) -- `5c4336a `_ #3570 Callback: [Validator, validate] expects validate to be static (nixilla) -- `a21fb26 `_ #3559 Remove reference to copying parameters.yml from Git cookbook (pwaring) -- `de71a51 `_ #3551 [Cookbook][Dynamic Form Modification] Fix sample code (rybakit) -- `143db2f `_ #3550 Update introduction.rst (taavit) -- `384538b `_ #3549 Fixed createPropertyAccessorBuilder usage (antonbabenko) -- `d275302 `_ #3541 Update generic_event.rst (Lumbendil) -- `819949c `_ #3537 Add missing variable assignment (colinodell) -- `d7e8262 `_ #3535 fix form type name. (yositani2002) -- `821af3b `_ #3493 Type fix in remove.rst (weaverryan) -- `003230f `_ #3530 Update form_customization.rst (dczech) -- `a43f15a `_ #3519 [Book][Service Container] Fix syntax highlighting (iamdto) -- `86e02c6 `_ #3514 Fixed some small typos in code example (RobinvdVleuten) -- `696313c `_ #3513 [Component-DI] Fixed typo (saro0h) -- `27dcebd `_ #3509 Fix typo: side.bar.twig => sidebar.twig (ifdattic) -- `0dc8c26 `_ #3507 Fix a typo (missing `````) in ``:doc:`` link (ifdattic) -- `272197b `_ #3504 fix include directive so that the contents are really included (xabbuh) -- `e385d28 `_ #3503 file extension correction xfliff to xliff (nixilla) -- `6d34aa6 `_ #3478 Update custom_password_authenticator.rst (piotras-s) -- `a171700 `_ #3477 Api key user provider should use "implements" instead of "extends" (skowi) -- `7fe0de3 `_ #3475 Fixed doc for framework.session.cookie_lifetime refrence. (tyomo4ka) -- `8155e4c `_ #3473 Update proxy_examples.rst (AZielinski) +- `f801e2e `_ #3805 Add missing autocomplete argument in askAndValidate method (ifdattic) +- `a81d367 `_ #3786 replaceArguments should be setArguments (RobinvdVleuten) +- `33b64e1 `_ #3788 Fix link for StopwatchEvent class (rpg600) +- `2ebabfb `_ #3792 Update commands_as_services.rst (mimol91) +- `529d4ce `_ #3761 buildViewBottomUp has been renamed to finishView (Nyholm) +- `d743139 `_ #3768 the Locale component does not have elements tagged with @api (xabbuh) +- `2b8e44d `_ #3747 Fix Image constraint class and validator link (weaverryan) +- `fa362ca `_ #3741 correct RuntimeException reference (shieldo) +- `d92545e `_ #3734 [book] [testing] fixed the path of the phpunit.xml file (javiereguiluz) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `0928249 `_ #3568 Update checkbox_compound.rst.inc (joshuaadickerson) -- `38def3b `_ #3567 Update checkbox_compound.rst.inc (joshuaadickerson) -- `15d8ab8 `_ #3553 Minimize horizontal scrolling in code blocks to improve readability (ifdattic) -- `5120863 `_ #3547 Update acl.rst (iqfoundry) -- `b7ac326 `_ #3557 Minimize horizontal scrolling in code block to improve readability (ifdattic) -- `d974c77 `_ #3556 Fix PSR error (ifdattic) -- `f4bb017 `_ #3555 Wrap variables in {} for safer interpolation (ifdattic) -- `5f02bca `_ #3552 Fix typos (ifdattic) -- `6e32c47 `_ #3546 Fix README: contributions should be based off 2.3 or higher (colinodell) -- `ffa8f76 `_ #3545 Example of getting entity managers directly from the container (colinodell) -- `6a2a55b `_ #3579 Fix build errors (xabbuh) -- `dce2e23 `_ #3532 Added tip for Entity Listeners (slavafomin) -- `73adf8b `_ #3528 Clarify service parameters usages (WouterJ) -- `f634600 `_ #3531 Remove horizontal scrolling in code block (ifdattic) -- `9ba4fa7 `_ #3527 Changes to components domcrawler (ifdattic) -- `8973c81 `_ #3526 Changes for Console component (ifdattic) -- `6848bed `_ #3538 Rebasing #3518 (weaverryan) -- `c838df8 `_ #3511 [Component-DI] Removed useless else statement in code example (saro0h) -- `1af6742 `_ #3510 add empty line (lazyants) -- `1131247 `_ #3508 Add 'in XML' for additional clarity (ifdattic) -- `a650b93 `_ #3506 Nykopol overriden options (weaverryan) -- `ab10035 `_ #3505 replace Akamaï with Akamai (xabbuh) -- `7f56c20 `_ #3501 [Security] Fix markup (tyx) -- `80a90ba `_ #3500 Minimize horizontal scrolling in code blocks (improve readability) (ifdattic) -- `e5bc4ea `_ #3498 Remove second empty data (xabbuh) -- `d084d87 `_ #3485 [Cookbook][Assetic] Fix "javascripts" tag name typo (bicpi) -- `3250aba `_ #3481 Fix code block (minimise horizontal scrolling), typo in yaml (ifdattic) +- `136f98c `_ #3784 [Expression Langage] be consistent in "print/print out" uses (mickaelandrieu) +- `1094a13 `_ #3807 Added some exceptions to the method order in CS (stof) +- `55442b5 `_ #3800 Fixed another blockquote rendering issue (WouterJ) +- `969fd71 `_ #3785 ensure that destination directories don't exist before creating them (xabbuh) +- `79322ff `_ #3799 Fix list to not render in a block quote (WouterJ) +- `1a6f730 `_ #3793 language tweak for the tip introduced in #3743 (xabbuh) +- `dda9e88 `_ #3778 Adding information on internal reverse proxy (tcz) +- `d36bbd9 `_ #3765 [WIP] make headlines consistent with our standards (xabbuh) +- `daa81a0 `_ #3766 [Book] add note about services and the service container in the form cha... (xabbuh) +- `4529858 `_ #3767 [Book] link to the bc promise in the stable API description (xabbuh) +- `a5471b3 `_ #3775 Fixed variable naming (peterrehm) +- `703c2a6 `_ #3772 [Cookbook][Sessions] some language improvements (xabbuh) +- `3d30b56 `_ #3773 modify Symfony CMF configuration values in the build process so that the... (xabbuh) +- `cfd6d7c `_ #3758 [Book][Routing] Fixed typo on PHP version of a route definition (saro0h) +- `6bd134c `_ #3754 ignore more files and directories which are created when building the documentation (xabbuh) +- `610462e `_ #3755 [Cookbook][Security] Firewall resitrction tweaks, fix markup, add to toc (xabbuh) +- `0a21718 `_ #3695 Firewall backport (weaverryan) +- `54d6a9e `_ #3736 [book] Misc. routing fixes (javiereguiluz) +- `f149dcf `_ #3739 [book] [forms] misc. fixes and tweaks (javiereguiluz) +- `ce582ec `_ #3735 [book] [controller] fixed the code of a session sample code (javiereguiluz) +- `499ba5c `_ #3733 [book] [validation] fixed typos (javiereguiluz) +- `4d0ff8f `_ #3732 Update routing.rst. Explain using url() v. path(). (ackerman) +- `44c6273 `_ #3727 Added a note about inlined private services (javiereguiluz) March, 2014 ----------- @@ -229,55 +160,122 @@ Minor Documentation Changes - `1714a31 `_ #3585 Use consistent method chaining in BlogBundle sample application (ockcyp) - `cb61f4f `_ #3581 Add missing hyphen in HTTP Fundamentals page (ockcyp) +February, 2014 +-------------- -April, 2014 ------------ +New Documentation +~~~~~~~~~~~~~~~~~ + +- `9dcf467 `_ #3613 Javiereguiluz revamped quick tour (weaverryan) +- `89c6f1d `_ #3439 [Review] Added detailed Backwards Compatibility Promise text (webmozart) +- `0029408 `_ #3558 Created Documentation CHANGELOG (WouterJ) +- `f6dd678 `_ #3548 Update forms.rst (atmosf3ar) +- `9676f2c `_ #3523 [Components][EventDispatcher] describe that the event name and the event dispatcher are passed to even... (xabbuh) +- `5c367b4 `_ #3517 Fixed OptionsResolver component docs (WouterJ) +- `527c8b6 `_ #3496 Added a section about using named assets (vmattila) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `adcbb5d `_ #3615 Fixes to cookbook/doctrine/registration_form.rst (Crushnaut) +- `5c4336a `_ #3570 Callback: [Validator, validate] expects validate to be static (nixilla) +- `a21fb26 `_ #3559 Remove reference to copying parameters.yml from Git cookbook (pwaring) +- `de71a51 `_ #3551 [Cookbook][Dynamic Form Modification] Fix sample code (rybakit) +- `143db2f `_ #3550 Update introduction.rst (taavit) +- `384538b `_ #3549 Fixed createPropertyAccessorBuilder usage (antonbabenko) +- `d275302 `_ #3541 Update generic_event.rst (Lumbendil) +- `819949c `_ #3537 Add missing variable assignment (colinodell) +- `d7e8262 `_ #3535 fix form type name. (yositani2002) +- `821af3b `_ #3493 Type fix in remove.rst (weaverryan) +- `003230f `_ #3530 Update form_customization.rst (dczech) +- `a43f15a `_ #3519 [Book][Service Container] Fix syntax highlighting (iamdto) +- `86e02c6 `_ #3514 Fixed some small typos in code example (RobinvdVleuten) +- `696313c `_ #3513 [Component-DI] Fixed typo (saro0h) +- `27dcebd `_ #3509 Fix typo: side.bar.twig => sidebar.twig (ifdattic) +- `0dc8c26 `_ #3507 Fix a typo (missing `````) in ``:doc:`` link (ifdattic) +- `272197b `_ #3504 fix include directive so that the contents are really included (xabbuh) +- `e385d28 `_ #3503 file extension correction xfliff to xliff (nixilla) +- `6d34aa6 `_ #3478 Update custom_password_authenticator.rst (piotras-s) +- `a171700 `_ #3477 Api key user provider should use "implements" instead of "extends" (skowi) +- `7fe0de3 `_ #3475 Fixed doc for framework.session.cookie_lifetime refrence. (tyomo4ka) +- `8155e4c `_ #3473 Update proxy_examples.rst (AZielinski) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `0928249 `_ #3568 Update checkbox_compound.rst.inc (joshuaadickerson) +- `38def3b `_ #3567 Update checkbox_compound.rst.inc (joshuaadickerson) +- `15d8ab8 `_ #3553 Minimize horizontal scrolling in code blocks to improve readability (ifdattic) +- `5120863 `_ #3547 Update acl.rst (iqfoundry) +- `b7ac326 `_ #3557 Minimize horizontal scrolling in code block to improve readability (ifdattic) +- `d974c77 `_ #3556 Fix PSR error (ifdattic) +- `f4bb017 `_ #3555 Wrap variables in {} for safer interpolation (ifdattic) +- `5f02bca `_ #3552 Fix typos (ifdattic) +- `6e32c47 `_ #3546 Fix README: contributions should be based off 2.3 or higher (colinodell) +- `ffa8f76 `_ #3545 Example of getting entity managers directly from the container (colinodell) +- `6a2a55b `_ #3579 Fix build errors (xabbuh) +- `dce2e23 `_ #3532 Added tip for Entity Listeners (slavafomin) +- `73adf8b `_ #3528 Clarify service parameters usages (WouterJ) +- `f634600 `_ #3531 Remove horizontal scrolling in code block (ifdattic) +- `9ba4fa7 `_ #3527 Changes to components domcrawler (ifdattic) +- `8973c81 `_ #3526 Changes for Console component (ifdattic) +- `6848bed `_ #3538 Rebasing #3518 (weaverryan) +- `c838df8 `_ #3511 [Component-DI] Removed useless else statement in code example (saro0h) +- `1af6742 `_ #3510 add empty line (lazyants) +- `1131247 `_ #3508 Add 'in XML' for additional clarity (ifdattic) +- `a650b93 `_ #3506 Nykopol overriden options (weaverryan) +- `ab10035 `_ #3505 replace Akamaï with Akamai (xabbuh) +- `7f56c20 `_ #3501 [Security] Fix markup (tyx) +- `80a90ba `_ #3500 Minimize horizontal scrolling in code blocks (improve readability) (ifdattic) +- `e5bc4ea `_ #3498 Remove second empty data (xabbuh) +- `d084d87 `_ #3485 [Cookbook][Assetic] Fix "javascripts" tag name typo (bicpi) +- `3250aba `_ #3481 Fix code block (minimise horizontal scrolling), typo in yaml (ifdattic) + +January, 2014 +------------- New Documentation ~~~~~~~~~~~~~~~~~ -- `322972e `_ #3803 [Book][Validation] configuration examples for the GroupSequenceProvider (xabbuh) -- `d4ca16a `_ #3743 Improve examples in parent services (WouterJ) -- `70a3893 `_ #3774 [Book][Internals] add description for the kernel.finish_request event (xabbuh) -- `d611e77 `_ #3701 [Serializer] add documentation for serializer callbacks (cordoval) -- `80c645c `_ #3719 Fixed event listeners priority (tony-co) +- `d52f3f8 `_ #3454 [Security] Add host option (ghostika) +- `6b3c424 `_ #3428 Translation - Added info about JsonFileLoader added in 2.4 (singles) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `f801e2e `_ #3805 Add missing autocomplete argument in askAndValidate method (ifdattic) -- `a81d367 `_ #3786 replaceArguments should be setArguments (RobinvdVleuten) -- `33b64e1 `_ #3788 Fix link for StopwatchEvent class (rpg600) -- `2ebabfb `_ #3792 Update commands_as_services.rst (mimol91) -- `529d4ce `_ #3761 buildViewBottomUp has been renamed to finishView (Nyholm) -- `d743139 `_ #3768 the Locale component does not have elements tagged with @api (xabbuh) -- `2b8e44d `_ #3747 Fix Image constraint class and validator link (weaverryan) -- `fa362ca `_ #3741 correct RuntimeException reference (shieldo) -- `d92545e `_ #3734 [book] [testing] fixed the path of the phpunit.xml file (javiereguiluz) +- `fb22fa0 `_ #3456 remove duplicate label (xabbuh) +- `c205bc6 `_ #3468 enclose YAML string with double quotes to fix syntax highlighting (xabbuh) +- `89963cc `_ #3463 Fix typos in cookbook/testing/database (ifdattic) +- `e0a52ec `_ #3460 remove confusing outdated note on interactive rebasing (xabbuh) +- `6831b13 `_ #3455 [Contributing][Code] fix indentation so that the text is rendered properly (xabbuh) +- `ea5816f `_ #3433 [WIP][Reference][Form Types] Update "radio" form type (bicpi) +- `42c80d1 `_ #3448 Overridden tweak (weaverryan) +- `bede4c3 `_ #3447 Fix error in namespace when use TokenInterface (joanteixi) +- `d9d7c58 `_ #3444 Fix issue #3442 (ifdattic) +- `a6ad607 `_ #3441 [Expression]Change title 'Accessing Public Methods' (Pyrech) +- `9e2e64b `_ #3427 Removed code references to Symfony Standard Distribution (danielcsgomes) +- `3c2c5fc `_ #3435 Update custom_password_authenticator.rst (boardyuk) +- `26b8146 `_ #3415 [#3334] the data_class option was not introduced in 2.4 (xabbuh) +- `0b2a491 `_ #3414 add missing code-block directive (xabbuh) +- `4988118 `_ #3432 [Reference][Form Types] Add "max_length" option in form type (nykopol) +- `26a7b1b `_ #3423 [Session Configuration] add clarifying notes on session save handler proxies (cordoval) +- `f2f5e9a `_ #3421 [Contributing] Cleaning the "contributing patch" page a bit (lemoinem) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `136f98c `_ #3784 [Expression Langage] be consistent in "print/print out" uses (mickaelandrieu) -- `1094a13 `_ #3807 Added some exceptions to the method order in CS (stof) -- `55442b5 `_ #3800 Fixed another blockquote rendering issue (WouterJ) -- `969fd71 `_ #3785 ensure that destination directories don't exist before creating them (xabbuh) -- `79322ff `_ #3799 Fix list to not render in a block quote (WouterJ) -- `1a6f730 `_ #3793 language tweak for the tip introduced in #3743 (xabbuh) -- `dda9e88 `_ #3778 Adding information on internal reverse proxy (tcz) -- `d36bbd9 `_ #3765 [WIP] make headlines consistent with our standards (xabbuh) -- `daa81a0 `_ #3766 [Book] add note about services and the service container in the form cha... (xabbuh) -- `4529858 `_ #3767 [Book] link to the bc promise in the stable API description (xabbuh) -- `a5471b3 `_ #3775 Fixed variable naming (peterrehm) -- `703c2a6 `_ #3772 [Cookbook][Sessions] some language improvements (xabbuh) -- `3d30b56 `_ #3773 modify Symfony CMF configuration values in the build process so that the... (xabbuh) -- `cfd6d7c `_ #3758 [Book][Routing] Fixed typo on PHP version of a route definition (saro0h) -- `6bd134c `_ #3754 ignore more files and directories which are created when building the documentation (xabbuh) -- `610462e `_ #3755 [Cookbook][Security] Firewall resitrction tweaks, fix markup, add to toc (xabbuh) -- `0a21718 `_ #3695 Firewall backport (weaverryan) -- `54d6a9e `_ #3736 [book] Misc. routing fixes (javiereguiluz) -- `f149dcf `_ #3739 [book] [forms] misc. fixes and tweaks (javiereguiluz) -- `ce582ec `_ #3735 [book] [controller] fixed the code of a session sample code (javiereguiluz) -- `499ba5c `_ #3733 [book] [validation] fixed typos (javiereguiluz) -- `4d0ff8f `_ #3732 Update routing.rst. Explain using url() v. path(). (ackerman) -- `44c6273 `_ #3727 Added a note about inlined private services (javiereguiluz) \ No newline at end of file +- `f285d93 `_ #3451 some language tweaks (AE, third-person perspective) (xabbuh) +- `b9bbe5d `_ #3499 Fix YAML syntax highlight + remove trailing whitespace (ifdattic) +- `2b7e0f6 `_ #3497 Fix highlighting (WouterJ) +- `a535ae0 `_ #3471 Fixed `````versionadded````` inconsistencies in Symfony 2.3 (danielcsgomes) +- `f077a8e `_ #3465 change wording in versionadded example to be consistent with what we use... (xabbuh) +- `f9f7548 `_ #3462 Replace ... with etc (ifdattic) +- `65efcc4 `_ #3445 [Reference][Form Types] Add missing (but existing) options to "form" type (bicpi) +- `1d1b91d `_ #3431 [Config] add cautionary note on ini file loader limitation (cordoval) +- `f2eaf9b `_ #3419 doctrine file upload example uses dir -- caution added (cordoval) +- `72b53ad `_ #3404 [#3276] Trying to further clarify the session storage directory details (weaverryan) +- `67b7bbd `_ #3413 [Cookbook][Bundles] improve explanation of code block for bundle removal (cordoval) +- `7c5a914 `_ #3369 Indicate that Group Sequence Providers can use YAML (karptonite) +- `1e0311e `_ #3416 add empty_data option where required option is used (xabbuh) +- `2be3f52 `_ #3422 [Cookbook][Custom Authentication Provider] add a note of warning for when forbidding anonymous users (cordoval) +- `e255de9 `_ #3429 [Reference][Form Types] Document "with_minutes" time/datetime option (bicpi) From c01e87c9d6ad98f1acd245c2d53b6337d45c09d8 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 6 May 2014 16:40:38 +0200 Subject: [PATCH 0311/1181] Added April changelog --- changelog.rst | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/changelog.rst b/changelog.rst index 0187663a180..f18908513c4 100644 --- a/changelog.rst +++ b/changelog.rst @@ -258,3 +258,62 @@ Minor Documentation Changes - `664a0be `_ #3633 Added missing PHP syntax coloration (DerekRoth) - `1714a31 `_ #3585 Use consistent method chaining in BlogBundle sample application (ockcyp) - `cb61f4f `_ #3581 Add missing hyphen in HTTP Fundamentals page (ockcyp) + + +April, 2014 +----------- + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `322972e `_ #3803 [Book][Validation] configuration examples for the GroupSequenceProvider (xabbuh) +- `9e129bc `_ #3752 [Console] Add documentation for QuestionHelper (romainneutron) +- `64a924d `_ #3756 [WCM][Console] Add Process Helper documentation (romainneutron) +- `d4ca16a `_ #3743 Improve examples in parent services (WouterJ) +- `be4b9d3 `_ #3729 Added documentation for the new PropertyAccessor``::``isReadable() and isWritable() methods (webmozart) +- `70a3893 `_ #3774 [Book][Internals] add description for the kernel.finish_request event (xabbuh) +- `1934720 `_ #3461 [Form] Deprecated max_length and pattern options (stefanosala) +- `d611e77 `_ #3701 [Serializer] add documentation for serializer callbacks (cordoval) +- `80c645c `_ #3719 Fixed event listeners priority (tony-co) +- `c062d81 `_ #3469 [Validator] - EmailConstraint reference (egulias) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `f801e2e `_ #3805 Add missing autocomplete argument in askAndValidate method (ifdattic) +- `a81d367 `_ #3786 replaceArguments should be setArguments (RobinvdVleuten) +- `33b64e1 `_ #3788 Fix link for StopwatchEvent class (rpg600) +- `2ebabfb `_ #3792 Update commands_as_services.rst (mimol91) +- `529d4ce `_ #3761 buildViewBottomUp has been renamed to finishView (Nyholm) +- `d743139 `_ #3768 the Locale component does not have elements tagged with @api (xabbuh) +- `2b8e44d `_ #3747 Fix Image constraint class and validator link (weaverryan) +- `fa362ca `_ #3741 correct RuntimeException reference (shieldo) +- `d92545e `_ #3734 [book] [testing] fixed the path of the phpunit.xml file (javiereguiluz) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `136f98c `_ #3784 [Expression Langage] be consistent in "print/print out" uses (mickaelandrieu) +- `1094a13 `_ #3807 Added some exceptions to the method order in CS (stof) +- `55442b5 `_ #3800 Fixed another blockquote rendering issue (WouterJ) +- `969fd71 `_ #3785 ensure that destination directories don't exist before creating them (xabbuh) +- `79322ff `_ #3799 Fix list to not render in a block quote (WouterJ) +- `1a6f730 `_ #3793 language tweak for the tip introduced in #3743 (xabbuh) +- `dda9e88 `_ #3778 Adding information on internal reverse proxy (tcz) +- `d36bbd9 `_ #3765 [WIP] make headlines consistent with our standards (xabbuh) +- `daa81a0 `_ #3766 [Book] add note about services and the service container in the form cha... (xabbuh) +- `4529858 `_ #3767 [Book] link to the bc promise in the stable API description (xabbuh) +- `a5471b3 `_ #3775 Fixed variable naming (peterrehm) +- `703c2a6 `_ #3772 [Cookbook][Sessions] some language improvements (xabbuh) +- `3d30b56 `_ #3773 modify Symfony CMF configuration values in the build process so that the... (xabbuh) +- `cfd6d7c `_ #3758 [Book][Routing] Fixed typo on PHP version of a route definition (saro0h) +- `cedfdce `_ #3757 Fixed a typo in the request formats configuration page (gquemener) +- `6bd134c `_ #3754 ignore more files and directories which are created when building the documentation (xabbuh) +- `610462e `_ #3755 [Cookbook][Security] Firewall resitrction tweaks, fix markup, add to toc (xabbuh) +- `0a21718 `_ #3695 Firewall backport (weaverryan) +- `54d6a9e `_ #3736 [book] Misc. routing fixes (javiereguiluz) +- `f149dcf `_ #3739 [book] [forms] misc. fixes and tweaks (javiereguiluz) +- `ce582ec `_ #3735 [book] [controller] fixed the code of a session sample code (javiereguiluz) +- `499ba5c `_ #3733 [book] [validation] fixed typos (javiereguiluz) +- `4d0ff8f `_ #3732 Update routing.rst. Explain using url() v. path(). (ackerman) +- `44c6273 `_ #3727 Added a note about inlined private services (javiereguiluz) \ No newline at end of file From 6d00c3d330d2f6eff4a74452b8ea3a48fc7d0740 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 6 May 2014 16:40:51 +0200 Subject: [PATCH 0312/1181] [#3797] Reordered changelog --- changelog.rst | 322 +++++++++++++++++++++++++------------------------- 1 file changed, 160 insertions(+), 162 deletions(-) diff --git a/changelog.rst b/changelog.rst index f18908513c4..e7a6d40c2b2 100644 --- a/changelog.rst +++ b/changelog.rst @@ -13,135 +13,63 @@ documentation. Do you also want to participate in the Symfony Documentation? Take a look at the ":doc:`/contributing/documentation/overview`" article. - -January, 2014 -------------- - -New Documentation -~~~~~~~~~~~~~~~~~ - -- `d52f3f8 `_ #3454 [Security] Add host option (ghostika) -- `11e079b `_ #3446 [WCM] Documented deprecation of the apache router. (jakzal) -- `0a0bf4c `_ #3437 Add info about callback in options resolver (marekkalnik) -- `6db5f23 `_ #3426 New Feature: Change the Default Command in the Console component (danielcsgomes) -- `6b3c424 `_ #3428 Translation - Added info about JsonFileLoader added in 2.4 (singles) - -Fixed Documentation -~~~~~~~~~~~~~~~~~~~ - -- `fb22fa0 `_ #3456 remove duplicate label (xabbuh) -- `a87fe18 `_ #3470 Fixed typo (danielcsgomes) -- `c205bc6 `_ #3468 enclose YAML string with double quotes to fix syntax highlighting (xabbuh) -- `89963cc `_ #3463 Fix typos in cookbook/testing/database (ifdattic) -- `e0a52ec `_ #3460 remove confusing outdated note on interactive rebasing (xabbuh) -- `6831b13 `_ #3455 [Contributing][Code] fix indentation so that the text is rendered properly (xabbuh) -- `ea5816f `_ #3433 [WIP][Reference][Form Types] Update "radio" form type (bicpi) -- `42c80d1 `_ #3448 Overridden tweak (weaverryan) -- `bede4c3 `_ #3447 Fix error in namespace when use TokenInterface (joanteixi) -- `d9d7c58 `_ #3444 Fix issue #3442 (ifdattic) -- `a6ad607 `_ #3441 [Expression]Change title 'Accessing Public Methods' (Pyrech) -- `9e2e64b `_ #3427 Removed code references to Symfony Standard Distribution (danielcsgomes) -- `3c2c5fc `_ #3435 Update custom_password_authenticator.rst (boardyuk) -- `26b8146 `_ #3415 [#3334] the data_class option was not introduced in 2.4 (xabbuh) -- `0b2a491 `_ #3414 add missing code-block directive (xabbuh) -- `4988118 `_ #3432 [Reference][Form Types] Add "max_length" option in form type (nykopol) -- `26a7b1b `_ #3423 [Session Configuration] add clarifying notes on session save handler proxies (cordoval) -- `f2f5e9a `_ #3421 [Contributing] Cleaning the "contributing patch" page a bit (lemoinem) - -Minor Documentation Changes -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- `f285d93 `_ #3451 some language tweaks (AE, third-person perspective) (xabbuh) -- `b9bbe5d `_ #3499 Fix YAML syntax highlight + remove trailing whitespace (ifdattic) -- `2b7e0f6 `_ #3497 Fix highlighting (WouterJ) -- `2746067 `_ #3472 Fixed `````versionadded````` inconsistencies in Symfony 2.5+ (danielcsgomes) -- `a535ae0 `_ #3471 Fixed `````versionadded````` inconsistencies in Symfony 2.3 (danielcsgomes) -- `f077a8e `_ #3465 change wording in versionadded example to be consistent with what we use... (xabbuh) -- `f9f7548 `_ #3462 Replace ... with etc (ifdattic) -- `65efcc4 `_ #3445 [Reference][Form Types] Add missing (but existing) options to "form" type (bicpi) -- `1d1b91d `_ #3431 [Config] add cautionary note on ini file loader limitation (cordoval) -- `f2eaf9b `_ #3419 doctrine file upload example uses dir -- caution added (cordoval) -- `72b53ad `_ #3404 [#3276] Trying to further clarify the session storage directory details (weaverryan) -- `67b7bbd `_ #3413 [Cookbook][Bundles] improve explanation of code block for bundle removal (cordoval) -- `7c5a914 `_ #3369 Indicate that Group Sequence Providers can use YAML (karptonite) -- `1e0311e `_ #3416 add empty_data option where required option is used (xabbuh) -- `2be3f52 `_ #3422 [Cookbook][Custom Authentication Provider] add a note of warning for when forbidding anonymous users (cordoval) -- `e255de9 `_ #3429 [Reference][Form Types] Document "with_minutes" time/datetime option (bicpi) - -February, 2014 --------------- +April, 2014 +----------- New Documentation ~~~~~~~~~~~~~~~~~ -- `9dcf467 `_ #3613 Javiereguiluz revamped quick tour (weaverryan) -- `89c6f1d `_ #3439 [Review] Added detailed Backwards Compatibility Promise text (webmozart) -- `0029408 `_ #3558 Created Documentation CHANGELOG (WouterJ) -- `f6dd678 `_ #3548 Update forms.rst (atmosf3ar) -- `9676f2c `_ #3523 [Components][EventDispatcher] describe that the event name and the event dispatcher are passed to even... (xabbuh) -- `5c367b4 `_ #3517 Fixed OptionsResolver component docs (WouterJ) -- `527c8b6 `_ #3496 Added a section about using named assets (vmattila) -- `8ccfe85 `_ #3491 Added doc for named encoders (tamirvs) -- `46377b2 `_ #3486 Documenting createAccessDeniedException() method (klaussilveira) +- `322972e `_ #3803 [Book][Validation] configuration examples for the GroupSequenceProvider (xabbuh) +- `9e129bc `_ #3752 [Console] Add documentation for QuestionHelper (romainneutron) +- `64a924d `_ #3756 [WCM][Console] Add Process Helper documentation (romainneutron) +- `d4ca16a `_ #3743 Improve examples in parent services (WouterJ) +- `be4b9d3 `_ #3729 Added documentation for the new PropertyAccessor``::``isReadable() and isWritable() methods (webmozart) +- `70a3893 `_ #3774 [Book][Internals] add description for the kernel.finish_request event (xabbuh) +- `1934720 `_ #3461 [Form] Deprecated max_length and pattern options (stefanosala) +- `d611e77 `_ #3701 [Serializer] add documentation for serializer callbacks (cordoval) +- `80c645c `_ #3719 Fixed event listeners priority (tony-co) +- `c062d81 `_ #3469 [Validator] - EmailConstraint reference (egulias) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `adcbb5d `_ #3615 Fixes to cookbook/doctrine/registration_form.rst (Crushnaut) -- `5c4336a `_ #3570 Callback: [Validator, validate] expects validate to be static (nixilla) -- `a21fb26 `_ #3559 Remove reference to copying parameters.yml from Git cookbook (pwaring) -- `de71a51 `_ #3551 [Cookbook][Dynamic Form Modification] Fix sample code (rybakit) -- `143db2f `_ #3550 Update introduction.rst (taavit) -- `384538b `_ #3549 Fixed createPropertyAccessorBuilder usage (antonbabenko) -- `642e776 `_ #3544 Fix build errors (xabbuh) -- `d275302 `_ #3541 Update generic_event.rst (Lumbendil) -- `819949c `_ #3537 Add missing variable assignment (colinodell) -- `d7e8262 `_ #3535 fix form type name. (yositani2002) -- `821af3b `_ #3493 Type fix in remove.rst (weaverryan) -- `003230f `_ #3530 Update form_customization.rst (dczech) -- `a43f15a `_ #3519 [Book][Service Container] Fix syntax highlighting (iamdto) -- `86e02c6 `_ #3514 Fixed some small typos in code example (RobinvdVleuten) -- `696313c `_ #3513 [Component-DI] Fixed typo (saro0h) -- `27dcebd `_ #3509 Fix typo: side.bar.twig => sidebar.twig (ifdattic) -- `0dc8c26 `_ #3507 Fix a typo (missing `````) in ``:doc:`` link (ifdattic) -- `272197b `_ #3504 fix include directive so that the contents are really included (xabbuh) -- `e385d28 `_ #3503 file extension correction xfliff to xliff (nixilla) -- `6d34aa6 `_ #3478 Update custom_password_authenticator.rst (piotras-s) -- `a171700 `_ #3477 Api key user provider should use "implements" instead of "extends" (skowi) -- `7fe0de3 `_ #3475 Fixed doc for framework.session.cookie_lifetime refrence. (tyomo4ka) -- `8155e4c `_ #3473 Update proxy_examples.rst (AZielinski) +- `f801e2e `_ #3805 Add missing autocomplete argument in askAndValidate method (ifdattic) +- `a81d367 `_ #3786 replaceArguments should be setArguments (RobinvdVleuten) +- `33b64e1 `_ #3788 Fix link for StopwatchEvent class (rpg600) +- `2ebabfb `_ #3792 Update commands_as_services.rst (mimol91) +- `529d4ce `_ #3761 buildViewBottomUp has been renamed to finishView (Nyholm) +- `d743139 `_ #3768 the Locale component does not have elements tagged with @api (xabbuh) +- `2b8e44d `_ #3747 Fix Image constraint class and validator link (weaverryan) +- `fa362ca `_ #3741 correct RuntimeException reference (shieldo) +- `d92545e `_ #3734 [book] [testing] fixed the path of the phpunit.xml file (javiereguiluz) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `0928249 `_ #3568 Update checkbox_compound.rst.inc (joshuaadickerson) -- `38def3b `_ #3567 Update checkbox_compound.rst.inc (joshuaadickerson) -- `15d8ab8 `_ #3553 Minimize horizontal scrolling in code blocks to improve readability (ifdattic) -- `5120863 `_ #3547 Update acl.rst (iqfoundry) -- `b7ac326 `_ #3557 Minimize horizontal scrolling in code block to improve readability (ifdattic) -- `d974c77 `_ #3556 Fix PSR error (ifdattic) -- `f4bb017 `_ #3555 Wrap variables in {} for safer interpolation (ifdattic) -- `5f02bca `_ #3552 Fix typos (ifdattic) -- `6e32c47 `_ #3546 Fix README: contributions should be based off 2.3 or higher (colinodell) -- `ffa8f76 `_ #3545 Example of getting entity managers directly from the container (colinodell) -- `6a2a55b `_ #3579 Fix build errors (xabbuh) -- `dce2e23 `_ #3532 Added tip for Entity Listeners (slavafomin) -- `73adf8b `_ #3528 Clarify service parameters usages (WouterJ) -- `7e75b64 `_ #3533 Moving the new named algorithms into their own cookbook entry (weaverryan) -- `f634600 `_ #3531 Remove horizontal scrolling in code block (ifdattic) -- `9ba4fa7 `_ #3527 Changes to components domcrawler (ifdattic) -- `8973c81 `_ #3526 Changes for Console component (ifdattic) -- `6848bed `_ #3538 Rebasing #3518 (weaverryan) -- `c838df8 `_ #3511 [Component-DI] Removed useless else statement in code example (saro0h) -- `1af6742 `_ #3510 add empty line (lazyants) -- `1131247 `_ #3508 Add 'in XML' for additional clarity (ifdattic) -- `a650b93 `_ #3506 Nykopol overriden options (weaverryan) -- `ab10035 `_ #3505 replace Akamaï with Akamai (xabbuh) -- `7f56c20 `_ #3501 [Security] Fix markup (tyx) -- `80a90ba `_ #3500 Minimize horizontal scrolling in code blocks (improve readability) (ifdattic) -- `e5bc4ea `_ #3498 Remove second empty data (xabbuh) -- `d084d87 `_ #3485 [Cookbook][Assetic] Fix "javascripts" tag name typo (bicpi) -- `3250aba `_ #3481 Fix code block (minimise horizontal scrolling), typo in yaml (ifdattic) +- `136f98c `_ #3784 [Expression Langage] be consistent in "print/print out" uses (mickaelandrieu) +- `1094a13 `_ #3807 Added some exceptions to the method order in CS (stof) +- `55442b5 `_ #3800 Fixed another blockquote rendering issue (WouterJ) +- `969fd71 `_ #3785 ensure that destination directories don't exist before creating them (xabbuh) +- `79322ff `_ #3799 Fix list to not render in a block quote (WouterJ) +- `1a6f730 `_ #3793 language tweak for the tip introduced in #3743 (xabbuh) +- `dda9e88 `_ #3778 Adding information on internal reverse proxy (tcz) +- `d36bbd9 `_ #3765 [WIP] make headlines consistent with our standards (xabbuh) +- `daa81a0 `_ #3766 [Book] add note about services and the service container in the form cha... (xabbuh) +- `4529858 `_ #3767 [Book] link to the bc promise in the stable API description (xabbuh) +- `a5471b3 `_ #3775 Fixed variable naming (peterrehm) +- `703c2a6 `_ #3772 [Cookbook][Sessions] some language improvements (xabbuh) +- `3d30b56 `_ #3773 modify Symfony CMF configuration values in the build process so that the... (xabbuh) +- `cfd6d7c `_ #3758 [Book][Routing] Fixed typo on PHP version of a route definition (saro0h) +- `cedfdce `_ #3757 Fixed a typo in the request formats configuration page (gquemener) +- `6bd134c `_ #3754 ignore more files and directories which are created when building the documentation (xabbuh) +- `610462e `_ #3755 [Cookbook][Security] Firewall resitrction tweaks, fix markup, add to toc (xabbuh) +- `0a21718 `_ #3695 Firewall backport (weaverryan) +- `54d6a9e `_ #3736 [book] Misc. routing fixes (javiereguiluz) +- `f149dcf `_ #3739 [book] [forms] misc. fixes and tweaks (javiereguiluz) +- `ce582ec `_ #3735 [book] [controller] fixed the code of a session sample code (javiereguiluz) +- `499ba5c `_ #3733 [book] [validation] fixed typos (javiereguiluz) +- `4d0ff8f `_ #3732 Update routing.rst. Explain using url() v. path(). (ackerman) +- `44c6273 `_ #3727 Added a note about inlined private services (javiereguiluz) March, 2014 ----------- @@ -259,61 +187,131 @@ Minor Documentation Changes - `1714a31 `_ #3585 Use consistent method chaining in BlogBundle sample application (ockcyp) - `cb61f4f `_ #3581 Add missing hyphen in HTTP Fundamentals page (ockcyp) +February, 2014 +-------------- -April, 2014 ------------ +New Documentation +~~~~~~~~~~~~~~~~~ + +- `9dcf467 `_ #3613 Javiereguiluz revamped quick tour (weaverryan) +- `89c6f1d `_ #3439 [Review] Added detailed Backwards Compatibility Promise text (webmozart) +- `0029408 `_ #3558 Created Documentation CHANGELOG (WouterJ) +- `f6dd678 `_ #3548 Update forms.rst (atmosf3ar) +- `9676f2c `_ #3523 [Components][EventDispatcher] describe that the event name and the event dispatcher are passed to even... (xabbuh) +- `5c367b4 `_ #3517 Fixed OptionsResolver component docs (WouterJ) +- `527c8b6 `_ #3496 Added a section about using named assets (vmattila) +- `8ccfe85 `_ #3491 Added doc for named encoders (tamirvs) +- `46377b2 `_ #3486 Documenting createAccessDeniedException() method (klaussilveira) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `adcbb5d `_ #3615 Fixes to cookbook/doctrine/registration_form.rst (Crushnaut) +- `5c4336a `_ #3570 Callback: [Validator, validate] expects validate to be static (nixilla) +- `a21fb26 `_ #3559 Remove reference to copying parameters.yml from Git cookbook (pwaring) +- `de71a51 `_ #3551 [Cookbook][Dynamic Form Modification] Fix sample code (rybakit) +- `143db2f `_ #3550 Update introduction.rst (taavit) +- `384538b `_ #3549 Fixed createPropertyAccessorBuilder usage (antonbabenko) +- `642e776 `_ #3544 Fix build errors (xabbuh) +- `d275302 `_ #3541 Update generic_event.rst (Lumbendil) +- `819949c `_ #3537 Add missing variable assignment (colinodell) +- `d7e8262 `_ #3535 fix form type name. (yositani2002) +- `821af3b `_ #3493 Type fix in remove.rst (weaverryan) +- `003230f `_ #3530 Update form_customization.rst (dczech) +- `a43f15a `_ #3519 [Book][Service Container] Fix syntax highlighting (iamdto) +- `86e02c6 `_ #3514 Fixed some small typos in code example (RobinvdVleuten) +- `696313c `_ #3513 [Component-DI] Fixed typo (saro0h) +- `27dcebd `_ #3509 Fix typo: side.bar.twig => sidebar.twig (ifdattic) +- `0dc8c26 `_ #3507 Fix a typo (missing `````) in ``:doc:`` link (ifdattic) +- `272197b `_ #3504 fix include directive so that the contents are really included (xabbuh) +- `e385d28 `_ #3503 file extension correction xfliff to xliff (nixilla) +- `6d34aa6 `_ #3478 Update custom_password_authenticator.rst (piotras-s) +- `a171700 `_ #3477 Api key user provider should use "implements" instead of "extends" (skowi) +- `7fe0de3 `_ #3475 Fixed doc for framework.session.cookie_lifetime refrence. (tyomo4ka) +- `8155e4c `_ #3473 Update proxy_examples.rst (AZielinski) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `0928249 `_ #3568 Update checkbox_compound.rst.inc (joshuaadickerson) +- `38def3b `_ #3567 Update checkbox_compound.rst.inc (joshuaadickerson) +- `15d8ab8 `_ #3553 Minimize horizontal scrolling in code blocks to improve readability (ifdattic) +- `5120863 `_ #3547 Update acl.rst (iqfoundry) +- `b7ac326 `_ #3557 Minimize horizontal scrolling in code block to improve readability (ifdattic) +- `d974c77 `_ #3556 Fix PSR error (ifdattic) +- `f4bb017 `_ #3555 Wrap variables in {} for safer interpolation (ifdattic) +- `5f02bca `_ #3552 Fix typos (ifdattic) +- `6e32c47 `_ #3546 Fix README: contributions should be based off 2.3 or higher (colinodell) +- `ffa8f76 `_ #3545 Example of getting entity managers directly from the container (colinodell) +- `6a2a55b `_ #3579 Fix build errors (xabbuh) +- `dce2e23 `_ #3532 Added tip for Entity Listeners (slavafomin) +- `73adf8b `_ #3528 Clarify service parameters usages (WouterJ) +- `7e75b64 `_ #3533 Moving the new named algorithms into their own cookbook entry (weaverryan) +- `f634600 `_ #3531 Remove horizontal scrolling in code block (ifdattic) +- `9ba4fa7 `_ #3527 Changes to components domcrawler (ifdattic) +- `8973c81 `_ #3526 Changes for Console component (ifdattic) +- `6848bed `_ #3538 Rebasing #3518 (weaverryan) +- `c838df8 `_ #3511 [Component-DI] Removed useless else statement in code example (saro0h) +- `1af6742 `_ #3510 add empty line (lazyants) +- `1131247 `_ #3508 Add 'in XML' for additional clarity (ifdattic) +- `a650b93 `_ #3506 Nykopol overriden options (weaverryan) +- `ab10035 `_ #3505 replace Akamaï with Akamai (xabbuh) +- `7f56c20 `_ #3501 [Security] Fix markup (tyx) +- `80a90ba `_ #3500 Minimize horizontal scrolling in code blocks (improve readability) (ifdattic) +- `e5bc4ea `_ #3498 Remove second empty data (xabbuh) +- `d084d87 `_ #3485 [Cookbook][Assetic] Fix "javascripts" tag name typo (bicpi) +- `3250aba `_ #3481 Fix code block (minimise horizontal scrolling), typo in yaml (ifdattic) + +January, 2014 +------------- New Documentation ~~~~~~~~~~~~~~~~~ -- `322972e `_ #3803 [Book][Validation] configuration examples for the GroupSequenceProvider (xabbuh) -- `9e129bc `_ #3752 [Console] Add documentation for QuestionHelper (romainneutron) -- `64a924d `_ #3756 [WCM][Console] Add Process Helper documentation (romainneutron) -- `d4ca16a `_ #3743 Improve examples in parent services (WouterJ) -- `be4b9d3 `_ #3729 Added documentation for the new PropertyAccessor``::``isReadable() and isWritable() methods (webmozart) -- `70a3893 `_ #3774 [Book][Internals] add description for the kernel.finish_request event (xabbuh) -- `1934720 `_ #3461 [Form] Deprecated max_length and pattern options (stefanosala) -- `d611e77 `_ #3701 [Serializer] add documentation for serializer callbacks (cordoval) -- `80c645c `_ #3719 Fixed event listeners priority (tony-co) -- `c062d81 `_ #3469 [Validator] - EmailConstraint reference (egulias) +- `d52f3f8 `_ #3454 [Security] Add host option (ghostika) +- `11e079b `_ #3446 [WCM] Documented deprecation of the apache router. (jakzal) +- `0a0bf4c `_ #3437 Add info about callback in options resolver (marekkalnik) +- `6db5f23 `_ #3426 New Feature: Change the Default Command in the Console component (danielcsgomes) +- `6b3c424 `_ #3428 Translation - Added info about JsonFileLoader added in 2.4 (singles) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `f801e2e `_ #3805 Add missing autocomplete argument in askAndValidate method (ifdattic) -- `a81d367 `_ #3786 replaceArguments should be setArguments (RobinvdVleuten) -- `33b64e1 `_ #3788 Fix link for StopwatchEvent class (rpg600) -- `2ebabfb `_ #3792 Update commands_as_services.rst (mimol91) -- `529d4ce `_ #3761 buildViewBottomUp has been renamed to finishView (Nyholm) -- `d743139 `_ #3768 the Locale component does not have elements tagged with @api (xabbuh) -- `2b8e44d `_ #3747 Fix Image constraint class and validator link (weaverryan) -- `fa362ca `_ #3741 correct RuntimeException reference (shieldo) -- `d92545e `_ #3734 [book] [testing] fixed the path of the phpunit.xml file (javiereguiluz) +- `fb22fa0 `_ #3456 remove duplicate label (xabbuh) +- `a87fe18 `_ #3470 Fixed typo (danielcsgomes) +- `c205bc6 `_ #3468 enclose YAML string with double quotes to fix syntax highlighting (xabbuh) +- `89963cc `_ #3463 Fix typos in cookbook/testing/database (ifdattic) +- `e0a52ec `_ #3460 remove confusing outdated note on interactive rebasing (xabbuh) +- `6831b13 `_ #3455 [Contributing][Code] fix indentation so that the text is rendered properly (xabbuh) +- `ea5816f `_ #3433 [WIP][Reference][Form Types] Update "radio" form type (bicpi) +- `42c80d1 `_ #3448 Overridden tweak (weaverryan) +- `bede4c3 `_ #3447 Fix error in namespace when use TokenInterface (joanteixi) +- `d9d7c58 `_ #3444 Fix issue #3442 (ifdattic) +- `a6ad607 `_ #3441 [Expression]Change title 'Accessing Public Methods' (Pyrech) +- `9e2e64b `_ #3427 Removed code references to Symfony Standard Distribution (danielcsgomes) +- `3c2c5fc `_ #3435 Update custom_password_authenticator.rst (boardyuk) +- `26b8146 `_ #3415 [#3334] the data_class option was not introduced in 2.4 (xabbuh) +- `0b2a491 `_ #3414 add missing code-block directive (xabbuh) +- `4988118 `_ #3432 [Reference][Form Types] Add "max_length" option in form type (nykopol) +- `26a7b1b `_ #3423 [Session Configuration] add clarifying notes on session save handler proxies (cordoval) +- `f2f5e9a `_ #3421 [Contributing] Cleaning the "contributing patch" page a bit (lemoinem) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `136f98c `_ #3784 [Expression Langage] be consistent in "print/print out" uses (mickaelandrieu) -- `1094a13 `_ #3807 Added some exceptions to the method order in CS (stof) -- `55442b5 `_ #3800 Fixed another blockquote rendering issue (WouterJ) -- `969fd71 `_ #3785 ensure that destination directories don't exist before creating them (xabbuh) -- `79322ff `_ #3799 Fix list to not render in a block quote (WouterJ) -- `1a6f730 `_ #3793 language tweak for the tip introduced in #3743 (xabbuh) -- `dda9e88 `_ #3778 Adding information on internal reverse proxy (tcz) -- `d36bbd9 `_ #3765 [WIP] make headlines consistent with our standards (xabbuh) -- `daa81a0 `_ #3766 [Book] add note about services and the service container in the form cha... (xabbuh) -- `4529858 `_ #3767 [Book] link to the bc promise in the stable API description (xabbuh) -- `a5471b3 `_ #3775 Fixed variable naming (peterrehm) -- `703c2a6 `_ #3772 [Cookbook][Sessions] some language improvements (xabbuh) -- `3d30b56 `_ #3773 modify Symfony CMF configuration values in the build process so that the... (xabbuh) -- `cfd6d7c `_ #3758 [Book][Routing] Fixed typo on PHP version of a route definition (saro0h) -- `cedfdce `_ #3757 Fixed a typo in the request formats configuration page (gquemener) -- `6bd134c `_ #3754 ignore more files and directories which are created when building the documentation (xabbuh) -- `610462e `_ #3755 [Cookbook][Security] Firewall resitrction tweaks, fix markup, add to toc (xabbuh) -- `0a21718 `_ #3695 Firewall backport (weaverryan) -- `54d6a9e `_ #3736 [book] Misc. routing fixes (javiereguiluz) -- `f149dcf `_ #3739 [book] [forms] misc. fixes and tweaks (javiereguiluz) -- `ce582ec `_ #3735 [book] [controller] fixed the code of a session sample code (javiereguiluz) -- `499ba5c `_ #3733 [book] [validation] fixed typos (javiereguiluz) -- `4d0ff8f `_ #3732 Update routing.rst. Explain using url() v. path(). (ackerman) -- `44c6273 `_ #3727 Added a note about inlined private services (javiereguiluz) \ No newline at end of file +- `f285d93 `_ #3451 some language tweaks (AE, third-person perspective) (xabbuh) +- `b9bbe5d `_ #3499 Fix YAML syntax highlight + remove trailing whitespace (ifdattic) +- `2b7e0f6 `_ #3497 Fix highlighting (WouterJ) +- `2746067 `_ #3472 Fixed `````versionadded````` inconsistencies in Symfony 2.5+ (danielcsgomes) +- `a535ae0 `_ #3471 Fixed `````versionadded````` inconsistencies in Symfony 2.3 (danielcsgomes) +- `f077a8e `_ #3465 change wording in versionadded example to be consistent with what we use... (xabbuh) +- `f9f7548 `_ #3462 Replace ... with etc (ifdattic) +- `65efcc4 `_ #3445 [Reference][Form Types] Add missing (but existing) options to "form" type (bicpi) +- `1d1b91d `_ #3431 [Config] add cautionary note on ini file loader limitation (cordoval) +- `f2eaf9b `_ #3419 doctrine file upload example uses dir -- caution added (cordoval) +- `72b53ad `_ #3404 [#3276] Trying to further clarify the session storage directory details (weaverryan) +- `67b7bbd `_ #3413 [Cookbook][Bundles] improve explanation of code block for bundle removal (cordoval) +- `7c5a914 `_ #3369 Indicate that Group Sequence Providers can use YAML (karptonite) +- `1e0311e `_ #3416 add empty_data option where required option is used (xabbuh) +- `2be3f52 `_ #3422 [Cookbook][Custom Authentication Provider] add a note of warning for when forbidding anonymous users (cordoval) +- `e255de9 `_ #3429 [Reference][Form Types] Document "with_minutes" time/datetime option (bicpi) From fe5a39f79ed85c86a216d286efe61e2905e220ec Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 9 May 2014 16:54:10 +0200 Subject: [PATCH 0313/1181] fix literal positions --- changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.rst b/changelog.rst index e7a6d40c2b2..5399a286543 100644 --- a/changelog.rst +++ b/changelog.rst @@ -23,7 +23,7 @@ New Documentation - `9e129bc `_ #3752 [Console] Add documentation for QuestionHelper (romainneutron) - `64a924d `_ #3756 [WCM][Console] Add Process Helper documentation (romainneutron) - `d4ca16a `_ #3743 Improve examples in parent services (WouterJ) -- `be4b9d3 `_ #3729 Added documentation for the new PropertyAccessor``::``isReadable() and isWritable() methods (webmozart) +- `be4b9d3 `_ #3729 Added documentation for the new ``PropertyAccessor::isReadable()`` and ``isWritable()`` methods (webmozart) - `70a3893 `_ #3774 [Book][Internals] add description for the kernel.finish_request event (xabbuh) - `1934720 `_ #3461 [Form] Deprecated max_length and pattern options (stefanosala) - `d611e77 `_ #3701 [Serializer] add documentation for serializer callbacks (cordoval) From 1dbf4f956f3c2e5f73590018e4429b19be2ead61 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Fri, 9 May 2014 13:11:50 -0500 Subject: [PATCH 0314/1181] Removing incorrect "No Changes" after merge conflicts --- changelog.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/changelog.rst b/changelog.rst index eae6a2b8361..ef4f2f3226c 100644 --- a/changelog.rst +++ b/changelog.rst @@ -240,7 +240,6 @@ New Documentation - `d52f3f8 `_ #3454 [Security] Add host option (ghostika) - `6b3c424 `_ #3428 Translation - Added info about JsonFileLoader added in 2.4 (singles) -No changes Fixed Documentation ~~~~~~~~~~~~~~~~~~~ From 36f68b6758c18eb305b4a4a7bbdf21b6c4258532 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 5 May 2014 18:40:47 +0200 Subject: [PATCH 0315/1181] fix the wording in versionadded directives --- components/property_access/introduction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/property_access/introduction.rst b/components/property_access/introduction.rst index 3a55ce8bb82..0a938117923 100644 --- a/components/property_access/introduction.rst +++ b/components/property_access/introduction.rst @@ -313,7 +313,7 @@ Checking Property Paths ----------------------- .. versionadded:: 2.5 - The methods + The :method:`PropertyAccessor::isReadable ` and :method:`PropertyAccessor::isWritable ` From 4eafdbde933b4dc850531ec94a373e440e7ee7bf Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 10 May 2014 17:02:41 -0500 Subject: [PATCH 0316/1181] [#3837] Fixes thanks to stof and WouterJ --- book/templating.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/book/templating.rst b/book/templating.rst index 7c3c31aa7a8..545e1c24531 100644 --- a/book/templating.rst +++ b/book/templating.rst @@ -991,10 +991,10 @@ assets won't be cached when deployed. For example, ``/images/logo.png`` might look like ``/images/logo.png?v2``. For more information, see the :ref:`ref-framework-assets-version` configuration option. -.. _` +.. _`book-templating-version-by-asset`: .. versionadded:: 2.5 - Setting versioned URLs on an asset-by-asset basis were introduced in Symfony 2.5. + Setting versioned URLs on an asset-by-asset basis was introduced in Symfony 2.5. If you need to set a version for a specific asset, you can set the fourth argument (or the ``version`` argument) to the desired version: @@ -1003,14 +1003,14 @@ argument (or the ``version`` argument) to the desired version: .. code-block:: html+jinja - Symfony! + Symfony! .. code-block:: html+php Symfony! If you dont give a version or pass ``null``, the default package version -(from :ref:`ref-framework-assets-version`) wil be used. If you pass ``false``, +(from :ref:`ref-framework-assets-version`) will be used. If you pass ``false``, versioned URL will be deactivated for this asset. .. versionadded:: 2.5 From 83bb7237461c9cd6028ed01f062a5a31b76ed29f Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 26 May 2014 13:08:52 +0200 Subject: [PATCH 0317/1181] Updated the installation instructions to Symfony 2.5+ --- quick_tour/the_big_picture.rst | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/quick_tour/the_big_picture.rst b/quick_tour/the_big_picture.rst index eb98595f979..aafbc41cb29 100644 --- a/quick_tour/the_big_picture.rst +++ b/quick_tour/the_big_picture.rst @@ -18,7 +18,7 @@ directory: .. code-block:: bash - $ composer create-project symfony/framework-standard-edition myproject/ ~2.4 + $ composer create-project symfony/framework-standard-edition myproject/ ~2.5 .. note:: @@ -35,9 +35,25 @@ directory: Beware that the first time you install Symfony2, it may take a few minutes to download all its components. At the end of the installation process, the -installer will ask you to provide some configuration options for the Symfony2 -project. For this first project you can safely ignore this configuration by -pressing the ```` key repeatedly. +installer will ask you four questions: + +1. **Would you like to use Symfony 3 directory structure? [y/N]** The upcoming + Symfony 3 version will modify the default directory structure for Symfony + applications. If you want to test drive this new structure, type ``y``. + In order to follow this tutorial, press the ```` key to accept the + default ``N`` value and to keep using the default Symfony2 structure. +2. **Would you like to install Acme demo bundle? [y/N]** Symfony versions prior + to 2.5 included a demo application to test drive some features of the + framework. However, as this demo application is only useful for newcomers, + installing it is now optional. In order to follow this tutorial, type the + ``y`` key to install the demo application. +3. **Some parameters are missing. Please provide them.** Symfony2 asks you for + the value of all the configuration parameters. For this first project, + you can safely ignore this configuration by pressing the ```` key + repeatedly. +4. **Do you want to remove the existing VCS (.git, .svn..) history? [Y,n]?** + The development history of large projects such as Symfony can take a lot of + disk space. Press the ```` key to safely remove all this history data. Running Symfony2 ---------------- From 1f5d980fedb8007bc775542b61e16749c1dd90b6 Mon Sep 17 00:00:00 2001 From: Marcin Chwedziak Date: Mon, 24 Feb 2014 18:01:05 +0100 Subject: [PATCH 0318/1181] added a note about is* getters support with GetSetMethodNormalizer --- components/serializer.rst | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/components/serializer.rst b/components/serializer.rst index aeaabeb6067..872c5936e8b 100644 --- a/components/serializer.rst +++ b/components/serializer.rst @@ -62,6 +62,7 @@ exists in your project:: { private $age; private $name; + private $sportsman; // Getters public function getName() @@ -74,6 +75,12 @@ exists in your project:: return $this->age; } + // Issers + public function isSportsman() + { + return $this->sportsman; + } + // Setters public function setName($name) { @@ -84,6 +91,11 @@ exists in your project:: { $this->age = $age; } + + public function setSportsman($sportsman) + { + $this->sportsman = $sportsman; + } } Now, if you want to serialize this object into JSON, you only need to @@ -92,10 +104,11 @@ use the Serializer service created before:: $person = new Acme\Person(); $person->setName('foo'); $person->setAge(99); + $person->setSportsman(false); $jsonContent = $serializer->serialize($person, 'json'); - // $jsonContent contains {"name":"foo","age":99} + // $jsonContent contains {"name":"foo","age":99,"sportsman":false} echo $jsonContent; // or return it in a Response @@ -124,7 +137,7 @@ method on the normalizer definition:: $encoder = new JsonEncoder(); $serializer = new Serializer(array($normalizer), array($encoder)); - $serializer->serialize($person, 'json'); // Output: {"name":"foo"} + $serializer->serialize($person, 'json'); // Output: {"name":"foo","sportsman":false} Deserializing an Object ----------------------- @@ -136,6 +149,7 @@ of the ``Person`` class would be encoded in XML format:: foo 99 + false EOF; @@ -181,6 +195,18 @@ method on the normalizer definition:: As a final result, the deserializer uses the ``first_name`` attribute as if it were ``firstName`` and uses the ``getFirstName`` and ``setFirstName`` methods. +Serializing Boolean Attributes +------------------------------ + +.. versionadded:: 2.5 + Support for ``is*`` accessors in + :class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer` + was introduced in Symfony 2.5. + +If you are using isser methods (methods prefixed by ``is``, like +``Acme\Person::isSportsman()``), the Serializer component will automatically +detect and use it to serialize related attributes. + Using Callbacks to Serialize Properties with Object Instances ------------------------------------------------------------- From beceed47a38650a78ef4246dec92568f7a8576f4 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 28 May 2014 19:55:03 +0200 Subject: [PATCH 0319/1181] add versionadded for the data collector form extension --- components/form/form_events.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/form/form_events.rst b/components/form/form_events.rst index 1b81360f529..b6f10e538ba 100644 --- a/components/form/form_events.rst +++ b/components/form/form_events.rst @@ -110,6 +110,9 @@ the form. .. sidebar:: ``FormEvents::POST_SET_DATA`` in the Form component + .. versionadded:: 2.4 + The data collector extension was introduced in Symfony 2.4. + The :class:`Symfony\\Component\\Form\\Extension\\DataCollector\\EventListener\\DataCollectorListener` class is subscribed to listen to the ``FormEvents::POST_SET_DATA`` event in order to collect information about the forms from the denormalized @@ -218,6 +221,9 @@ It can be used to fetch data after denormalization. .. sidebar:: ``FormEvents::POST_SUBMIT`` in the Form component + .. versionadded:: 2.4 + The data collector extension was introduced in Symfony 2.4. + The :class:`Symfony\\Component\\Form\\Extension\\DataCollector\\EventListener\\DataCollectorListener` subscribes to the ``FormEvents::POST_SUBMIT`` event in order to collect information about the forms. From e6bc038e2a61550c4bb75fd890976f60bf372a37 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Thu, 3 Apr 2014 15:07:28 +0200 Subject: [PATCH 0320/1181] Add documentation about service decoration --- components/dependency_injection/advanced.rst | 92 ++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/components/dependency_injection/advanced.rst b/components/dependency_injection/advanced.rst index 77056c296ce..95d7e5b2697 100644 --- a/components/dependency_injection/advanced.rst +++ b/components/dependency_injection/advanced.rst @@ -185,3 +185,95 @@ the service itself gets loaded. To do so, you can use the ``file`` directive. Notice that Symfony will internally call the PHP statement ``require_once``, which means that your file will be included only once per request. + +Decorating Services +------------------- + +.. versionadded:: 2.5 + Decorated services were introduced in Symfony 2.5. + +When overriding an existing definition, the old service is lost: + +.. code-block:: php + + $container->register('foo', 'FooService'); + + // this is going to replace the old definition with the new one + // old definition is lost + $container->register('foo', 'CustomFooService'); + +Most of the time, that's exactly what you want to do. But sometimes, +you might want to decorate the old one instead. In this case, the +old service should be kept around to be able to reference it in the +new one. This configuration replaces ``foo`` with a new one, but keeps +a reference of the old one as ``bar.inner``: + +.. configuration-block:: + + .. code-block:: yaml + + bar: + public: false + class: stdClass + decorates: foo + arguments: ["@bar.inner"] + + .. code-block:: xml + + + + + + .. code-block:: php + + use Symfony\Component\DependencyInjection\Reference; + + $container->register('bar', 'stdClass') + ->addArgument(new Reference('bar.inner')) + ->setPublic(false) + ->setDecoratedService('foo'); + +Here is what's going on here: the ``setDecoratedService()` method tells +the container that the ``bar`` service should replace the ``foo`` service, +renaming ``foo`` to ``bar.inner``. +By convention, the old ``foo`` service is going to be renamed ``bar.inner``, +so you can inject it into your new service. + +.. note:: + The generated inner id is based on the id of the decorator service + (``bar`` here), not of the decorated service (``foo`` here). This is + mandatory to allow several decorators on the same service (they need to have + different generated inner ids). + + Most of the time, the decorator should be declared private, as you will not + need to retrieve it as ``bar`` from the container. The visibility of the + decorated ``foo`` service (which is an alias for ``bar``) will still be the + same as the original ``foo`` visibility. + +You can change the inner service name if you want to: + +.. configuration-block:: + + .. code-block:: yaml + + bar: + class: stdClass + public: false + decorates: foo + decoration_inner_name: bar.wooz + arguments: ["@bar.wooz"] + + .. code-block:: xml + + + + + + .. code-block:: php + + use Symfony\Component\DependencyInjection\Reference; + + $container->register('bar', 'stdClass') + ->addArgument(new Reference('bar.wooz')) + ->setPublic(false) + ->setDecoratedService('foo', 'bar.wooz'); From 564f60d68943b7c870cc82a5dde196827e0c2318 Mon Sep 17 00:00:00 2001 From: Abdellatif AitBoudad Date: Sun, 25 May 2014 20:33:58 +0100 Subject: [PATCH 0321/1181] Fixed link. --- book/security.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/security.rst b/book/security.rst index c42a7f49934..3a9bf341674 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1099,7 +1099,7 @@ authorization from inside a controller:: .. versionadded:: 2.5 The ``createAccessDeniedException`` method was introduced in Symfony 2.5. -The :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::createAccessDeniedException()` +The :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::createAccessDeniedException` method creates a special :class:`Symfony\\Component\\Security\\Core\Exception\\AccessDeniedException` object, which ultimately triggers a 403 HTTP response inside Symfony. From 47ce3f1a09c63bfb0ebfd6341f47c74bb1568389 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Fri, 6 Jun 2014 14:48:18 +0200 Subject: [PATCH 0322/1181] Fixed syntax --- components/console/helpers/progressbar.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/console/helpers/progressbar.rst b/components/console/helpers/progressbar.rst index 0cd119a0a9b..2ae9e64844a 100644 --- a/components/console/helpers/progressbar.rst +++ b/components/console/helpers/progressbar.rst @@ -55,7 +55,7 @@ instance:: $progress = new ProgressBar($output); -The progress will then be displayed as a throbber:: +The progress will then be displayed as a throbber: .. code-block:: text From b937b41b2cb26aa4c063804228ecd771d97485e2 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sun, 8 Jun 2014 17:22:28 +0200 Subject: [PATCH 0323/1181] Added May changelog --- changelog.rst | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/changelog.rst b/changelog.rst index ef4f2f3226c..db4ed4f8fe0 100644 --- a/changelog.rst +++ b/changelog.rst @@ -13,6 +13,71 @@ documentation. Do you also want to participate in the Symfony Documentation? Take a look at the ":doc:`/contributing/documentation/overview`" article. +May, 2014 +--------- + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `e8511cb `_ #3776 Updated event_listener.rst (bfgasparin) +- `af8c20f `_ #3818 [Form customization] added block_name example. (aitboudad) +- `c788325 `_ #3841 [Cookbook][Logging] register processor per handler and per channel (xabbuh) +- `979533a `_ #3839 document how to test actions (greg0ire) +- `d8aaac3 `_ #3835 Updated framework.ide configuration (WouterJ) +- `f665e14 `_ #3704 [Form] Added documentation for Form Events (csarrazi) +- `14b9f14 `_ #3777 added docs for the core team (fabpot) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `0649c21 `_ #3869 Add a missing argument to the PdoSessionHandler (jakzal) +- `259a2b7 `_ #3866 [Book][Security]fixed Login when there is no session. (aitboudad) +- `9b7584f `_ #3863 Error in XML (tvlooy) +- `0cb9c3b `_ #3827 Update 'How to Create and store a Symfony2 Project in Git' (nicwortel) +- `4ed9a08 `_ #3830 Generate an APC prefix based on __FILE__ (trsteel88) +- `9a65412 `_ #3840 Update dialoghelper.rst (jdecoster) +- `1853fea `_ #3716 Fix issue #3712 (umpirsky) +- `80d70a4 `_ #3779 [Book][Security] constants are defined in the SecurityContextInterface (xabbuh) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `302fa82 `_ #3872 Update hostname_pattern.rst (sofany) +- `50672f7 `_ #3867 fixed missing info about FosUserBundle. (aitboudad) +- `b32ec15 `_ #3856 Update voters_data_permission.rst (MarcomTeam) +- `bffe163 `_ #3859 Add filter cssrewrite (DOEO) +- `f617ff8 `_ #3764 Update testing.rst (NAYZO) +- `3792fee `_ #3858 Clarified Password Encoders example (WouterJ) +- `663d68c `_ #3857 Added little bit information about the route name (WouterJ) +- `4211bff `_ #3852 Fixed link and typo in type_guesser.rst (rpg600) +- `78ae7ec `_ #3845 added link to /cookbook/security/force_https. (aitboudad) +- `6c69362 `_ #3846 [Routing][Loader] added JMSI18nRoutingBundle (aitboudad) +- `136864b `_ #3844 [Components] Fixed some typos. (ahsio) +- `b0710bc `_ #3842 Update dialoghelper.rst (bijsterdee) +- `9f1a354 `_ #3804 [Components][DependencyInjection] add note about a use case that requires to compile the container (xabbuh) +- `d92c522 `_ #3769 Updated references to new Session() (scottwarren) +- `7288a33 `_ #3789 [Reference][Forms] Improvements to the form type (xabbuh) +- `72fae25 `_ #3790 [Reference][Forms] move versionadded directives for form options directly below the option's headline (xabbuh) +- `b4d4ac3 `_ #3838 fix filename typo in cookbook/form/unit_testing.rst (hice3000) +- `0b06287 `_ #3836 remove unnecessary rewrite from nginx conf (Burgov) +- `89d0dae `_ #3833 fix the wording in versionadded directives (for the 2.4 branch) (xabbuh) +- `e58e39f `_ #3832 fix the wording in versionadded directives (for the 2.3 branch) (xabbuh) +- `09d6ca1 `_ #3829 [Components] consistent headlines (xabbuh) +- `54e0882 `_ #3828 [Contributing] consistent headlines (xabbuh) +- `b1336d7 `_ #3823 Added empty line after if statements (zomberg) +- `79b9fdc `_ #3822 Update voters_data_permission.rst (mimol91) +- `69cb7b8 `_ #3821 Update custom_authentication_provider.rst (leberknecht) +- `9f602c4 `_ #3820 Update page_creation.rst (adreeun) +- `52518c0 `_ #3819 Update csrf_in_login_form.rst (micheal) +- `1adfd9b `_ #3802 Add a note about which types can be used in Symfony (fabpot) +- `fa27ded `_ #3801 [Cookbook][Form] Fixed Typo & missing word. (ahsio) +- `127beed `_ #3770 Update factories.rst (AlaaAttya) +- `822d985 `_ #3817 Update translation.rst (richardpi) +- `241d923 `_ #3813 [Reference][Forms]fix time field count. (yositani2002) +- `bc96f55 `_ #3812 [Cookbook][Configuration] Fixed broken link. (ahsio) +- `5867327 `_ #3809 Fixed typo (WouterJ) +- `678224e `_ #3808 Fixed broken link in "Handling Authentication Failure" (stacyhorton) + April, 2014 ----------- From c5ca4978cb98f378c92cdf9d5c40611b8349a132 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sun, 8 Jun 2014 17:22:57 +0200 Subject: [PATCH 0324/1181] Added May changelog --- changelog.rst | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/changelog.rst b/changelog.rst index f5b997e4cea..46868fdda58 100644 --- a/changelog.rst +++ b/changelog.rst @@ -13,6 +13,80 @@ documentation. Do you also want to participate in the Symfony Documentation? Take a look at the ":doc:`/contributing/documentation/overview`" article. +May, 2014 +--------- + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `4fd1b49 `_ #3753 [DependencyInjection] Add documentation about service decoration (romainneutron) +- `f913dd7 `_ #3603 [Serializer] Support for is.* getters in GetSetMethodNormalizer (tiraeth) +- `e8511cb `_ #3776 Updated event_listener.rst (bfgasparin) +- `af8c20f `_ #3818 [Form customization] added block_name example. (aitboudad) +- `c788325 `_ #3841 [Cookbook][Logging] register processor per handler and per channel (xabbuh) +- `979533a `_ #3839 document how to test actions (greg0ire) +- `d8aaac3 `_ #3835 Updated framework.ide configuration (WouterJ) +- `a9648e8 `_ #3742 [2.5][Templating] Add documentation about generating versioned URLs (romainneutron) +- `f665e14 `_ #3704 [Form] Added documentation for Form Events (csarrazi) +- `14b9f14 `_ #3777 added docs for the core team (fabpot) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `0649c21 `_ #3869 Add a missing argument to the PdoSessionHandler (jakzal) +- `259a2b7 `_ #3866 [Book][Security]fixed Login when there is no session. (aitboudad) +- `9b7584f `_ #3863 Error in XML (tvlooy) +- `0cb9c3b `_ #3827 Update 'How to Create and store a Symfony2 Project in Git' (nicwortel) +- `4ed9a08 `_ #3830 Generate an APC prefix based on __FILE__ (trsteel88) +- `9a65412 `_ #3840 Update dialoghelper.rst (jdecoster) +- `1853fea `_ #3716 Fix issue #3712 (umpirsky) +- `baa9759 `_ #3791 Property access tweaks (weaverryan) +- `80d70a4 `_ #3779 [Book][Security] constants are defined in the SecurityContextInterface (xabbuh) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `302fa82 `_ #3872 Update hostname_pattern.rst (sofany) +- `50672f7 `_ #3867 fixed missing info about FosUserBundle. (aitboudad) +- `3e3004f `_ #3865 Fixed link. (aitboudad) +- `b32ec15 `_ #3856 Update voters_data_permission.rst (MarcomTeam) +- `bffe163 `_ #3859 Add filter cssrewrite (DOEO) +- `f617ff8 `_ #3764 Update testing.rst (NAYZO) +- `3792fee `_ #3858 Clarified Password Encoders example (WouterJ) +- `663d68c `_ #3857 Added little bit information about the route name (WouterJ) +- `797cbd5 `_ #3794 Adds link to new QuestionHelper (weaverryan) +- `4211bff `_ #3852 Fixed link and typo in type_guesser.rst (rpg600) +- `78ae7ec `_ #3845 added link to /cookbook/security/force_https. (aitboudad) +- `6c69362 `_ #3846 [Routing][Loader] added JMSI18nRoutingBundle (aitboudad) +- `136864b `_ #3844 [Components] Fixed some typos. (ahsio) +- `b0710bc `_ #3842 Update dialoghelper.rst (bijsterdee) +- `9f1a354 `_ #3804 [Components][DependencyInjection] add note about a use case that requires to compile the container (xabbuh) +- `d92c522 `_ #3769 Updated references to new Session() (scottwarren) +- `00f60a8 `_ #3837 More asset version details (weaverryan) +- `681ddc8 `_ #3843 [Changelog] fix literal positions (xabbuh) +- `1aa79d5 `_ #3834 fix the wording in versionadded directives (for the master branch) (xabbuh) +- `7288a33 `_ #3789 [Reference][Forms] Improvements to the form type (xabbuh) +- `72fae25 `_ #3790 [Reference][Forms] move versionadded directives for form options directly below the option's headline (xabbuh) +- `b4d4ac3 `_ #3838 fix filename typo in cookbook/form/unit_testing.rst (hice3000) +- `0b06287 `_ #3836 remove unnecessary rewrite from nginx conf (Burgov) +- `89d0dae `_ #3833 fix the wording in versionadded directives (for the 2.4 branch) (xabbuh) +- `e58e39f `_ #3832 fix the wording in versionadded directives (for the 2.3 branch) (xabbuh) +- `09d6ca1 `_ #3829 [Components] consistent headlines (xabbuh) +- `54e0882 `_ #3828 [Contributing] consistent headlines (xabbuh) +- `b1336d7 `_ #3823 Added empty line after if statements (zomberg) +- `79b9fdc `_ #3822 Update voters_data_permission.rst (mimol91) +- `69cb7b8 `_ #3821 Update custom_authentication_provider.rst (leberknecht) +- `9f602c4 `_ #3820 Update page_creation.rst (adreeun) +- `52518c0 `_ #3819 Update csrf_in_login_form.rst (micheal) +- `1adfd9b `_ #3802 Add a note about which types can be used in Symfony (fabpot) +- `fa27ded `_ #3801 [Cookbook][Form] Fixed Typo & missing word. (ahsio) +- `127beed `_ #3770 Update factories.rst (AlaaAttya) +- `822d985 `_ #3817 Update translation.rst (richardpi) +- `241d923 `_ #3813 [Reference][Forms]fix time field count. (yositani2002) +- `bc96f55 `_ #3812 [Cookbook][Configuration] Fixed broken link. (ahsio) +- `5867327 `_ #3809 Fixed typo (WouterJ) +- `678224e `_ #3808 Fixed broken link in "Handling Authentication Failure" (stacyhorton) + April, 2014 ----------- From 43ae4f132cc9fa125fee8e0374bd7ab00451b6d1 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sun, 8 Jun 2014 17:23:21 +0200 Subject: [PATCH 0325/1181] Added May changelog --- changelog.rst | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/changelog.rst b/changelog.rst index f5b997e4cea..46868fdda58 100644 --- a/changelog.rst +++ b/changelog.rst @@ -13,6 +13,80 @@ documentation. Do you also want to participate in the Symfony Documentation? Take a look at the ":doc:`/contributing/documentation/overview`" article. +May, 2014 +--------- + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `4fd1b49 `_ #3753 [DependencyInjection] Add documentation about service decoration (romainneutron) +- `f913dd7 `_ #3603 [Serializer] Support for is.* getters in GetSetMethodNormalizer (tiraeth) +- `e8511cb `_ #3776 Updated event_listener.rst (bfgasparin) +- `af8c20f `_ #3818 [Form customization] added block_name example. (aitboudad) +- `c788325 `_ #3841 [Cookbook][Logging] register processor per handler and per channel (xabbuh) +- `979533a `_ #3839 document how to test actions (greg0ire) +- `d8aaac3 `_ #3835 Updated framework.ide configuration (WouterJ) +- `a9648e8 `_ #3742 [2.5][Templating] Add documentation about generating versioned URLs (romainneutron) +- `f665e14 `_ #3704 [Form] Added documentation for Form Events (csarrazi) +- `14b9f14 `_ #3777 added docs for the core team (fabpot) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `0649c21 `_ #3869 Add a missing argument to the PdoSessionHandler (jakzal) +- `259a2b7 `_ #3866 [Book][Security]fixed Login when there is no session. (aitboudad) +- `9b7584f `_ #3863 Error in XML (tvlooy) +- `0cb9c3b `_ #3827 Update 'How to Create and store a Symfony2 Project in Git' (nicwortel) +- `4ed9a08 `_ #3830 Generate an APC prefix based on __FILE__ (trsteel88) +- `9a65412 `_ #3840 Update dialoghelper.rst (jdecoster) +- `1853fea `_ #3716 Fix issue #3712 (umpirsky) +- `baa9759 `_ #3791 Property access tweaks (weaverryan) +- `80d70a4 `_ #3779 [Book][Security] constants are defined in the SecurityContextInterface (xabbuh) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `302fa82 `_ #3872 Update hostname_pattern.rst (sofany) +- `50672f7 `_ #3867 fixed missing info about FosUserBundle. (aitboudad) +- `3e3004f `_ #3865 Fixed link. (aitboudad) +- `b32ec15 `_ #3856 Update voters_data_permission.rst (MarcomTeam) +- `bffe163 `_ #3859 Add filter cssrewrite (DOEO) +- `f617ff8 `_ #3764 Update testing.rst (NAYZO) +- `3792fee `_ #3858 Clarified Password Encoders example (WouterJ) +- `663d68c `_ #3857 Added little bit information about the route name (WouterJ) +- `797cbd5 `_ #3794 Adds link to new QuestionHelper (weaverryan) +- `4211bff `_ #3852 Fixed link and typo in type_guesser.rst (rpg600) +- `78ae7ec `_ #3845 added link to /cookbook/security/force_https. (aitboudad) +- `6c69362 `_ #3846 [Routing][Loader] added JMSI18nRoutingBundle (aitboudad) +- `136864b `_ #3844 [Components] Fixed some typos. (ahsio) +- `b0710bc `_ #3842 Update dialoghelper.rst (bijsterdee) +- `9f1a354 `_ #3804 [Components][DependencyInjection] add note about a use case that requires to compile the container (xabbuh) +- `d92c522 `_ #3769 Updated references to new Session() (scottwarren) +- `00f60a8 `_ #3837 More asset version details (weaverryan) +- `681ddc8 `_ #3843 [Changelog] fix literal positions (xabbuh) +- `1aa79d5 `_ #3834 fix the wording in versionadded directives (for the master branch) (xabbuh) +- `7288a33 `_ #3789 [Reference][Forms] Improvements to the form type (xabbuh) +- `72fae25 `_ #3790 [Reference][Forms] move versionadded directives for form options directly below the option's headline (xabbuh) +- `b4d4ac3 `_ #3838 fix filename typo in cookbook/form/unit_testing.rst (hice3000) +- `0b06287 `_ #3836 remove unnecessary rewrite from nginx conf (Burgov) +- `89d0dae `_ #3833 fix the wording in versionadded directives (for the 2.4 branch) (xabbuh) +- `e58e39f `_ #3832 fix the wording in versionadded directives (for the 2.3 branch) (xabbuh) +- `09d6ca1 `_ #3829 [Components] consistent headlines (xabbuh) +- `54e0882 `_ #3828 [Contributing] consistent headlines (xabbuh) +- `b1336d7 `_ #3823 Added empty line after if statements (zomberg) +- `79b9fdc `_ #3822 Update voters_data_permission.rst (mimol91) +- `69cb7b8 `_ #3821 Update custom_authentication_provider.rst (leberknecht) +- `9f602c4 `_ #3820 Update page_creation.rst (adreeun) +- `52518c0 `_ #3819 Update csrf_in_login_form.rst (micheal) +- `1adfd9b `_ #3802 Add a note about which types can be used in Symfony (fabpot) +- `fa27ded `_ #3801 [Cookbook][Form] Fixed Typo & missing word. (ahsio) +- `127beed `_ #3770 Update factories.rst (AlaaAttya) +- `822d985 `_ #3817 Update translation.rst (richardpi) +- `241d923 `_ #3813 [Reference][Forms]fix time field count. (yositani2002) +- `bc96f55 `_ #3812 [Cookbook][Configuration] Fixed broken link. (ahsio) +- `5867327 `_ #3809 Fixed typo (WouterJ) +- `678224e `_ #3808 Fixed broken link in "Handling Authentication Failure" (stacyhorton) + April, 2014 ----------- From c24d262a848de52a55f2aae9336319c06e340d86 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 27 May 2014 22:43:49 +0200 Subject: [PATCH 0326/1181] change version numbers in installation notes to be in line with the documented Symfony version --- book/installation.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/book/installation.rst b/book/installation.rst index a929a0a9692..c9e24f32721 100644 --- a/book/installation.rst +++ b/book/installation.rst @@ -57,7 +57,7 @@ Distribution: .. code-block:: bash - $ php composer.phar create-project symfony/framework-standard-edition /path/to/webroot/Symfony dev-master + $ php composer.phar create-project symfony/framework-standard-edition /path/to/webroot/Symfony 2.5.* .. tip:: @@ -104,10 +104,10 @@ one of the following commands (replacing ``###`` with your actual filename): .. code-block:: bash # for .tgz file - $ tar zxvf Symfony_Standard_Vendors_2.4.###.tgz + $ tar zxvf Symfony_Standard_Vendors_2.5.###.tgz # for a .zip file - $ unzip Symfony_Standard_Vendors_2.4.###.zip + $ unzip Symfony_Standard_Vendors_2.5.###.zip If you've downloaded "without vendors", you'll definitely need to read the next section. From 864d9309ec743f0d537a44a1b9de82428ebdc0af Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 9 Jun 2014 19:56:53 +0200 Subject: [PATCH 0327/1181] Fixed the headers of one table --- components/http_kernel/introduction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/http_kernel/introduction.rst b/components/http_kernel/introduction.rst index 4128ef85ee2..3598eec9a8f 100644 --- a/components/http_kernel/introduction.rst +++ b/components/http_kernel/introduction.rst @@ -571,7 +571,7 @@ each event has their own event object: +-----------------------+----------------------------------+-------------------------------------------------------------------------------------+ | Name | ``KernelEvents`` Constant | Argument passed to the listener | -+-----------------------+----------------------------------+-------------------------------------------------------------------------------------+ ++=======================+==================================+=====================================================================================+ | kernel.request | ``KernelEvents::REQUEST`` | :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent` | +-----------------------+----------------------------------+-------------------------------------------------------------------------------------+ | kernel.controller | ``KernelEvents::CONTROLLER`` | :class:`Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent` | From cf667c94daa0d29e797d9d3c0031feeec87ac51e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 11 Jun 2014 00:15:12 +0200 Subject: [PATCH 0328/1181] update the TraceableEventDispatcher to reflect its movement to the EventDispatcher component in Symfony 2.5 --- components/event_dispatcher/traceable_dispatcher.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/components/event_dispatcher/traceable_dispatcher.rst b/components/event_dispatcher/traceable_dispatcher.rst index 6b1cb19db86..22404865fbf 100644 --- a/components/event_dispatcher/traceable_dispatcher.rst +++ b/components/event_dispatcher/traceable_dispatcher.rst @@ -5,13 +5,17 @@ The Traceable Event Dispatcher ============================== -The :class:`Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher` +.. versionadded:: 2.5 + The ``TraceableEventDispatcher`` class was moved to the EventDispatcher + component in Symfony 2.5. Before, it was located in the HttpKernel component. + +The :class:`Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher` is an event dispatcher that wraps any other event dispatcher and can then be used to determine which event listeners have been called by the dispatcher. Pass the event dispatcher to be wrapped and an instance of the :class:`Symfony\\Component\\Stopwatch\\Stopwatch` to its constructor:: - use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher; + use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; use Symfony\Component\Stopwatch\Stopwatch; // the event dispatcher to debug From c7c48b86e84d03df2b08daec12ceda9d550fae5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Wed, 11 Jun 2014 14:05:59 +0200 Subject: [PATCH 0329/1181] fix typo --- book/translation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/translation.rst b/book/translation.rst index 0f46aa03923..ce10b796644 100644 --- a/book/translation.rst +++ b/book/translation.rst @@ -647,7 +647,7 @@ Translating Database Content The translation of database content should be handled by Doctrine through the `Translatable Extension`_ or the `Translatable Behavior`_ (PHP 5.4+). -For more information, see the documentation for thes libraries. +For more information, see the documentation for these libraries. Debugging Translations ---------------------- From 3ec651cb2bc519d82f78e9e7fa8f15e4259fe8ec Mon Sep 17 00:00:00 2001 From: Mitchel Date: Tue, 10 Jun 2014 15:24:04 +0200 Subject: [PATCH 0330/1181] Update custom_authentication_provider.rst Removed response because it will always be overwritten "By default deny authorization" response --- cookbook/security/custom_authentication_provider.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/cookbook/security/custom_authentication_provider.rst b/cookbook/security/custom_authentication_provider.rst index 42f098464ab..73f76f2857e 100644 --- a/cookbook/security/custom_authentication_provider.rst +++ b/cookbook/security/custom_authentication_provider.rst @@ -159,12 +159,6 @@ set an authenticated token in the security context if successful. // $this->securityContext->setToken(null); // } // return; - - // Deny authentication with a '403 Forbidden' HTTP response - $response = new Response(); - $response->setStatusCode(Response::HTTP_FORBIDDEN); - $event->setResponse($response); - } // By default deny authorization From 84ea4c87916ae7323b8dd45bcac5ee8a8b8baf16 Mon Sep 17 00:00:00 2001 From: Cliff Odijk Date: Wed, 11 Jun 2014 11:58:07 +0200 Subject: [PATCH 0331/1181] Move __construct after the repository assignment The configure function is called from the parent::__construct(); so the $this->nameRepository is still empty during the configure. Thats why it should be the other way around. --- cookbook/console/commands_as_services.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook/console/commands_as_services.rst b/cookbook/console/commands_as_services.rst index 60f22824686..a60ebaa11e7 100644 --- a/cookbook/console/commands_as_services.rst +++ b/cookbook/console/commands_as_services.rst @@ -90,9 +90,9 @@ have some ``NameRepository`` service that you'll use to get your default value:: public function __construct(NameRepository $nameRepository) { - parent::__construct(); - $this->nameRepository = $nameRepository; + + parent::__construct(); } protected function configure() From 6c4421b2a30806fabd8b6e5001882aedc9d3dcb4 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 11 Jun 2014 18:20:17 +0200 Subject: [PATCH 0332/1181] properly escape backslashes in class and method directives --- book/security.rst | 2 +- components/class_loader/psr4_class_loader.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/book/security.rst b/book/security.rst index fb0f7884dfb..0572bc13330 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1105,7 +1105,7 @@ authorization from inside a controller:: The ``createAccessDeniedException`` method was introduced in Symfony 2.5. The :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::createAccessDeniedException` -method creates a special :class:`Symfony\\Component\\Security\\Core\Exception\\AccessDeniedException` +method creates a special :class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException` object, which ultimately triggers a 403 HTTP response inside Symfony. Thanks to the SensioFrameworkExtraBundle, you can also secure your controller using annotations:: diff --git a/components/class_loader/psr4_class_loader.rst b/components/class_loader/psr4_class_loader.rst index 489db8a351d..e388590310d 100644 --- a/components/class_loader/psr4_class_loader.rst +++ b/components/class_loader/psr4_class_loader.rst @@ -59,7 +59,7 @@ first need to configure the ``Psr4ClassLoader``: First of all, the class loader is loaded manually using a ``require`` statement, since there is no autoload mechanism yet. With the -:method:`Symfony\Component\ClassLoader\Psr4ClassLoader::addPrefix` call, you +:method:`Symfony\\Component\\ClassLoader\\Psr4ClassLoader::addPrefix` call, you tell the class loader where to look for classes with the ``Symfony\Component\Yaml\`` namespace prefix. After registering the autoloader, the Yaml component is ready to be used. From 34ad1b5773820bc4c80b17d3984aedae1691a8c1 Mon Sep 17 00:00:00 2001 From: Maxime Douailin Date: Fri, 6 Jun 2014 14:28:59 +0200 Subject: [PATCH 0333/1181] [Security] Added remote_user firewall info and documentation for pre authenticated firewalls --- reference/configuration/security.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/reference/configuration/security.rst b/reference/configuration/security.rst index 2eda8410c86..340d9af8c3a 100644 --- a/reference/configuration/security.rst +++ b/reference/configuration/security.rst @@ -121,6 +121,9 @@ Each part will be explained in the next section. stateless: false x509: provider: some_key_from_above + # new in Symfony 2.6 + remote_user: + provider: some_key_from_above http_basic: provider: some_key_from_above http_digest: From 8465d465f8cde4a60d35a776313bee363f38e577 Mon Sep 17 00:00:00 2001 From: Maxime Douailin Date: Fri, 6 Jun 2014 14:56:44 +0200 Subject: [PATCH 0334/1181] [Reference][Configuration] Removed version added for remote_user --- reference/configuration/security.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/reference/configuration/security.rst b/reference/configuration/security.rst index 340d9af8c3a..66c15ae0916 100644 --- a/reference/configuration/security.rst +++ b/reference/configuration/security.rst @@ -121,7 +121,6 @@ Each part will be explained in the next section. stateless: false x509: provider: some_key_from_above - # new in Symfony 2.6 remote_user: provider: some_key_from_above http_basic: From 86ba188bbe274d9e1d9b3d392e2c57a737eb63cd Mon Sep 17 00:00:00 2001 From: Maxime Douailin Date: Thu, 12 Jun 2014 17:34:04 +0200 Subject: [PATCH 0335/1181] rebased using x509 pr, added remote_user pre authenticated part --- cookbook/security/pre_authenticated.rst | 66 ++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/cookbook/security/pre_authenticated.rst b/cookbook/security/pre_authenticated.rst index fe77000422c..d5490fde519 100644 --- a/cookbook/security/pre_authenticated.rst +++ b/cookbook/security/pre_authenticated.rst @@ -66,6 +66,8 @@ the user provider, and sets the ``SSL_CLIENT_S_DN`` as credentials in the You can override these by setting the ``user`` and the ``credentials`` keys in the x509 firewall configuration respectively. +.. _cookbook-security-pre-authenticated-user-provider-note: + .. note:: An authentication provider will only inform the user provider of the username @@ -76,4 +78,66 @@ in the x509 firewall configuration respectively. provider, see: * :doc:`/cookbook/security/custom_provider` - * :doc:`/cookbook/security/entity_provider` \ No newline at end of file + * :doc:`/cookbook/security/entity_provider` + +REMOTE_USER based Authentication +-------------------------------- + +.. versionadded:: 2.6 + REMOTE_USER pre authenticated firewall was introduced in Symfony 2.6. + +A lot of authentication modules, like ``auth_kerb` for Apache provide the username +using the ``REMOTE_USER`` environment variable. This variable can be trusted by +the application since the authentication happened before the request reached it. + +To configure Symfony using the ``REMOTE_USER` environment variable, simply enable the +corresponding firewall in your security configuration: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/security.yml + security: + firewalls: + secured_area: + pattern: ^/ + remote_user: + provider: your_user_provider + + .. code-block:: xml + + + + + + + + + + + + + .. code-block:: php + + // app/config/security.php + $container->loadFromExtension('security', array( + 'firewalls' => array( + 'secured_area' => array( + 'pattern' => '^/' + 'remote_user' => array( + 'provider' => 'your_user_provider', + ), + ), + ), + )); + +The firewall will then provide the ``REMOTE_USER`` environment variable to +your user provider. You can change the variable name used by setting the ``user`` +key in the ``remote_user`` firewall configuration. + +.. note:: + + Just like for X509 authentication, you will need to configure a "user provider". + See :ref:`the note about it `. From be0d866de3fe6392d1dceddbff08d0e31025dc9e Mon Sep 17 00:00:00 2001 From: Maxime Douailin Date: Thu, 12 Jun 2014 19:08:02 +0200 Subject: [PATCH 0336/1181] fix missing backtick, rephrased bottom note --- cookbook/security/pre_authenticated.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cookbook/security/pre_authenticated.rst b/cookbook/security/pre_authenticated.rst index d5490fde519..640fc9f5cf7 100644 --- a/cookbook/security/pre_authenticated.rst +++ b/cookbook/security/pre_authenticated.rst @@ -73,8 +73,8 @@ in the x509 firewall configuration respectively. An authentication provider will only inform the user provider of the username that made the request. You will need to create (or use) a "user provider" that is referenced by the ``provider`` configuration parameter (``your_user_provider`` - in the configuration example). This provider will turn the username into a User - object of your choice. For more information on creating or configuring a user + in the configuration example). This provider will turn the username into a User + object of your choice. For more information on creating or configuring a user provider, see: * :doc:`/cookbook/security/custom_provider` @@ -86,11 +86,11 @@ REMOTE_USER based Authentication .. versionadded:: 2.6 REMOTE_USER pre authenticated firewall was introduced in Symfony 2.6. -A lot of authentication modules, like ``auth_kerb` for Apache provide the username -using the ``REMOTE_USER`` environment variable. This variable can be trusted by +A lot of authentication modules, like ``auth_kerb` for Apache provide the username +using the ``REMOTE_USER`` environment variable. This variable can be trusted by the application since the authentication happened before the request reached it. -To configure Symfony using the ``REMOTE_USER` environment variable, simply enable the +To configure Symfony using the ``REMOTE_USER`` environment variable, simply enable the corresponding firewall in your security configuration: .. configuration-block:: @@ -140,4 +140,5 @@ key in the ``remote_user`` firewall configuration. .. note:: Just like for X509 authentication, you will need to configure a "user provider". - See :ref:`the note about it `. + See :ref:`the note previous note ` + for more information. From 9dfc088545d453ae938e40dd7621b32af58edb95 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Fri, 13 Jun 2014 13:28:38 +0200 Subject: [PATCH 0337/1181] Fixed missing component name in namespaces --- components/console/helpers/table.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/console/helpers/table.rst b/components/console/helpers/table.rst index 7729ecce6eb..0f3511fe040 100644 --- a/components/console/helpers/table.rst +++ b/components/console/helpers/table.rst @@ -24,7 +24,7 @@ When building a console application it may be useful to display tabular data: To display a table, use :class:`Symfony\\Component\\Console\\Helper\\Table`, set the headers, set the rows and then render the table:: - use Symfony\Component\Helper\Table; + use Symfony\Component\Console\Helper\Table; $table = new Table($output); $table @@ -41,7 +41,7 @@ set the headers, set the rows and then render the table:: You can add a table separator anywhere in the output by passing an instance of :class:`Symfony\\Component\\Console\\Helper\\TableSeparator` as a row:: - use Symfony\Component\Helper\TableSeparator; + use Symfony\Component\Console\Helper\TableSeparator; $table->setRows(array( array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), @@ -103,7 +103,7 @@ which outputs: If the built-in styles do not fit your need, define your own:: - use Symfony\Component\Helper\TableStyle; + use Symfony\Component\Console\Helper\TableStyle; // by default, this is based on the default style $style = new TableStyle(); From 80673d58627435aeab3d0daa0891205c2306b344 Mon Sep 17 00:00:00 2001 From: Vyacheslav Salakhutdinov Date: Mon, 23 Jun 2014 05:23:37 +0000 Subject: [PATCH 0338/1181] Disallow empty file in FileValidator --- reference/constraints/File.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/reference/constraints/File.rst b/reference/constraints/File.rst index 683d0fe6a49..c06a20fd71b 100644 --- a/reference/constraints/File.rst +++ b/reference/constraints/File.rst @@ -23,6 +23,7 @@ form type. | | - `mimeTypes`_ | | | - `maxSizeMessage`_ | | | - `mimeTypesMessage`_ | +| | - `disallowEmptyMessage`_ | | | - `notFoundMessage`_ | | | - `notReadableMessage`_ | | | - `uploadIniSizeErrorMessage`_ | @@ -194,6 +195,18 @@ mimeTypesMessage The message displayed if the mime type of the file is not a valid mime type per the `mimeTypes`_ option. +disallowEmptyMessage +~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 2.6 + The ``disallowEmptyMessage`` option was introduced in Symfony 2.6. Prior to 2.6, + if the user uploaded an empty file, no validation error occurred. + +**type**: ``string`` **default**: ``An empty file is not allowed.`` + +This constraint checks if the uploaded file is empty (i.e. 0 bytes). If it is, +this message is displayed. + notFoundMessage ~~~~~~~~~~~~~~~ From d1c95ceeb2722ff8935f3b40aef4b0fbf6b6ba27 Mon Sep 17 00:00:00 2001 From: Diego Saint Esteben Date: Tue, 24 Jun 2014 00:14:32 -0300 Subject: [PATCH 0339/1181] Added PSR-4 ClassLoader to list --- components/class_loader/introduction.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/class_loader/introduction.rst b/components/class_loader/introduction.rst index 2eff7ee69e8..8e529c0ac52 100644 --- a/components/class_loader/introduction.rst +++ b/components/class_loader/introduction.rst @@ -12,11 +12,14 @@ Usage Whenever you reference a class that has not been required or included yet, PHP uses the `autoloading mechanism`_ to delegate the loading of a file defining -the class. Symfony2 provides two autoloaders, which are able to load your classes: +the class. Symfony2 provides three autoloaders, which are able to load your classes: * :doc:`/components/class_loader/class_loader`: loads classes that follow the `PSR-0` class naming standard; +* :doc:`/components/class_loader/psr4_class_loader`: loads classes that follow + the `PSR-4` class naming standard; + * :doc:`/components/class_loader/map_class_loader`: loads classes using a static map from class name to file path. From e3acdc5dcfcf6419c0a784a8151b90067d01452e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sat, 31 May 2014 23:26:15 +0200 Subject: [PATCH 0340/1181] Support MaxSize in KiB and MiB --- reference/constraints/File.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/reference/constraints/File.rst b/reference/constraints/File.rst index 683d0fe6a49..7d200e4f36b 100644 --- a/reference/constraints/File.rst +++ b/reference/constraints/File.rst @@ -163,10 +163,16 @@ to be valid. The size of the file can be given in one of the following formats: numeric (e.g. ``4096``); * **kilobytes**: To specify the ``maxSize`` in kilobytes, pass a number and - suffix it with a lowercase "k" (e.g. ``200k``); + suffix it with a "k" (e.g. ``200k``); * **megabytes**: To specify the ``maxSize`` in megabytes, pass a number and - suffix it with a capital "M" (e.g. ``4M``). + suffix it with a "M" (e.g. ``4M``). + +* **kibibytes**: To specify the ``maxSize`` in kibibytes, pass a number and + suffix it with a "Ki" (e.g. ``600Ki``); + +* **mebibytes**: To specify the ``maxSize`` in mebibytes, pass a number and + suffix it with a "Mi" (e.g. ``8Mi``). mimeTypes ~~~~~~~~~ From deac0c3a6fd13c61eeca59d715c7fab014836f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sun, 1 Jun 2014 15:33:56 +0200 Subject: [PATCH 0341/1181] Add option binaryFormat in constraint file --- reference/constraints/File.rst | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/reference/constraints/File.rst b/reference/constraints/File.rst index 7d200e4f36b..a09c98a70d8 100644 --- a/reference/constraints/File.rst +++ b/reference/constraints/File.rst @@ -20,6 +20,7 @@ form type. | Applies to | :ref:`property or method ` | +----------------+---------------------------------------------------------------------+ | Options | - `maxSize`_ | +| | - `binaryFormat`_ | | | - `mimeTypes`_ | | | - `maxSizeMessage`_ | | | - `mimeTypesMessage`_ | @@ -78,7 +79,7 @@ below a certain file size and a valid PDF, add the following: maxSize: 1024k mimeTypes: [application/pdf, application/x-pdf] mimeTypesMessage: Please upload a valid PDF - + .. code-block:: php-annotations @@ -151,6 +152,18 @@ have been specified. Options ------- +.. versionadded:: 2.6 + The ``binaryFormat`` option was introduced in Symfony 2.6. + +binaryFormat +~~~~~~~~~~~~ + +**type**: ``boolean`` **default**: ``null`` + +When true, the sizes will be displayed in messages with binary suffixes (KiB, MiB). +When false, the sizes will be displayed with SI suffixes (kB, MB). +When null, then the binaryFormat will be guessed from the suffix defined in the maxSize option. + maxSize ~~~~~~~ From 3f3f4e0292a80194e6c54d048feabef81a75c610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sun, 1 Jun 2014 16:05:54 +0200 Subject: [PATCH 0342/1181] Provide information about SI and Binary prefixes --- reference/constraints/File.rst | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/reference/constraints/File.rst b/reference/constraints/File.rst index a09c98a70d8..0c02b191097 100644 --- a/reference/constraints/File.rst +++ b/reference/constraints/File.rst @@ -164,6 +164,8 @@ When true, the sizes will be displayed in messages with binary suffixes (KiB, Mi When false, the sizes will be displayed with SI suffixes (kB, MB). When null, then the binaryFormat will be guessed from the suffix defined in the maxSize option. +For more information about the difference between binary and SI suffixes, see `Wikipedia: Binary prefix`_. + maxSize ~~~~~~~ @@ -173,19 +175,21 @@ If set, the size of the underlying file must be below this file size in order to be valid. The size of the file can be given in one of the following formats: * **bytes**: To specify the ``maxSize`` in bytes, pass a value that is entirely - numeric (e.g. ``4096``); + numeric (e.g. ``4096``). * **kilobytes**: To specify the ``maxSize`` in kilobytes, pass a number and - suffix it with a "k" (e.g. ``200k``); + suffix it with a "k" (e.g. ``200k``); 1k = 1 000 bytes. * **megabytes**: To specify the ``maxSize`` in megabytes, pass a number and - suffix it with a "M" (e.g. ``4M``). + suffix it with a "M" (e.g. ``4M``); 1M = 1 000 000 bytes. * **kibibytes**: To specify the ``maxSize`` in kibibytes, pass a number and - suffix it with a "Ki" (e.g. ``600Ki``); + suffix it with a "Ki" (e.g. ``600Ki``); 1Ki = 1 024 bytes. * **mebibytes**: To specify the ``maxSize`` in mebibytes, pass a number and - suffix it with a "Mi" (e.g. ``8Mi``). + suffix it with a "Mi" (e.g. ``8Mi``); 1Mi = 1 048 576 bytes. + +For more information about the difference between binary and SI suffixes, see `Wikipedia: Binary prefix`_. mimeTypes ~~~~~~~~~ @@ -257,3 +261,4 @@ to disk. .. _`IANA website`: http://www.iana.org/assignments/media-types/index.html +.. _`Wikipedia: Binary prefix`: http://en.wikipedia.org/wiki/Binary_prefix From 71fdd60f3c28521b4588f0908dedb1ce06f0d36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sun, 1 Jun 2014 16:53:08 +0200 Subject: [PATCH 0343/1181] Fix line wrap --- reference/constraints/File.rst | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/reference/constraints/File.rst b/reference/constraints/File.rst index 0c02b191097..cd573c3a7e3 100644 --- a/reference/constraints/File.rst +++ b/reference/constraints/File.rst @@ -160,11 +160,13 @@ binaryFormat **type**: ``boolean`` **default**: ``null`` -When true, the sizes will be displayed in messages with binary suffixes (KiB, MiB). -When false, the sizes will be displayed with SI suffixes (kB, MB). -When null, then the binaryFormat will be guessed from the suffix defined in the maxSize option. +When ``true``, the sizes will be displayed in messages with binary suffixes +(KiB, MiB). When ``false``, the sizes will be displayed with SI suffixes (kB, +MB). When ``null``, then the binaryFormat will be guessed from the suffix +defined in the maxSize option. -For more information about the difference between binary and SI suffixes, see `Wikipedia: Binary prefix`_. +For more information about the difference between binary and SI suffixes, +see `Wikipedia: Binary prefix`_. maxSize ~~~~~~~ @@ -189,7 +191,8 @@ to be valid. The size of the file can be given in one of the following formats: * **mebibytes**: To specify the ``maxSize`` in mebibytes, pass a number and suffix it with a "Mi" (e.g. ``8Mi``); 1Mi = 1 048 576 bytes. -For more information about the difference between binary and SI suffixes, see `Wikipedia: Binary prefix`_. +For more information about the difference between binary and SI suffixes, +see `Wikipedia: Binary prefix`_. mimeTypes ~~~~~~~~~ From 7dcd7c3b9b0d85be92a074f0dce8d28ae6fd7629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sun, 1 Jun 2014 20:51:03 +0200 Subject: [PATCH 0344/1181] Move secion "binaryFormat" to the right place --- reference/constraints/File.rst | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/reference/constraints/File.rst b/reference/constraints/File.rst index cd573c3a7e3..355901362b1 100644 --- a/reference/constraints/File.rst +++ b/reference/constraints/File.rst @@ -152,22 +152,6 @@ have been specified. Options ------- -.. versionadded:: 2.6 - The ``binaryFormat`` option was introduced in Symfony 2.6. - -binaryFormat -~~~~~~~~~~~~ - -**type**: ``boolean`` **default**: ``null`` - -When ``true``, the sizes will be displayed in messages with binary suffixes -(KiB, MiB). When ``false``, the sizes will be displayed with SI suffixes (kB, -MB). When ``null``, then the binaryFormat will be guessed from the suffix -defined in the maxSize option. - -For more information about the difference between binary and SI suffixes, -see `Wikipedia: Binary prefix`_. - maxSize ~~~~~~~ @@ -194,6 +178,22 @@ to be valid. The size of the file can be given in one of the following formats: For more information about the difference between binary and SI suffixes, see `Wikipedia: Binary prefix`_. +binaryFormat +~~~~~~~~~~~~ + +.. versionadded:: 2.6 + The ``binaryFormat`` option was introduced in Symfony 2.6. + +**type**: ``boolean`` **default**: ``null`` + +When ``true``, the sizes will be displayed in messages with binary suffixes +(KiB, MiB). When ``false``, the sizes will be displayed with SI suffixes (kB, +MB). When ``null``, then the binaryFormat will be guessed from the suffix +defined in the maxSize option. + +For more information about the difference between binary and SI suffixes, +see `Wikipedia: Binary prefix`_. + mimeTypes ~~~~~~~~~ From b414f5c6e69cbad6a6c6a4d860f8144d0644650a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Thu, 19 Jun 2014 23:16:21 +0200 Subject: [PATCH 0345/1181] Use comma as thousands separator --- reference/constraints/File.rst | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/reference/constraints/File.rst b/reference/constraints/File.rst index 355901362b1..6eb19e232af 100644 --- a/reference/constraints/File.rst +++ b/reference/constraints/File.rst @@ -80,7 +80,6 @@ below a certain file size and a valid PDF, add the following: mimeTypes: [application/pdf, application/x-pdf] mimeTypesMessage: Please upload a valid PDF - .. code-block:: php-annotations // src/Acme/BlogBundle/Entity/Author.php @@ -161,19 +160,19 @@ If set, the size of the underlying file must be below this file size in order to be valid. The size of the file can be given in one of the following formats: * **bytes**: To specify the ``maxSize`` in bytes, pass a value that is entirely - numeric (e.g. ``4096``). + numeric (e.g. ``4096``); * **kilobytes**: To specify the ``maxSize`` in kilobytes, pass a number and - suffix it with a "k" (e.g. ``200k``); 1k = 1 000 bytes. + suffix it with a "k" (e.g. ``200k``); 1k = 1,000 bytes; * **megabytes**: To specify the ``maxSize`` in megabytes, pass a number and - suffix it with a "M" (e.g. ``4M``); 1M = 1 000 000 bytes. + suffix it with a "M" (e.g. ``4M``); 1M = 1,000,000 bytes; * **kibibytes**: To specify the ``maxSize`` in kibibytes, pass a number and - suffix it with a "Ki" (e.g. ``600Ki``); 1Ki = 1 024 bytes. + suffix it with a "Ki" (e.g. ``600Ki``); 1Ki = 1,024 bytes; * **mebibytes**: To specify the ``maxSize`` in mebibytes, pass a number and - suffix it with a "Mi" (e.g. ``8Mi``); 1Mi = 1 048 576 bytes. + suffix it with a "Mi" (e.g. ``8Mi``); 1Mi = 1,048,576 bytes. For more information about the difference between binary and SI suffixes, see `Wikipedia: Binary prefix`_. From 77a0687f3f2ca2a9aed57984d0fc0d73801317b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Tue, 24 Jun 2014 22:15:47 +0200 Subject: [PATCH 0346/1181] Add versionAdded on binary suffix --- reference/constraints/File.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/reference/constraints/File.rst b/reference/constraints/File.rst index 6eb19e232af..25edb10c8da 100644 --- a/reference/constraints/File.rst +++ b/reference/constraints/File.rst @@ -154,6 +154,9 @@ Options maxSize ~~~~~~~ +.. versionadded:: 2.6 + The suffixes ``Ki`` and ``Mi`` were introduced in Symfony 2.6. + **type**: ``mixed`` If set, the size of the underlying file must be below this file size in order @@ -188,7 +191,7 @@ binaryFormat When ``true``, the sizes will be displayed in messages with binary suffixes (KiB, MiB). When ``false``, the sizes will be displayed with SI suffixes (kB, MB). When ``null``, then the binaryFormat will be guessed from the suffix -defined in the maxSize option. +defined in the ``maxSize`` option. For more information about the difference between binary and SI suffixes, see `Wikipedia: Binary prefix`_. From 1e8fa48566091c10eb2ce40611e1909e6f73c9ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Tue, 24 Jun 2014 22:17:51 +0200 Subject: [PATCH 0347/1181] Replace bullet list by a table --- reference/constraints/File.rst | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/reference/constraints/File.rst b/reference/constraints/File.rst index 25edb10c8da..686442cb365 100644 --- a/reference/constraints/File.rst +++ b/reference/constraints/File.rst @@ -162,20 +162,19 @@ maxSize If set, the size of the underlying file must be below this file size in order to be valid. The size of the file can be given in one of the following formats: -* **bytes**: To specify the ``maxSize`` in bytes, pass a value that is entirely - numeric (e.g. ``4096``); - -* **kilobytes**: To specify the ``maxSize`` in kilobytes, pass a number and - suffix it with a "k" (e.g. ``200k``); 1k = 1,000 bytes; - -* **megabytes**: To specify the ``maxSize`` in megabytes, pass a number and - suffix it with a "M" (e.g. ``4M``); 1M = 1,000,000 bytes; - -* **kibibytes**: To specify the ``maxSize`` in kibibytes, pass a number and - suffix it with a "Ki" (e.g. ``600Ki``); 1Ki = 1,024 bytes; - -* **mebibytes**: To specify the ``maxSize`` in mebibytes, pass a number and - suffix it with a "Mi" (e.g. ``8Mi``); 1Mi = 1,048,576 bytes. ++--------+-----------+-----------------+------+ +| Suffix | Unit Name | value | e.g. | ++========+===========+=================+======+ +| | byte | 1 byte | 4096 | ++--------+-----------+-----------------+------+ +| k | kilobyte | 1,000 bytes | 200k | ++--------+-----------+-----------------+------+ +| M | megabyte | 1,000,000 bytes | 2M | ++--------+-----------+-----------------+------+ +| Ki | kibibyte | 1,024 bytes | 32Ki | ++--------+-----------+-----------------+------+ +| Mi | mebibyte | 1,048,576 bytes | 8Mi | ++--------+-----------+-----------------+------+ For more information about the difference between binary and SI suffixes, see `Wikipedia: Binary prefix`_. From b8a0eb2660c073c4742c85f47cfa3109314106af Mon Sep 17 00:00:00 2001 From: Maxime Douailin Date: Wed, 25 Jun 2014 14:19:25 +0200 Subject: [PATCH 0348/1181] fixes missing backtick --- cookbook/security/pre_authenticated.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/pre_authenticated.rst b/cookbook/security/pre_authenticated.rst index 640fc9f5cf7..394ae4f739e 100644 --- a/cookbook/security/pre_authenticated.rst +++ b/cookbook/security/pre_authenticated.rst @@ -86,7 +86,7 @@ REMOTE_USER based Authentication .. versionadded:: 2.6 REMOTE_USER pre authenticated firewall was introduced in Symfony 2.6. -A lot of authentication modules, like ``auth_kerb` for Apache provide the username +A lot of authentication modules, like ``auth_kerb`` for Apache provide the username using the ``REMOTE_USER`` environment variable. This variable can be trusted by the application since the authentication happened before the request reached it. From 1e6b55e01dd974641d378c2b46a3764df65585d1 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 1 Jul 2014 19:18:07 +0200 Subject: [PATCH 0349/1181] Added June changelog --- changelog.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/changelog.rst b/changelog.rst index 292e5132f4d..8e418377db9 100644 --- a/changelog.rst +++ b/changelog.rst @@ -34,6 +34,7 @@ Fixed Documentation - `aeffd12 `_ #3961 Fixing php coding (mvhirsch) - `d8329dc `_ #3943 Fixing simple quotes in double quotes (ptitlazy) +- `04f4318 `_ #3934 Move __construct after the repository assignment (cmodijk) - `0626f2b `_ #3897 Collection constraint (hhamon) - `3387cb2 `_ #3871 Fix missing Front Controller (parthasarathigk) - `8257be9 `_ #3891 Fixed wrong method call. (cmfcmf) @@ -48,10 +49,13 @@ Minor Documentation Changes - `c444b5d `_ #3948 update the Sphinx extensions to raise warnings when backslashes are not ... (xabbuh) - `8fef7b7 `_ #3938 [Contributing][Documentation] don't render the list inside a blockquote (xabbuh) - `222a014 `_ #3933 render directory inside a code block (xabbuh) +- `b31ea51 `_ #3929 Update custom_authentication_provider.rst (verschoof) - `7937864 `_ #3927 [Cookbook][Security] Explicit 'your_user_provider' configuration parameter (zefrog) - `26d00d0 `_ #3925 Fixed the indentation of two code blocks (javiereguiluz) - `351b2cf `_ #3922 update fabpot Sphinx extensions version (xabbuh) +- `3ddbe1b `_ #3923 Fixed the headers of one table (javiereguiluz) - `35cbffc `_ #3920 [Components][Form] remove blank line to render the versionadded directive properly (xabbuh) +- `ed496ae `_ #3887 [Components][Form] add versionadded for the data collector form extension (xabbuh) - `36337e7 `_ #3906 Blockquote introductions (xabbuh) - `5e0e119 `_ #3899 [RFR] Misc. fixes mostly related to formatting issues (javiereguiluz) - `349cbeb `_ #3900 Fixed the formatting of the table headers (javiereguiluz) From f34eaed712931efa116d588793ec07f40b102bb2 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 1 Jul 2014 19:18:58 +0200 Subject: [PATCH 0350/1181] Added June changelog --- changelog.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/changelog.rst b/changelog.rst index 61eecf7732b..8e8f7f27c7f 100644 --- a/changelog.rst +++ b/changelog.rst @@ -28,11 +28,13 @@ New Documentation - `23b51c8 `_ #3901 Bootstraped the standards for "Files and Directories" (javiereguiluz) - `8931c36 `_ #3889 Fixed the section about getting services from a command (javiereguiluz) - `9fddab6 `_ #3877 Added a note about configuring several paths under the same namespace (javiereguiluz) +- `eadf281 `_ #3874 Updated the installation instructions for Symfony 2.5+ (javiereguiluz) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ - `aeffd12 `_ #3961 Fixing php coding (mvhirsch) +- `84332ff `_ #3945 Fixed missing component name in namespaces (WouterJ) - `d8329dc `_ #3943 Fixing simple quotes in double quotes (ptitlazy) - `04f4318 `_ #3934 Move __construct after the repository assignment (cmodijk) - `0626f2b `_ #3897 Collection constraint (hhamon) @@ -48,13 +50,17 @@ Minor Documentation Changes - `fba083e `_ #3957 [Cookbook][Bundles] fix typos in the prepend extension chapter (xabbuh) - `c444b5d `_ #3948 update the Sphinx extensions to raise warnings when backslashes are not ... (xabbuh) - `8fef7b7 `_ #3938 [Contributing][Documentation] don't render the list inside a blockquote (xabbuh) +- `b7a03f8 `_ #3937 properly escape backslashes in class and method directives (xabbuh) +- `882471f `_ #3935 Typo (greg0ire) - `222a014 `_ #3933 render directory inside a code block (xabbuh) +- `0c2a9b3 `_ #3931 [Component][EventDispatcher] 2.5 specific documentation for the TraceableEventDispatcher (xabbuh) - `b31ea51 `_ #3929 Update custom_authentication_provider.rst (verschoof) - `7937864 `_ #3927 [Cookbook][Security] Explicit 'your_user_provider' configuration parameter (zefrog) - `26d00d0 `_ #3925 Fixed the indentation of two code blocks (javiereguiluz) - `351b2cf `_ #3922 update fabpot Sphinx extensions version (xabbuh) - `3ddbe1b `_ #3923 Fixed the headers of one table (javiereguiluz) - `35cbffc `_ #3920 [Components][Form] remove blank line to render the versionadded directive properly (xabbuh) +- `df9f31a `_ #3882 change version numbers in installation notes to be in line with the docu... (xabbuh) - `ed496ae `_ #3887 [Components][Form] add versionadded for the data collector form extension (xabbuh) - `36337e7 `_ #3906 Blockquote introductions (xabbuh) - `5e0e119 `_ #3899 [RFR] Misc. fixes mostly related to formatting issues (javiereguiluz) From fcae3cd8faee35aba5077b8754e7874d3c52fdff Mon Sep 17 00:00:00 2001 From: Manuel Reinhard Date: Thu, 27 Mar 2014 08:00:15 +0100 Subject: [PATCH 0351/1181] Updated ISBN validator --- reference/constraints/Isbn.rst | 63 ++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/reference/constraints/Isbn.rst b/reference/constraints/Isbn.rst index 9518c527042..fb0be64a49b 100644 --- a/reference/constraints/Isbn.rst +++ b/reference/constraints/Isbn.rst @@ -4,14 +4,21 @@ Isbn .. versionadded:: 2.3 The Isbn constraint was introduced in Symfony 2.3. +.. caution:: + + The ``isbn10`` and ``isbn13`` options are deprecated since Symfony 2.5 + and will be removed in Symfony 3.0. Use the ``type`` option instead. + Furthermore, when using the ``type`` option, lowercase characters are no + longer supported starting in Symfony 2.5, as they are not allowed in ISBNs. + This constraint validates that an `International Standard Book Number (ISBN)`_ -is either a valid ISBN-10, a valid ISBN-13 or both. +is either a valid ISBN-10 or a valid ISBN-13. +----------------+----------------------------------------------------------------------+ | Applies to | :ref:`property or method` | +----------------+----------------------------------------------------------------------+ -| Options | - `isbn10`_ | -| | - `isbn13`_ | +| Options | - `type`_ | +| | - `message`_ | | | - `isbn10Message`_ | | | - `isbn13Message`_ | | | - `bothIsbnMessage`_ | @@ -25,7 +32,7 @@ Basic Usage ----------- To use the ``Isbn`` validator, simply apply it to a property or method -on an object that will contain a ISBN number. +on an object that will contain an ISBN. .. configuration-block:: @@ -36,9 +43,8 @@ on an object that will contain a ISBN number. properties: isbn: - Isbn: - isbn10: true - isbn13: true - bothIsbnMessage: This value is neither a valid ISBN-10 nor a valid ISBN-13. + type: isbn10 + message: This value is not valid. .. code-block:: php-annotations @@ -49,9 +55,8 @@ on an object that will contain a ISBN number. { /** * @Assert\Isbn( - * isbn10 = true, - * isbn13 = true, - * bothIsbnMessage = "This value is neither a valid ISBN-10 nor a valid ISBN-13." + * type = isbn10, + * message: This value is not valid. * ) */ protected $isbn; @@ -63,9 +68,8 @@ on an object that will contain a ISBN number. - - - + + @@ -85,9 +89,8 @@ on an object that will contain a ISBN number. public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('isbn', new Assert\Isbn(array( - 'isbn10' => true, - 'isbn13' => true, - 'bothIsbnMessage' => 'This value is neither a valid ISBN-10 nor a valid ISBN-13.' + 'type' => isbn10, + 'message' => 'This value is not valid.' ))); } } @@ -95,28 +98,28 @@ on an object that will contain a ISBN number. Available Options ----------------- -isbn10 -~~~~~~ +type +~~~~ -**type**: ``boolean`` +**type**: ``string`` **default**: ``null`` -If this required option is set to ``true`` the constraint will check if the -code is a valid ISBN-10 code. +The type of ISBN to validate against. +Valid values are ``isbn10``, ``isbn13`` and ``null`` to accept any kind of ISBN. -isbn13 -~~~~~~ +message +~~~~~~~ -**type**: ``boolean`` +**type**: ``string`` **default**: ``null`` -If this required option is set to ``true`` the constraint will check if the -code is a valid ISBN-13 code. +The message that will be shown if the value is not valid. +If not ``null``, this message has priority over all the other messages. isbn10Message ~~~~~~~~~~~~~ **type**: ``string`` **default**: ``This value is not a valid ISBN-10.`` -The message that will be shown if the `isbn10`_ option is true and the given +The message that will be shown if the `type`_ option is ``isbn10`` and the given value does not pass the ISBN-10 check. isbn13Message @@ -124,7 +127,7 @@ isbn13Message **type**: ``string`` **default**: ``This value is not a valid ISBN-13.`` -The message that will be shown if the `isbn13`_ option is true and the given +The message that will be shown if the `type`_ option is ``isbn13`` and the given value does not pass the ISBN-13 check. bothIsbnMessage @@ -132,7 +135,7 @@ bothIsbnMessage **type**: ``string`` **default**: ``This value is neither a valid ISBN-10 nor a valid ISBN-13.`` -The message that will be shown if both the `isbn10`_ and `isbn13`_ options -are true and the given value does not pass the ISBN-13 nor the ISBN-13 check. +The message that will be shown if the `type`_ option is ``null`` and the given +value does not pass any of the ISBN checks. .. _`International Standard Book Number (ISBN)`: http://en.wikipedia.org/wiki/Isbn From abda29b0a6957bbb1418fa87254db0a080a7741d Mon Sep 17 00:00:00 2001 From: WybrenKoelmans Date: Fri, 4 Jul 2014 10:31:37 +0200 Subject: [PATCH 0352/1181] #11212 [HttpFoundation] Added a switch to delete file after the response is send --- components/http_foundation/introduction.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index 4db19238609..92034f4efe6 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -515,6 +515,13 @@ You can still set the ``Content-Type`` of the sent file, or change its ``Content 'filename.txt' ); +.. versionadded:: 2.6 + The ``deleteFileAfterSend()`` method was introduced in Symfony 2.6. + +It is possible to delete the file after the request is send with the +:method:`Symfony\\Component\\HttpFoundation\\BinaryFileResponse::deleteFileAfterSend` method. +Please note that this will not work when the ``X-Sendfile`` header is set. + .. _component-http-foundation-json-response: Creating a JSON Response From 1f4dc760c8283c656f1ae157391ed240108f61b3 Mon Sep 17 00:00:00 2001 From: Vincent Composieux Date: Sat, 5 Jul 2014 13:06:07 +0200 Subject: [PATCH 0353/1181] [Console] Fix Console some $app to $this and getHelperSet()->get() to getHelper() --- components/console/helpers/dialoghelper.rst | 10 +++++----- components/console/helpers/formatterhelper.rst | 2 +- components/console/helpers/progresshelper.rst | 2 +- components/console/helpers/questionhelper.rst | 10 +++++----- components/console/helpers/tablehelper.rst | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/components/console/helpers/dialoghelper.rst b/components/console/helpers/dialoghelper.rst index 3e7c016886e..cda8d8e934f 100644 --- a/components/console/helpers/dialoghelper.rst +++ b/components/console/helpers/dialoghelper.rst @@ -16,7 +16,7 @@ functions to ask the user for more information. It is included in the default helper set, which you can get by calling :method:`Symfony\\Component\\Console\\Command\\Command::getHelperSet`:: - $dialog = $this->getHelperSet()->get('dialog'); + $dialog = $this->getHelper('dialog'); All the methods inside the Dialog Helper have an :class:`Symfony\\Component\\Console\\Output\\OutputInterface` as the first @@ -69,7 +69,7 @@ Autocompletion You can also specify an array of potential answers for a given question. These will be autocompleted as the user types:: - $dialog = $this->getHelperSet()->get('dialog'); + $dialog = $this->getHelper('dialog'); $bundleNames = array('AcmeDemoBundle', 'AcmeBlogBundle', 'AcmeStoreBundle'); $name = $dialog->ask( $output, @@ -84,7 +84,7 @@ Hiding the User's Response You can also ask a question and hide the response. This is particularly convenient for passwords:: - $dialog = $this->getHelperSet()->get('dialog'); + $dialog = $this->getHelper('dialog'); $password = $dialog->askHiddenResponse( $output, 'What is the database password?', @@ -152,7 +152,7 @@ Validating a Hidden Response You can also ask and validate a hidden response:: - $dialog = $this->getHelperSet()->get('dialog'); + $dialog = $this->getHelper('dialog'); $validator = function ($value) { if ('' === trim($value)) { @@ -186,7 +186,7 @@ Instead, you can use the method, which makes sure that the user can only enter a valid string from a predefined list:: - $dialog = $this->getHelperSet()->get('dialog'); + $dialog = $this->getHelper('dialog'); $colors = array('red', 'blue', 'yellow'); $color = $dialog->select( diff --git a/components/console/helpers/formatterhelper.rst b/components/console/helpers/formatterhelper.rst index 565be6e6bab..12386d04c3f 100644 --- a/components/console/helpers/formatterhelper.rst +++ b/components/console/helpers/formatterhelper.rst @@ -12,7 +12,7 @@ The :class:`Symfony\\Component\\Console\\Helper\\FormatterHelper` is included in the default helper set, which you can get by calling :method:`Symfony\\Component\\Console\\Command\\Command::getHelperSet`:: - $formatter = $this->getHelperSet()->get('formatter'); + $formatter = $this->getHelper('formatter'); The methods return a string, which you'll usually render to the console by passing it to the diff --git a/components/console/helpers/progresshelper.rst b/components/console/helpers/progresshelper.rst index 3662fff8800..78e09e0eb25 100644 --- a/components/console/helpers/progresshelper.rst +++ b/components/console/helpers/progresshelper.rst @@ -25,7 +25,7 @@ information, which updates as your command runs: To display progress details, use the :class:`Symfony\\Component\\Console\\Helper\\ProgressHelper`, pass it a total number of units, and advance the progress as your command executes:: - $progress = $this->getHelperSet()->get('progress'); + $progress = $this->getHelper('progress'); $progress->start($output, 50); $i = 0; diff --git a/components/console/helpers/questionhelper.rst b/components/console/helpers/questionhelper.rst index 0f1031392c1..3305cb3776e 100644 --- a/components/console/helpers/questionhelper.rst +++ b/components/console/helpers/questionhelper.rst @@ -12,7 +12,7 @@ functions to ask the user for more information. It is included in the default helper set, which you can get by calling :method:`Symfony\\Component\\Console\\Command\\Command::getHelperSet`:: - $helper = $this->getHelperSet()->get('question'); + $helper = $this->getHelper('question'); The Question Helper has a single method :method:`Symfony\\Component\\Console\\Command\\Command::ask` that needs an @@ -30,7 +30,7 @@ the following to your command:: use Symfony\Component\Console\Question\ConfirmationQuestion; // ... - $helper = $this->getHelperSet()->get('question'); + $helper = $this->getHelper('question'); $question = new ConfirmationQuestion('Continue with this action?', false); if (!$helper->ask($input, $output, $question)) { @@ -73,7 +73,7 @@ from a predefined list:: use Symfony\Component\Console\Question\ChoiceQuestion; // ... - $helper = $app->getHelperSet()->get('question'); + $helper = $this->getHelper('question'); $question = new ChoiceQuestion( 'Please select your favorite color (defaults to red)', array('red', 'blue', 'yellow'), @@ -107,7 +107,7 @@ this use :method:`Symfony\\Component\\Console\\Question\\ChoiceQuestion::setMult use Symfony\Component\Console\Question\ChoiceQuestion; // ... - $helper = $app->getHelperSet()->get('question'); + $helper = $this->getHelper('question'); $question = new ChoiceQuestion( 'Please select your favorite color (defaults to red)', array('red', 'blue', 'yellow'), @@ -206,7 +206,7 @@ You can also use a validator with a hidden question:: use Symfony\Component\Console\Question\Question; // ... - $helper = $this->getHelperSet()->get('question'); + $helper = $this->getHelper('question'); $question = new Question('Please enter your password'); $question->setValidator(function ($value) { diff --git a/components/console/helpers/tablehelper.rst b/components/console/helpers/tablehelper.rst index 93643837181..d1c094938cf 100644 --- a/components/console/helpers/tablehelper.rst +++ b/components/console/helpers/tablehelper.rst @@ -21,7 +21,7 @@ When building a console application it may be useful to display tabular data: To display a table, use the :class:`Symfony\\Component\\Console\\Helper\\TableHelper`, set headers, rows and render:: - $table = $this->getHelperSet()->get('table'); + $table = $this->getHelper('table'); $table ->setHeaders(array('ISBN', 'Title', 'Author')) ->setRows(array( From 97c3894dd801a02f8af79925ea90b5fdfa1e6640 Mon Sep 17 00:00:00 2001 From: florianv Date: Sun, 6 Jul 2014 09:51:26 +0200 Subject: [PATCH 0354/1181] [Console] Fixed QuestionHelper examples --- components/console/helpers/questionhelper.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/console/helpers/questionhelper.rst b/components/console/helpers/questionhelper.rst index 0f1031392c1..2f756434edc 100644 --- a/components/console/helpers/questionhelper.rst +++ b/components/console/helpers/questionhelper.rst @@ -77,7 +77,7 @@ from a predefined list:: $question = new ChoiceQuestion( 'Please select your favorite color (defaults to red)', array('red', 'blue', 'yellow'), - 'red' + 0 ); $question->setErrorMessage('Color %s is invalid.'); @@ -109,9 +109,9 @@ this use :method:`Symfony\\Component\\Console\\Question\\ChoiceQuestion::setMult $helper = $app->getHelperSet()->get('question'); $question = new ChoiceQuestion( - 'Please select your favorite color (defaults to red)', + 'Please select your favorite colors (defaults to red and blue)', array('red', 'blue', 'yellow'), - 'red' + '0,1' ); $question->setMultiselect(true); @@ -121,6 +121,9 @@ this use :method:`Symfony\\Component\\Console\\Question\\ChoiceQuestion::setMult Now, when the user enters ``1,2``, the result will be: ``You have just selected: blue, yellow``. +If the user does not enter anything, the result will be: +``You have just selected: red, blue``. + Autocompletion ~~~~~~~~~~~~~~ From b8f27ef7c4246133c75764026d5086d4ade1d639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gildas=20Qu=C3=A9m=C3=A9ner?= Date: Wed, 9 Jul 2014 17:37:48 +0200 Subject: [PATCH 0355/1181] Removed wrong reference to cookbook The /cookbook/request/mime_type article does not contain an example to register a kernel listener since 2.5 --- reference/dic_tags.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/reference/dic_tags.rst b/reference/dic_tags.rst index 7ed9632e57b..18fce432bff 100644 --- a/reference/dic_tags.rst +++ b/reference/dic_tags.rst @@ -508,9 +508,6 @@ points. For a full example of this listener, read the :doc:`/cookbook/service_container/event_listener` cookbook entry. -For another practical example of a kernel listener, see the cookbook -article: :doc:`/cookbook/request/mime_type`. - Core Event Listener Reference ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From d87d8030b23bb12f47c8661cc3535f83c18132e1 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 10 Jul 2014 13:23:48 +0200 Subject: [PATCH 0356/1181] Fixed the format of one letter-based list --- reference/constraints/Expression.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/reference/constraints/Expression.rst b/reference/constraints/Expression.rst index 430e53ecba1..d491adea2db 100644 --- a/reference/constraints/Expression.rst +++ b/reference/constraints/Expression.rst @@ -53,10 +53,9 @@ properties:: To validate the object, you have some special requirements: -* A) If ``isTechnicalPost`` is true, then ``category`` must be either ``php`` - or ``symfony``; - -* B) If ``isTechnicalPost`` is false, then ``category`` can be anything. +A) If ``isTechnicalPost`` is true, then ``category`` must be either ``php`` + or ``symfony``; +B) If ``isTechnicalPost`` is false, then ``category`` can be anything. One way to accomplish this is with the Expression constraint: From 4bc00df2dd1413adf0f80821184f369e55aa2cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Va=C5=A1ek=20Purchart?= Date: Wed, 9 Jul 2014 10:57:13 +0200 Subject: [PATCH 0357/1181] Fixed documentation for ProgressBar This place is using the old ProgressHelper API and can be confusing when migrating. --- components/console/helpers/progressbar.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/console/helpers/progressbar.rst b/components/console/helpers/progressbar.rst index 2ae9e64844a..46e993c08c0 100644 --- a/components/console/helpers/progressbar.rst +++ b/components/console/helpers/progressbar.rst @@ -265,10 +265,11 @@ to display it can be customized:: For performance reasons, be careful if you set the total number of steps to a high number. For example, if you're iterating over a large number of items, consider setting the redraw frequency to a higher value by calling - :method:`Symfony\\Component\\Console\\Helper\\ProgressHelper::setRedrawFrequency`, + :method:`Symfony\\Component\\Console\\Helper\\ProgressBar::setRedrawFrequency`, so it updates on only some iterations:: - $progress->start($output, 50000); + $progress = new ProgressBar($output, 50000); + $progress->start(); // update every 100 iterations $progress->setRedrawFrequency(100); From 755b1c1fb2dc9272aeff585a7f17406805321695 Mon Sep 17 00:00:00 2001 From: Raul Fraile Date: Mon, 7 Apr 2014 16:46:31 +0200 Subject: [PATCH 0358/1181] Fix function example in expression language component The is_string check needs to be part of the runtime code, not of the compilation code, because it needs to check that the argument is a string, not the compiled code to access it (which is always a string as it is source code --- components/expression_language/extending.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/components/expression_language/extending.rst b/components/expression_language/extending.rst index e2678236d17..56147de15d8 100644 --- a/components/expression_language/extending.rst +++ b/components/expression_language/extending.rst @@ -35,11 +35,7 @@ This method has 3 arguments: $language = new ExpressionLanguage(); $language->register('lowercase', function ($str) { - if (!is_string($str)) { - return $str; - } - - return sprintf('strtolower(%s)', $str); + return sprintf('$result = (is_string(%1$s)) ? strtolower(%1$s) : %1$s; return $result;', $str); }, function ($arguments, $str) { if (!is_string($str)) { return $str; From 235cf33466dd299ef5bc3d250cabfeea090062d3 Mon Sep 17 00:00:00 2001 From: Raul Fraile Date: Thu, 3 Jul 2014 23:14:42 +0200 Subject: [PATCH 0359/1181] Removed return statement --- components/expression_language/extending.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/expression_language/extending.rst b/components/expression_language/extending.rst index 56147de15d8..94762110bcd 100644 --- a/components/expression_language/extending.rst +++ b/components/expression_language/extending.rst @@ -35,7 +35,7 @@ This method has 3 arguments: $language = new ExpressionLanguage(); $language->register('lowercase', function ($str) { - return sprintf('$result = (is_string(%1$s)) ? strtolower(%1$s) : %1$s; return $result;', $str); + is_string(%1$s) ? strtolower(%1$s) : %1$s; }, function ($arguments, $str) { if (!is_string($str)) { return $str; From df8849136c94b1214cd4cec13a8111bb9174f49c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 15 Jul 2014 16:59:49 +0200 Subject: [PATCH 0360/1181] added CVE 2014-4931 --- contributing/code/security.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/contributing/code/security.rst b/contributing/code/security.rst index de7b63f8930..49a6ff35e30 100644 --- a/contributing/code/security.rst +++ b/contributing/code/security.rst @@ -96,6 +96,7 @@ Security Advisories This section indexes security vulnerabilities that were fixed in Symfony releases, starting from Symfony 1.0.0: +* July 15, 2014: `Security releases: Symfony 2.3.18, 2.4.8, and 2.5.2 released `_ (`CVE-2014-4931 `_) * October 10, 2013: `Security releases: Symfony 2.0.25, 2.1.13, 2.2.9, and 2.3.6 released `_ (`CVE-2013-5958 `_) * August 7, 2013: `Security releases: Symfony 2.0.24, 2.1.12, 2.2.5, and 2.3.3 released `_ (`CVE-2013-4751 `_ and `CVE-2013-4752 `_) * January 17, 2013: `Security release: Symfony 2.0.22 and 2.1.7 released `_ (`CVE-2013-1348 `_ and `CVE-2013-1397 `_) From 2299df0d643be336d277e01c92721b7d18f0b8ca Mon Sep 17 00:00:00 2001 From: Daniel Santana Date: Tue, 15 Jul 2014 13:25:28 -0400 Subject: [PATCH 0361/1181] Updating Symfony version from 2.4 to 2.5 The descriptions are still displaying the old version --- book/from_flat_php_to_symfony2.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/book/from_flat_php_to_symfony2.rst b/book/from_flat_php_to_symfony2.rst index 0a333f4b7d3..e094d8b3716 100644 --- a/book/from_flat_php_to_symfony2.rst +++ b/book/from_flat_php_to_symfony2.rst @@ -431,7 +431,7 @@ content: { "require": { - "symfony/symfony": "2.4.*" + "symfony/symfony": "2.5.*" }, "autoload": { "files": ["model.php","controllers.php"] @@ -480,8 +480,8 @@ the HTTP response being returned. Use them to improve the blog: // echo the headers and send the response $response->send(); -.. versionadded:: 2.4 - Support for HTTP status code constants was introduced in Symfony 2.4. +.. versionadded:: 2.5 + Support for HTTP status code constants was introduced in Symfony 2.5. The controllers are now responsible for returning a ``Response`` object. To make this easier, you can add a new ``render_template()`` function, which, From 81d962f26ea9673a8d61cd0c562bc07f74f8cb9a Mon Sep 17 00:00:00 2001 From: Daniel Santana Date: Tue, 15 Jul 2014 16:30:39 -0400 Subject: [PATCH 0362/1181] Configuring composer.json to use the 2.5 version Configuring composer.json to use the 2.5 version Rather than 2.4 --- book/from_flat_php_to_symfony2.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/from_flat_php_to_symfony2.rst b/book/from_flat_php_to_symfony2.rst index e094d8b3716..565a57fd565 100644 --- a/book/from_flat_php_to_symfony2.rst +++ b/book/from_flat_php_to_symfony2.rst @@ -480,8 +480,8 @@ the HTTP response being returned. Use them to improve the blog: // echo the headers and send the response $response->send(); -.. versionadded:: 2.5 - Support for HTTP status code constants was introduced in Symfony 2.5. +.. versionadded:: 2.4 + Support for HTTP status code constants was introduced in Symfony 2.4. The controllers are now responsible for returning a ``Response`` object. To make this easier, you can add a new ``render_template()`` function, which, From e918a6d972e899428f47daa698870a7fa13489f9 Mon Sep 17 00:00:00 2001 From: Xavier Briand Date: Wed, 9 Jul 2014 10:48:13 -0400 Subject: [PATCH 0363/1181] Fix xml route configuration for routing condition Current XML documentation doesn't respect routing schema (https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd) --- book/routing.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/book/routing.rst b/book/routing.rst index 5f65f9b793e..f6dc2625182 100644 --- a/book/routing.rst +++ b/book/routing.rst @@ -758,11 +758,9 @@ can be extended to have an almost infinite flexibility using ``conditions``: xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> - + AcmeDemoBundle:Main:contact + context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i' From cb508f7a17dd1eb106649a7d32ecd5e3e853ff74 Mon Sep 17 00:00:00 2001 From: Thomas Ploch Date: Fri, 25 Jul 2014 12:57:58 +0200 Subject: [PATCH 0364/1181] [WCM] Skip console commands from event listeners | Q | A | ------------- | --- | Doc fix? | no | New docs? | yes (symfony/symfony#9235) | Applies to | master | Fixed tickets | none --- components/console/events.rst | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/components/console/events.rst b/components/console/events.rst index ff7048138e8..210f445d4ef 100644 --- a/components/console/events.rst +++ b/components/console/events.rst @@ -51,6 +51,40 @@ dispatched. Listeners receive a $application = $command->getApplication(); }); +Disable Commands inside Listeners +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 2.6 + Disabling commands inside listeners was introduced in Symfony 2.6. + +Using the +:method:`Symfony\\Component\\Console\\Event\\ConsoleCommandEvent::disableCommand` +method, you can disable a command inside a listener. The application +will then not execute the command but return the code `113` (defined in +``ConsoleCommandEvent::RETURN_CODE_DISABLED``), which is one of the +`reserved exit codes`_ for console commands to conform with the C/C++ standard.:: + + use Symfony\Component\Console\Event\ConsoleCommandEvent; + use Symfony\Component\Console\ConsoleEvents; + + $dispatcher->addListener(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) { + // get the command to be executed + $command = $event->getCommand(); + + // ... check if the command can be executed + + // disable the command, this will result in the command being skipped + // and code 113 being returned from the Application + $event->disableCommand(); + + // it is possible to enable the command in a later listener + if (!$event->commandShouldRun()) { + $event->enableCommand(); + } + }); + +.. _`reserved exit codes`: http://www.tldp.org/LDP/abs/html/exitcodes.html + The ``ConsoleEvents::TERMINATE`` Event -------------------------------------- @@ -118,3 +152,4 @@ Listeners receive a // change the exception to another one $event->setException(new \LogicException('Caught exception', $exitCode, $event->getException())); }); + From 6236fdbf8d49f5275c1fef7095529cbfe1488421 Mon Sep 17 00:00:00 2001 From: Pablo Martelletti Date: Tue, 29 Jul 2014 18:36:03 -0300 Subject: [PATCH 0365/1181] Remove diff info from file. --- cookbook/security/voters.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cookbook/security/voters.rst b/cookbook/security/voters.rst index 69e67944b4c..1760cb43db7 100644 --- a/cookbook/security/voters.rst +++ b/cookbook/security/voters.rst @@ -49,11 +49,7 @@ and compare the IP address against a set of blacklisted IP addresses: protected $requestStack; private $blacklistedIp; -<<<<<<< HEAD public function __construct(RequestStack $requestStack, array $blacklistedIp = array()) -======= - public function __construct(ContainerInterface $container, array $blacklistedIp = array()) ->>>>>>> 2.3 { $this->requestStack = $requestStack; $this->blacklistedIp = $blacklistedIp; From 9879ee6601b97d3a473592a26079ccf4a819c4d3 Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Sat, 21 Jun 2014 12:59:31 -0400 Subject: [PATCH 0366/1181] Add note about invokable controller services --- cookbook/controller/service.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cookbook/controller/service.rst b/cookbook/controller/service.rst index 602b14aead3..da39e672401 100644 --- a/cookbook/controller/service.rst +++ b/cookbook/controller/service.rst @@ -136,6 +136,10 @@ the route ``_controller`` value: :doc:`FrameworkExtraBundle documentation ` for details. +.. versionadded:: 2.6 + If your controller service implements the ``__invoke`` method, you can simply refer to the service id + (``acme.hello.controller``). + Alternatives to base Controller Methods --------------------------------------- From 09c9af499d64247e3658edfad44a6b7577432fae Mon Sep 17 00:00:00 2001 From: Endre Fejes Date: Wed, 30 Jul 2014 19:34:32 +0200 Subject: [PATCH 0367/1181] [DomCrawler] Added node name getter --- components/dom_crawler.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index 2d17126b89f..37ef6e24827 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -193,6 +193,15 @@ Get all the child or parent nodes:: Accessing Node Values ~~~~~~~~~~~~~~~~~~~~~ +.. versionadded:: 2.6 + The :method:`Symfony\\Component\\DomCrawler\\Crawler::nodeName` + method was introduced in Symfony 2.6. + +Access the node name (HTML tag name) of the first node of the current selection (eg. "p" or "div"):: + + // will return the node name (HTML tag name) of the first child element under + $tag = $crawler->filterXPath('//body/*')->nodeName(); + Access the value of the first node of the current selection:: $message = $crawler->filterXPath('//body/p')->text(); From 6dc62a80e02a45d125d91b32af00ced420588b17 Mon Sep 17 00:00:00 2001 From: Danny Kopping Date: Tue, 5 Aug 2014 16:21:50 +0200 Subject: [PATCH 0368/1181] Put version into quotes, otherwise it fails When using the `zsh` shell, the command fails because of: ``` $ composer create-project symfony/framework-standard-edition myproject/ ~2.5 zsh: no such user or named directory: 2.5 ``` This problem does not occur in Bash. Quoting the version number does not effect Bash, and fixes ZSH. --- quick_tour/the_big_picture.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quick_tour/the_big_picture.rst b/quick_tour/the_big_picture.rst index bd6297b1c38..08bc43c77b8 100644 --- a/quick_tour/the_big_picture.rst +++ b/quick_tour/the_big_picture.rst @@ -18,7 +18,7 @@ directory: .. code-block:: bash - $ composer create-project symfony/framework-standard-edition myproject/ ~2.5 + $ composer create-project symfony/framework-standard-edition myproject/ '~2.5' .. note:: From e586e6c13f10964bb736034e2f10065980f6a4bf Mon Sep 17 00:00:00 2001 From: Danny Kopping Date: Tue, 5 Aug 2014 16:49:10 +0200 Subject: [PATCH 0369/1181] See #4091 --- book/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/installation.rst b/book/installation.rst index c9e24f32721..2ad27b8d8ac 100644 --- a/book/installation.rst +++ b/book/installation.rst @@ -57,7 +57,7 @@ Distribution: .. code-block:: bash - $ php composer.phar create-project symfony/framework-standard-edition /path/to/webroot/Symfony 2.5.* + $ php composer.phar create-project symfony/framework-standard-edition /path/to/webroot/Symfony '~2.5' .. tip:: From 8cbdf15fd518c473ebeaee994054f6a7a6b28e19 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sun, 10 Aug 2014 15:01:00 +0200 Subject: [PATCH 0370/1181] Added July changelog --- changelog.rst | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/changelog.rst b/changelog.rst index 8e418377db9..04cc5e66038 100644 --- a/changelog.rst +++ b/changelog.rst @@ -13,6 +13,58 @@ documentation. Do you also want to participate in the Symfony Documentation? Take a look at the ":doc:`/contributing/documentation/overview`" article. +July, 2014 +---------- + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `1b4c1c8 `_ #4045 Added a new "Deploying to Heroku Cloud" cookbook article (javiereguiluz) +- `f943eee `_ #4009 Remove "Controllers extends ContainerAware" best practice (tgalopin) +- `eae9ad0 `_ #3875 Added a note about customizing a form with more than one template (javiereguiluz) +- `d6787b7 `_ #3989 adde stof as a merger (fabpot) +- `4a9e49e `_ #3946 DQL custom functions on doctrine reference page (healdropper) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `1b695b5 `_ #4063 fix parent form types (xabbuh) +- `7901005 `_ #4048 $this->request replaced by $request (danielsan) +- `f6123f1 `_ #4031 Update form_events.rst (redstar504) +- `06f8c31 `_ #4012 Fix xml route configuration for routing condition (xavierbriand) +- `b32f9f2 `_ #3771 Fix function example in expression language component (raulfraile) +- `eb813a5 `_ #3979 removed invalid processors option (ricoli) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `a4bdb97 `_ #4070 Added a note about permissions in the Quick Tour (javiereguiluz) +- `a7fe00f `_ #4068 Remove diff info from cookbook/security/voters.rst (pmartelletti) +- `b3f15b2 `_ #4059 eraseCredentials method typo (danielsan) +- `44091b1 `_ #4053 Update doctrine.rst (sr972) +- `b06ad60 `_ #4052 [Security] [Custom Provider] Use properties on WebserviceUser (entering) +- `a834a7e `_ #4042 [Cookbook] apply headline guidelines to the cookbook articles (xabbuh) +- `f25faf3 `_ #4046 Fixed a syntax error (javiereguiluz) +- `3c660d1 `_ #4044 Added editorconfig (WouterJ) +- `ae3ec04 `_ #4041 [Cookbook][Deployment] link to the deployment index (xabbuh) +- `2e4fc7f `_ #4030 enclose YAML strings containing % with quotes (xabbuh) +- `9520d92 `_ #4038 Update rendered tag (kirill-oficerov) +- `f5c2602 `_ #4036 Update page_creation.rst (redstar504) +- `c2eda93 `_ #4034 Update internals.rst (redstar504) +- `a5ad0df `_ #4035 Update version in Rework your Patch section (yguedidi) +- `d8b037a `_ #4019 Update twig_reference.rst (redstar504) +- `7ea87e6 `_ #4016 Fixed the format of one letter-based list (javiereguiluz) +- `579a873 `_ #4015 Fixed bad indenting (the list was treated as a blockquote) (javiereguiluz) +- `4669620 `_ #4004 use GitHub instead of Github (xabbuh) +- `a3fe74f `_ #3993 [Console] Fix Console component getHelperSet()->get() to getHelper() (eko) +- `a41af7e `_ #3880 document the mysterious abc part of the header (greg0ire) +- `90773b0 `_ #3990 Move the section about collect: false to the cookbook entry (weaverryan) +- `2ae8281 `_ #3864 plug rules for static methods (cordoval) +- `d882cc0 `_ #3988 fix typos. (yositani2002) +- `b67a059 `_ #3986 Rebased #3982 - Some fixes (WouterJ) +- `801c756 `_ #3977 [WCM] removed call to deprecated getRequest() method (Baptouuuu) +- `4c1d4ae `_ #3968 Proofreading the new Azure deployment article (weaverryan) + June, 2014 ---------- From b2a70d16a75de6d4a76af815fe4d60d862d2994a Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sun, 10 Aug 2014 15:01:44 +0200 Subject: [PATCH 0371/1181] Added July changelog --- changelog.rst | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/changelog.rst b/changelog.rst index 8e8f7f27c7f..b3dd93e571a 100644 --- a/changelog.rst +++ b/changelog.rst @@ -13,6 +13,65 @@ documentation. Do you also want to participate in the Symfony Documentation? Take a look at the ":doc:`/contributing/documentation/overview`" article. +July, 2014 +---------- + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `1b4c1c8 `_ #4045 Added a new "Deploying to Heroku Cloud" cookbook article (javiereguiluz) +- `f943eee `_ #4009 Remove "Controllers extends ContainerAware" best practice (tgalopin) +- `eae9ad0 `_ #3875 Added a note about customizing a form with more than one template (javiereguiluz) +- `1938c2f `_ #3724 Updated ISBN validator docs (sprain) +- `d6787b7 `_ #3989 adde stof as a merger (fabpot) +- `4a9e49e `_ #3946 DQL custom functions on doctrine reference page (healdropper) +- `2b2d9d3 `_ #3972 Added PSR-4 to Class Loaders list (dosten) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `1b695b5 `_ #4063 fix parent form types (xabbuh) +- `7901005 `_ #4048 $this->request replaced by $request (danielsan) +- `f6123f1 `_ #4031 Update form_events.rst (redstar504) +- `99932cf `_ #4010 [Console] Fixed documentation for ProgressBar (VasekPurchart) +- `06f8c31 `_ #4012 Fix xml route configuration for routing condition (xavierbriand) +- `a1435e5 `_ #3998 [Console] Fixed QuestionHelper examples (florianv) +- `b32f9f2 `_ #3771 Fix function example in expression language component (raulfraile) +- `eb813a5 `_ #3979 removed invalid processors option (ricoli) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `a4bdb97 `_ #4070 Added a note about permissions in the Quick Tour (javiereguiluz) +- `a7fe00f `_ #4068 Remove diff info from cookbook/security/voters.rst (pmartelletti) +- `b3f15b2 `_ #4059 eraseCredentials method typo (danielsan) +- `44091b1 `_ #4053 Update doctrine.rst (sr972) +- `b06ad60 `_ #4052 [Security] [Custom Provider] Use properties on WebserviceUser (entering) +- `a834a7e `_ #4042 [Cookbook] apply headline guidelines to the cookbook articles (xabbuh) +- `f25faf3 `_ #4046 Fixed a syntax error (javiereguiluz) +- `3c660d1 `_ #4044 Added editorconfig (WouterJ) +- `ae3ec04 `_ #4041 [Cookbook][Deployment] link to the deployment index (xabbuh) +- `2e4fc7f `_ #4030 enclose YAML strings containing % with quotes (xabbuh) +- `9520d92 `_ #4038 Update rendered tag (kirill-oficerov) +- `f5c2602 `_ #4036 Update page_creation.rst (redstar504) +- `c2eda93 `_ #4034 Update internals.rst (redstar504) +- `a5ad0df `_ #4035 Update version in Rework your Patch section (yguedidi) +- `eed8d64 `_ #4026 Updating Symfony version from 2.4 to 2.5 (danielsan) +- `d8b037a `_ #4019 Update twig_reference.rst (redstar504) +- `7ea87e6 `_ #4016 Fixed the format of one letter-based list (javiereguiluz) +- `579a873 `_ #4015 Fixed bad indenting (the list was treated as a blockquote) (javiereguiluz) +- `12752c1 `_ #4013 Removed wrong reference to cookbook (gquemener) +- `4669620 `_ #4004 use GitHub instead of Github (xabbuh) +- `ec832dc `_ #3994 [Console] Fix Console component $app to $this and use of getHelper() method (eko) +- `a3fe74f `_ #3993 [Console] Fix Console component getHelperSet()->get() to getHelper() (eko) +- `a41af7e `_ #3880 document the mysterious abc part of the header (greg0ire) +- `90773b0 `_ #3990 Move the section about collect: false to the cookbook entry (weaverryan) +- `2ae8281 `_ #3864 plug rules for static methods (cordoval) +- `d882cc0 `_ #3988 fix typos. (yositani2002) +- `b67a059 `_ #3986 Rebased #3982 - Some fixes (WouterJ) +- `801c756 `_ #3977 [WCM] removed call to deprecated getRequest() method (Baptouuuu) +- `4c1d4ae `_ #3968 Proofreading the new Azure deployment article (weaverryan) + June, 2014 ---------- From 47c7fe20ca558131af6a55ae96022fc00447916b Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sun, 10 Aug 2014 15:02:18 +0200 Subject: [PATCH 0372/1181] Added July changelog --- changelog.rst | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/changelog.rst b/changelog.rst index 8e8f7f27c7f..e9def3e513f 100644 --- a/changelog.rst +++ b/changelog.rst @@ -13,6 +13,68 @@ documentation. Do you also want to participate in the Symfony Documentation? Take a look at the ":doc:`/contributing/documentation/overview`" article. +July, 2014 +---------- + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `1b4c1c8 `_ #4045 Added a new "Deploying to Heroku Cloud" cookbook article (javiereguiluz) +- `f943eee `_ #4009 Remove "Controllers extends ContainerAware" best practice (tgalopin) +- `eae9ad0 `_ #3875 Added a note about customizing a form with more than one template (javiereguiluz) +- `2ae4f34 `_ #3746 [Validator] Disallow empty file in FileValidator (megazoll) +- `1938c2f `_ #3724 Updated ISBN validator docs (sprain) +- `7c71b18 `_ #2952 Enabling profiler in test (danieledangeli) +- `d6787b7 `_ #3989 adde stof as a merger (fabpot) +- `4a9e49e `_ #3946 DQL custom functions on doctrine reference page (healdropper) +- `2b2d9d3 `_ #3972 Added PSR-4 to Class Loaders list (dosten) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `1b695b5 `_ #4063 fix parent form types (xabbuh) +- `7901005 `_ #4048 $this->request replaced by $request (danielsan) +- `f6123f1 `_ #4031 Update form_events.rst (redstar504) +- `99932cf `_ #4010 [Console] Fixed documentation for ProgressBar (VasekPurchart) +- `06f8c31 `_ #4012 Fix xml route configuration for routing condition (xavierbriand) +- `a2a628f `_ #4025 added CVE 2014-4931 (fabpot) +- `a1435e5 `_ #3998 [Console] Fixed QuestionHelper examples (florianv) +- `b32f9f2 `_ #3771 Fix function example in expression language component (raulfraile) +- `eb813a5 `_ #3979 removed invalid processors option (ricoli) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `a4bdb97 `_ #4070 Added a note about permissions in the Quick Tour (javiereguiluz) +- `a7fe00f `_ #4068 Remove diff info from cookbook/security/voters.rst (pmartelletti) +- `b3f15b2 `_ #4059 eraseCredentials method typo (danielsan) +- `44091b1 `_ #4053 Update doctrine.rst (sr972) +- `b06ad60 `_ #4052 [Security] [Custom Provider] Use properties on WebserviceUser (entering) +- `a834a7e `_ #4042 [Cookbook] apply headline guidelines to the cookbook articles (xabbuh) +- `f25faf3 `_ #4046 Fixed a syntax error (javiereguiluz) +- `3c660d1 `_ #4044 Added editorconfig (WouterJ) +- `ae3ec04 `_ #4041 [Cookbook][Deployment] link to the deployment index (xabbuh) +- `2e4fc7f `_ #4030 enclose YAML strings containing % with quotes (xabbuh) +- `9520d92 `_ #4038 Update rendered tag (kirill-oficerov) +- `f5c2602 `_ #4036 Update page_creation.rst (redstar504) +- `c2eda93 `_ #4034 Update internals.rst (redstar504) +- `a5ad0df `_ #4035 Update version in Rework your Patch section (yguedidi) +- `eed8d64 `_ #4026 Updating Symfony version from 2.4 to 2.5 (danielsan) +- `d8b037a `_ #4019 Update twig_reference.rst (redstar504) +- `7ea87e6 `_ #4016 Fixed the format of one letter-based list (javiereguiluz) +- `579a873 `_ #4015 Fixed bad indenting (the list was treated as a blockquote) (javiereguiluz) +- `12752c1 `_ #4013 Removed wrong reference to cookbook (gquemener) +- `4669620 `_ #4004 use GitHub instead of Github (xabbuh) +- `ec832dc `_ #3994 [Console] Fix Console component $app to $this and use of getHelper() method (eko) +- `a3fe74f `_ #3993 [Console] Fix Console component getHelperSet()->get() to getHelper() (eko) +- `a41af7e `_ #3880 document the mysterious abc part of the header (greg0ire) +- `90773b0 `_ #3990 Move the section about collect: false to the cookbook entry (weaverryan) +- `2ae8281 `_ #3864 plug rules for static methods (cordoval) +- `d882cc0 `_ #3988 fix typos. (yositani2002) +- `b67a059 `_ #3986 Rebased #3982 - Some fixes (WouterJ) +- `801c756 `_ #3977 [WCM] removed call to deprecated getRequest() method (Baptouuuu) +- `4c1d4ae `_ #3968 Proofreading the new Azure deployment article (weaverryan) + June, 2014 ---------- From 3eaaf26ab241aa6635974a0f788c833096335799 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Tue, 12 Aug 2014 15:04:39 +0200 Subject: [PATCH 0373/1181] Fixed the code snippets for the expression language functions --- components/expression_language/extending.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/components/expression_language/extending.rst b/components/expression_language/extending.rst index 94762110bcd..5f1f743d631 100644 --- a/components/expression_language/extending.rst +++ b/components/expression_language/extending.rst @@ -35,7 +35,7 @@ This method has 3 arguments: $language = new ExpressionLanguage(); $language->register('lowercase', function ($str) { - is_string(%1$s) ? strtolower(%1$s) : %1$s; + return sprintf('(is_string(%1$s) ? strtolower(%1$s) : %1$s)', $str); }, function ($arguments, $str) { if (!is_string($str)) { return $str; @@ -69,11 +69,7 @@ Override ``registerFunctions`` to add your own functions:: parent::registerFunctions(); // do not forget to also register core functions $this->register('lowercase', function ($str) { - if (!is_string($str)) { - return $str; - } - - return sprintf('strtolower(%s)', $str); + return sprintf('(is_string(%1$s) ? strtolower(%1$s) : %1$s)', $str); }, function ($arguments, $str) { if (!is_string($str)) { return $str; From 98aed88e93d24dc2bba6c8c0425a47155d5224be Mon Sep 17 00:00:00 2001 From: Peter Rehm Date: Thu, 31 Jul 2014 22:28:37 +0200 Subject: [PATCH 0374/1181] Fixed description for session storage --- cookbook/security/api_key_authentication.rst | 47 +++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index 1965847c009..0add181f1c0 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -232,7 +232,7 @@ you can use to create an error ``Response``. class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface, AuthenticationFailureHandlerInterface { - //... + // ... public function onAuthenticationFailure(Request $request, AuthenticationException $exception) { @@ -427,6 +427,51 @@ configuration or set it to ``false``: ), )); +Even though the token is being stored in the session, the credentials - in this +case the API key (i.e. ``$token->getCredentials()``) - are not stored in the session +for security reasons. To take advantage of the session, update ``ApiKeyAuthenticator`` +to see if the stored token has a valid User object that can be used:: + + // src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php + // ... + + class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface + { + // ... + public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) + { + $apiKey = $token->getCredentials(); + $username = $this->userProvider->getUsernameForApiKey($apiKey); + + // User is the Entity which represents your user + $user = $token->getUser(); + if ($user instanceof User) { + return new PreAuthenticatedToken( + $user, + $apiKey, + $providerKey, + $user->getRoles() + ); + } + + if (!$username) { + throw new AuthenticationException( + sprintf('API Key "%s" does not exist.', $apiKey) + ); + } + + $user = $this->userProvider->loadUserByUsername($username); + + return new PreAuthenticatedToken( + $user, + $apiKey, + $providerKey, + $user->getRoles() + ); + } + // ... + } + Storing authentication information in the session works like this: #. At the end of each request, Symfony serializes the token object (returned From 3ecfb851d5f74068c73a7688a3db4505710b2a9c Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 13 Aug 2014 15:40:01 -0400 Subject: [PATCH 0375/1181] Fixing my bad merge conflict resolution --- reference/forms/types/number.rst | 7 ------- 1 file changed, 7 deletions(-) diff --git a/reference/forms/types/number.rst b/reference/forms/types/number.rst index f44b48be514..76493b8fa2b 100644 --- a/reference/forms/types/number.rst +++ b/reference/forms/types/number.rst @@ -45,16 +45,9 @@ rounding_mode If a submitted number needs to be rounded (based on the ``precision`` option), you have several configurable options for that rounding. Each -<<<<<<< HEAD option is a constant on the :class:`Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\NumberToLocalizedStringTransformer`: * ``NumberToLocalizedStringTransformer::ROUND_DOWN`` Round towards zero. -======= -option is a constant on the :class:`Symfony\\Component\\Form\\Extension\\Core\\DataTransformer\\IntegerToLocalizedStringTransformer`: - -* ``IntegerToLocalizedStringTransformer::ROUND_DOWN`` Rounding mode to - round towards zero. ->>>>>>> 2.3 * ``NumberToLocalizedStringTransformer::ROUND_FLOOR`` Round towards negative infinity. From f701f73838223885f48dc6674fb07b96e2f2dadc Mon Sep 17 00:00:00 2001 From: Hryhorii Hrebiniuk Date: Thu, 26 Dec 2013 12:28:36 +0200 Subject: [PATCH 0376/1181] [Translation] added method to expose collected message --- components/translation/usage.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/components/translation/usage.rst b/components/translation/usage.rst index fbb6664c607..63daff8d7a8 100644 --- a/components/translation/usage.rst +++ b/components/translation/usage.rst @@ -371,3 +371,25 @@ use for translation:: .. _`L10n`: http://en.wikipedia.org/wiki/Internationalization_and_localization .. _`ISO 31-11`: http://en.wikipedia.org/wiki/Interval_(mathematics)#Notations_for_intervals + +Retrieving the Message Catalogue +-------------------------------- + +In case you want to use the same translation catalogue outside your application +(e.g. use translation on a client side), it's possible to fetch raw translation messages. +You just need to specify required locale:: + + $messages = $translator->getMessages('fr_FR'); + +``$messages`` will have the following structure:: + + array( + 'messages' => array( + 'Hello world' => 'Bonjour tout le monde', + ), + 'validators' => array( + 'Value should not be empty' => 'Valeur ne doit pas être vide', + 'Value is too long' => 'Valeur est trop long', + ), + ); + From c7d17912c557c1c79544597d6112aeec5336b585 Mon Sep 17 00:00:00 2001 From: Pascal Borreli Date: Sun, 11 May 2014 01:54:57 +0200 Subject: [PATCH 0377/1181] Fixed typos --- cookbook/security/named_encoders.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/named_encoders.rst b/cookbook/security/named_encoders.rst index cf9ea3770c2..3b22a2d9343 100644 --- a/cookbook/security/named_encoders.rst +++ b/cookbook/security/named_encoders.rst @@ -105,7 +105,7 @@ named encoders: This creates an encoder named ``harsh``. In order for a ``User`` instance to use it, the class must implement :class:`Symfony\\Component\\Security\\Core\\Encoder\\EncoderAwareInterface`. -The interface requires one method - ``getEncoderName`` - which should reutrn +The interface requires one method - ``getEncoderName`` - which should return the name of the encoder to use:: // src/Acme/UserBundle/Entity/User.php From 59e4bd4c2a6d23d02f518cc83a21fe2cbbfad6dc Mon Sep 17 00:00:00 2001 From: Benjamin Bourot Date: Fri, 4 Apr 2014 15:22:13 +0200 Subject: [PATCH 0378/1181] Update api_key_authentication.rst - POST Method --- cookbook/security/api_key_authentication.rst | 26 ++++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index 0add181f1c0..1a542793731 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -45,15 +45,25 @@ value and then a User object is created:: public function createToken(Request $request, $providerKey) { - if (!$request->query->has('apikey')) { - throw new BadCredentialsException('No API key found'); + if ($request->query->has('apikey')) { + return new PreAuthenticatedToken( + 'anon.', + $request->query->get('apikey'), + $providerKey + ); } - - return new PreAuthenticatedToken( - 'anon.', - $request->query->get('apikey'), - $providerKey - ); + else if($request->request->has('apikey')) + { + return new PreAuthenticatedToken( + 'anon.', + $request->request->get('apikey'), + $providerKey + ); + } + else + { + throw new BadCredentialsException('No API key found'); + } } public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) From 529675a9d946bebb81eb86a436aa48fe9c86820c Mon Sep 17 00:00:00 2001 From: Benjamin Bourot Date: Thu, 12 Jun 2014 18:38:05 +0200 Subject: [PATCH 0379/1181] Check for api_key in request --- cookbook/security/api_key_authentication.rst | 32 +++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index 1a542793731..0feefca9a4b 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -45,25 +45,21 @@ value and then a User object is created:: public function createToken(Request $request, $providerKey) { - if ($request->query->has('apikey')) { - return new PreAuthenticatedToken( - 'anon.', - $request->query->get('apikey'), - $providerKey - ); - } - else if($request->request->has('apikey')) - { - return new PreAuthenticatedToken( - 'anon.', - $request->request->get('apikey'), - $providerKey - ); - } - else - { + // look for an apikey query parameter + $apiKey = $request->query->get('apikey'); + + // or if you want to use an "apikey" header, then do something like this: + // $apiKey = $request->headers->get('apikey'); + + if (!$apiKey) { throw new BadCredentialsException('No API key found'); - } + } + + return new PreAuthenticatedToken( + 'anon.', + $apiKey, + $providerKey + ); } public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) From d753d0e3acb9ab313b73b829c2d862d36011829a Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Wed, 30 Jul 2014 00:06:58 +0200 Subject: [PATCH 0380/1181] document the namespace alias feature --- cookbook/doctrine/mapping_model_classes.rst | 61 ++++++++++++--------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/cookbook/doctrine/mapping_model_classes.rst b/cookbook/doctrine/mapping_model_classes.rst index 975d95cd0be..9894777a339 100644 --- a/cookbook/doctrine/mapping_model_classes.rst +++ b/cookbook/doctrine/mapping_model_classes.rst @@ -14,23 +14,23 @@ register the mappings for your model classes. For non-reusable bundles, the easiest option is to put your model classes in the default locations: ``Entity`` for the Doctrine ORM or ``Document`` for one of the ODMs. For reusable bundles, rather than duplicate model classes - just to get the auto mapping, use the compiler pass. + just to get the auto-mapping, use the compiler pass. .. versionadded:: 2.3 The base mapping compiler pass was introduced in Symfony 2.3. The Doctrine bundles support it from DoctrineBundle >= 1.2.1, MongoDBBundle >= 3.0.0, - PHPCRBundle >= 1.0.0-alpha2 and the (unversioned) CouchDBBundle supports the + PHPCRBundle >= 1.0.0 and the (unversioned) CouchDBBundle supports the compiler pass since the `CouchDB Mapping Compiler Pass pull request`_ was merged. - If you want your bundle to support older versions of Symfony and - Doctrine, you can provide a copy of the compiler pass in your bundle. - See for example the `FOSUserBundle mapping configuration`_ - ``addRegisterMappingsPass``. - +.. versionadded:: 2.6 + Support for defining namespace aliases was introduced in Symfony 2.6. + It is safe to define the aliases with older versions of Symfony as + the aliases are the last argument to ``createXmlMappingDriver`` and + are ignored by PHP if that argument doesn't exist. In your bundle class, write the following code to register the compiler pass. -This one is written for the FOSUserBundle, so parts of it will need to +This one is written for the CmfRoutingBundle, so parts of it will need to be adapted for your case:: use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass; @@ -38,7 +38,7 @@ be adapted for your case:: use Doctrine\Bundle\CouchDBBundle\DependencyInjection\Compiler\DoctrineCouchDBMappingsPass; use Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass; - class FOSUserBundle extends Bundle + class CmfRoutingBundle extends Bundle { public function build(ContainerBuilder $container) { @@ -47,7 +47,7 @@ be adapted for your case:: $modelDir = realpath(__DIR__.'/Resources/config/doctrine/model'); $mappings = array( - $modelDir => 'FOS\UserBundle\Model', + $modelDir => 'Symfony\Cmf\RoutingBundle\Model', ); $ormCompilerClass = 'Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass'; @@ -55,8 +55,9 @@ be adapted for your case:: $container->addCompilerPass( DoctrineOrmMappingsPass::createXmlMappingDriver( $mappings, - array('fos_user.model_manager_name'), - 'fos_user.backend_type_orm' + array('cmf_routing.model_manager_name'), + 'cmf_routing.backend_type_orm', + array('CmfRoutingBundle' => 'Symfony\Cmf\RoutingBundle\Model') )); } @@ -65,8 +66,9 @@ be adapted for your case:: $container->addCompilerPass( DoctrineMongoDBMappingsPass::createXmlMappingDriver( $mappings, - array('fos_user.model_manager_name'), - 'fos_user.backend_type_mongodb' + array('cmf_routing.model_manager_name'), + 'cmf_routing.backend_type_mongodb', + array('CmfRoutingBundle' => 'Symfony\Cmf\RoutingBundle\Model') )); } @@ -75,8 +77,9 @@ be adapted for your case:: $container->addCompilerPass( DoctrineCouchDBMappingsPass::createXmlMappingDriver( $mappings, - array('fos_user.model_manager_name'), - 'fos_user.backend_type_couchdb' + array('cmf_routing.model_manager_name'), + 'cmf_routing.backend_type_couchdb', + array('CmfRoutingBundle' => 'Symfony\Cmf\RoutingBundle\Model') )); } @@ -85,8 +88,9 @@ be adapted for your case:: $container->addCompilerPass( DoctrinePhpcrMappingsPass::createXmlMappingDriver( $mappings, - array('fos_user.model_manager_name'), - 'fos_user.backend_type_phpcr' + array('cmf_routing.model_manager_name'), + 'cmf_routing.backend_type_phpcr', + array('CmfRoutingBundle' => 'Symfony\Cmf\RoutingBundle\Model') )); } } @@ -99,17 +103,20 @@ decide which to use. The compiler pass provides factory methods for all drivers provided by Doctrine: Annotations, XML, Yaml, PHP and StaticPHP. The arguments are: -* a map/hash of absolute directory path to namespace; -* an array of container parameters that your bundle uses to specify the name of - the Doctrine manager that it is using. In the above example, the FOSUserBundle - stores the manager name that's being used under the ``fos_user.model_manager_name`` +* A map/hash of absolute directory path to namespace; +* An array of container parameters that your bundle uses to specify the name of + the Doctrine manager that it is using. In the example above, the CmfRoutingBundle + stores the manager name that's being used under the ``cmf_routing.model_manager_name`` parameter. The compiler pass will append the parameter Doctrine is using to specify the name of the default manager. The first parameter found is used and the mappings are registered with that manager; -* an optional container parameter name that will be used by the compiler +* An optional container parameter name that will be used by the compiler pass to determine if this Doctrine type is used at all. This is relevant if your user has more than one type of Doctrine bundle installed, but your - bundle is only used with one type of Doctrine. + bundle is only used with one type of Doctrine; +* A map/hash of aliases to namespace. This should be the same convention used + by Doctrine auto-mapping. In the example above, this allows the user to call + ``$om->getRepository('CmfRoutingBundle:Route')``. .. note:: @@ -120,7 +127,7 @@ Annotations, XML, Yaml, PHP and StaticPHP. The arguments are: of the class as their filename (e.g. ``BlogPost.orm.xml``) If you also need to map a base class, you can register a compiler pass - with the ``DefaultFileLocator`` like this. This code is simply taken from the + with the ``DefaultFileLocator`` like this. This code is taken from the ``DoctrineOrmMappingsPass`` and adapted to use the ``DefaultFileLocator`` instead of the ``SymfonyFileLocator``:: @@ -138,6 +145,9 @@ Annotations, XML, Yaml, PHP and StaticPHP. The arguments are: ); } + Note that you do not need to provide a namespace alias unless your users are + expected to ask Doctrine for the base classes. + Now place your mapping file into ``/Resources/config/doctrine-base`` with the fully qualified class name, separated by ``.`` instead of ``\``, for example ``Other.Namespace.Model.Name.orm.xml``. You may not mix the two as otherwise @@ -146,4 +156,3 @@ Annotations, XML, Yaml, PHP and StaticPHP. The arguments are: Adjust accordingly for the other Doctrine implementations. .. _`CouchDB Mapping Compiler Pass pull request`: https://github.com/doctrine/DoctrineCouchDBBundle/pull/27 -.. _`FOSUserBundle mapping configuration`: https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/FOSUserBundle.php From aa70a98fd3fa2eaff454c8f87569001a5906e998 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 16 Aug 2014 12:31:35 -0400 Subject: [PATCH 0381/1181] [#3975] Minor typo --- components/http_foundation/introduction.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index 92034f4efe6..60bdb7c9ffc 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -518,7 +518,7 @@ You can still set the ``Content-Type`` of the sent file, or change its ``Content .. versionadded:: 2.6 The ``deleteFileAfterSend()`` method was introduced in Symfony 2.6. -It is possible to delete the file after the request is send with the +It is possible to delete the file after the request is sent with the :method:`Symfony\\Component\\HttpFoundation\\BinaryFileResponse::deleteFileAfterSend` method. Please note that this will not work when the ``X-Sendfile`` header is set. From d185f40b4c7e337f31797f279b2831df9d163484 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 16 Aug 2014 19:37:04 +0200 Subject: [PATCH 0382/1181] fix from suffix to prefix --- reference/constraints/File.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/reference/constraints/File.rst b/reference/constraints/File.rst index 1759cf374cd..eb45c931475 100644 --- a/reference/constraints/File.rst +++ b/reference/constraints/File.rst @@ -177,7 +177,7 @@ to be valid. The size of the file can be given in one of the following formats: | Mi | mebibyte | 1,048,576 bytes | 8Mi | +--------+-----------+-----------------+------+ -For more information about the difference between binary and SI suffixes, +For more information about the difference between binary and SI prefixes, see `Wikipedia: Binary prefix`_. binaryFormat @@ -188,12 +188,12 @@ binaryFormat **type**: ``boolean`` **default**: ``null`` -When ``true``, the sizes will be displayed in messages with binary suffixes -(KiB, MiB). When ``false``, the sizes will be displayed with SI suffixes (kB, -MB). When ``null``, then the binaryFormat will be guessed from the suffix -defined in the ``maxSize`` option. +When ``true``, the sizes will be displayed in messages with binary-prefixed +units (KiB, MiB). When ``false``, the sizes will be displayed with SI-prefixed +units (kB, MB). When ``null``, then the binaryFormat will be guessed from +the value defined in the ``maxSize`` option. -For more information about the difference between binary and SI suffixes, +For more information about the difference between binary and SI prefixes, see `Wikipedia: Binary prefix`_. mimeTypes From 1deabdefa6d7fc4f758c217f964437f736a08be3 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 20 Aug 2014 18:23:26 +0200 Subject: [PATCH 0383/1181] [Reference] fix namespace in Expression constraint --- reference/constraints/Expression.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/reference/constraints/Expression.rst b/reference/constraints/Expression.rst index d491adea2db..018d9549917 100644 --- a/reference/constraints/Expression.rst +++ b/reference/constraints/Expression.rst @@ -73,7 +73,7 @@ One way to accomplish this is with the Expression constraint: .. code-block:: php-annotations // src/Acme/DemoBundle/Model/BlogPost.php - namespace Acme\DemoBundle\Model\BlogPost; + namespace Acme\DemoBundle\Model; use Symfony\Component\Validator\Constraints as Assert; @@ -102,11 +102,10 @@ One way to accomplish this is with the Expression constraint: - .. code-block:: php // src/Acme/DemoBundle/Model/BlogPost.php - namespace Acme\DemoBundle\Model\BlogPost; + namespace Acme\DemoBundle\Model; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints as Assert; From abc39275c36ae73f99ebeccbaaf16066f2a206a2 Mon Sep 17 00:00:00 2001 From: Peter Rehm Date: Mon, 4 Aug 2014 13:27:35 +0200 Subject: [PATCH 0384/1181] Added hint about attaching the expression constraint to a form field --- reference/constraints/Expression.rst | 116 +++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 14 deletions(-) diff --git a/reference/constraints/Expression.rst b/reference/constraints/Expression.rst index d491adea2db..b6723ffc371 100644 --- a/reference/constraints/Expression.rst +++ b/reference/constraints/Expression.rst @@ -74,7 +74,7 @@ One way to accomplish this is with the Expression constraint: // src/Acme/DemoBundle/Model/BlogPost.php namespace Acme\DemoBundle\Model\BlogPost; - + use Symfony\Component\Validator\Constraints as Assert; /** @@ -91,23 +91,27 @@ One way to accomplish this is with the Expression constraint: .. code-block:: xml - - - - - - - + + + + + + + + + .. code-block:: php // src/Acme/DemoBundle/Model/BlogPost.php - namespace Acme\DemoBundle\Model\BlogPost; - + namespace Acme\DemoBundle\Model; + use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Constraints as Assert; @@ -129,6 +133,90 @@ expression that must return true in order for validation to pass. To learn more about the expression language syntax, see :doc:`/components/expression_language/syntax`. +.. sidebar:: Mapping the Error to a Specific Field + + You can also attach the constraint to a specific property and still validate + based on the values of the entire entity. This is handy if you want to attach + the error to a specific field. In this context, ``value`` represents the value + of ``isTechnicalPost``. + + .. configuration-block:: + + .. code-block:: yaml + + # src/Acme/DemoBundle/Resources/config/validation.yml + Acme\DemoBundle\Model\BlogPost: + properties: + isTechnicalPost: + - Expression: + expression: "this.getCategory() in ['php', 'symfony'] or value == false" + message: "If this is a tech post, the category should be either php or symfony!" + + .. code-block:: php-annotations + + // src/Acme/DemoBundle/Model/BlogPost.php + namespace Acme\DemoBundle\Model; + + use Symfony\Component\Validator\Constraints as Assert; + + class BlogPost + { + // ... + + /** + * @Assert\Expression( + * "this.getCategory() in ['php', 'symfony'] or value == false", + * message="If this is a tech post, the category should be either php or symfony!" + * ) + */ + private $isTechnicalPost; + + // ... + } + + .. code-block:: xml + + + + + + + + + + + + + + + + .. code-block:: php + + // src/Acme/DemoBundle/Model/BlogPost.php + namespace Acme\DemoBundle\Model; + + use Symfony\Component\Validator\Constraints as Assert; + use Symfony\Component\Validator\Mapping\ClassMetadata; + + class BlogPost + { + public static function loadValidatorMetadata(ClassMetadata $metadata) + { + $metadata->addPropertyConstraint('isTechnicalPost', new Assert\Expression(array( + 'expression' => 'this.getCategory() in ["php", "symfony"] or value == false', + 'message' => 'If this is a tech post, the category should be either php or symfony!', + ))); + } + + // ... + } + For more information about the expression and what variables are available to you, see the :ref:`expression ` option details below. From 43ae1d8b1bae03577018027a229b3bacce0c8c69 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 21 Aug 2014 19:42:57 +0200 Subject: [PATCH 0385/1181] [OptionsResolver] Adjusted the OptionsResolver documentation to describe the 2.6 API --- components/options_resolver.rst | 665 +++++++++++++++++++++----------- 1 file changed, 445 insertions(+), 220 deletions(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index eaad4bc7eb1..cf7ac0953cb 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -5,8 +5,7 @@ The OptionsResolver Component ============================= - The OptionsResolver component helps you configure objects with option - arrays. It supports default values, option constraints and lazy options. + The OptionsResolver component helps you to easily process option arrays. Installation ------------ @@ -19,11 +18,13 @@ You can install the component in 2 different ways: Usage ----- -Imagine you have a ``Mailer`` class which has 2 options: ``host`` and -``password``. These options are going to be handled by the OptionsResolver -Component. +.. versionadded:: 2.6 + This documentation was written for Symfony 2.6 and later. If you use an older + version, please read the corresponding documentation using the version + drop-down on the upper right. -First, create the ``Mailer`` class:: +Imagine you have a ``Mailer`` class which has four options: ``host``, +``username``, ``password`` and ``port``:: class Mailer { @@ -31,27 +32,63 @@ First, create the ``Mailer`` class:: public function __construct(array $options = array()) { + $this->options = $options; } } -You could of course set the ``$options`` value directly on the property. Instead, -use the :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` class -and let it resolve the options by calling -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::resolve`. -The advantages of doing this will become more obvious as you continue:: +When accessing the ``$options``, you need to add a lot of boilerplate code to +check which options are set:: - use Symfony\Component\OptionsResolver\OptionsResolver; + // ... + public function sendMail($from, $to) + { + $mail = ...; + $mail->setHost(isset($this->options['host']) + ? $this->options['host'] + : 'smtp.example.org'); + $mail->setUsername(isset($this->options['username']) + ? $this->options['username'] + : 'user'); + $mail->setPassword(isset($this->options['password']) + ? $this->options['password'] + : 'pa$$word'); + $mail->setPort(isset($this->options['port']) + ? $this->options['port'] + : 25); + // ... + } + +This boilerplate is hard to read and repetitive. Also, the default values of the +options are buried in the business logic of your code. Let's use +:method:`Symfony\\Component\\OptionsResolver\\Options::resolve` to fix that:: + + use Symfony\Component\OptionsResolver\Options; // ... public function __construct(array $options = array()) { - $resolver = new OptionsResolver(); - - $this->options = $resolver->resolve($options); + $this->options = Options::resolve($options, array( + 'host' => 'smtp.example.org', + 'username' => 'user', + 'password' => 'pa$$word', + 'port' => 25, + )); } -The options property now is a well defined array with all resolved options -readily available:: +Now all options are guaranteed to be set. Any option that wasn't passed through +``$options`` will be set to the specified default value. Additionally, an +:class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException` +is thrown if an unknown option is passed:: + + $mailer = new Mailer(array( + 'usernme' => 'johndoe', + )); + + // InvalidOptionsException: The option "usernme" does not exist. Known + // options are: "host", "password", "username" + +The rest of your code can now access the values of the options without +boilerplate code:: // ... public function sendMail($from, $to) @@ -60,154 +97,148 @@ readily available:: $mail->setHost($this->options['host']); $mail->setUsername($this->options['username']); $mail->setPassword($this->options['password']); + $mail->setPort($this->options['port']); // ... } -Configuring the OptionsResolver -------------------------------- +Required Options +~~~~~~~~~~~~~~~~ -Now, try to actually use the class:: +If an option must be set by the caller, pass that option to +:method:`Symfony\\Component\\OptionsResolver\\Options::validateRequired`. +For example, let's make the ``host`` option required:: - $mailer = new Mailer(array( - 'host' => 'smtp.example.org', - 'username' => 'user', - 'password' => 'pa$$word', - )); + // ... + public function __construct(array $options = array()) + { + Options::validateRequired($options, 'host'); -Right now, you'll receive a -:class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException`, -which tells you that the options ``host`` and ``password`` do not exist. -This is because you need to configure the ``OptionsResolver`` first, so it -knows which options should be resolved. + $this->options = Options::resolve($options, array( + 'host' => null, + 'username' => 'user', + 'password' => 'pa$$word', + 'port' => 25, + )); + } -.. tip:: +If you omit a required option, a +:class:`Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException` +will be thrown:: - To check if an option exists, you can use the - :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isKnown` - function. + $mailer = new Mailer(); -A best practice is to put the configuration in a method (e.g. -``configureOptions``). You call this method in the constructor to configure -the ``OptionsResolver`` class:: + // MissingOptionsException: The required option "host" is missing. - use Symfony\Component\OptionsResolver\OptionsResolver; - use Symfony\Component\OptionsResolver\OptionsResolverInterface; +The :method:`Symfony\\Component\\OptionsResolver\\Options::validateRequired` +method accepts a single name or an array of option names if you have more than +one required option. - class Mailer - { - protected $options; - - public function __construct(array $options = array()) - { - $resolver = new OptionsResolver(); - $this->configureOptions($resolver); - - $this->options = $resolver->resolve($options); - } +.. note:: - protected function configureOptions(OptionsResolverInterface $resolver) - { - // ... configure the resolver, you will learn this - // in the sections below - } - } + As you can see, the ``host`` option must still be passed to + :method:`Symfony\\Component\\OptionsResolver\\Options::resolve`, + otherwise the method will not accept that option. The default value, + however, can be omitted as the option must be set by the caller. -Set default Values -~~~~~~~~~~~~~~~~~~ +Type Validation +~~~~~~~~~~~~~~~ -Most of the options have a default value. You can configure these options by -calling :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setDefaults`:: +You can run additional checks on the options to make sure they were passed +correctly. To validate the types of the options, call +:method:`Symfony\\Component\\OptionsResolver\\Options::validateTypes`:: // ... - protected function setDefaultOptions(OptionsResolverInterface $resolver) + public function __construct(array $options = array()) { // ... + Options::validateTypes($options, array( + 'host' => 'string', + 'port' => array('null', 'int'), + )); - $resolver->setDefaults(array( - 'username' => 'root', + $this->options = Options::resolve($options, array( + 'host' => null, + 'username' => 'user', + 'password' => 'pa$$word', + 'port' => 25, )); } -This would add an option - ``username`` - and give it a default value of -``root``. If the user passes in a ``username`` option, that value will -override this default. You don't need to configure ``username`` as an optional -option. - -Required Options -~~~~~~~~~~~~~~~~ - -The ``host`` option is required: the class can't work without it. You can set -the required options by calling -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setRequired`:: +For each option, you can define either just one type or an array of acceptable +types. You can pass any type for which an ``is_()`` method is defined. +Additionally, you may pass fully qualified class or interface names. - // ... - protected function setDefaultOptions(OptionsResolverInterface $resolver) - { - $resolver->setRequired(array('host')); - } - -You are now able to use the class without errors:: +If you pass an invalid option now, an :class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException` +is thrown:: $mailer = new Mailer(array( - 'host' => 'smtp.example.org', + 'host' => 25, )); - echo $mailer->getHost(); // 'smtp.example.org' - -If you don't pass a required option, a -:class:`Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException` -will be thrown. - -.. tip:: - - To determine if an option is required, you can use the - :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isRequired` - method. + // InvalidOptionsException: The option "host" with value "25" is expected to + // be of type "string" -Optional Options +Value Validation ~~~~~~~~~~~~~~~~ -Sometimes, an option can be optional (e.g. the ``password`` option in the -``Mailer`` class), but it doesn't have a default value. You can configure -these options by calling -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setOptional`:: +Some options can only take one of a fixed list of predefined values. For +example, suppose the ``Mailer`` class has a ``transport`` option which can be +one of ``sendmail``, ``mail`` and ``smtp``. Use the method +:method:`Symfony\\Component\\OptionsResolver\\Options::validateValues` to verify +that the passed option contains one of these values:: // ... - protected function setDefaultOptions(OptionsResolverInterface $resolver) + public function __construct(array $options = array()) { // ... + Options::validateValues($options, array( + 'transport' => array('sendmail', 'mail', 'smtp'), + )); - $resolver->setOptional(array('password')); + $this->options = Options::resolve($options, array( + // ... + 'transport' => 'sendmail', + )); } -Options with defaults are already marked as optional. +If you pass an invalid transport, an :class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException` +is thrown:: -.. tip:: + $mailer = new Mailer(array( + 'transport' => 'send-mail', + )); + + // InvalidOptionsException: The option "transport" has the value "send-mail", + // but is expected to be one of "sendmail", "mail", "smtp" - When setting an option as optional, you can't be sure if it's in the array - or not. You have to check if the option exists before using it. +For options with more complicated validation schemes, pass a callback which +returns ``true`` for acceptable values and ``false`` for invalid values:: - To avoid checking if it exists everytime, you can also set a default of - ``null`` to an option using the ``setDefaults()`` method (see `Set Default Values`_), - this means the element always exists in the array, but with a default of - ``null``. + Options::validateValues($options, array( + // ... + 'transport' => function ($value) { + // return true or false + }, + )); Default Values that Depend on another Option ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Suppose you add a ``port`` option to the ``Mailer`` class, whose default -value you guess based on the encryption. You can do that easily by using a -closure as the default value:: +Suppose you want to set the default value of the ``port`` option based on the +encryption chosen by the user of the ``Mailer`` class. More precisely, we want +to set the port to ``465`` if SSL is used and to ``25`` otherwise. - use Symfony\Component\OptionsResolver\Options; - use Symfony\Component\OptionsResolver\OptionsResolverInterface; +You can implement this feature by passing a closure as default value of the +``port`` option. The closure receives the options as argument. Based on these +options, you can return the desired default value:: // ... - protected function setDefaultOptions(OptionsResolverInterface $resolver) + public function __construct(array $options = array()) { // ... - $resolver->setDefaults(array( + $this->options = Options::resolve($options, new Options(array( + // ... 'encryption' => null, 'port' => function (Options $options) { if ('ssl' === $options['encryption']) { @@ -216,45 +247,288 @@ closure as the default value:: return 25; }, - )); + ))); + } + +Instead of a simple array, we now pass the default options as +:class:`Symfony\\Component\\OptionsResolver\\Options` instance to +:method:`Symfony\\Component\\OptionsResolver\\Options::resolve`. This class +makes sure that the closure stored in the default value of the ``port`` option +is called. In the closure, you can use the +:class:`Symfony\\Component\\OptionsResolver\\Options` instance just like a +normal option array. + +.. caution:: + + The first argument of the closure must be type hinted as ``Options``. + Otherwise, the closure is considered as the default value of the option. + If the closure is still not called, double check that you passed the default + options as :class:`Symfony\\Component\\OptionsResolver\\Options` instance. + +.. note:: + + The closure is only executed if the ``port`` option isn't set by the user. + +Coding Patterns +~~~~~~~~~~~~~~~ + +If you have a large list of options, the option processing code can take up a +lot of space of your method. To make your code easier to read and maintain, it +is a good practice to put the option definitions into static class properties:: + + class Mailer + { + private static $defaultOptions = array( + 'host' => null, + 'username' => 'user', + 'password' => 'pa$$word', + 'port' => 25, + 'encryption' => null, + ); + + private static $requiredOptions = array( + 'host', + ); + + private static $optionTypes = array( + 'host' => 'string', + 'username' => 'string', + 'password' => 'string', + 'port' => 'int', + ); + + private static $optionValues = array( + 'encryption' => array(null, 'ssl', 'tls'), + ); + + protected $options; + + public function __construct(array $options = array()) + { + Options::validateRequired($options, static::$requiredOptions); + Options::validateTypes($options, static::$optionTypes); + Options::validateValues($options, static::$optionValues); + + $this->options = Options::resolve($options, static::$defaultOptions); + } } -The :class:`Symfony\\Component\\OptionsResolver\\Options` class implements -:phpclass:`ArrayAccess`, :phpclass:`Iterator` and :phpclass:`Countable`. That -means you can handle it just like a normal array containing the options. +In this way, the class remains easy to read and maintain even with a lot of +options being processed and validated. .. caution:: - The first argument of the closure must be typehinted as ``Options``, - otherwise it is considered as the value. + PHP does not support closures in property definitions. In such cases, you + must move your closure to a static method:: + + private static $defaultOptions = array( + // ... + 'port' => array(__CLASS__, 'getDefaultPort'), + ); + + public static function getDefaultPort(Options $options) + { + if ('ssl' === $options['encryption']) { + return 465; + } + + return 25; + } + +Decoupling the Option Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +So far, the configuration of the options, their allowed types etc. was very +tightly coupled to the code that resolves the options. This is fine in most cases. +In some cases, however, the configuration of options must be distributed across +multiple classes. An example is a class hierarchy that supports the addition of +options by subclasses. In those cases, you can create an +:class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` object and pass that +object everywhere that you want to adjust the option configuration. Then, call +:method:`Symfony\\Component\\OptionsResolver\\Options::resolve` with the +configuration object to resolve the options. + +The following code demonstrates how to write our previous ``Mailer`` class with +an :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` object:: + + use Symfony\Component\OptionsResolver\Options; + use Symfony\Component\OptionsResolver\OptionsConfig; + + class Mailer + { + protected $options; + + public function __construct(array $options = array()) + { + $config = new OptionsConfig(); + $this->configureOptions($config); + + $this->options = Options::resolve($options, $config); + } + + protected function configureOptions(OptionsConfig $config) + { + $config->setDefaults(array( + 'host' => null, + 'username' => 'user', + 'password' => 'pa$$word', + 'port' => 25, + 'encryption' => null, + )); + + $config->setRequired(array( + 'host', + )); + + $config->setAllowedTypes(array( + 'host' => 'string', + 'username' => 'string', + 'password' => 'string', + 'port' => 'int', + )); + + $config->setAllowedValues(array( + 'encryption' => array(null, 'ssl', 'tls'), + )); + } + } + +As you can see, the code is very similar as before. However, the performance +is marginally worse, since the creation of an additional object is required: +the :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` instance. + +Nevertheless, this design also has a benefit: We can extend the ``Mailer`` +class and adjust the options of the parent class in the subclass:: + + use Symfony\Component\OptionsResolver\Options; + use Symfony\Component\OptionsResolver\OptionsConfig; + + class GoogleMailer extends Mailer + { + protected function configureOptions(OptionsConfig $config) + { + $config->setDefaults(array( + 'host' => 'smtp.google.com', + 'port' => 25, + 'encryption' => 'ssl', + )); + + $config->setRequired(array( + 'username', + 'password', + )); + } + } + +The ``host`` option is no longer required now, but defaults to "smtp.google.com". +The ``username`` and ``password`` options, however, are required in the +subclass. + +The :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` has various +useful methods to find out which options are set or required. Check out the +API documentation to find out more about these methods. + +.. note:: + + The :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` class used + by the Form Component inherits from + :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig`. All the + documentation for ``OptionsConfig`` applies to ``OptionsResolver`` as well. + +Optional Options +~~~~~~~~~~~~~~~~ + +The :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` has one feature +that is not available when not using this class: You can specify optional +options. Optional options will be accepted and validated when set. When not set, +however, *no default value* will be added to the options array. Pass the names +of the optional options to +:method:`Symfony\\Component\\OptionsResolver\\OptionsConfig::setOptional`:: + + // ... + protected function configureOptions(OptionsConfig $config) + { + // ... + + $config->setOptional(array('port')); + } + +This is useful if you need to know whether an option was explicitly passed. If +not, it will be missing from the options array:: + + class Mailer + { + // ... + public function __construct(array $options = array()) + { + // ... + + if (array_key_exists('port', $this->options)) { + echo "Set!"; + } else { + echo "Not Set!"; + } + } + } + + $mailer = new Mailer(array( + 'port' => 25, + )); + // Set! + + $mailer = new Mailer(); + // Not Set! + +.. tip:: -Overwriting default Values + If you need this functionality when not using an + :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` object, check + the options before calling + :method:`Symfony\\Component\\OptionsResolver\\Options::resolve`:: + + // ... + public function __construct(array $options = array()) + { + // ... + + if (array_key_exists('port', $options)) { + echo "Set!"; + } else { + echo "Not Set!"; + } + + $this->options = Options::resolve($options, array( + // ... + )); + } + +Overwriting Default Values ~~~~~~~~~~~~~~~~~~~~~~~~~~ A previously set default value can be overwritten by invoking -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setDefaults` +:method:`Symfony\\Component\\OptionsResolver\\OptionsConfig::setDefaults` again. When using a closure as the new value it is passed 2 arguments: * ``$options``: an :class:`Symfony\\Component\\OptionsResolver\\Options` instance with all the other default options -* ``$previousValue``: the previous set default value +* ``$previousValue``: the previously set default value .. code-block:: php use Symfony\Component\OptionsResolver\Options; - use Symfony\Component\OptionsResolver\OptionsResolverInterface; + use Symfony\Component\OptionsResolver\OptionsConfig; // ... - protected function setDefaultOptions(OptionsResolverInterface $resolver) + protected function configureOptions(OptionsConfig $config) { // ... - $resolver->setDefaults(array( + $config->setDefaults(array( 'encryption' => 'ssl', 'host' => 'localhost', )); // ... - $resolver->setDefaults(array( + $config->setDefaults(array( 'encryption' => 'tls', // simple overwrite 'host' => function (Options $options, $previousValue) { return 'localhost' == $previousValue @@ -267,20 +541,20 @@ again. When using a closure as the new value it is passed 2 arguments: .. tip:: If the previous default value is calculated by an expensive closure and - you don't need access to it, you can use the - :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::replaceDefaults` - method instead. It acts like ``setDefaults`` but simply erases the - previous value to improve performance. This means that the previous - default value is not available when overwriting with another closure:: + you don't need access to it, use the + :method:`Symfony\\Component\\OptionsResolver\\OptionsConfig::replaceDefaults` + method instead. It acts like ``setDefaults`` but erases the previous value + to improve performance. This means that the previous default value is not + available when overwriting with another closure:: use Symfony\Component\OptionsResolver\Options; - use Symfony\Component\OptionsResolver\OptionsResolverInterface; + use Symfony\Component\OptionsResolver\OptionsConfig; // ... - protected function setDefaultOptions(OptionsResolverInterface $resolver) + protected function configureOptions(OptionsConfig $config) { // ... - $resolver->setDefaults(array( + $config->setDefaults(array( 'encryption' => 'ssl', 'heavy' => function (Options $options) { // Some heavy calculations to create the $result @@ -289,7 +563,7 @@ again. When using a closure as the new value it is passed 2 arguments: }, )); - $resolver->replaceDefaults(array( + $config->replaceDefaults(array( 'encryption' => 'tls', // simple overwrite 'heavy' => function (Options $options) { // $previousValue not available @@ -304,92 +578,21 @@ again. When using a closure as the new value it is passed 2 arguments: Existing option keys that you do not mention when overwriting are preserved. -Configure Allowed Values -~~~~~~~~~~~~~~~~~~~~~~~~ - -Not all values are valid values for options. Suppose the ``Mailer`` class has -a ``transport`` option, it can only be one of ``sendmail``, ``mail`` or -``smtp``. You can configure these allowed values by calling -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedValues`:: - - // ... - protected function setDefaultOptions(OptionsResolverInterface $resolver) - { - // ... - - $resolver->setAllowedValues(array( - 'encryption' => array(null, 'ssl', 'tls'), - )); - } - -There is also an -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::addAllowedValues` -method, which you can use if you want to add an allowed value to the previously -configured allowed values. - -.. versionadded:: 2.5 - The callback support for allowed values was introduced in Symfony 2.5. - -If you need to add some more logic to the value validation process, you can pass a callable -as an allowed value:: - - // ... - protected function setDefaultOptions(OptionsResolverInterface $resolver) - { - // ... - - $resolver->setAllowedValues(array( - 'transport' => function($value) { - return false !== strpos($value, 'mail'); - }, - )); - } - -.. caution:: - - Note that using this together with ``addAllowedValues`` will not work. - -Configure Allowed Types -~~~~~~~~~~~~~~~~~~~~~~~ - -You can also specify allowed types. For instance, the ``port`` option can -be anything, but it must be an integer. You can configure these types by calling -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedTypes`:: - - // ... - protected function setDefaultOptions(OptionsResolverInterface $resolver) - { - // ... - - $resolver->setAllowedTypes(array( - 'port' => 'integer', - )); - } - -Possible types are the ones associated with the ``is_*`` PHP functions or a -class name. You can also pass an array of types as the value. For instance, -``array('null', 'string')`` allows ``port`` to be ``null`` or a ``string``. - -There is also an -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::addAllowedTypes` -method, which you can use to add an allowed type to the previous allowed types. - -Normalize the Options -~~~~~~~~~~~~~~~~~~~~~ +Option Normalization +~~~~~~~~~~~~~~~~~~~~ Some values need to be normalized before you can use them. For instance, -pretend that the ``host`` should always start with ``http://``. To do that, -you can write normalizers. These closures will be executed after all options -are passed and should return the normalized value. You can configure these -normalizers by calling -:method:`Symfony\\Components\\OptionsResolver\\OptionsResolver::setNormalizers`:: +assume that the ``host`` should always start with ``http://``. To do that, +you can write normalizers. Normalizers are executed after all options were +processed. You can configure these normalizers by calling +:method:`Symfony\\Components\\OptionsResolver\\OptionsConfig::setNormalizers`:: // ... - protected function setDefaultOptions(OptionsResolverInterface $resolver) + protected function configureOptions(OptionsConfig $config) { // ... - $resolver->setNormalizers(array( + $config->setNormalizers(array( 'host' => function (Options $options, $value) { if ('http://' !== substr($value, 0, 7)) { $value = 'http://'.$value; @@ -400,15 +603,16 @@ normalizers by calling )); } -You see that the closure also gets an ``$options`` parameter. Sometimes, you -need to use the other options for normalizing:: +The normalizer receives the actual ``$value`` and returns the normalized form. +You see that the closure also takes an ``$options`` parameter. This is useful +if you need to use other options for the normalization:: // ... - protected function setDefaultOptions(OptionsResolverInterface $resolver) + protected function configureOptions(OptionsConfig $config) { // ... - $resolver->setNormalizers(array( + $config->setNormalizers(array( 'host' => function (Options $options, $value) { if (!in_array(substr($value, 0, 7), array('http://', 'https://'))) { if ($options['ssl']) { @@ -423,4 +627,25 @@ need to use the other options for normalizing:: )); } +.. tip:: + + When not using an :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` + object, perform normalization after the call to + :method:`Symfony\\Component\\OptionsResolver\\Options::resolve`:: + + // ... + public function __construct(array $options = array()) + { + $this->options = Options::resolve($options, array( + // ... + )); + + if ('http://' !== substr($this->options['host'], 0, 7)) { + $this->options['host'] = 'http://'.$this->options['host']; + } + } + +That's it! You now have all the tools and knowledge needed to easily process +options in your code. + .. _Packagist: https://packagist.org/packages/symfony/options-resolver From ae668939a713442ebeb57bebd4a468b416fcc8f2 Mon Sep 17 00:00:00 2001 From: Peter Rehm Date: Sat, 23 Aug 2014 16:17:51 +0200 Subject: [PATCH 0386/1181] Added missing mailer class and use statements --- components/options_resolver.rst | 369 +++++++++++++++++++------------- 1 file changed, 217 insertions(+), 152 deletions(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index cf7ac0953cb..11899762de0 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -39,23 +39,26 @@ Imagine you have a ``Mailer`` class which has four options: ``host``, When accessing the ``$options``, you need to add a lot of boilerplate code to check which options are set:: - // ... - public function sendMail($from, $to) + class Mailer { - $mail = ...; - $mail->setHost(isset($this->options['host']) - ? $this->options['host'] - : 'smtp.example.org'); - $mail->setUsername(isset($this->options['username']) - ? $this->options['username'] - : 'user'); - $mail->setPassword(isset($this->options['password']) - ? $this->options['password'] - : 'pa$$word'); - $mail->setPort(isset($this->options['port']) - ? $this->options['port'] - : 25); // ... + public function sendMail($from, $to) + { + $mail = ...; + $mail->setHost(isset($this->options['host']) + ? $this->options['host'] + : 'smtp.example.org'); + $mail->setUsername(isset($this->options['username']) + ? $this->options['username'] + : 'user'); + $mail->setPassword(isset($this->options['password']) + ? $this->options['password'] + : 'pa$$word'); + $mail->setPort(isset($this->options['port']) + ? $this->options['port'] + : 25); + // ... + } } This boilerplate is hard to read and repetitive. Also, the default values of the @@ -64,15 +67,18 @@ options are buried in the business logic of your code. Let's use use Symfony\Component\OptionsResolver\Options; - // ... - public function __construct(array $options = array()) + class Mailer { - $this->options = Options::resolve($options, array( - 'host' => 'smtp.example.org', - 'username' => 'user', - 'password' => 'pa$$word', - 'port' => 25, - )); + // ... + public function __construct(array $options = array()) + { + $this->options = Options::resolve($options, array( + 'host' => 'smtp.example.org', + 'username' => 'user', + 'password' => 'pa$$word', + 'port' => 25, + )); + } } Now all options are guaranteed to be set. Any option that wasn't passed through @@ -90,15 +96,18 @@ is thrown if an unknown option is passed:: The rest of your code can now access the values of the options without boilerplate code:: - // ... - public function sendMail($from, $to) + class Mailer { - $mail = ...; - $mail->setHost($this->options['host']); - $mail->setUsername($this->options['username']); - $mail->setPassword($this->options['password']); - $mail->setPort($this->options['port']); // ... + public function sendMail($from, $to) + { + $mail = ...; + $mail->setHost($this->options['host']); + $mail->setUsername($this->options['username']); + $mail->setPassword($this->options['password']); + $mail->setPort($this->options['port']); + // ... + } } Required Options @@ -108,17 +117,22 @@ If an option must be set by the caller, pass that option to :method:`Symfony\\Component\\OptionsResolver\\Options::validateRequired`. For example, let's make the ``host`` option required:: - // ... - public function __construct(array $options = array()) + use Symfony\Component\OptionsResolver\Options; + + class Mailer { - Options::validateRequired($options, 'host'); - - $this->options = Options::resolve($options, array( - 'host' => null, - 'username' => 'user', - 'password' => 'pa$$word', - 'port' => 25, - )); + // ... + public function __construct(array $options = array()) + { + Options::validateRequired($options, 'host'); + + $this->options = Options::resolve($options, array( + 'host' => null, + 'username' => 'user', + 'password' => 'pa$$word', + 'port' => 25, + )); + } } If you omit a required option, a @@ -147,21 +161,26 @@ You can run additional checks on the options to make sure they were passed correctly. To validate the types of the options, call :method:`Symfony\\Component\\OptionsResolver\\Options::validateTypes`:: - // ... - public function __construct(array $options = array()) + use Symfony\Component\OptionsResolver\Options; + + class Mailer { // ... - Options::validateTypes($options, array( - 'host' => 'string', - 'port' => array('null', 'int'), - )); - - $this->options = Options::resolve($options, array( - 'host' => null, - 'username' => 'user', - 'password' => 'pa$$word', - 'port' => 25, - )); + public function __construct(array $options = array()) + { + // ... + Options::validateTypes($options, array( + 'host' => 'string', + 'port' => array('null', 'int'), + )); + + $this->options = Options::resolve($options, array( + 'host' => null, + 'username' => 'user', + 'password' => 'pa$$word', + 'port' => 25, + )); + } } For each option, you can define either just one type or an array of acceptable @@ -187,18 +206,23 @@ one of ``sendmail``, ``mail`` and ``smtp``. Use the method :method:`Symfony\\Component\\OptionsResolver\\Options::validateValues` to verify that the passed option contains one of these values:: - // ... - public function __construct(array $options = array()) + use Symfony\Component\OptionsResolver\Options; + + class Mailer { // ... - Options::validateValues($options, array( - 'transport' => array('sendmail', 'mail', 'smtp'), - )); - - $this->options = Options::resolve($options, array( + public function __construct(array $options = array()) + { // ... - 'transport' => 'sendmail', - )); + Options::validateValues($options, array( + 'transport' => array('sendmail', 'mail', 'smtp'), + )); + + $this->options = Options::resolve($options, array( + // ... + 'transport' => 'sendmail', + )); + } } If you pass an invalid transport, an :class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException` @@ -232,22 +256,27 @@ You can implement this feature by passing a closure as default value of the ``port`` option. The closure receives the options as argument. Based on these options, you can return the desired default value:: - // ... - public function __construct(array $options = array()) + use Symfony\Component\OptionsResolver\Options; + + class Mailer { // ... - - $this->options = Options::resolve($options, new Options(array( + public function __construct(array $options = array()) + { // ... - 'encryption' => null, - 'port' => function (Options $options) { - if ('ssl' === $options['encryption']) { - return 465; - } - return 25; - }, - ))); + $this->options = Options::resolve($options, new Options(array( + // ... + 'encryption' => null, + 'port' => function (Options $options) { + if ('ssl' === $options['encryption']) { + return 465; + } + + return 25; + }, + ))); + } } Instead of a simple array, we now pass the default options as @@ -276,6 +305,8 @@ If you have a large list of options, the option processing code can take up a lot of space of your method. To make your code easier to read and maintain, it is a good practice to put the option definitions into static class properties:: + use Symfony\Component\OptionsResolver\Options; + class Mailer { private static $defaultOptions = array( @@ -445,12 +476,18 @@ however, *no default value* will be added to the options array. Pass the names of the optional options to :method:`Symfony\\Component\\OptionsResolver\\OptionsConfig::setOptional`:: - // ... - protected function configureOptions(OptionsConfig $config) + use Symfony\Component\OptionsResolver\Options; + use Symfony\Component\OptionsResolver\OptionsConfig; + + class Mailer { // ... + protected function configureOptions(OptionsConfig $config) + { + // ... - $config->setOptional(array('port')); + $config->setOptional(array('port')); + } } This is useful if you need to know whether an option was explicitly passed. If @@ -486,20 +523,25 @@ not, it will be missing from the options array:: the options before calling :method:`Symfony\\Component\\OptionsResolver\\Options::resolve`:: - // ... - public function __construct(array $options = array()) + use Symfony\Component\OptionsResolver\Options; + + class Mailer { // ... + public function __construct(array $options = array()) + { + // ... - if (array_key_exists('port', $options)) { - echo "Set!"; - } else { - echo "Not Set!"; - } + if (array_key_exists('port', $options)) { + echo "Set!"; + } else { + echo "Not Set!"; + } - $this->options = Options::resolve($options, array( - // ... - )); + $this->options = Options::resolve($options, array( + // ... + )); + } } Overwriting Default Values @@ -518,24 +560,27 @@ again. When using a closure as the new value it is passed 2 arguments: use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsConfig; - // ... - protected function configureOptions(OptionsConfig $config) + class Mailer { // ... - $config->setDefaults(array( - 'encryption' => 'ssl', - 'host' => 'localhost', - )); + protected function configureOptions(OptionsConfig $config) + { + // ... + $config->setDefaults(array( + 'encryption' => 'ssl', + 'host' => 'localhost', + )); - // ... - $config->setDefaults(array( - 'encryption' => 'tls', // simple overwrite - 'host' => function (Options $options, $previousValue) { - return 'localhost' == $previousValue - ? '127.0.0.1' - : $previousValue; - }, - )); + // ... + $config->setDefaults(array( + 'encryption' => 'tls', // simple overwrite + 'host' => function (Options $options, $previousValue) { + return 'localhost' == $previousValue + ? '127.0.0.1' + : $previousValue; + }, + )); + } } .. tip:: @@ -550,28 +595,31 @@ again. When using a closure as the new value it is passed 2 arguments: use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsConfig; - // ... - protected function configureOptions(OptionsConfig $config) + class Mailer { // ... - $config->setDefaults(array( - 'encryption' => 'ssl', - 'heavy' => function (Options $options) { - // Some heavy calculations to create the $result - - return $result; - }, - )); - - $config->replaceDefaults(array( - 'encryption' => 'tls', // simple overwrite - 'heavy' => function (Options $options) { - // $previousValue not available - // ... - - return $someOtherResult; - }, - )); + protected function configureOptions(OptionsConfig $config) + { + // ... + $config->setDefaults(array( + 'encryption' => 'ssl', + 'heavy' => function (Options $options) { + // Some heavy calculations to create the $result + + return $result; + }, + )); + + $config->replaceDefaults(array( + 'encryption' => 'tls', // simple overwrite + 'heavy' => function (Options $options) { + // $previousValue not available + // ... + + return $someOtherResult; + }, + )); + } } .. note:: @@ -587,44 +635,56 @@ you can write normalizers. Normalizers are executed after all options were processed. You can configure these normalizers by calling :method:`Symfony\\Components\\OptionsResolver\\OptionsConfig::setNormalizers`:: - // ... - protected function configureOptions(OptionsConfig $config) + use Symfony\Component\OptionsResolver\Options; + use Symfony\Component\OptionsResolver\OptionsConfig; + + class Mailer { // ... + protected function configureOptions(OptionsConfig $config) + { + // ... - $config->setNormalizers(array( - 'host' => function (Options $options, $value) { - if ('http://' !== substr($value, 0, 7)) { - $value = 'http://'.$value; - } + $config->setNormalizers(array( + 'host' => function (Options $options, $value) { + if ('http://' !== substr($value, 0, 7)) { + $value = 'http://'.$value; + } - return $value; - }, - )); + return $value; + }, + )); + } } The normalizer receives the actual ``$value`` and returns the normalized form. You see that the closure also takes an ``$options`` parameter. This is useful if you need to use other options for the normalization:: - // ... - protected function configureOptions(OptionsConfig $config) + use Symfony\Component\OptionsResolver\Options; + use Symfony\Component\OptionsResolver\OptionsConfig; + + class Mailer { // ... + protected function configureOptions(OptionsConfig $config) + { + // ... - $config->setNormalizers(array( - 'host' => function (Options $options, $value) { - if (!in_array(substr($value, 0, 7), array('http://', 'https://'))) { - if ($options['ssl']) { - $value = 'https://'.$value; - } else { - $value = 'http://'.$value; + $config->setNormalizers(array( + 'host' => function (Options $options, $value) { + if (!in_array(substr($value, 0, 7), array('http://', 'https://'))) { + if ($options['ssl']) { + $value = 'https://'.$value; + } else { + $value = 'http://'.$value; + } } - } - return $value; - }, - )); + return $value; + }, + )); + } } .. tip:: @@ -633,15 +693,20 @@ if you need to use other options for the normalization:: object, perform normalization after the call to :method:`Symfony\\Component\\OptionsResolver\\Options::resolve`:: - // ... - public function __construct(array $options = array()) + use Symfony\Component\OptionsResolver\Options; + + class Mailer { - $this->options = Options::resolve($options, array( - // ... - )); + // ... + public function __construct(array $options = array()) + { + $this->options = Options::resolve($options, array( + // ... + )); - if ('http://' !== substr($this->options['host'], 0, 7)) { - $this->options['host'] = 'http://'.$this->options['host']; + if ('http://' !== substr($this->options['host'], 0, 7)) { + $this->options['host'] = 'http://'.$this->options['host']; + } } } From df640b2ba0c31c928b14b6aaae9f640a44f973af Mon Sep 17 00:00:00 2001 From: WouterJ Date: Mon, 25 Aug 2014 12:14:01 +0200 Subject: [PATCH 0387/1181] Updated for CMF doc refactoring --- redirection_map | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/redirection_map b/redirection_map index e632d829662..1a6758a5560 100644 --- a/redirection_map +++ b/redirection_map @@ -22,3 +22,25 @@ /cookbook/console/generating_urls /cookbook/console/sending_emails /components/yaml /components/yaml/introduction /components/templating /components/templating/introduction +/cmf/reference/configuration/block /cmf/bundles/block/configuration +/cmf/reference/configuration/content /cmf/bundles/content/configuration +/cmf/reference/configuration/core /cmf/bundles/core/configuration +/cmf/reference/configuration/create /cmf/bundles/create/configuration +/cmf/reference/configuration/media /cmf/bundles/media/configuration +/cmf/reference/configuration/menu /cmf/bundles/menu/configuration +/cmf/reference/configuration/phpcr_odm /cmf/bundles/phpcr_odm/configuration +/cmf/reference/configuration/routing /cmf/bundles/routing/configuration +/cmf/reference/configuration/search /cmf/bundles/search/configuration +/cmf/reference/configuration/seo /cmf/bundles/seo/configuration +/cmf/reference/configuration/simple_cms /cmf/bundles/simple_cms/configuration +/cmf/reference/configuration/tree_browser /cmf/bundles/tree_browser/configuration +/cmf/cookbook/exposing_content_via_rest /cmf/bundles/content/exposing_content_via_rest +/cmf/cookbook/creating_a_cms/auto-routing /cmf/tutorial/auto-routing +/cmf/cookbook/creating_a_cms/conclusion /cmf/tutorial/conclusion +/cmf/cookbook/creating_a_cms/content-to-controllers /cmf/tutorial/content-to-controllers +/cmf/cookbook/creating_a_cms/getting-started /cmf/tutorial/getting-started +/cmf/cookbook/creating_a_cms/index /cmf/tutorial/index +/cmf/cookbook/creating_a_cms/introduction /cmf/tutorial/introduction +/cmf/cookbook/creating_a_cms/make-homepage /cmf/tutorial/make-homepage +/cmf/cookbook/creating_a_cms/sonata-admin /cmf/tutorial/sonata-admin +/cmf/cookbook/creating_a_cms/the-frontend /cmf/tutorial/the-frontend From a5f54e3d91d154b6c04d6265ba002865e4f20ef2 Mon Sep 17 00:00:00 2001 From: gerryvdm Date: Fri, 22 Aug 2014 17:21:40 +0200 Subject: [PATCH 0388/1181] Update voters.rst Corrected the service name to be injected0 --- cookbook/security/voters.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/voters.rst b/cookbook/security/voters.rst index 1760cb43db7..e27f922a700 100644 --- a/cookbook/security/voters.rst +++ b/cookbook/security/voters.rst @@ -32,7 +32,7 @@ access, not to grant access. Creating a custom Voter ----------------------- -To blacklist a user based on its IP, you can use the ``request`` service +To blacklist a user based on its IP, you can use the ``request_stack`` service and compare the IP address against a set of blacklisted IP addresses: .. code-block:: php From 785827fda1a15c46ae63842e5b1534ea06afae27 Mon Sep 17 00:00:00 2001 From: Ariel Ferrandini Date: Tue, 26 Aug 2014 12:04:34 +0200 Subject: [PATCH 0389/1181] New service to simplify password encoding --- book/security.rst | 35 +++++++++++++++-- .../custom_password_authenticator.rst | 38 ++++++++----------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/book/security.rst b/book/security.rst index 0572bc13330..ab1ce30c862 100644 --- a/book/security.rst +++ b/book/security.rst @@ -1459,23 +1459,36 @@ is available by calling the PHP function :phpfunction:`hash_algos`. Determining the Hashed Password ............................... +.. versionadded:: 2.6 + The ``security.password_encoder`` service was introduced in Symfony 2.6. + If you're storing users in the database and you have some sort of registration form for users, you'll need to be able to determine the hashed password so that you can set it on your user before inserting it. No matter what algorithm you configure for your user object, the hashed password can always be determined in the following way from a controller:: - $factory = $this->get('security.encoder_factory'); $user = new Acme\UserBundle\Entity\User(); + $plainPassword = 'ryanpass'; + $encoded = $this->container->get('security.password_encoder') + ->encodePassword($user, $plainPassword); - $encoder = $factory->getEncoder($user); - $password = $encoder->encodePassword('ryanpass', $user->getSalt()); - $user->setPassword($password); + $user->setPassword($encoded); In order for this to work, just make sure that you have the encoder for your user class (e.g. ``Acme\UserBundle\Entity\User``) configured under the ``encoders`` key in ``app/config/security.yml``. +.. sidebar:: Get the User Encoder + + In some cases, you need a specific encoder for a given user (e.g. ``Acme\UserBundle\Entity\User``). + You can use the ``EncoderFactory`` to get this encoder:: + + $factory = $this->get('security.encoder_factory'); + $user = new Acme\UserBundle\Entity\User(); + + $encoder = $factory->getEncoder($user); + .. caution:: When you allow a user to submit a plaintext password (e.g. registration @@ -1483,6 +1496,20 @@ key in ``app/config/security.yml``. that the password is 4096 characters or less. Read more details in :ref:`How to implement a simple Registration Form `. +Validating a Plaintext Password +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sometimes you want to check if a plain password is valid for a given user:: + + // a user instance of some class which implements Symfony\Component\Security\Core\User\UserInterface + $user = ...; + + // the password that should be checked + $plainPassword = ...; + + $isValidPassword = $this->container->get('security.password_encoder') + ->isPasswordValid($user, $plainPassword); + Retrieving the User Object ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/cookbook/security/custom_password_authenticator.rst b/cookbook/security/custom_password_authenticator.rst index 288d0e65a6f..6894a5043c2 100644 --- a/cookbook/security/custom_password_authenticator.rst +++ b/cookbook/security/custom_password_authenticator.rst @@ -8,6 +8,7 @@ Imagine you want to allow access to your website only between 2pm and 4pm UTC. Before Symfony 2.4, you had to create a custom token, factory, listener and provider. In this entry, you'll learn how to do this for a login form (i.e. where your user submits their username and password). +Before Symfony 2.6, you had to use the password encoder to authenticate the user password. The Password Authenticator -------------------------- @@ -15,6 +16,9 @@ The Password Authenticator .. versionadded:: 2.4 The ``SimpleFormAuthenticatorInterface`` interface was introduced in Symfony 2.4. +.. versionadded:: 2.6 + The ``UserPasswordEncoderInterface`` interface was introduced in Symfony 2.6. + First, create a new class that implements :class:`Symfony\\Component\\Security\\Core\\Authentication\\SimpleFormAuthenticatorInterface`. Eventually, this will allow you to create custom logic for authenticating @@ -27,18 +31,18 @@ the user:: use Symfony\Component\Security\Core\Authentication\SimpleFormAuthenticatorInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; - use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; + use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\User\UserProviderInterface; class TimeAuthenticator implements SimpleFormAuthenticatorInterface { - private $encoderFactory; + private $encoder; - public function __construct(EncoderFactoryInterface $encoderFactory) + public function __construct(UserPasswordEncoderInterface $encoder) { - $this->encoderFactory = $encoderFactory; + $this->encoder = $encoder; } public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey) @@ -49,12 +53,7 @@ the user:: throw new AuthenticationException('Invalid username or password'); } - $encoder = $this->encoderFactory->getEncoder($user); - $passwordValid = $encoder->isPasswordValid( - $user->getPassword(), - $token->getCredentials(), - $user->getSalt() - ); + $passwordValid = $this->encoder->isPasswordValid($user, $token->getCredentials()); if ($passwordValid) { $currentHour = date('G'); @@ -127,17 +126,12 @@ Ultimately, your job is to return a *new* token object that is "authenticated" (i.e. it has at least 1 role set on it) and which has the ``User`` object inside of it. -Inside this method, an encoder is needed to check the password's validity:: +Inside this method, the password encoder is needed to check the password's validity:: - $encoder = $this->encoderFactory->getEncoder($user); - $passwordValid = $encoder->isPasswordValid( - $user->getPassword(), - $token->getCredentials(), - $user->getSalt() - ); + $passwordValid = $this->encoder->isPasswordValid($user, $token->getCredentials()); -This is a service that is already available in Symfony and the password algorithm -is configured in the security configuration (e.g. ``security.yml``) under +This is a service that is already available in Symfony and it uses the password algorithm +that is configured in the security configuration (e.g. ``security.yml``) under the ``encoders`` key. Below, you'll see how to inject that into the ``TimeAuthenticator``. .. _cookbook-security-password-authenticator-config: @@ -157,7 +151,7 @@ Now, configure your ``TimeAuthenticator`` as a service: time_authenticator: class: Acme\HelloBundle\Security\TimeAuthenticator - arguments: ["@security.encoder_factory"] + arguments: ["@security.password_encoder"] .. code-block:: xml @@ -173,7 +167,7 @@ Now, configure your ``TimeAuthenticator`` as a service: - + @@ -188,7 +182,7 @@ Now, configure your ``TimeAuthenticator`` as a service: $container->setDefinition('time_authenticator', new Definition( 'Acme\HelloBundle\Security\TimeAuthenticator', - array(new Reference('security.encoder_factory')) + array(new Reference('security.password_encoder')) )); Then, activate it in the ``firewalls`` section of the security configuration From 0a4511345a82313cb6cc5fc0dae1351073f50c6a Mon Sep 17 00:00:00 2001 From: Bruno Vitorino Date: Wed, 27 Aug 2014 16:16:55 +0200 Subject: [PATCH 0390/1181] Route description correction. The actual route is '/random/{limit}' and not '/number/{limit}'. --- book/page_creation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/page_creation.rst b/book/page_creation.rst index da550fa60e4..fd6889868d0 100644 --- a/book/page_creation.rst +++ b/book/page_creation.rst @@ -231,7 +231,7 @@ the new route that defines the URL of the page that you're about to create: The routing consists of two basic pieces: the ``path``, which is the URL that this route will match, and a ``defaults`` array, which specifies the controller that should be executed. The placeholder syntax in the path -(``{limit}``) is a wildcard. It means that ``/number/10``, ``/number/327`` +(``{limit}``) is a wildcard. It means that ``/random/10``, ``/random/327`` or any other similar URL will match this route. The ``{limit}`` placeholder parameter will also be passed to the controller so that you can use its value to generate the proper random number. From fb0e79cfa21c733763855c8ca4486fe8503aa0b0 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Sat, 6 Sep 2014 19:37:30 +0200 Subject: [PATCH 0391/1181] Fix method for adding placholders in progressBar The method is called setPlaceholderFormatterDefinition and not setPlaceholderFormatter --- components/console/helpers/progressbar.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/console/helpers/progressbar.rst b/components/console/helpers/progressbar.rst index 46e993c08c0..a242791eda3 100644 --- a/components/console/helpers/progressbar.rst +++ b/components/console/helpers/progressbar.rst @@ -289,7 +289,7 @@ display that are not available in the list of built-in placeholders, you can create your own. Let's see how you can create a ``remaining_steps`` placeholder that displays the number of remaining steps:: - ProgressBar::setPlaceholderFormatter( + ProgressBar::setPlaceholderFormatterDefinition( '%remaining_steps%', function (ProgressBar $bar, OutputInterface $output) { return $bar->getMaxSteps() - $bar->getStep(); From f3ef9dc5aa3c0f5bbd70de0556f941dbdf100180 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Sat, 6 Sep 2014 19:55:20 +0200 Subject: [PATCH 0392/1181] The name of the placeholder must not be encapsulated in % --- components/console/helpers/progressbar.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/console/helpers/progressbar.rst b/components/console/helpers/progressbar.rst index a242791eda3..fec1b8c127f 100644 --- a/components/console/helpers/progressbar.rst +++ b/components/console/helpers/progressbar.rst @@ -290,7 +290,7 @@ create your own. Let's see how you can create a ``remaining_steps`` placeholder that displays the number of remaining steps:: ProgressBar::setPlaceholderFormatterDefinition( - '%remaining_steps%', + 'remaining_steps', function (ProgressBar $bar, OutputInterface $output) { return $bar->getMaxSteps() - $bar->getStep(); } From c723d8dd546412b08ffaf3846b5574f4f4021418 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Mon, 8 Sep 2014 17:38:40 +0200 Subject: [PATCH 0393/1181] Missing backtick, thanks to @Baptouuuu --- components/dependency_injection/advanced.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dependency_injection/advanced.rst b/components/dependency_injection/advanced.rst index f3fde08777c..babd7cfd0fc 100644 --- a/components/dependency_injection/advanced.rst +++ b/components/dependency_injection/advanced.rst @@ -269,7 +269,7 @@ a reference of the old one as ``bar.inner``: ->setPublic(false) ->setDecoratedService('foo'); -Here is what's going on here: the ``setDecoratedService()` method tells +Here is what's going on here: the ``setDecoratedService()`` method tells the container that the ``bar`` service should replace the ``foo`` service, renaming ``foo`` to ``bar.inner``. By convention, the old ``foo`` service is going to be renamed ``bar.inner``, From be4ec85e76f4982342d66cdd72db6da7c5a9bf9a Mon Sep 17 00:00:00 2001 From: Wouter J Date: Mon, 8 Sep 2014 17:40:11 +0200 Subject: [PATCH 0394/1181] Reverts c723d8dd546412b08ffaf3846b5574f4f4021418 --- components/dependency_injection/advanced.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dependency_injection/advanced.rst b/components/dependency_injection/advanced.rst index babd7cfd0fc..f3fde08777c 100644 --- a/components/dependency_injection/advanced.rst +++ b/components/dependency_injection/advanced.rst @@ -269,7 +269,7 @@ a reference of the old one as ``bar.inner``: ->setPublic(false) ->setDecoratedService('foo'); -Here is what's going on here: the ``setDecoratedService()`` method tells +Here is what's going on here: the ``setDecoratedService()` method tells the container that the ``bar`` service should replace the ``foo`` service, renaming ``foo`` to ``bar.inner``. By convention, the old ``foo`` service is going to be renamed ``bar.inner``, From dadaea3d9d82a1d9bb7e29ccf26036d74ccf7e1f Mon Sep 17 00:00:00 2001 From: Wouter J Date: Mon, 8 Sep 2014 17:41:33 +0200 Subject: [PATCH 0395/1181] Missing backtick, thanks to @Baptouuuu --- components/dependency_injection/advanced.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dependency_injection/advanced.rst b/components/dependency_injection/advanced.rst index f3fde08777c..babd7cfd0fc 100644 --- a/components/dependency_injection/advanced.rst +++ b/components/dependency_injection/advanced.rst @@ -269,7 +269,7 @@ a reference of the old one as ``bar.inner``: ->setPublic(false) ->setDecoratedService('foo'); -Here is what's going on here: the ``setDecoratedService()` method tells +Here is what's going on here: the ``setDecoratedService()`` method tells the container that the ``bar`` service should replace the ``foo`` service, renaming ``foo`` to ``bar.inner``. By convention, the old ``foo`` service is going to be renamed ``bar.inner``, From 070489b57b203acd824e71587050bddd432b721f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 5 Sep 2014 12:19:26 +0200 Subject: [PATCH 0396/1181] caution on `null` values in Expression constraint This adds a warning to the reference of the Expression constraint explaining that `null` values won't be validated in Symfony 2.4 and Symfony 2.5. --- reference/constraints/Expression.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/reference/constraints/Expression.rst b/reference/constraints/Expression.rst index 5db3373b55e..68526372837 100644 --- a/reference/constraints/Expression.rst +++ b/reference/constraints/Expression.rst @@ -217,6 +217,13 @@ more about the expression language syntax, see // ... } + .. caution:: + + In Symfony 2.4 and Symfony 2.5, if the property (e.g. ``isTechnicalPost``) + were ``null``, the expression would never be called and the value + would be seen as valid. To ensure that the value is not ``null``, + use the :doc:`NotNull constraint `. + For more information about the expression and what variables are available to you, see the :ref:`expression ` option details below. From d6dd54087f9f3589fd691e23c852beae8354b8e4 Mon Sep 17 00:00:00 2001 From: Matthieu Auger Date: Mon, 15 Sep 2014 23:46:38 +0200 Subject: [PATCH 0397/1181] Move debug command to the debug namespace --- book/controller.rst | 7 +++++-- book/routing.rst | 9 ++++++--- book/service_container.rst | 11 +++++++---- book/testing.rst | 5 ++++- book/translation.rst | 15 +++++++++------ 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/book/controller.rst b/book/controller.rst index 17902efcf9e..f8b8cb0b41c 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -613,12 +613,15 @@ via the ``get()`` method. Here are several common services you might need:: $mailer = $this->get('mailer'); There are countless other services available and you are encouraged to define -your own. To list all available services, use the ``container:debug`` console +your own. To list all available services, use the ``debug:container`` console command: .. code-block:: bash - $ php app/console container:debug + $ php app/console debug:container + +.. versionadded:: 2.6 + Prior to Symfony 2.6, this command was called ``container:debug``. For more information, see the :doc:`/book/service_container` chapter. diff --git a/book/routing.rst b/book/routing.rst index 3b82cb3033a..69ce87f6429 100644 --- a/book/routing.rst +++ b/book/routing.rst @@ -1192,12 +1192,15 @@ Visualizing & Debugging Routes While adding and customizing routes, it's helpful to be able to visualize and get detailed information about your routes. A great way to see every route -in your application is via the ``router:debug`` console command. Execute +in your application is via the ``debug:router`` console command. Execute the command by running the following from the root of your project. .. code-block:: bash - $ php app/console router:debug + $ php app/console debug:router + +.. versionadded:: 2.6 + Prior to Symfony 2.6, this command was called ``router:debug``. This command will print a helpful list of *all* the configured routes in your application: @@ -1216,7 +1219,7 @@ the route name after the command: .. code-block:: bash - $ php app/console router:debug article_show + $ php app/console debug:router article_show Likewise, if you want to test whether a URL matches a given route, you can use the ``router:match`` console command: diff --git a/book/service_container.rst b/book/service_container.rst index 34120f60ee7..f7b4808d7c7 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -1169,18 +1169,21 @@ console. To show all services and the class for each service, run: .. code-block:: bash - $ php app/console container:debug + $ php app/console debug:container + +.. versionadded:: 2.6 + Prior to Symfony 2.6, this command was called ``container:debug``. By default only public services are shown, but you can also view private services: .. code-block:: bash - $ php app/console container:debug --show-private + $ php app/console debug:container --show-private .. note:: If a private service is only used as an argument to just *one* other service, - it won't be displayed by the ``container:debug`` command, even when using + it won't be displayed by the ``debug:container`` command, even when using the ``--show-private`` option. See :ref:`Inline Private Services ` for more details. @@ -1189,7 +1192,7 @@ its id: .. code-block:: bash - $ php app/console container:debug my_mailer + $ php app/console debug:container my_mailer Learn more ---------- diff --git a/book/testing.rst b/book/testing.rst index f870ac58272..67c5f798f2b 100644 --- a/book/testing.rst +++ b/book/testing.rst @@ -459,7 +459,10 @@ injection container:: Be warned that this does not work if you insulate the client or if you use an HTTP layer. For a list of services available in your application, use the -``container:debug`` console task. +``debug:container`` console task. + +.. versionadded:: 2.6 + Prior to Symfony 2.6, this command was called ``container:debug``. .. tip:: diff --git a/book/translation.rst b/book/translation.rst index 8abe3c8da2c..63a98e8309b 100644 --- a/book/translation.rst +++ b/book/translation.rst @@ -662,10 +662,13 @@ Debugging Translations ---------------------- .. versionadded:: 2.5 - The ``translation:debug`` command was introduced in Symfony 2.5. + The ``debug:translation`` command was introduced in Symfony 2.5. + +.. versionadded:: 2.6 + Prior to Symfony 2.6, this command was called ``translation:debug``. When maintaining a bundle, you may use or remove the usage of a translation -message without updating all message catalogues. The ``translation:debug`` +message without updating all message catalogues. The ``debug:translation`` command helps you to find these missing or unused translation messages for a given locale. It shows you a table with the result when translating the message in the given locale and the result when the fallback would be used. @@ -774,7 +777,7 @@ To inspect all messages in the ``fr`` locale for the AcmeDemoBundle, run: .. code-block:: bash - $ php app/console translation:debug fr AcmeDemoBundle + $ php app/console debug:translation fr AcmeDemoBundle You will get this output: @@ -815,15 +818,15 @@ By default all domains are inspected, but it is possible to specify a single dom .. code-block:: bash - $ php app/console translation:debug en AcmeDemoBundle --domain=messages + $ php app/console debug:translation en AcmeDemoBundle --domain=messages When bundles have a lot of messages, it is useful to display only the unused or only the missing messages, by using the ``--only-unused`` or ``--only-missing`` switches: .. code-block:: bash - $ php app/console translation:debug en AcmeDemoBundle --only-unused - $ php app/console translation:debug en AcmeDemoBundle --only-missing + $ php app/console debug:translation en AcmeDemoBundle --only-unused + $ php app/console debug:translation en AcmeDemoBundle --only-missing Summary ------- From f202fb83e60254b9938aefb00acaef1aa1fdf704 Mon Sep 17 00:00:00 2001 From: Peter Rehm Date: Wed, 17 Sep 2014 07:52:36 +0200 Subject: [PATCH 0398/1181] Removed duplicate use statements --- components/options_resolver.rst | 51 +++++++++++---------------------- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index 11899762de0..22b1943f9e9 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -96,6 +96,7 @@ is thrown if an unknown option is passed:: The rest of your code can now access the values of the options without boilerplate code:: + // ... class Mailer { // ... @@ -117,8 +118,7 @@ If an option must be set by the caller, pass that option to :method:`Symfony\\Component\\OptionsResolver\\Options::validateRequired`. For example, let's make the ``host`` option required:: - use Symfony\Component\OptionsResolver\Options; - + // ... class Mailer { // ... @@ -160,9 +160,8 @@ Type Validation You can run additional checks on the options to make sure they were passed correctly. To validate the types of the options, call :method:`Symfony\\Component\\OptionsResolver\\Options::validateTypes`:: - - use Symfony\Component\OptionsResolver\Options; - + + // ... class Mailer { // ... @@ -206,8 +205,7 @@ one of ``sendmail``, ``mail`` and ``smtp``. Use the method :method:`Symfony\\Component\\OptionsResolver\\Options::validateValues` to verify that the passed option contains one of these values:: - use Symfony\Component\OptionsResolver\Options; - + // ... class Mailer { // ... @@ -256,8 +254,7 @@ You can implement this feature by passing a closure as default value of the ``port`` option. The closure receives the options as argument. Based on these options, you can return the desired default value:: - use Symfony\Component\OptionsResolver\Options; - + // ... class Mailer { // ... @@ -305,8 +302,7 @@ If you have a large list of options, the option processing code can take up a lot of space of your method. To make your code easier to read and maintain, it is a good practice to put the option definitions into static class properties:: - use Symfony\Component\OptionsResolver\Options; - + // ... class Mailer { private static $defaultOptions = array( @@ -382,7 +378,7 @@ configuration object to resolve the options. The following code demonstrates how to write our previous ``Mailer`` class with an :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` object:: - use Symfony\Component\OptionsResolver\Options; + // ... use Symfony\Component\OptionsResolver\OptionsConfig; class Mailer @@ -431,9 +427,7 @@ the :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` instance. Nevertheless, this design also has a benefit: We can extend the ``Mailer`` class and adjust the options of the parent class in the subclass:: - use Symfony\Component\OptionsResolver\Options; - use Symfony\Component\OptionsResolver\OptionsConfig; - + // ... class GoogleMailer extends Mailer { protected function configureOptions(OptionsConfig $config) @@ -476,9 +470,7 @@ however, *no default value* will be added to the options array. Pass the names of the optional options to :method:`Symfony\\Component\\OptionsResolver\\OptionsConfig::setOptional`:: - use Symfony\Component\OptionsResolver\Options; - use Symfony\Component\OptionsResolver\OptionsConfig; - + // ... class Mailer { // ... @@ -493,6 +485,7 @@ of the optional options to This is useful if you need to know whether an option was explicitly passed. If not, it will be missing from the options array:: + // ... class Mailer { // ... @@ -523,8 +516,7 @@ not, it will be missing from the options array:: the options before calling :method:`Symfony\\Component\\OptionsResolver\\Options::resolve`:: - use Symfony\Component\OptionsResolver\Options; - + // ... class Mailer { // ... @@ -557,9 +549,7 @@ again. When using a closure as the new value it is passed 2 arguments: .. code-block:: php - use Symfony\Component\OptionsResolver\Options; - use Symfony\Component\OptionsResolver\OptionsConfig; - + // ... class Mailer { // ... @@ -592,9 +582,7 @@ again. When using a closure as the new value it is passed 2 arguments: to improve performance. This means that the previous default value is not available when overwriting with another closure:: - use Symfony\Component\OptionsResolver\Options; - use Symfony\Component\OptionsResolver\OptionsConfig; - + // ... class Mailer { // ... @@ -635,9 +623,7 @@ you can write normalizers. Normalizers are executed after all options were processed. You can configure these normalizers by calling :method:`Symfony\\Components\\OptionsResolver\\OptionsConfig::setNormalizers`:: - use Symfony\Component\OptionsResolver\Options; - use Symfony\Component\OptionsResolver\OptionsConfig; - + // ... class Mailer { // ... @@ -661,9 +647,7 @@ The normalizer receives the actual ``$value`` and returns the normalized form. You see that the closure also takes an ``$options`` parameter. This is useful if you need to use other options for the normalization:: - use Symfony\Component\OptionsResolver\Options; - use Symfony\Component\OptionsResolver\OptionsConfig; - + // ... class Mailer { // ... @@ -693,8 +677,7 @@ if you need to use other options for the normalization:: object, perform normalization after the call to :method:`Symfony\\Component\\OptionsResolver\\Options::resolve`:: - use Symfony\Component\OptionsResolver\Options; - + // ... class Mailer { // ... From 26edf7ad4f2ada551c145cf81e7a3c9fccf5b567 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 17 Sep 2014 18:55:15 +0200 Subject: [PATCH 0399/1181] intro the var-dumper component --- components/index.rst | 1 + components/map.rst.inc | 4 ++ components/var_dumper.rst | 134 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 components/var_dumper.rst diff --git a/components/index.rst b/components/index.rst index 8e167cd2ac9..be74544ce43 100644 --- a/components/index.rst +++ b/components/index.rst @@ -29,6 +29,7 @@ The Components stopwatch templating/index translation/index + var_dumper yaml/index .. include:: /components/map.rst.inc diff --git a/components/map.rst.inc b/components/map.rst.inc index f9eab711e07..d3ce97a167f 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -143,6 +143,10 @@ * :doc:`/components/translation/usage` * :doc:`/components/translation/custom_formats` +* **VarDumper** + + * :doc:`/components/var_dumper` + * :doc:`/components/yaml/index` * :doc:`/components/yaml/introduction` diff --git a/components/var_dumper.rst b/components/var_dumper.rst new file mode 100644 index 00000000000..01d8f237673 --- /dev/null +++ b/components/var_dumper.rst @@ -0,0 +1,134 @@ +.. index:: + single: VarDumper + single: Components; VarDumper + +The VarDumper Component +======================= + + The VarDumper component provides mechanisms for walking through any arbitrary PHP variable. + Built on top, it provides a better ``dump()`` function, that you can use instead of ``var_dump()``, + *better* meaning: + + - per object and resource types specialized view to e.g. filter out Doctrine noise + while dumping a single proxy entity, or get more insight on opened files with + ``stream_get_meta_data()``. + - configurable output format: HTML, command line with colors or JSON. + - ability to dump internal references, either soft ones (objects or resources) + or hard ones (``=&`` on arrays or objects properties). Repeated occurrences of + the same object/array/resource won't appear again and again anymore. Moreover, + you'll be able to inspected the reference structure of your data. + - ability to operate in the context of an output buffering handler. + +.. versionadded:: 2.6 + The VarDumper component was introduced in Symfony 2.6. + +Installation +------------ + +You can install the component in 2 different ways: + +* :doc:`Install it via Composer ` (``symfony/var-dumper`` on `Packagist`_); +* Use the official Git repository (https://github.com/symfony/VarDumper). + +The dump() function +------------------- + +The VarDumper component creates a global ``dump()`` function that is auto-configured out of the box: +HTML or CLI output is automatically selected based on the current PHP SAPI. + +``dump()`` is just a thin wrapper for ``\Symfony\Component\VarDumper\VarDumper::dump()`` so can you also use it directly. +You can change the behavior of this function by calling ``\Symfony\Component\VarDumper\VarDumper::setHandler($callable)``: +calls to ``dump()`` will then be forwarded to the ``$callable`` given as first argument. + +Advanced usage +-------------- + +Cloners +~~~~~~~ + +A cloner is used to create an intermediate representation of any PHP variable. +Its output is a Data object that wraps this representation. +A cloner also applies limits when creating the representation, so that the corresponding +Data object could represent only a subset of the cloned variable. + +You can create a Data object this way:: + + $cloner = new PhpCloner(); + $data = $cloner->cloneVar($myVar); + +Before cloning, you can configure the limits with:: + + $cloner->setMaxItems($number); + $cloner->setMaxString($number); + +These limits will be applied when calling ``->cloneVar()`` afterwise. + +Casters +~~~~~~~ + +Objects and resources nested in a PHP variable are casted to arrays in the intermediate Data representation. +You can tweak the array representation for each object/resource by hooking a Caster into this process. +The component already has a many casters for base PHP classes and other common classes. + +If you want to build your how Caster, you can register one before cloning a PHP variable. +Casters are registered using either a Cloner's constructor or its ``addCasters()`` method:: + + $myCasters = array(...); + $cloner = new PhpCloner($myCasters); + +or:: + + $cloner->addCasters($myCasters); + +The provided ``$myCasters`` argument is an array that maps a class, an interface or a resource type to a callable:: + + $myCasters = array( + 'FooClass' => $myFooClassCallableCaster, + ':bar resource' => $myBarResourceCallableCaster, + ); + +As you can notice, resource types are prefixed by a ``:`` to prevent colliding with a class name. + +Because an object has one main class and potentially many parent classes or interfaces, +many casters can be applied to one object. In this case, casters are called one after the other, +starting from casters bound to the interfaces, the parents classes and then the main class. +Several casters can also be registered for the same resource type/class/interface. +They are called in registration order. + +Casters are responsible for returning the properties of the object or resource being cloned in an array. +They are callables that accept four arguments:: + + /** + * A caster not doing anything. + * + * @param object|resource $object The object or resource being casted. + * @param array $array An array modelled for objects after PHP's native `(array)` cast operator. + * @param Stub $stub A Cloner\Stub object representing the main properties of $object (class, type, etc.). + * @param bool $isNested True/false when the caster is called nested is a structure or not. + * + * @return array The properties of $object casted in an array. + */ + function myCaster($origValue, $array, $stub, $isNested) + { + // Here, populate/alter $array to your needs. + + return $array; + } + +For objects, the ``$array`` parameter comes pre-populated with PHP's native ``(array)`` casting operator, +or with the return value of ``$object->__debugInfo()`` if the magic method exists. +Then, the return value of one Caster is given as argument to the next Caster in the chain. + +When casting with the ``(array)`` operator, PHP prefixes protected properties with a ``\0*\0`` +and private ones with the class owning the property: e.g. ``\0Foobar\0`` prefixes all private properties +of objects of type Foobar. Casters follow this convention and add two more prefixes: ``\0~\0`` is used for +virtual properties and ``\0+\0`` for dynamic ones (runtime added properties not in the class declaration). + +.. note:: + + Although you can, it is best advised not to alter the state of an object while casting it in a Caster. + +Dumpers +~~~~~~~ + +.. _Packagist: https://packagist.org/packages/symfony/var-dumper From 4e2142d44e5a35feee34333cd9bb7e233fc5bbf4 Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Fri, 5 Sep 2014 14:02:00 -0400 Subject: [PATCH 0400/1181] Added note about ProgressBar changes --- components/console/helpers/progressbar.rst | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/components/console/helpers/progressbar.rst b/components/console/helpers/progressbar.rst index 46e993c08c0..eb13c69b587 100644 --- a/components/console/helpers/progressbar.rst +++ b/components/console/helpers/progressbar.rst @@ -46,8 +46,16 @@ you can also set the current progress by calling the .. caution:: - The progress bar only works if your platform supports ANSI codes; on other - platforms, no output is generated. + Prior to version 2.6, the progress bar only works if your platform + supports ANSI codes; on other platforms, no output is generated. + +.. versionadded:: 2.6 + If your platform doesn't support ANSI codes, updates to the progress + bar are added as new lines. To prevent the output from being flooded, + adjust the + :method:`Symfony\\Component\\Console\\Helper\\ProgressBar::setRedrawFrequency` + accordingly. By default, when using a ``max``, the redraw frequency + is set to *10%* of your ``max``. If you don't know the number of steps in advance, just omit the steps argument when creating the :class:`Symfony\\Component\\Console\\Helper\\ProgressBar` From 63d8657a1b6a456bfe69c6f3de99813c151acab2 Mon Sep 17 00:00:00 2001 From: Stefano Sala Date: Mon, 7 Jul 2014 14:47:02 +0200 Subject: [PATCH 0401/1181] [Twig][Form] Moved twig.form.resources to a higher level --- cookbook/form/form_customization.rst | 28 +++++++++------------------ reference/configuration/twig.rst | 29 +++++++++++++++------------- 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/cookbook/form/form_customization.rst b/cookbook/form/form_customization.rst index fb36e4fc01f..358fab95a31 100644 --- a/cookbook/form/form_customization.rst +++ b/cookbook/form/form_customization.rst @@ -439,18 +439,15 @@ form is rendered. # app/config/config.yml twig: - form: - resources: - - 'AcmeDemoBundle:Form:fields.html.twig' + form_themes: + - 'AcmeDemoBundle:Form:fields.html.twig' # ... .. code-block:: xml - - AcmeDemoBundle:Form:fields.html.twig - + AcmeDemoBundle:Form:fields.html.twig @@ -458,10 +455,8 @@ form is rendered. // app/config/config.php $container->loadFromExtension('twig', array( - 'form' => array( - 'resources' => array( - 'AcmeDemoBundle:Form:fields.html.twig', - ), + 'form_themes' => array( + 'AcmeDemoBundle:Form:fields.html.twig', ), // ... @@ -477,17 +472,14 @@ resource to use such a layout: # app/config/config.yml twig: - form: - resources: ['form_table_layout.html.twig'] + form_themes: ['form_table_layout.html.twig'] # ... .. code-block:: xml - - form_table_layout.html.twig - + form_table_layout.html.twig @@ -495,10 +487,8 @@ resource to use such a layout: // app/config/config.php $container->loadFromExtension('twig', array( - 'form' => array( - 'resources' => array( - 'form_table_layout.html.twig', - ), + 'form_themes' => array( + 'form_table_layout.html.twig', ), // ... diff --git a/reference/configuration/twig.rst b/reference/configuration/twig.rst index cdb3de3bd00..cd121710277 100644 --- a/reference/configuration/twig.rst +++ b/reference/configuration/twig.rst @@ -10,14 +10,13 @@ TwigBundle Configuration ("twig") twig: exception_controller: twig.controller.exception:showAction - form: - resources: + form_themes: - # Default: - - form_div_layout.html.twig + # Default: + - form_div_layout.html.twig - # Example: - - MyBundle::form.html.twig + # Example: + - MyBundle::form.html.twig globals: # Examples: @@ -54,9 +53,8 @@ TwigBundle Configuration ("twig") http://symfony.com/schema/dic/twig http://symfony.com/schema/dic/doctrine/twig-1.0.xsd"> - - MyBundle::form.html.twig - + form_div_layout.html.twig + MyBundle::form.html.twig 3.14 @@ -65,10 +63,9 @@ TwigBundle Configuration ("twig") .. code-block:: php $container->loadFromExtension('twig', array( - 'form' => array( - 'resources' => array( - 'MyBundle::form.html.twig', - ) + 'form_themes' => array( + 'form_div_layout.html.twig', // Default + 'MyBundle::form.html.twig', ), 'globals' => array( 'foo' => '@bar', @@ -83,6 +80,12 @@ TwigBundle Configuration ("twig") 'strict_variables' => false, )); +.. caution:: + + The ``twig.form`` (```` tag for xml) configuration key + has been deprecated and will be removed in 3.0. Instead, use the ``twig.form_themes`` + option. + Configuration ------------- From e6aa73314d5e092bedd2d4b468c3e278d4feabcd Mon Sep 17 00:00:00 2001 From: Maxime Douailin Date: Wed, 24 Sep 2014 16:58:43 +0200 Subject: [PATCH 0402/1181] swapped comment and opening in xml configuration example --- cookbook/security/pre_authenticated.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook/security/pre_authenticated.rst b/cookbook/security/pre_authenticated.rst index 394ae4f739e..63405fb7f53 100644 --- a/cookbook/security/pre_authenticated.rst +++ b/cookbook/security/pre_authenticated.rst @@ -34,8 +34,8 @@ Enable the x509 authentication for a particular firewall in the security configu .. code-block:: xml - + @@ -107,8 +107,8 @@ corresponding firewall in your security configuration: .. code-block:: xml - + From 695cb2056e966d48e71108b41ba3999a2fa91dc8 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 24 Sep 2014 11:00:32 -0500 Subject: [PATCH 0403/1181] [#4003] A few more form_themes config changes --- book/forms.rst | 15 +++++---------- cookbook/form/create_custom_field_type.rst | 15 +++++---------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/book/forms.rst b/book/forms.rst index b6f4ddbfd4d..b66dab4a1de 100644 --- a/book/forms.rst +++ b/book/forms.rst @@ -1578,9 +1578,8 @@ file: # app/config/config.yml twig: - form: - resources: - - 'AcmeTaskBundle:Form:fields.html.twig' + form_themes: + - 'AcmeTaskBundle:Form:fields.html.twig' # ... .. code-block:: xml @@ -1594,9 +1593,7 @@ file: http://symfony.com/schema/dic/twig http://symfony.com/schema/dic/twig/twig-1.0.xsd"> - - AcmeTaskBundle:Form:fields.html.twig - + AcmeTaskBundle:Form:fields.html.twig @@ -1605,10 +1602,8 @@ file: // app/config/config.php $container->loadFromExtension('twig', array( - 'form' => array( - 'resources' => array( - 'AcmeTaskBundle:Form:fields.html.twig', - ), + 'form_themes' => array( + 'AcmeTaskBundle:Form:fields.html.twig', ), // ... )); diff --git a/cookbook/form/create_custom_field_type.rst b/cookbook/form/create_custom_field_type.rst index 3cb5f33c265..aa5420d32a6 100644 --- a/cookbook/form/create_custom_field_type.rst +++ b/cookbook/form/create_custom_field_type.rst @@ -159,27 +159,22 @@ link for details), create a ``gender_widget`` block to handle this: # app/config/config.yml twig: - form: - resources: - - 'AcmeDemoBundle:Form:fields.html.twig' + form_themes: + - 'AcmeDemoBundle:Form:fields.html.twig' .. code-block:: xml - - AcmeDemoBundle:Form:fields.html.twig - + AcmeDemoBundle:Form:fields.html.twig .. code-block:: php // app/config/config.php $container->loadFromExtension('twig', array( - 'form' => array( - 'resources' => array( - 'AcmeDemoBundle:Form:fields.html.twig', - ), + 'form_themes' => array( + 'AcmeDemoBundle:Form:fields.html.twig', ), )); From 881f8d883178065905d5ef7bde94a7bdda25f45a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 26 Sep 2014 15:10:20 +0200 Subject: [PATCH 0404/1181] added Nicolas to the list of mergers for the new var dumper component --- contributing/code/core_team.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contributing/code/core_team.rst b/contributing/code/core_team.rst index 03f866f2e3e..5ec7ac23fd6 100644 --- a/contributing/code/core_team.rst +++ b/contributing/code/core_team.rst @@ -51,8 +51,8 @@ Active Core Members * **Romain Neutron** (:merger:`romainneutron`) can merge into the Process_ component; - * **Nicolas Grekas** (:merger:`nicolas-grekas`) can merge into the Debug_ - component; + * **Nicolas Grekas** (:merger:`nicolas-grekas`) can merge into the Debug_ and + VarDumper_ components, and into the DebugBundle_ bundle; * **Christophe Coevoet** (:merger:`stof`) can merge into the BrowserKit_, Config_, Console_, DependencyInjection_, DomCrawler_, EventDispatcher_, @@ -164,3 +164,5 @@ discretion of the **Project Leader**. .. _Stopwatch: https://github.com/symfony/Stopwatch .. _TwigBridge: https://github.com/symfony/TwigBridge .. _Validator: https://github.com/symfony/Validator +.. _VarDumper: https://github.com/symfony/var-dumper +.. _DebugBundle: https://github.com/symfony/debug-bundle From 2a14bf30e2ff9847eb46d1db711528345f743c0d Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Fri, 26 Sep 2014 14:26:53 -0500 Subject: [PATCH 0405/1181] Clarifying some language --- contributing/code/core_team.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contributing/code/core_team.rst b/contributing/code/core_team.rst index 5ec7ac23fd6..32390121dc3 100644 --- a/contributing/code/core_team.rst +++ b/contributing/code/core_team.rst @@ -51,8 +51,8 @@ Active Core Members * **Romain Neutron** (:merger:`romainneutron`) can merge into the Process_ component; - * **Nicolas Grekas** (:merger:`nicolas-grekas`) can merge into the Debug_ and - VarDumper_ components, and into the DebugBundle_ bundle; + * **Nicolas Grekas** (:merger:`nicolas-grekas`) can merge into the Debug_ + component, the VarDumper_ component and the DebugBundle_; * **Christophe Coevoet** (:merger:`stof`) can merge into the BrowserKit_, Config_, Console_, DependencyInjection_, DomCrawler_, EventDispatcher_, From f641e69bc34c9b6bac85165f15346d016774cd1c Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sun, 28 Sep 2014 14:25:45 +0200 Subject: [PATCH 0406/1181] Created August CHANGELOG --- changelog.rst | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/changelog.rst b/changelog.rst index 04cc5e66038..1ff28341e50 100644 --- a/changelog.rst +++ b/changelog.rst @@ -13,6 +13,84 @@ documentation. Do you also want to participate in the Symfony Documentation? Take a look at the ":doc:`/contributing/documentation/overview`" article. +August, 2014 +------------ + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `bccb080 `_ #4140 [Cookbook][Logging] document multiple recipients in XML configs (xabbuh) +- `7a6e3d1 `_ #4150 Added the schema_filter option to the reference (peterrehm) +- `be90d8a `_ #4142 [Cookbook][Configuration] tweaks for the web server configuration chapter (xabbuh) +- `5379f54 `_ #4086 [Reference][Constraints] Added hint about attaching the expression constraint to a form field (peterrehm) +- `041105c `_ #3883 Removed redundant POST request exclusion info (ryancastle) +- `4f9fef6 `_ #4000 [Cookbook] add cookbook article for the server:run command (xabbuh) +- `4ea4dfe `_ #3915 [Cookbook][Configuration] documentation of Apache + PHP-FPM (xabbuh) +- `08bed5f `_ #4128 Finished #3759 (WouterJ) +- `4d5adaa `_ #4125 Added link to JSFiddle example (WouterJ) +- `75bda4b `_ #4124 Rebased #3965 (WouterJ) +- `fdb8a32 `_ #3950 [Components][EventDispatcher] describe the usage of the RegisterListenersPass (xabbuh) +- `7e09383 `_ #3940 Updated docs for Monolog "swift" handler in cookbook. (phansys) +- `8adfe98 `_ #3894 Rewrote Extension & Configuration docs (WouterJ) +- `cafea43 `_ #3888 Updated the example used to explain page creation (javiereguiluz) +- `df0cf68 `_ #3885 [RFR] Added "How to Organize Configuration Files" cookbook (javiereguiluz) +- `41116da `_ #4081 [Components][ClassLoader] documentation for the ClassMapGenerator class (xabbuh) +- `2b9cb7c `_ #4076 Fixed description of session storage of the ApiKeyAuthenticator (peterrehm) +- `35a0f66 `_ #4102 Adding a new entry about reverse proxies in the framework (weaverryan) +- `95c2066 `_ #4096 labels in submit buttons + new screenshot (ricardclau) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `5fac303 `_ #4165 Update voters.rst (gerryvdm) +- `4882b99 `_ #4164 Fixed minor typos. (ahsio) +- `eaaa35a `_ #4145 Fix documentation for group_sequence_provider (giosh94mhz) +- `155c3e8 `_ #4153 [Reference] fix namespace in Expression constraint (xabbuh) +- `2c93aa5 `_ #4147 [Cookbook][Logging] add missing Monolog handler type in XML config (xabbuh) +- `53b2c2b `_ #4139 cleaned up the code example (gondo) +- `b5c9f2a `_ #4138 fixed wrongly linked dependency (gondo) +- `b486b22 `_ #4131 Replaced old way of specifying http method by the new one (Baptouuuu) +- `93481d7 `_ #4120 Fix use mistakes (mbutkereit) +- `c0a0120 `_ #4119 Fix class name in ConsoleTerminateListener example (alOneh) +- `4629d8b `_ #4116 Fixed the code snippets for the expression language functions (stof) +- `d699255 `_ #4083 [Reference] field dependent empty_data option description (xabbuh) +- `3ffc20f `_ #4103 [Cookbook][Forms] fix PHP template file name (xabbuh) +- `234fa36 `_ #4095 Fix php template (piotrantosik) +- `01fb9f2 `_ #4093 See #4091 (dannykopping) +- `7d39b03 `_ #4079 Fixed typo in filesystem component (kohkimakimoto) +- `f0bde03 `_ #4075 Fixed typo in the yml validation (timothymctim) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `e9d317a `_ #4160 [Reference] consistent & complete config examples (xabbuh) +- `3e68ee7 `_ #4152 Adding 'attr' option to the Textarea options list (ronanguilloux) +- `c4eb628 `_ #4130 A set of small typos (Baptouuuu) +- `236d8e0 `_ #4137 fixed directive syntax (WouterJ) +- `6e90520 `_ #4135 [#3940] Adding php example for an array of emails (weaverryan) +- `b37ee61 `_ #4132 Use proper way to reference a doc page for legacy sessions (Baptouuuu) +- `189a123 `_ #4129 [Components] consistent & complete config examples (xabbuh) +- `46f3108 `_ #4126 Rebased #3848 (WouterJ) +- `84e6e7f `_ #4114 [Book] consistent and complete config examples (xabbuh) +- `03fcab1 `_ #4112 [Contributing][Documentation] add order of translation formats (xabbuh) +- `650120a `_ #4002 added Github teams for the core team (fabpot) +- `10792c3 `_ #3959 [book][cache][tip] added cache annotations. (aitboudad) +- `ebaed21 `_ #3944 Update dbal.rst (bpiepiora) +- `16e346a `_ #3890 [Components][HttpFoundation] use a placeholder for the constructor arguments (xabbuh) +- `7bb4f34 `_ #4115 [Documentation] [Minor] Changes foobar.net in example.com (magnetik) +- `12d0b82 `_ #4113 tweaks to the new reverse proxy/load balancer chapter (xabbuh) +- `4cce133 `_ #4057 Update introduction.rst (carltondickson) +- `26141d6 `_ #4080 [Reference] order form type options alphabetically (xabbuh) +- `7806aa7 `_ #4117 Added a note about the automatic handling of the memory spool in the CLI (stof) +- `5959b6c `_ #4101 [Contributing] extended Symfony 2.4 maintenance (xabbuh) +- `e2056ad `_ #4072 [Contributing][Code] add note on Symfony SE forks for bug reports (xabbuh) +- `665c091 `_ #4087 Typo (tvlooy) +- `f95bbf3 `_ #4023 [Cookbook][Security] usage of a non-default entity manager in an entity user provider (xabbuh) +- `27b1003 `_ #4074 Fixed (again) a typo: Toolbet --> Toolbelt (javiereguiluz) +- `c97418f `_ #4073 Reworded bundle requirement (WouterJ) +- `e5d5eb8 `_ #4066 Update inherit_data_option.rst (Oylex) +- `9c08572 `_ #4064 Fixed typo on tag service (saro0h) + July, 2014 ---------- From 9dd3a772c5dead301838e397f50b8f65c4392d3f Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sun, 28 Sep 2014 14:26:10 +0200 Subject: [PATCH 0407/1181] Created August CHANGELOG --- changelog.rst | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/changelog.rst b/changelog.rst index 62cb6670efe..1fa891aeb67 100644 --- a/changelog.rst +++ b/changelog.rst @@ -13,6 +13,86 @@ documentation. Do you also want to participate in the Symfony Documentation? Take a look at the ":doc:`/contributing/documentation/overview`" article. +August, 2014 +------------ + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `bccb080 `_ #4140 [Cookbook][Logging] document multiple recipients in XML configs (xabbuh) +- `7a6e3d1 `_ #4150 Added the schema_filter option to the reference (peterrehm) +- `be90d8a `_ #4142 [Cookbook][Configuration] tweaks for the web server configuration chapter (xabbuh) +- `5379f54 `_ #4086 [Reference][Constraints] Added hint about attaching the expression constraint to a form field (peterrehm) +- `041105c `_ #3883 Removed redundant POST request exclusion info (ryancastle) +- `4f9fef6 `_ #4000 [Cookbook] add cookbook article for the server:run command (xabbuh) +- `4ea4dfe `_ #3915 [Cookbook][Configuration] documentation of Apache + PHP-FPM (xabbuh) +- `08bed5f `_ #4128 Finished #3759 (WouterJ) +- `4d5adaa `_ #4125 Added link to JSFiddle example (WouterJ) +- `75bda4b `_ #4124 Rebased #3965 (WouterJ) +- `fdb8a32 `_ #3950 [Components][EventDispatcher] describe the usage of the RegisterListenersPass (xabbuh) +- `7e09383 `_ #3940 Updated docs for Monolog "swift" handler in cookbook. (phansys) +- `8adfe98 `_ #3894 Rewrote Extension & Configuration docs (WouterJ) +- `cafea43 `_ #3888 Updated the example used to explain page creation (javiereguiluz) +- `df0cf68 `_ #3885 [RFR] Added "How to Organize Configuration Files" cookbook (javiereguiluz) +- `41116da `_ #4081 [Components][ClassLoader] documentation for the ClassMapGenerator class (xabbuh) +- `2b9cb7c `_ #4076 Fixed description of session storage of the ApiKeyAuthenticator (peterrehm) +- `35a0f66 `_ #4102 Adding a new entry about reverse proxies in the framework (weaverryan) +- `95c2066 `_ #4096 labels in submit buttons + new screenshot (ricardclau) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `5fac303 `_ #4165 Update voters.rst (gerryvdm) +- `4882b99 `_ #4164 Fixed minor typos. (ahsio) +- `eaaa35a `_ #4145 Fix documentation for group_sequence_provider (giosh94mhz) +- `155c3e8 `_ #4153 [Reference] fix namespace in Expression constraint (xabbuh) +- `2c93aa5 `_ #4147 [Cookbook][Logging] add missing Monolog handler type in XML config (xabbuh) +- `53b2c2b `_ #4139 cleaned up the code example (gondo) +- `b5c9f2a `_ #4138 fixed wrongly linked dependency (gondo) +- `b486b22 `_ #4131 Replaced old way of specifying http method by the new one (Baptouuuu) +- `93481d7 `_ #4120 Fix use mistakes (mbutkereit) +- `c0a0120 `_ #4119 Fix class name in ConsoleTerminateListener example (alOneh) +- `4629d8b `_ #4116 Fixed the code snippets for the expression language functions (stof) +- `d699255 `_ #4083 [Reference] field dependent empty_data option description (xabbuh) +- `3ffc20f `_ #4103 [Cookbook][Forms] fix PHP template file name (xabbuh) +- `234fa36 `_ #4095 Fix php template (piotrantosik) +- `01fb9f2 `_ #4093 See #4091 (dannykopping) +- `7d39b03 `_ #4079 Fixed typo in filesystem component (kohkimakimoto) +- `f0bde03 `_ #4075 Fixed typo in the yml validation (timothymctim) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `e9d317a `_ #4160 [Reference] consistent & complete config examples (xabbuh) +- `3e68ee7 `_ #4152 Adding 'attr' option to the Textarea options list (ronanguilloux) +- `c4eb628 `_ #4130 A set of small typos (Baptouuuu) +- `236d8e0 `_ #4137 fixed directive syntax (WouterJ) +- `6e90520 `_ #4135 [#3940] Adding php example for an array of emails (weaverryan) +- `b37ee61 `_ #4132 Use proper way to reference a doc page for legacy sessions (Baptouuuu) +- `189a123 `_ #4129 [Components] consistent & complete config examples (xabbuh) +- `5ab5246 `_ #4127 Second part of #3848 (WouterJ) +- `46f3108 `_ #4126 Rebased #3848 (WouterJ) +- `84e6e7f `_ #4114 [Book] consistent and complete config examples (xabbuh) +- `03fcab1 `_ #4112 [Contributing][Documentation] add order of translation formats (xabbuh) +- `650120a `_ #4002 added Github teams for the core team (fabpot) +- `10792c3 `_ #3959 [book][cache][tip] added cache annotations. (aitboudad) +- `ebaed21 `_ #3944 Update dbal.rst (bpiepiora) +- `16e346a `_ #3890 [Components][HttpFoundation] use a placeholder for the constructor arguments (xabbuh) +- `7bb4f34 `_ #4115 [Documentation] [Minor] Changes foobar.net in example.com (magnetik) +- `12d0b82 `_ #4113 tweaks to the new reverse proxy/load balancer chapter (xabbuh) +- `4cce133 `_ #4057 Update introduction.rst (carltondickson) +- `26141d6 `_ #4080 [Reference] order form type options alphabetically (xabbuh) +- `7806aa7 `_ #4117 Added a note about the automatic handling of the memory spool in the CLI (stof) +- `5959b6c `_ #4101 [Contributing] extended Symfony 2.4 maintenance (xabbuh) +- `e2056ad `_ #4072 [Contributing][Code] add note on Symfony SE forks for bug reports (xabbuh) +- `b8687dd `_ #4091 Put version into quotes, otherwise it fails in ZSH (dannykopping) +- `665c091 `_ #4087 Typo (tvlooy) +- `f95bbf3 `_ #4023 [Cookbook][Security] usage of a non-default entity manager in an entity user provider (xabbuh) +- `27b1003 `_ #4074 Fixed (again) a typo: Toolbet --> Toolbelt (javiereguiluz) +- `c97418f `_ #4073 Reworded bundle requirement (WouterJ) +- `e5d5eb8 `_ #4066 Update inherit_data_option.rst (Oylex) +- `9c08572 `_ #4064 Fixed typo on tag service (saro0h) + July, 2014 ---------- From f4d308a28450cdbebca0873fd4050ec275b5882a Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sun, 28 Sep 2014 14:26:41 +0200 Subject: [PATCH 0408/1181] Created August CHANGELOG --- changelog.rst | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/changelog.rst b/changelog.rst index 057384a6dfe..a9996af5728 100644 --- a/changelog.rst +++ b/changelog.rst @@ -13,6 +13,92 @@ documentation. Do you also want to participate in the Symfony Documentation? Take a look at the ":doc:`/contributing/documentation/overview`" article. +August, 2014 +------------ + +New Documentation +~~~~~~~~~~~~~~~~~ + +- `bccb080 `_ #4140 [Cookbook][Logging] document multiple recipients in XML configs (xabbuh) +- `7a6e3d1 `_ #4150 Added the schema_filter option to the reference (peterrehm) +- `be90d8a `_ #4142 [Cookbook][Configuration] tweaks for the web server configuration chapter (xabbuh) +- `5379f54 `_ #4086 [Reference][Constraints] Added hint about attaching the expression constraint to a form field (peterrehm) +- `041105c `_ #3883 Removed redundant POST request exclusion info (ryancastle) +- `4f9fef6 `_ #4000 [Cookbook] add cookbook article for the server:run command (xabbuh) +- `4ea4dfe `_ #3915 [Cookbook][Configuration] documentation of Apache + PHP-FPM (xabbuh) +- `79cb4f1 `_ #4069 document the namespace alias (dbu) +- `08bed5f `_ #4128 Finished #3759 (WouterJ) +- `4d5adaa `_ #4125 Added link to JSFiddle example (WouterJ) +- `75bda4b `_ #4124 Rebased #3965 (WouterJ) +- `e2f13a4 `_ #4039 [DomCrawler] Added node name getter (fejese) +- `3f92d5f `_ #3966 [Cookbook][Controller] Add note about invokable controller services (kbond) +- `fdb8a32 `_ #3950 [Components][EventDispatcher] describe the usage of the RegisterListenersPass (xabbuh) +- `7e09383 `_ #3940 Updated docs for Monolog "swift" handler in cookbook. (phansys) +- `9d7c999 `_ #3895 [Validator] Support "maxSize" given in KiB (jeremy-derusse) +- `8adfe98 `_ #3894 Rewrote Extension & Configuration docs (WouterJ) +- `cafea43 `_ #3888 Updated the example used to explain page creation (javiereguiluz) +- `df0cf68 `_ #3885 [RFR] Added "How to Organize Configuration Files" cookbook (javiereguiluz) +- `41116da `_ #4081 [Components][ClassLoader] documentation for the ClassMapGenerator class (xabbuh) +- `2b9cb7c `_ #4076 Fixed description of session storage of the ApiKeyAuthenticator (peterrehm) +- `35a0f66 `_ #4102 Adding a new entry about reverse proxies in the framework (weaverryan) +- `95c2066 `_ #4096 labels in submit buttons + new screenshot (ricardclau) + +Fixed Documentation +~~~~~~~~~~~~~~~~~~~ + +- `5fac303 `_ #4165 Update voters.rst (gerryvdm) +- `4882b99 `_ #4164 Fixed minor typos. (ahsio) +- `eaaa35a `_ #4145 Fix documentation for group_sequence_provider (giosh94mhz) +- `155c3e8 `_ #4153 [Reference] fix namespace in Expression constraint (xabbuh) +- `2c93aa5 `_ #4147 [Cookbook][Logging] add missing Monolog handler type in XML config (xabbuh) +- `53b2c2b `_ #4139 cleaned up the code example (gondo) +- `b5c9f2a `_ #4138 fixed wrongly linked dependency (gondo) +- `b486b22 `_ #4131 Replaced old way of specifying http method by the new one (Baptouuuu) +- `93481d7 `_ #4120 Fix use mistakes (mbutkereit) +- `c0a0120 `_ #4119 Fix class name in ConsoleTerminateListener example (alOneh) +- `4629d8b `_ #4116 Fixed the code snippets for the expression language functions (stof) +- `d699255 `_ #4083 [Reference] field dependent empty_data option description (xabbuh) +- `3ffc20f `_ #4103 [Cookbook][Forms] fix PHP template file name (xabbuh) +- `234fa36 `_ #4095 Fix php template (piotrantosik) +- `01fb9f2 `_ #4093 See #4091 (dannykopping) +- `8f3a261 `_ #4092 See #4091 (dannykopping) +- `7d39b03 `_ #4079 Fixed typo in filesystem component (kohkimakimoto) +- `f0bde03 `_ #4075 Fixed typo in the yml validation (timothymctim) + +Minor Documentation Changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `e9d317a `_ #4160 [Reference] consistent & complete config examples (xabbuh) +- `3e68ee7 `_ #4152 Adding 'attr' option to the Textarea options list (ronanguilloux) +- `a7f3297 `_ #4136 [Reference] fix from suffix to prefix (xabbuh) +- `c4eb628 `_ #4130 A set of small typos (Baptouuuu) +- `236d8e0 `_ #4137 fixed directive syntax (WouterJ) +- `6e90520 `_ #4135 [#3940] Adding php example for an array of emails (weaverryan) +- `b37ee61 `_ #4132 Use proper way to reference a doc page for legacy sessions (Baptouuuu) +- `189a123 `_ #4129 [Components] consistent & complete config examples (xabbuh) +- `5ab5246 `_ #4127 Second part of #3848 (WouterJ) +- `46f3108 `_ #4126 Rebased #3848 (WouterJ) +- `84e6e7f `_ #4114 [Book] consistent and complete config examples (xabbuh) +- `03fcab1 `_ #4112 [Contributing][Documentation] add order of translation formats (xabbuh) +- `650120a `_ #4002 added Github teams for the core team (fabpot) +- `10792c3 `_ #3959 [book][cache][tip] added cache annotations. (aitboudad) +- `ebaed21 `_ #3944 Update dbal.rst (bpiepiora) +- `16e346a `_ #3890 [Components][HttpFoundation] use a placeholder for the constructor arguments (xabbuh) +- `7bb4f34 `_ #4115 [Documentation] [Minor] Changes foobar.net in example.com (magnetik) +- `12d0b82 `_ #4113 tweaks to the new reverse proxy/load balancer chapter (xabbuh) +- `4cce133 `_ #4057 Update introduction.rst (carltondickson) +- `26141d6 `_ #4080 [Reference] order form type options alphabetically (xabbuh) +- `7806aa7 `_ #4117 Added a note about the automatic handling of the memory spool in the CLI (stof) +- `5959b6c `_ #4101 [Contributing] extended Symfony 2.4 maintenance (xabbuh) +- `e2056ad `_ #4072 [Contributing][Code] add note on Symfony SE forks for bug reports (xabbuh) +- `b8687dd `_ #4091 Put version into quotes, otherwise it fails in ZSH (dannykopping) +- `665c091 `_ #4087 Typo (tvlooy) +- `f95bbf3 `_ #4023 [Cookbook][Security] usage of a non-default entity manager in an entity user provider (xabbuh) +- `27b1003 `_ #4074 Fixed (again) a typo: Toolbet --> Toolbelt (javiereguiluz) +- `c97418f `_ #4073 Reworded bundle requirement (WouterJ) +- `e5d5eb8 `_ #4066 Update inherit_data_option.rst (Oylex) +- `9c08572 `_ #4064 Fixed typo on tag service (saro0h) + July, 2014 ---------- From 5e0b9bdc34ee60d1bb00e20d6949c03e38564371 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 30 Sep 2014 09:14:20 +0200 Subject: [PATCH 0409/1181] review effect --- components/var_dumper.rst | 76 ++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/components/var_dumper.rst b/components/var_dumper.rst index 01d8f237673..bcc1d66f139 100644 --- a/components/var_dumper.rst +++ b/components/var_dumper.rst @@ -6,18 +6,8 @@ The VarDumper Component ======================= The VarDumper component provides mechanisms for walking through any arbitrary PHP variable. - Built on top, it provides a better ``dump()`` function, that you can use instead of ``var_dump()``, - *better* meaning: + Built on top, it provides a better ``dump()`` function that you can use instead of :phpfunction:`var_dump`. - - per object and resource types specialized view to e.g. filter out Doctrine noise - while dumping a single proxy entity, or get more insight on opened files with - ``stream_get_meta_data()``. - - configurable output format: HTML, command line with colors or JSON. - - ability to dump internal references, either soft ones (objects or resources) - or hard ones (``=&`` on arrays or objects properties). Repeated occurrences of - the same object/array/resource won't appear again and again anymore. Moreover, - you'll be able to inspected the reference structure of your data. - - ability to operate in the context of an output buffering handler. .. versionadded:: 2.6 The VarDumper component was introduced in Symfony 2.6. @@ -33,21 +23,34 @@ You can install the component in 2 different ways: The dump() function ------------------- -The VarDumper component creates a global ``dump()`` function that is auto-configured out of the box: +The VarDumper component creates a global ``dump()`` function that is configured out of the box: HTML or CLI output is automatically selected based on the current PHP SAPI. -``dump()`` is just a thin wrapper for ``\Symfony\Component\VarDumper\VarDumper::dump()`` so can you also use it directly. -You can change the behavior of this function by calling ``\Symfony\Component\VarDumper\VarDumper::setHandler($callable)``: -calls to ``dump()`` will then be forwarded to the ``$callable`` given as first argument. +The advantages of this function are: -Advanced usage + - per object and resource types specialized view to e.g. filter out Doctrine internals + while dumping a single proxy entity, or get more insight on opened files with + :phpfunction:`stream_get_meta_data()`. + - configurable output formats: HTML or colored command line output. + - ability to dump internal references, either soft ones (objects or resources) + or hard ones (``=&`` on arrays or objects properties). Repeated occurrences of + the same object/array/resource won't appear again and again anymore. Moreover, + you'll be able to inspect the reference structure of your data. + - ability to operate in the context of an output buffering handler. + +``dump()`` is just a thin wrapper for :method:`VarDumper::dump() ` +so can you also use it directly. You can change the behavior of this function by calling +:method:`VarDumper::setHandler($callable) `: +calls to ``dump()`` will then be forwarded to ``$callable``, given as first argument. + +Advanced Usage -------------- Cloners ~~~~~~~ A cloner is used to create an intermediate representation of any PHP variable. -Its output is a Data object that wraps this representation. +Its output is a :class:`Data ` object that wraps this representation. A cloner also applies limits when creating the representation, so that the corresponding Data object could represent only a subset of the cloned variable. @@ -61,26 +64,27 @@ Before cloning, you can configure the limits with:: $cloner->setMaxItems($number); $cloner->setMaxString($number); -These limits will be applied when calling ``->cloneVar()`` afterwise. +They will be applied when calling ``->cloneVar()`` afterwards. Casters ~~~~~~~ Objects and resources nested in a PHP variable are casted to arrays in the intermediate Data representation. You can tweak the array representation for each object/resource by hooking a Caster into this process. -The component already has a many casters for base PHP classes and other common classes. +The component already includes many casters for base PHP classes and other common classes. -If you want to build your how Caster, you can register one before cloning a PHP variable. +If you want to build your own Caster, you can register one before cloning a PHP variable. Casters are registered using either a Cloner's constructor or its ``addCasters()`` method:: $myCasters = array(...); $cloner = new PhpCloner($myCasters); -or:: + // or $cloner->addCasters($myCasters); -The provided ``$myCasters`` argument is an array that maps a class, an interface or a resource type to a callable:: +The provided ``$myCasters`` argument is an array that maps a class, +an interface or a resource type to a callable:: $myCasters = array( 'FooClass' => $myFooClassCallableCaster, @@ -96,26 +100,24 @@ Several casters can also be registered for the same resource type/class/interfac They are called in registration order. Casters are responsible for returning the properties of the object or resource being cloned in an array. -They are callables that accept four arguments:: - - /** - * A caster not doing anything. - * - * @param object|resource $object The object or resource being casted. - * @param array $array An array modelled for objects after PHP's native `(array)` cast operator. - * @param Stub $stub A Cloner\Stub object representing the main properties of $object (class, type, etc.). - * @param bool $isNested True/false when the caster is called nested is a structure or not. - * - * @return array The properties of $object casted in an array. - */ - function myCaster($origValue, $array, $stub, $isNested) +They are callables that accept four arguments: + + - the object or resource being casted, + - an array modelled for objects after PHP's native ``(array)`` cast operator, + - a :class:`Stub ` object representing + the main properties of the object (class, type, etc.), + - true/false when the caster is called nested is a structure or not. + +Here is a simple caster not doing anything:: + + function myCaster($object, $array, $stub, $isNested) { - // Here, populate/alter $array to your needs. + // ... populate/alter $array to your needs return $array; } -For objects, the ``$array`` parameter comes pre-populated with PHP's native ``(array)`` casting operator, +For objects, the ``$array`` parameter comes pre-populated with PHP's native ``(array)`` casting operator or with the return value of ``$object->__debugInfo()`` if the magic method exists. Then, the return value of one Caster is given as argument to the next Caster in the chain. From 7dc6e5cc24c522cab26cdcf38d954c26cc7a5c54 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 30 Sep 2014 12:05:55 +0200 Subject: [PATCH 0410/1181] Reduce line length --- components/var_dumper.rst | 90 ++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/components/var_dumper.rst b/components/var_dumper.rst index bcc1d66f139..db025c7cbfa 100644 --- a/components/var_dumper.rst +++ b/components/var_dumper.rst @@ -5,9 +5,9 @@ The VarDumper Component ======================= - The VarDumper component provides mechanisms for walking through any arbitrary PHP variable. - Built on top, it provides a better ``dump()`` function that you can use instead of :phpfunction:`var_dump`. - + The VarDumper component provides mechanisms for walking through any + arbitrary PHP variable. Built on top, it provides a better ``dump()`` + function that you can use instead of :phpfunction:`var_dump`. .. versionadded:: 2.6 The VarDumper component was introduced in Symfony 2.6. @@ -23,23 +23,26 @@ You can install the component in 2 different ways: The dump() function ------------------- -The VarDumper component creates a global ``dump()`` function that is configured out of the box: -HTML or CLI output is automatically selected based on the current PHP SAPI. +The VarDumper component creates a global ``dump()`` function that is +configured out of the box: HTML or CLI output is automatically selected based +on the current PHP SAPI. The advantages of this function are: - - per object and resource types specialized view to e.g. filter out Doctrine internals - while dumping a single proxy entity, or get more insight on opened files with - :phpfunction:`stream_get_meta_data()`. + - per object and resource types specialized view to e.g. filter out + Doctrine internals while dumping a single proxy entity, or get more + insight on opened files with :phpfunction:`stream_get_meta_data()`. - configurable output formats: HTML or colored command line output. - - ability to dump internal references, either soft ones (objects or resources) - or hard ones (``=&`` on arrays or objects properties). Repeated occurrences of - the same object/array/resource won't appear again and again anymore. Moreover, - you'll be able to inspect the reference structure of your data. + - ability to dump internal references, either soft ones (objects or + resources) or hard ones (``=&`` on arrays or objects properties). + Repeated occurrences of the same object/array/resource won't appear + again and again anymore. Moreover, you'll be able to inspect the + reference structure of your data. - ability to operate in the context of an output buffering handler. -``dump()`` is just a thin wrapper for :method:`VarDumper::dump() ` -so can you also use it directly. You can change the behavior of this function by calling +``dump()`` is just a thin wrapper for :method:`VarDumper::dump() +` so can you also use it directly. +You can change the behavior of this function by calling :method:`VarDumper::setHandler($callable) `: calls to ``dump()`` will then be forwarded to ``$callable``, given as first argument. @@ -50,9 +53,10 @@ Cloners ~~~~~~~ A cloner is used to create an intermediate representation of any PHP variable. -Its output is a :class:`Data ` object that wraps this representation. -A cloner also applies limits when creating the representation, so that the corresponding -Data object could represent only a subset of the cloned variable. +Its output is a :class:`Data ` +object that wraps this representation. A cloner also applies limits when +creating the representation, so that the corresponding Data object could +represent only a subset of the cloned variable. You can create a Data object this way:: @@ -69,12 +73,14 @@ They will be applied when calling ``->cloneVar()`` afterwards. Casters ~~~~~~~ -Objects and resources nested in a PHP variable are casted to arrays in the intermediate Data representation. -You can tweak the array representation for each object/resource by hooking a Caster into this process. -The component already includes many casters for base PHP classes and other common classes. +Objects and resources nested in a PHP variable are casted to arrays in the +intermediate Data representation. You can tweak the array representation for +each object/resource by hooking a Caster into this process. The component +already includes many casters for base PHP classes and other common classes. -If you want to build your own Caster, you can register one before cloning a PHP variable. -Casters are registered using either a Cloner's constructor or its ``addCasters()`` method:: +If you want to build your own Caster, you can register one before cloning +a PHP variable. Casters are registered using either a Cloner's constructor +or its ``addCasters()`` method:: $myCasters = array(...); $cloner = new PhpCloner($myCasters); @@ -91,21 +97,23 @@ an interface or a resource type to a callable:: ':bar resource' => $myBarResourceCallableCaster, ); -As you can notice, resource types are prefixed by a ``:`` to prevent colliding with a class name. +As you can notice, resource types are prefixed by a ``:`` to prevent +colliding with a class name. -Because an object has one main class and potentially many parent classes or interfaces, -many casters can be applied to one object. In this case, casters are called one after the other, -starting from casters bound to the interfaces, the parents classes and then the main class. -Several casters can also be registered for the same resource type/class/interface. +Because an object has one main class and potentially many parent classes +or interfaces, many casters can be applied to one object. In this case, +casters are called one after the other, starting from casters bound to the +interfaces, the parents classes and then the main class. Several casters +can also be registered for the same resource type/class/interface. They are called in registration order. -Casters are responsible for returning the properties of the object or resource being cloned in an array. -They are callables that accept four arguments: +Casters are responsible for returning the properties of the object orresource +being cloned in an array. They are callables that accept four arguments: - the object or resource being casted, - an array modelled for objects after PHP's native ``(array)`` cast operator, - - a :class:`Stub ` object representing - the main properties of the object (class, type, etc.), + - a :class:`Stub ` object + representing the main properties of the object (class, type, etc.), - true/false when the caster is called nested is a structure or not. Here is a simple caster not doing anything:: @@ -117,18 +125,22 @@ Here is a simple caster not doing anything:: return $array; } -For objects, the ``$array`` parameter comes pre-populated with PHP's native ``(array)`` casting operator -or with the return value of ``$object->__debugInfo()`` if the magic method exists. -Then, the return value of one Caster is given as argument to the next Caster in the chain. +For objects, the ``$array`` parameter comes pre-populated with PHP's native +``(array)`` casting operator or with the return value of ``$object->__debugInfo()`` +if the magic method exists. Then, the return value of one Caster is given +as argument to the next Caster in the chain. -When casting with the ``(array)`` operator, PHP prefixes protected properties with a ``\0*\0`` -and private ones with the class owning the property: e.g. ``\0Foobar\0`` prefixes all private properties -of objects of type Foobar. Casters follow this convention and add two more prefixes: ``\0~\0`` is used for -virtual properties and ``\0+\0`` for dynamic ones (runtime added properties not in the class declaration). +When casting with the ``(array)`` operator, PHP prefixes protected properties +with a ``\0*\0`` and private ones with the class owning the property: +e.g. ``\0Foobar\0`` prefixes all private properties of objects of type Foobar. +Casters follow this convention and add two more prefixes: ``\0~\0`` is used +for virtual properties and ``\0+\0`` for dynamic ones (runtime added +properties not in the class declaration). .. note:: - Although you can, it is best advised not to alter the state of an object while casting it in a Caster. + Although you can, it is best advised not to alter the state of an object + while casting it in a Caster. Dumpers ~~~~~~~ From ac4d9cd3ed24bd209a56555a42d44c00cb04d5a9 Mon Sep 17 00:00:00 2001 From: Claudio Galdiolo Date: Mon, 29 Sep 2014 00:37:43 -0400 Subject: [PATCH 0411/1181] Double-quotes instead of single quotes (UnexpectedValueException in Windows 8) --- cookbook/workflow/new_project_git.rst | 2 +- quick_tour/the_big_picture.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook/workflow/new_project_git.rst b/cookbook/workflow/new_project_git.rst index c40cba6d53f..7551e87622d 100644 --- a/cookbook/workflow/new_project_git.rst +++ b/cookbook/workflow/new_project_git.rst @@ -26,7 +26,7 @@ git repository: .. code-block:: bash - $ php composer.phar create-project symfony/framework-standard-edition path/ '~2.3' + $ php composer.phar create-project symfony/framework-standard-edition path/ "~2.3" Composer will now download the Standard Distribution along with all of the required vendor libraries. For more information about downloading Symfony using diff --git a/quick_tour/the_big_picture.rst b/quick_tour/the_big_picture.rst index 7d4fd3f4406..7d6728775fa 100644 --- a/quick_tour/the_big_picture.rst +++ b/quick_tour/the_big_picture.rst @@ -20,7 +20,7 @@ directory: .. code-block:: bash - $ composer create-project symfony/framework-standard-edition myproject/ '~2.3' + $ composer create-project symfony/framework-standard-edition myproject/ "~2.3" .. note:: From e5d432c28c5c68f60dab5d28e1f2e68d26b560e8 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 1 Oct 2014 09:37:30 -0400 Subject: [PATCH 0412/1181] [#4047] Re-adding the versionadded for the info() method --- components/config/definition.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/config/definition.rst b/components/config/definition.rst index 3b703559f1d..f0f45f4e585 100644 --- a/components/config/definition.rst +++ b/components/config/definition.rst @@ -290,6 +290,10 @@ method. The info will be printed as a comment when dumping the configuration tree. +.. versionadded:: 2.6 + Since Symfony 2.6, the info will also be added to the exception message + when an invalid type is given. + Optional Sections ----------------- From ad6a340e8e8eacce9fe2f18769b5100299b93d3c Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 5 Sep 2014 12:05:09 +0200 Subject: [PATCH 0413/1181] [Components][Process] `mustRun()` documentation --- components/process.rst | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/components/process.rst b/components/process.rst index a2d8dc67e4d..ef77f6078da 100644 --- a/components/process.rst +++ b/components/process.rst @@ -31,7 +31,7 @@ a command in a sub-process:: throw new \RuntimeException($process->getErrorOutput()); } - print $process->getOutput(); + echo $process->getOutput(); The component takes care of the subtle differences between the different platforms when executing the command. @@ -50,6 +50,27 @@ the contents of the output and :method:`Symfony\\Component\\Process\\Process::clearErrorOutput` clears the contents of the error output. +.. versionadded:: 2.5 + The ``mustRun()`` method was introduced in Symfony 2.5. + +The ``mustRun()`` method is identical to ``run()``, except that it will throw +a :class:`Symfony\\Component\\Process\\Exception\\ProcessFailedException` +if the process couldn't be executed successfully (i.e. the process exited +with a non-zero code):: + + use Symfony\Component\Process\Exception\ProcessFailedException; + use Symfony\Component\Process\Process; + + $process = new Process('ls -lsa'); + + try { + $process->mustRun(); + + echo $process->getOutput(); + } catch (ProcessFailedException $e) { + echo $e->getMessage(); + } + Getting real-time Process Output -------------------------------- @@ -218,17 +239,17 @@ Process Idle Timeout .. versionadded:: 2.4 The :method:`Symfony\\Component\\Process\\Process::setIdleTimeout` method was introduced in Symfony 2.4. - + In contrast to the timeout of the previous paragraph, the idle timeout only considers the time since the last output was produced by the process:: use Symfony\Component\Process\Process; - + $process = new Process('something-with-variable-runtime'); $process->setTimeout(3600); $process->setIdleTimeout(60); $process->run(); - + In the case above, a process is considered timed out, when either the total runtime exceeds 3600 seconds, or the process does not produce any output for 60 seconds. From 042dcf9c67396224ffa400f9264500428ab819d8 Mon Sep 17 00:00:00 2001 From: Nicolas Assing Date: Fri, 25 Jul 2014 10:10:57 +0200 Subject: [PATCH 0414/1181] Replace addViolationAt (deprecated) by buildViolation --- reference/constraints/Callback.rst | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/reference/constraints/Callback.rst b/reference/constraints/Callback.rst index 36b55e97910..43a29e4eb3e 100644 --- a/reference/constraints/Callback.rst +++ b/reference/constraints/Callback.rst @@ -114,12 +114,10 @@ those errors should be attributed:: // check if the name is actually a fake name if (in_array($this->getFirstName(), $fakeNames)) { - $context->addViolationAt( - 'firstName', - 'This name sounds totally fake!', - array(), - null - ); + $context->buildViolation('This name sounds totally fake!') + ->atPath('firstName') + ->addViolation() + ; } } } @@ -137,12 +135,10 @@ have access to the object instance, they receive the object as the first argumen // check if the name is actually a fake name if (in_array($object->getFirstName(), $fakeNames)) { - $context->addViolationAt( - 'firstName', - 'This name sounds totally fake!', - array(), - null - ); + $context->buildViolation('This name sounds totally fake!') + ->atPath('firstName') + ->addViolation() + ; } } From f4380ed2a973a7e198949e9400057ff994f53323 Mon Sep 17 00:00:00 2001 From: lashae Date: Fri, 22 Aug 2014 11:25:07 +0300 Subject: [PATCH 0415/1181] Update Callback.rst "Symfony\Component\Validator\ExecutionContextInterface" namespace is deprecated, new namespace should be "Symfony\Component\Validator\Context\ExecutionContextInterface" --- reference/constraints/Callback.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/reference/constraints/Callback.rst b/reference/constraints/Callback.rst index 43a29e4eb3e..1947a37089a 100644 --- a/reference/constraints/Callback.rst +++ b/reference/constraints/Callback.rst @@ -50,7 +50,7 @@ Configuration namespace Acme\BlogBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; - use Symfony\Component\Validator\ExecutionContextInterface; + use Symfony\Component\Validator\Context\ExecutionContextInterface; class Author { @@ -100,7 +100,7 @@ can set "violations" directly on this object and determine to which field those errors should be attributed:: // ... - use Symfony\Component\Validator\ExecutionContextInterface; + use Symfony\Component\Validator\Context\ExecutionContextInterface; class Author { @@ -152,7 +152,7 @@ your validation function is ``Vendor\Package\Validator::validate()``:: namespace Vendor\Package; - use Symfony\Component\Validator\ExecutionContextInterface; + use Symfony\Component\Validator\Context\ExecutionContextInterface; class Validator { @@ -270,7 +270,7 @@ callback method: * A closure. -Concrete callbacks receive an :class:`Symfony\\Component\\Validator\\ExecutionContextInterface` +Concrete callbacks receive an :class:`Symfony\\Component\\Validator\\Context\\ExecutionContextInterface` instance as only argument. Static or closure callbacks receive the validated object as the first argument From 5dfe499c0dbeaf9673551e75b3ff1eedb1542722 Mon Sep 17 00:00:00 2001 From: Rootie Date: Fri, 8 Aug 2014 07:54:47 +0200 Subject: [PATCH 0416/1181] Don't use deprecated functions in Callback.rst The addViolationAt function is marked as deprecated and should be replaced by buildViolation according to the Symfony update guides. --- reference/constraints/Callback.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/reference/constraints/Callback.rst b/reference/constraints/Callback.rst index 1947a37089a..7e41e4bda9c 100644 --- a/reference/constraints/Callback.rst +++ b/reference/constraints/Callback.rst @@ -116,8 +116,7 @@ those errors should be attributed:: if (in_array($this->getFirstName(), $fakeNames)) { $context->buildViolation('This name sounds totally fake!') ->atPath('firstName') - ->addViolation() - ; + ->addViolation(); } } } From 70c5ca12afb5e5acc0c611c5e6bd65216479b144 Mon Sep 17 00:00:00 2001 From: Rootie Date: Sat, 9 Aug 2014 00:02:22 +0200 Subject: [PATCH 0417/1181] Update custom_contraint.rst to meet the new 2.5 api --- cookbook/validation/custom_constraint.rst | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/cookbook/validation/custom_constraint.rst b/cookbook/validation/custom_constraint.rst index 5cfd2312759..bf4ecc2a410 100644 --- a/cookbook/validation/custom_constraint.rst +++ b/cookbook/validation/custom_constraint.rst @@ -65,9 +65,9 @@ The validator class is also simple, and only has one required method ``validate( public function validate($value, Constraint $constraint) { if (!preg_match('/^[a-zA-Za0-9]+$/', $value, $matches)) { - $this->context->addViolation( - $constraint->message, - array('%string%' => $value) + $this->context->buildViolation($constraint->message) + ->setParameter('%string%', $value) + ->addViolation(); ); } } @@ -76,11 +76,17 @@ The validator class is also simple, and only has one required method ``validate( .. note:: The ``validate`` method does not return a value; instead, it adds violations - to the validator's ``context`` property with an ``addViolation`` method - call if there are validation failures. Therefore, a value could be considered - as being valid if it causes no violations to be added to the context. - The first parameter of the ``addViolation`` call is the error message to - use for that violation. + to the validator's ``context`` property. Therefore, a value could be considered + as being valid if it causes no violations to be added to the context.The + violation is constructed and added to the context using a + ``ConstraintViolationBuilder`` returned by the ``buildViolation`` method + call. The parameter given to the ``buildViolation`` call is the error message + to use for that violation. The ``addViolation`` method call finally adds the + violation to the context. + +.. versionadded:: 2.5 + The ``buildViolation`` method was added in Symfony 2.5. For usage examples with + older Symfony versions, see the corresponding versions of this documentation page. Using the new Validator ----------------------- From e658b568ceb667aeb762f0e73fbeeafc4fa7c70e Mon Sep 17 00:00:00 2001 From: Rootie Date: Sat, 9 Aug 2014 00:05:33 +0200 Subject: [PATCH 0418/1181] added a versionadded comment to Callback.rst --- reference/constraints/Callback.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/reference/constraints/Callback.rst b/reference/constraints/Callback.rst index 7e41e4bda9c..a046095831a 100644 --- a/reference/constraints/Callback.rst +++ b/reference/constraints/Callback.rst @@ -121,6 +121,10 @@ those errors should be attributed:: } } +.. versionadded:: 2.5 + The ``buildViolation`` method was added in Symfony 2.5. For usage examples with + older Symfony versions, see the corresponding versions of this documentation page. + Static Callbacks ---------------- From 280440ea734e77cfe7ccfc1b100ad81940cd402c Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 15 Sep 2014 20:36:35 -0400 Subject: [PATCH 0419/1181] Adding details about the 2.4 API as comments --- cookbook/validation/custom_constraint.rst | 30 ++++++++++++++--------- reference/constraints/Callback.rst | 27 ++++++++++++++++++-- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/cookbook/validation/custom_constraint.rst b/cookbook/validation/custom_constraint.rst index bf4ecc2a410..fe46e79d01d 100644 --- a/cookbook/validation/custom_constraint.rst +++ b/cookbook/validation/custom_constraint.rst @@ -65,28 +65,34 @@ The validator class is also simple, and only has one required method ``validate( public function validate($value, Constraint $constraint) { if (!preg_match('/^[a-zA-Za0-9]+$/', $value, $matches)) { + // If you're using the new 2.5 validation API (you probably are!) $this->context->buildViolation($constraint->message) ->setParameter('%string%', $value) ->addViolation(); ); + + // If you're using the old 2.4 validation API + /* + $this->context->addViolation( + $constraint->message, + array('%string%' => $value) + ); + */ } } } -.. note:: - - The ``validate`` method does not return a value; instead, it adds violations - to the validator's ``context`` property. Therefore, a value could be considered - as being valid if it causes no violations to be added to the context.The - violation is constructed and added to the context using a - ``ConstraintViolationBuilder`` returned by the ``buildViolation`` method - call. The parameter given to the ``buildViolation`` call is the error message - to use for that violation. The ``addViolation`` method call finally adds the - violation to the context. +Inside ``validate``, you don't need to return a value. Instead, you add violations +to the validator's ``context`` property and a value will be considered valid +if it causes no violations. The ``buildViolation`` takes the error message +as its argument and returns an instance of +:class:`Symfony\\Component\\Validator\\Violation\\ConstraintViolationBuilder` +The ``addViolation`` method call finally adds the violation to the context. .. versionadded:: 2.5 - The ``buildViolation`` method was added in Symfony 2.5. For usage examples with - older Symfony versions, see the corresponding versions of this documentation page. + The ``buildViolation`` method was added in Symfony 2.5. For usage examples + with older Symfony versions, see the corresponding versions of this documentation + page. Using the new Validator ----------------------- diff --git a/reference/constraints/Callback.rst b/reference/constraints/Callback.rst index a046095831a..e0a21e4b2e0 100644 --- a/reference/constraints/Callback.rst +++ b/reference/constraints/Callback.rst @@ -51,6 +51,8 @@ Configuration use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Context\ExecutionContextInterface; + // if you're using the older 2.4 validation API, you'll need this instead + // use Symfony\Component\Validator\ExecutionContextInterface; class Author { @@ -101,6 +103,8 @@ those errors should be attributed:: // ... use Symfony\Component\Validator\Context\ExecutionContextInterface; + // if you're using the older 2.4 validation API, you'll need this instead + // use Symfony\Component\Validator\ExecutionContextInterface; class Author { @@ -114,16 +118,26 @@ those errors should be attributed:: // check if the name is actually a fake name if (in_array($this->getFirstName(), $fakeNames)) { + // If you're using the new 2.5 validation API (you probably are!) $context->buildViolation('This name sounds totally fake!') ->atPath('firstName') ->addViolation(); + + // If you're using the old 2.4 validation API + /* + $context->addViolationAt( + 'firstName', + 'This name sounds totally fake!' + ); + */ } } } .. versionadded:: 2.5 - The ``buildViolation`` method was added in Symfony 2.5. For usage examples with - older Symfony versions, see the corresponding versions of this documentation page. + The ``buildViolation`` method was added in Symfony 2.5. For usage examples + with older Symfony versions, see the corresponding versions of this documentation + page. Static Callbacks ---------------- @@ -138,10 +152,17 @@ have access to the object instance, they receive the object as the first argumen // check if the name is actually a fake name if (in_array($object->getFirstName(), $fakeNames)) { + // If you're using the new 2.5 validation API (you probably are!) $context->buildViolation('This name sounds totally fake!') ->atPath('firstName') ->addViolation() ; + + // If you're using the old 2.4 validation API + $context->addViolationAt( + 'firstName', + 'This name sounds totally fake!' + ); } } @@ -156,6 +177,8 @@ your validation function is ``Vendor\Package\Validator::validate()``:: namespace Vendor\Package; use Symfony\Component\Validator\Context\ExecutionContextInterface; + // if you're using the older 2.4 validation API, you'll need this instead + // use Symfony\Component\Validator\ExecutionContextInterface; class Validator { From 279d8d6bcf1a971e64a8af0d5021b7dba881cf37 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 18 Sep 2014 10:19:26 -0400 Subject: [PATCH 0420/1181] Adding a section about keeping BC in a re-usable bundle --- cookbook/bundles/best_practices.rst | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/cookbook/bundles/best_practices.rst b/cookbook/bundles/best_practices.rst index d9c5fa88801..54e719db215 100644 --- a/cookbook/bundles/best_practices.rst +++ b/cookbook/bundles/best_practices.rst @@ -328,6 +328,43 @@ semantic configuration described in the cookbook. If you are defining services, they should also be prefixed with the bundle alias. +Custom Validation Constraints +----------------------------- + +Starting with Symfony 2.5, a new Validation API was introduced. In fact, +there are 3 modes, which the user can configure in their project: + +* 2.4: the original 2.4 and earlier validation API; +* 2.5: the new 2.5 and later validation API; +* 2.5-BC: the new 2.5 API with a backwards-compatible layer so that the + 2.4 API still works. This is only available in PHP 5.3.9+. + +As a bundle author, you'll want to support *both* API's, since some users +may still be using the 2.4 API. Specifically, if your bundle adds a violation +directly to the :class:`Symfony\Component\Validator\Context\ExecutionContext` +(e.g. like in a custom validation constraint), you'll need to check for which +API is being used. The following code, would work for *all* users:: + + class ContainsAlphanumericValidator extends ConstraintValidator + { + public function validate($value, Constraint $constraint) + { + if ($this->context instanceof ExecutionContextInterface) { + // the 2.5 API + $this->context->buildViolation($constraint->message) + ->setParameter('%string%', $value) + ->addViolation(); + ); + } else { + // the 2.4 API + $this->context->addViolation( + $constraint->message, + array('%string%' => $value) + ); + } + } + } + Learn more from the Cookbook ---------------------------- From f97ba7ae29933e4487cbeeabb3143c1e4e6fc528 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 18 Sep 2014 10:19:44 -0400 Subject: [PATCH 0421/1181] Fixes thanks to @xabbuh --- cookbook/validation/custom_constraint.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cookbook/validation/custom_constraint.rst b/cookbook/validation/custom_constraint.rst index fe46e79d01d..caf582a4eee 100644 --- a/cookbook/validation/custom_constraint.rst +++ b/cookbook/validation/custom_constraint.rst @@ -84,9 +84,9 @@ The validator class is also simple, and only has one required method ``validate( Inside ``validate``, you don't need to return a value. Instead, you add violations to the validator's ``context`` property and a value will be considered valid -if it causes no violations. The ``buildViolation`` takes the error message -as its argument and returns an instance of -:class:`Symfony\\Component\\Validator\\Violation\\ConstraintViolationBuilder` +if it causes no violations. The ``buildViolation`` method takes the error +message as its argument and returns an instance of +:class:`Symfony\\Component\\Validator\\Violation\\ConstraintViolationBuilderInterface`. The ``addViolation`` method call finally adds the violation to the context. .. versionadded:: 2.5 From 94fc520c79839c9dfa3b06abcd8f5bf703ace561 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 2 Oct 2014 08:48:38 -0400 Subject: [PATCH 0422/1181] Minor tweaks and a missing location thanks to xabbuh and WouterJ --- cookbook/bundles/best_practices.rst | 7 ++++++- cookbook/form/unit_testing.rst | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cookbook/bundles/best_practices.rst b/cookbook/bundles/best_practices.rst index 54e719db215..bc97194336d 100644 --- a/cookbook/bundles/best_practices.rst +++ b/cookbook/bundles/best_practices.rst @@ -341,10 +341,15 @@ there are 3 modes, which the user can configure in their project: As a bundle author, you'll want to support *both* API's, since some users may still be using the 2.4 API. Specifically, if your bundle adds a violation -directly to the :class:`Symfony\Component\Validator\Context\ExecutionContext` +directly to the :class:`Symfony\\Component\\Validator\\Context\\ExecutionContext` (e.g. like in a custom validation constraint), you'll need to check for which API is being used. The following code, would work for *all* users:: + use Symfony\Component\Validator\ConstraintValidator; + use Symfony\Component\Validator\Constraint; + use Symfony\Component\Validator\Context\ExecutionContextInterface; + // ... + class ContainsAlphanumericValidator extends ConstraintValidator { public function validate($value, Constraint $constraint) diff --git a/cookbook/form/unit_testing.rst b/cookbook/form/unit_testing.rst index 944ed25b372..a6d2cd458ce 100644 --- a/cookbook/form/unit_testing.rst +++ b/cookbook/form/unit_testing.rst @@ -185,7 +185,7 @@ on other extensions. You need add those extensions to the factory object:: { parent::setUp(); - $validator = $this->getMock('\Symfony\Component\Validator\ValidatorInterface'); + $validator = $this->getMock('\Symfony\Component\Validator\Validator\ValidatorInterface'); $validator->method('validate')->will($this->returnValue(new ConstraintViolationList())); $this->factory = Forms::createFormFactoryBuilder() From 9874d8e5d533cf40bd2e182fa53ee4271e641f18 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 2 Oct 2014 08:53:32 -0400 Subject: [PATCH 0423/1181] [#4233][#4094] Making validateValue and validate changes --- book/validation.rst | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/book/validation.rst b/book/validation.rst index 4ccb264fe8a..73415ee8d97 100644 --- a/book/validation.rst +++ b/book/validation.rst @@ -822,9 +822,13 @@ With this configuration, there are three validation groups: fields only. To tell the validator to use a specific group, pass one or more group names -as the second argument to the ``validate()`` method:: +as the third argument to the ``validate()`` method:: - $errors = $validator->validate($author, array('registration')); + // If you're using the new 2.5 validation API (you probably are!) + $errors = $validator->validate($author, null, array('registration')); + + // If you're using the old 2.4 validation API + // $errors = $validator->validate($author, array('registration')); If no groups are specified, all constraints that belong in group ``Default`` will be applied. @@ -1189,10 +1193,19 @@ it looks like this:: $emailConstraint->message = 'Invalid email address'; // use the validator to validate the value + // If you're using the new 2.5 validation API (you probably are!) + $errorList = $this->get('validator')->validate( + $email, + $emailConstraint + ); + + // If you're using the old 2.4 validation API + /* $errorList = $this->get('validator')->validateValue( $email, $emailConstraint ); + */ if (count($errorList) == 0) { // this IS a valid email address, do something @@ -1206,13 +1219,13 @@ it looks like this:: // ... } -By calling ``validateValue`` on the validator, you can pass in a raw value and +By calling ``validate`` on the validator, you can pass in a raw value and the constraint object that you want to validate that value against. A full list of the available constraints - as well as the full class name for each constraint - is available in the :doc:`constraints reference ` section . -The ``validateValue`` method returns a :class:`Symfony\\Component\\Validator\\ConstraintViolationList` +The ``validate`` method returns a :class:`Symfony\\Component\\Validator\\ConstraintViolationList` object, which acts just like an array of errors. Each error in the collection is a :class:`Symfony\\Component\\Validator\\ConstraintViolation` object, which holds the error message on its ``getMessage`` method. From 036edcbcdcf9c6b48cc9c30dcff12377707874c6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 1 Oct 2014 09:48:39 +0200 Subject: [PATCH 0424/1181] doc for Dumpers --- components/var_dumper.rst | 111 ++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 27 deletions(-) diff --git a/components/var_dumper.rst b/components/var_dumper.rst index db025c7cbfa..b001162ed8a 100644 --- a/components/var_dumper.rst +++ b/components/var_dumper.rst @@ -17,8 +17,8 @@ Installation You can install the component in 2 different ways: -* :doc:`Install it via Composer ` (``symfony/var-dumper`` on `Packagist`_); -* Use the official Git repository (https://github.com/symfony/VarDumper). +- :doc:`Install it via Composer ` (``symfony/var-dumper`` on `Packagist`_); +- Use the official Git repository (https://github.com/symfony/var-dumper). The dump() function ------------------- @@ -29,19 +29,20 @@ on the current PHP SAPI. The advantages of this function are: - - per object and resource types specialized view to e.g. filter out - Doctrine internals while dumping a single proxy entity, or get more - insight on opened files with :phpfunction:`stream_get_meta_data()`. - - configurable output formats: HTML or colored command line output. - - ability to dump internal references, either soft ones (objects or - resources) or hard ones (``=&`` on arrays or objects properties). - Repeated occurrences of the same object/array/resource won't appear - again and again anymore. Moreover, you'll be able to inspect the - reference structure of your data. - - ability to operate in the context of an output buffering handler. - -``dump()`` is just a thin wrapper for :method:`VarDumper::dump() -` so can you also use it directly. +- per object and resource types specialized view to e.g. filter out + Doctrine internals while dumping a single proxy entity, or get more + insight on opened files with :phpfunction:`stream_get_meta_data()`. +- configurable output formats: HTML or colored command line output. +- ability to dump internal references, either soft ones (objects or + resources) or hard ones (``=&`` on arrays or objects properties). + Repeated occurrences of the same object/array/resource won't appear + again and again anymore. Moreover, you'll be able to inspect the + reference structure of your data. +- ability to operate in the context of an output buffering handler. + +``dump()`` is just a thin wrapper for +:method:`VarDumper::dump() ` +so can you also use it directly. You can change the behavior of this function by calling :method:`VarDumper::setHandler($callable) `: calls to ``dump()`` will then be forwarded to ``$callable``, given as first argument. @@ -53,12 +54,13 @@ Cloners ~~~~~~~ A cloner is used to create an intermediate representation of any PHP variable. -Its output is a :class:`Data ` +Its output is a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object that wraps this representation. A cloner also applies limits when creating the representation, so that the corresponding Data object could represent only a subset of the cloned variable. -You can create a Data object this way:: +You can create a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` +object this way:: $cloner = new PhpCloner(); $data = $cloner->cloneVar($myVar); @@ -74,9 +76,10 @@ Casters ~~~~~~~ Objects and resources nested in a PHP variable are casted to arrays in the -intermediate Data representation. You can tweak the array representation for -each object/resource by hooking a Caster into this process. The component -already includes many casters for base PHP classes and other common classes. +intermediate :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` +representation. You can tweak the array representation for each object/resource +by hooking a Caster into this process. The component already includes many +casters for base PHP classes and other common classes. If you want to build your own Caster, you can register one before cloning a PHP variable. Casters are registered using either a Cloner's constructor @@ -107,14 +110,14 @@ interfaces, the parents classes and then the main class. Several casters can also be registered for the same resource type/class/interface. They are called in registration order. -Casters are responsible for returning the properties of the object orresource +Casters are responsible for returning the properties of the object or resource being cloned in an array. They are callables that accept four arguments: - - the object or resource being casted, - - an array modelled for objects after PHP's native ``(array)`` cast operator, - - a :class:`Stub ` object - representing the main properties of the object (class, type, etc.), - - true/false when the caster is called nested is a structure or not. +- the object or resource being casted, +- an array modelled for objects after PHP's native ``(array)`` cast operator, +- a :class:`Symfony\\Component\\VarDumper\\Cloner\\Stub` object + representing the main properties of the object (class, type, etc.), +- true/false when the caster is called nested is a structure or not. Here is a simple caster not doing anything:: @@ -138,11 +141,65 @@ for virtual properties and ``\0+\0`` for dynamic ones (runtime added properties not in the class declaration). .. note:: - Although you can, it is best advised not to alter the state of an object while casting it in a Caster. Dumpers ~~~~~~~ +A dumper is responsible for outputting a string representation of a PHP variable, +using a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object as input. +The destination and the formatting of this output vary with dumpers. + +This component comes with an :class:`Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper` +for HTML output and a :class:`Symfony\\Component\\VarDumper\\Dumper\\CliDumper` +for optionally colored command line output. + +For example, if you want to dump some ``$variable``, just do:: + + $cloner = new PhpCloner(); + $dumper = new CliDumper(); + + $dumper->dump($cloner->cloneVar($variable)); + +By using the first argument of the constructor, you can select the output +stream where the dump will be written. By default, the ``CliDumper`` writes +on ``php://stdout`` and the ``HtmlDumper`` on ``php://output``, but any PHP +stream (resource or URL) is acceptable. + +Instead of a stream destination, you can also pass it a ``callable`` that +will be called repeatedly for each line generated by a dumper. This +callable can be configured using the first argument of a dumper's constructor, +but also using the +:method:`Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper::setLineDumper` +method or using the second argument of the +:method:`Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper::dump` method. + +For example, to get a dump in a variable, you can do:: + + $cloner = new PhpCloner(); + $dumper = new CliDumper(); + $output = ''; + + $dumper->dump( + $cloner->cloneVar($variable), + function ($line, $depth) use (&$output) { + // A negative depth means "end of dump" + if ($depth >= 0) { + // Adds a two spaces indentation to the line + $output .= str_repeat(' ', $depth).$line."\n"; + } + } + ); + + // $output is now populated with the dump representation of $variable + +Dumpers implement the :class:`Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface` +interface that specifies the +:method:`dump(Data $data) ` +method. They also typically implement the +:class:`Symfony\\Component\\VarDumper\\Cloner\\DumperInterface` that frees +them from re-implementing the logic required to walk through a +:class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object's internal structure. + .. _Packagist: https://packagist.org/packages/symfony/var-dumper From 350e0c7871bf05796954295757b981297676a4e1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 3 Oct 2014 09:30:07 +0200 Subject: [PATCH 0425/1181] split intro/advanced sections --- components/index.rst | 2 +- components/map.rst.inc | 5 +- .../advanced.rst} | 51 +------------------ components/var_dumper/index.rst | 8 +++ components/var_dumper/introduction.rst | 50 ++++++++++++++++++ 5 files changed, 64 insertions(+), 52 deletions(-) rename components/{var_dumper.rst => var_dumper/advanced.rst} (75%) create mode 100644 components/var_dumper/index.rst create mode 100644 components/var_dumper/introduction.rst diff --git a/components/index.rst b/components/index.rst index be74544ce43..6386caab5df 100644 --- a/components/index.rst +++ b/components/index.rst @@ -29,7 +29,7 @@ The Components stopwatch templating/index translation/index - var_dumper + var_dumper/index yaml/index .. include:: /components/map.rst.inc diff --git a/components/map.rst.inc b/components/map.rst.inc index d3ce97a167f..93797c2e5d3 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -143,9 +143,10 @@ * :doc:`/components/translation/usage` * :doc:`/components/translation/custom_formats` -* **VarDumper** +* :doc:`/components/var_dumper/index` - * :doc:`/components/var_dumper` + * :doc:`/components/var_dumper/introduction` + * :doc:`/components/var_dumper/advanced` * :doc:`/components/yaml/index` diff --git a/components/var_dumper.rst b/components/var_dumper/advanced.rst similarity index 75% rename from components/var_dumper.rst rename to components/var_dumper/advanced.rst index b001162ed8a..ac384d8f181 100644 --- a/components/var_dumper.rst +++ b/components/var_dumper/advanced.rst @@ -2,53 +2,8 @@ single: VarDumper single: Components; VarDumper -The VarDumper Component -======================= - - The VarDumper component provides mechanisms for walking through any - arbitrary PHP variable. Built on top, it provides a better ``dump()`` - function that you can use instead of :phpfunction:`var_dump`. - -.. versionadded:: 2.6 - The VarDumper component was introduced in Symfony 2.6. - -Installation ------------- - -You can install the component in 2 different ways: - -- :doc:`Install it via Composer ` (``symfony/var-dumper`` on `Packagist`_); -- Use the official Git repository (https://github.com/symfony/var-dumper). - -The dump() function -------------------- - -The VarDumper component creates a global ``dump()`` function that is -configured out of the box: HTML or CLI output is automatically selected based -on the current PHP SAPI. - -The advantages of this function are: - -- per object and resource types specialized view to e.g. filter out - Doctrine internals while dumping a single proxy entity, or get more - insight on opened files with :phpfunction:`stream_get_meta_data()`. -- configurable output formats: HTML or colored command line output. -- ability to dump internal references, either soft ones (objects or - resources) or hard ones (``=&`` on arrays or objects properties). - Repeated occurrences of the same object/array/resource won't appear - again and again anymore. Moreover, you'll be able to inspect the - reference structure of your data. -- ability to operate in the context of an output buffering handler. - -``dump()`` is just a thin wrapper for -:method:`VarDumper::dump() ` -so can you also use it directly. -You can change the behavior of this function by calling -:method:`VarDumper::setHandler($callable) `: -calls to ``dump()`` will then be forwarded to ``$callable``, given as first argument. - -Advanced Usage --------------- +Advanced Usage of the VarDumper Component +========================================= Cloners ~~~~~~~ @@ -201,5 +156,3 @@ method. They also typically implement the :class:`Symfony\\Component\\VarDumper\\Cloner\\DumperInterface` that frees them from re-implementing the logic required to walk through a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object's internal structure. - -.. _Packagist: https://packagist.org/packages/symfony/var-dumper diff --git a/components/var_dumper/index.rst b/components/var_dumper/index.rst new file mode 100644 index 00000000000..2c67f2aa53f --- /dev/null +++ b/components/var_dumper/index.rst @@ -0,0 +1,8 @@ +VarDumper +========= + +.. toctree:: + :maxdepth: 2 + + introduction + advanced diff --git a/components/var_dumper/introduction.rst b/components/var_dumper/introduction.rst new file mode 100644 index 00000000000..1b4669cc83c --- /dev/null +++ b/components/var_dumper/introduction.rst @@ -0,0 +1,50 @@ +.. index:: + single: VarDumper + single: Components; VarDumper + +The VarDumper Component +======================= + + The VarDumper component provides mechanisms for walking through any + arbitrary PHP variable. Built on top, it provides a better ``dump()`` + function that you can use instead of :phpfunction:`var_dump`. + +.. versionadded:: 2.6 + The VarDumper component was introduced in Symfony 2.6. + +Installation +------------ + +You can install the component in 2 different ways: + +- :doc:`Install it via Composer ` (``symfony/var-dumper`` on `Packagist`_); +- Use the official Git repository (https://github.com/symfony/var-dumper). + +The dump() function +------------------- + +The VarDumper component creates a global ``dump()`` function that is +configured out of the box: HTML or CLI output is automatically selected based +on the current PHP SAPI. + +The advantages of this function are: + +- per object and resource types specialized view to e.g. filter out + Doctrine internals while dumping a single proxy entity, or get more + insight on opened files with :phpfunction:`stream_get_meta_data()`. +- configurable output formats: HTML or colored command line output. +- ability to dump internal references, either soft ones (objects or + resources) or hard ones (``=&`` on arrays or objects properties). + Repeated occurrences of the same object/array/resource won't appear + again and again anymore. Moreover, you'll be able to inspect the + reference structure of your data. +- ability to operate in the context of an output buffering handler. + +``dump()`` is just a thin wrapper for +:method:`VarDumper::dump() ` +so can you also use it directly. +You can change the behavior of this function by calling +:method:`VarDumper::setHandler($callable) `: +calls to ``dump()`` will then be forwarded to ``$callable``, given as first argument. + +.. _Packagist: https://packagist.org/packages/symfony/var-dumper From 97a62902d93f55b75283c8bf19e11ca961a0431e Mon Sep 17 00:00:00 2001 From: Cyril Mouttet Date: Thu, 2 Oct 2014 14:16:03 +0200 Subject: [PATCH 0426/1181] Update security.rst --- book/security.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/security.rst b/book/security.rst index bd2d4f000a1..5996d8bdf56 100644 --- a/book/security.rst +++ b/book/security.rst @@ -938,7 +938,7 @@ will match any ``ip``, ``host`` or ``method``: ..................... Once Symfony has decided which ``access_control`` entry matches (if any), -it then *enforces* access restrictions based on the ``roles`` and ``requires_channel`` +it then *enforces* access restrictions based on the ``roles``, ``allow_if`` and ``requires_channel`` options: * ``role`` If the user does not have the given role(s), then access is denied From a535c9f7cc3dae9626fb633890662d9e78634284 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Fri, 3 Oct 2014 10:41:11 +0200 Subject: [PATCH 0427/1181] minor #4285 Update security.rst (placid2000) This PR was submitted for the 2.5 branch but it was merged into the 2.4 branch instead (closes #4285). Discussion ---------- Update security.rst Hotfix: allow_if option might been added afterwards and seems to miss in the description above the list Commits ------- 6a0551c Update security.rst From fb18056924f6462ec55bbb5dba6a98f8b021be51 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 5 Sep 2014 12:27:47 +0200 Subject: [PATCH 0428/1181] validate `null` (Expression constraint in 2.6) Since Symfony 2.6, the Expression constraint doesn't skip validating `null` values. --- reference/constraints/Expression.rst | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/reference/constraints/Expression.rst b/reference/constraints/Expression.rst index 68526372837..01eb69c3493 100644 --- a/reference/constraints/Expression.rst +++ b/reference/constraints/Expression.rst @@ -217,12 +217,11 @@ more about the expression language syntax, see // ... } - .. caution:: - - In Symfony 2.4 and Symfony 2.5, if the property (e.g. ``isTechnicalPost``) - were ``null``, the expression would never be called and the value - would be seen as valid. To ensure that the value is not ``null``, - use the :doc:`NotNull constraint `. + .. versionadded:: 2.6 + In Symfony 2.6, the Expression constraint *is* executed if the value + is ``null``. Before 2.6, if the value was ``null``, the expression + was never executed and the value was considered valid (unless you + also had a constraint like `NotBlank` on the property). For more information about the expression and what variables are available to you, see the :ref:`expression ` From f36c45e3a81fb9ec21b67474a66d9ed6709928ba Mon Sep 17 00:00:00 2001 From: Maxime Douailin Date: Tue, 7 Oct 2014 15:35:35 +0200 Subject: [PATCH 0429/1181] uppercase title --- cookbook/security/pre_authenticated.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/security/pre_authenticated.rst b/cookbook/security/pre_authenticated.rst index 63405fb7f53..7a0775a8ab8 100644 --- a/cookbook/security/pre_authenticated.rst +++ b/cookbook/security/pre_authenticated.rst @@ -80,7 +80,7 @@ in the x509 firewall configuration respectively. * :doc:`/cookbook/security/custom_provider` * :doc:`/cookbook/security/entity_provider` -REMOTE_USER based Authentication +REMOTE_USER Based Authentication -------------------------------- .. versionadded:: 2.6 From 2fc3811688f556946837df423a135c717fd267e2 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 7 Oct 2014 16:32:29 +0200 Subject: [PATCH 0430/1181] use VarCloner instead of Php/ExtCloner --- components/var_dumper/advanced.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/var_dumper/advanced.rst b/components/var_dumper/advanced.rst index ac384d8f181..d1c1609a229 100644 --- a/components/var_dumper/advanced.rst +++ b/components/var_dumper/advanced.rst @@ -17,7 +17,7 @@ represent only a subset of the cloned variable. You can create a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object this way:: - $cloner = new PhpCloner(); + $cloner = new VarCloner(); $data = $cloner->cloneVar($myVar); Before cloning, you can configure the limits with:: @@ -41,7 +41,7 @@ a PHP variable. Casters are registered using either a Cloner's constructor or its ``addCasters()`` method:: $myCasters = array(...); - $cloner = new PhpCloner($myCasters); + $cloner = new VarCloner($myCasters); // or @@ -112,7 +112,7 @@ for optionally colored command line output. For example, if you want to dump some ``$variable``, just do:: - $cloner = new PhpCloner(); + $cloner = new VarCloner(); $dumper = new CliDumper(); $dumper->dump($cloner->cloneVar($variable)); @@ -132,7 +132,7 @@ method or using the second argument of the For example, to get a dump in a variable, you can do:: - $cloner = new PhpCloner(); + $cloner = new VarCloner(); $dumper = new CliDumper(); $output = ''; From 8bb1c9a68204e362bb377e4e754b6ff305c0aec4 Mon Sep 17 00:00:00 2001 From: Evan Owens Date: Tue, 7 Oct 2014 16:34:04 -0400 Subject: [PATCH 0431/1181] Fix spelling "so-called" is a traditionally hyphenated compound word. --- cookbook/configuration/web_server_configuration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/configuration/web_server_configuration.rst b/cookbook/configuration/web_server_configuration.rst index e93e873307c..3e248ddf205 100644 --- a/cookbook/configuration/web_server_configuration.rst +++ b/cookbook/configuration/web_server_configuration.rst @@ -89,7 +89,7 @@ the FastCGI process manager ``php-fpm`` binary and Apache's FastCGI module installed (for example, on a Debian based system you have to install the ``libapache2-mod-fastcgi`` and ``php5-fpm`` packages). -PHP-FPM uses so called *pools* to handle incoming FastCGI requests. You can +PHP-FPM uses so-called *pools* to handle incoming FastCGI requests. You can configure an arbitrary number of pools in the FPM configuration. In a pool you configure either a TCP socket (IP and port) or a unix domain socket to listen on. Each pool can also be run under a different UID and GID: From 53638a698c03e7bed5d6d2f9120cb72dd4df5ba1 Mon Sep 17 00:00:00 2001 From: Andrew M Date: Sun, 12 Oct 2014 09:05:32 +0300 Subject: [PATCH 0432/1181] Remove horizontal scrollbar --- components/event_dispatcher/introduction.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/components/event_dispatcher/introduction.rst b/components/event_dispatcher/introduction.rst index 39e6c42b345..4775280a54f 100644 --- a/components/event_dispatcher/introduction.rst +++ b/components/event_dispatcher/introduction.rst @@ -509,8 +509,11 @@ Lazy loading listeners:: { private $started = false; - public function myLazyListener(Event $event, $eventName, EventDispatcherInterface $dispatcher) - { + public function myLazyListener( + Event $event, + $eventName, + EventDispatcherInterface $dispatcher + ) { if (false === $this->started) { $subscriber = new StoreSubscriber(); $dispatcher->addSubscriber($subscriber); @@ -529,8 +532,11 @@ Dispatching another event from within a listener:: class Foo { - public function myFooListener(Event $event, $eventName, EventDispatcherInterface $dispatcher) - { + public function myFooListener( + Event $event, + $eventName, + EventDispatcherInterface $dispatcher + ) { $dispatcher->dispatch('log', $event); // ... more code From a9d6a8b966ba6122d61e028a38d8a456c6e3b27c Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Thu, 3 Apr 2014 15:53:10 +0200 Subject: [PATCH 0433/1181] [Console] Add Process Helper documentation --- components/console/helpers/index.rst | 1 + components/console/helpers/map.rst.inc | 1 + components/console/helpers/processhelper.rst | 84 ++++++++++++++++++ .../console/process-helper-debug.png | Bin 0 -> 28822 bytes .../console/process-helper-error-debug.png | Bin 0 -> 19108 bytes .../console/process-helper-verbose.png | Bin 0 -> 14289 bytes 6 files changed, 86 insertions(+) create mode 100644 components/console/helpers/processhelper.rst create mode 100644 images/components/console/process-helper-debug.png create mode 100644 images/components/console/process-helper-error-debug.png create mode 100644 images/components/console/process-helper-verbose.png diff --git a/components/console/helpers/index.rst b/components/console/helpers/index.rst index d632eeeb66a..909671fb08c 100644 --- a/components/console/helpers/index.rst +++ b/components/console/helpers/index.rst @@ -9,6 +9,7 @@ The Console Helpers dialoghelper formatterhelper + processhelper progressbar progresshelper questionhelper diff --git a/components/console/helpers/map.rst.inc b/components/console/helpers/map.rst.inc index b9a1114cfc2..15e6e9f8da9 100644 --- a/components/console/helpers/map.rst.inc +++ b/components/console/helpers/map.rst.inc @@ -1,5 +1,6 @@ * :doc:`/components/console/helpers/dialoghelper` * :doc:`/components/console/helpers/formatterhelper` +* :doc:`/components/console/helpers/processhelper` * :doc:`/components/console/helpers/progressbar` * :doc:`/components/console/helpers/progresshelper` * :doc:`/components/console/helpers/questionhelper` diff --git a/components/console/helpers/processhelper.rst b/components/console/helpers/processhelper.rst new file mode 100644 index 00000000000..414724c7f87 --- /dev/null +++ b/components/console/helpers/processhelper.rst @@ -0,0 +1,84 @@ +.. index:: + single: Console Helpers; Process Helper + +Process Helper +============== + +.. versionadded:: 2.6 + The Process Helper was introduced in Symfony 2.6. + +The Process Helper shows processes as they're running and reports +useful information about process status. + +To display process details, use the :class:`Symfony\\Component\\Console\\Helper\\ProcessHelper` +and run your command with verbosity. For example, running the following code with +a very verbose verbosity (e.g. -vv):: + + use Symfony\Component\Process\ProcessBuilder; + + $helper = $this->getHelper('process'); + $process = ProcessBuilder::create(array('figlet', 'Symfony'))->getProcess(); + + $helper->run($output, $process); + +will result in this output: + +.. image:: /images/components/console/process-helper-verbose.png + +It will result in more detailed output with debug verbosity (e.g. ``-vvv``): + +.. image:: /images/components/console/process-helper-debug.png + +In case the process fails, debugging is easier: + +.. image:: /images/components/console/process-helper-error-debug.png + +Arguments +--------- + +There are three ways to use the process helper: + +* Either using a command line string:: + + // ... + $helper->run($output, 'figlet Symfony'); + +* An array of arguments:: + + // ... + $helper->run($output, array('figlet', 'Symfony')); + + .. note:: + + When running the helper against an array of arguments, be aware that + these ones will be automatically escaped. + +* Or a :class:`Symfony\\Component\\Process\\Process` instance:: + + use Symfony\Component\Process\ProcessBuilder; + + // ... + $process = ProcessBuilder::create(array('figlet', 'Symfony'))->getProcess(); + + $helper->run($output, $process); + +Customized Display +------------------ + +You can display a customized error message using the third argument of the +:method:`Symfony\\Component\\Console\\Helper\\ProcessHelper::run` method:: + + $helper->run($output, $process, 'The process failed :('); + +A custom process callback can be passed as fourth argument, refer to the +:doc:`Process Component ` for callback documentation:: + + use Symfony\Component\Process\Process; + + $helper->run($output, $process, 'The process failed :(', function ($type, $data) { + if (Process::ERR === $type) { + // ... do something with the stderr output + } else { + // ... do something with the stdout + } + }); diff --git a/images/components/console/process-helper-debug.png b/images/components/console/process-helper-debug.png new file mode 100644 index 0000000000000000000000000000000000000000..282e1336389762bb88f5fa6d61d4669066c483de GIT binary patch literal 28822 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 literal 0 HcmV?d00001 diff --git a/images/components/console/process-helper-error-debug.png b/images/components/console/process-helper-error-debug.png new file mode 100644 index 0000000000000000000000000000000000000000..8d1145478f2e3a0d6c0ee2074ea50883bd7c5107 GIT binary patch literal 19108 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 QS79}f`_V2ur+}ot0sK-87XSbN literal 0 HcmV?d00001 diff --git a/images/components/console/process-helper-verbose.png b/images/components/console/process-helper-verbose.png new file mode 100644 index 0000000000000000000000000000000000000000..c4c912e14331dc53482e25571d1f16ad4018765a GIT binary patch literal 14289 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 literal 0 HcmV?d00001 From 39b44300a30b34deb13a85776b276e19dac949a5 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Fri, 17 Oct 2014 16:12:33 -0400 Subject: [PATCH 0434/1181] Minor language tweaks --- components/console/helpers/processhelper.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/console/helpers/processhelper.rst b/components/console/helpers/processhelper.rst index 414724c7f87..5494ca0137f 100644 --- a/components/console/helpers/processhelper.rst +++ b/components/console/helpers/processhelper.rst @@ -38,7 +38,7 @@ Arguments There are three ways to use the process helper: -* Either using a command line string:: +* Using a command line string:: // ... $helper->run($output, 'figlet Symfony'); @@ -51,9 +51,9 @@ There are three ways to use the process helper: .. note:: When running the helper against an array of arguments, be aware that - these ones will be automatically escaped. + these will be automatically escaped. -* Or a :class:`Symfony\\Component\\Process\\Process` instance:: +* Passing a :class:`Symfony\\Component\\Process\\Process` instance:: use Symfony\Component\Process\ProcessBuilder; @@ -70,7 +70,7 @@ You can display a customized error message using the third argument of the $helper->run($output, $process, 'The process failed :('); -A custom process callback can be passed as fourth argument, refer to the +A custom process callback can be passed as the fourth argument. Refer to the :doc:`Process Component ` for callback documentation:: use Symfony\Component\Process\Process; From 8e7037357082048a5d754e6004e5b0f36df6570b Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Fri, 17 Oct 2014 23:48:17 +0200 Subject: [PATCH 0435/1181] Document error page preview in Symfony ~2.6 (#4293) Feature added in symfony/symfony#12096. --- cookbook/controller/error_pages.rst | 66 ++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/cookbook/controller/error_pages.rst b/cookbook/controller/error_pages.rst index fa8efef21fc..b087bd69fab 100644 --- a/cookbook/controller/error_pages.rst +++ b/cookbook/controller/error_pages.rst @@ -42,18 +42,10 @@ flag. While *exception* pages give you a lot of helpful information during development, *error* pages are meant to be shown to the user in production. -.. sidebar:: Testing Error Pages during Development - - You should not set ``kernel.debug`` to ``false`` in order to see your - *error* pages during development. This will also stop - Symfony from recompiling your twig templates, among other things. - - The third-party `WebfactoryExceptionsBundle`_ provides a special - test controller that allows you to display your custom error - pages for arbitrary HTTP status codes even with - ``kernel.debug`` set to ``true``. +.. tip:: -.. _`WebfactoryExceptionsBundle`: https://github.com/webfactory/exceptions-bundle + You can also :ref:`preview your error pages ` + in ``kernel.debug`` mode. .. _cookbook-error-pages-by-status-code: @@ -153,6 +145,53 @@ Refer to the previous section for the order in which the ``exception.html.twig`` for the standard HTML exception page or ``exception.json.twig`` for the JSON exception page. +.. _testing-error-pages: + +Testing Error Pages during Development +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The default ``ExceptionController`` also allows you to preview your +*error* pages during development. + +.. versionadded:: 2.6 + This feature was introduced in Symfony 2.6. Before, the third-party + `WebfactoryExceptionsBundle`_ could be used for the same purpose. + +To use this feature, you need to have a definition in your +``routing_dev.yml`` file like so: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/routing_dev.yml + _errors: + resource: "@TwigBundle/Resources/config/routing/errors.xml" + prefix: /_error + +If you're coming from an older version of Symfony, you might need to +add this to your ``routing_dev.yml`` file. If you're starting from +scratch, the `Symfony Standard Edition`_ already contains it for you. + +With this route added, you can use URLs like + +.. code-block:: text + + http://localhost/app_dev.php/_error/{statusCode} + http://localhost/app_dev.php/_error/{statusCode}.{format} + +to preview the *error* page for a given status code as HTML or for a +given status code and format. + +.. tip:: + + You should not set ``kernel.debug`` to ``false`` in order to see your + error pages during development. This will also stop + Symfony from recompiling your twig templates, among other things. + +.. _`WebfactoryExceptionsBundle`: https://github.com/webfactory/exceptions-bundle +.. _`Symfony Standard Edition`: https://github.com/symfony/symfony-standard/ + .. _custom-exception-controller: Replacing the Default ExceptionController @@ -235,6 +274,11 @@ template to be used. As of writing, the ``ExceptionController`` is *not* part of the Symfony API, so be aware that it might change in following releases. +.. tip:: + + The :ref:`error page preview ` also works for + your own controllers set up this way. + .. _use-kernel-exception-event: Working with the kernel.exception Event From 2bf8c55a79474a3750c92891797969c706e59528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 22 Sep 2014 19:36:36 +0200 Subject: [PATCH 0436/1181] [Filesystem] Moved current document to a dedicated folder --- components/{ => filesystem}/filesystem.rst | 21 ++------------------- components/filesystem/index.rst | 9 +++++++++ components/filesystem/introduction.rst | 16 ++++++++++++++++ components/filesystem/lockhandler.rst | 2 ++ components/index.rst | 2 +- redirection_map | 1 + 6 files changed, 31 insertions(+), 20 deletions(-) rename components/{ => filesystem}/filesystem.rst (92%) create mode 100644 components/filesystem/index.rst create mode 100644 components/filesystem/introduction.rst create mode 100644 components/filesystem/lockhandler.rst diff --git a/components/filesystem.rst b/components/filesystem/filesystem.rst similarity index 92% rename from components/filesystem.rst rename to components/filesystem/filesystem.rst index 076d7c38d1f..e41dfd0b98b 100644 --- a/components/filesystem.rst +++ b/components/filesystem/filesystem.rst @@ -1,22 +1,5 @@ -.. index:: - single: Filesystem - -The Filesystem Component -======================== - - The Filesystem component provides basic utilities for the filesystem. - -.. versionadded:: 2.1 - The Filesystem component was introduced in Symfony 2.1. Previously, the - ``Filesystem`` class was located in the HttpKernel component. - -Installation ------------- - -You can install the component in 2 different ways: - -* :doc:`Install it via Composer ` (``symfony/filesystem`` on `Packagist`_); -* Use the official Git repository (https://github.com/symfony/Filesystem). +Filesystem +========== Usage ----- diff --git a/components/filesystem/index.rst b/components/filesystem/index.rst new file mode 100644 index 00000000000..b3629ef0af9 --- /dev/null +++ b/components/filesystem/index.rst @@ -0,0 +1,9 @@ +Filesystem +========== + +.. toctree:: + :maxdepth: 2 + + introduction + filesystem + lockhandler diff --git a/components/filesystem/introduction.rst b/components/filesystem/introduction.rst new file mode 100644 index 00000000000..15c8d46628a --- /dev/null +++ b/components/filesystem/introduction.rst @@ -0,0 +1,16 @@ +The Filesystem Component +======================== + + The Filesystem component provides basic utilities for the filesystem. + +.. versionadded:: 2.1 + The Filesystem component was introduced in Symfony 2.1. Previously, the + ``Filesystem`` class was located in the HttpKernel component. + +Installation +------------ + +You can install the component in 2 different ways: + +* :doc:`Install it via Composer ` (``symfony/filesystem`` on `Packagist`_); +* Use the official Git repository (https://github.com/symfony/Filesystem). diff --git a/components/filesystem/lockhandler.rst b/components/filesystem/lockhandler.rst new file mode 100644 index 00000000000..30aa687bd9b --- /dev/null +++ b/components/filesystem/lockhandler.rst @@ -0,0 +1,2 @@ +Lockhandler +=========== diff --git a/components/index.rst b/components/index.rst index 8e167cd2ac9..91b3dfc466a 100644 --- a/components/index.rst +++ b/components/index.rst @@ -14,7 +14,7 @@ The Components dom_crawler event_dispatcher/index expression_language/index - filesystem + filesystem/index finder form/index http_foundation/index diff --git a/redirection_map b/redirection_map index 1a6758a5560..33d8293f670 100644 --- a/redirection_map +++ b/redirection_map @@ -22,6 +22,7 @@ /cookbook/console/generating_urls /cookbook/console/sending_emails /components/yaml /components/yaml/introduction /components/templating /components/templating/introduction +/components/filesystem /components/filesystem/introduction /cmf/reference/configuration/block /cmf/bundles/block/configuration /cmf/reference/configuration/content /cmf/bundles/content/configuration /cmf/reference/configuration/core /cmf/bundles/core/configuration From 909a2940c86110752c7401bf9998aac479712cc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 22 Sep 2014 20:00:46 +0200 Subject: [PATCH 0437/1181] [Filesystem] Added documentation for the new LockHandler --- components/filesystem/filesystem.rst | 253 ------------------------ components/filesystem/index.rst | 3 +- components/filesystem/introduction.rst | 260 +++++++++++++++++++++++++ components/filesystem/lock_handler.rst | 69 +++++++ components/filesystem/lockhandler.rst | 2 - components/map.rst.inc | 5 +- 6 files changed, 333 insertions(+), 259 deletions(-) delete mode 100644 components/filesystem/filesystem.rst create mode 100644 components/filesystem/lock_handler.rst delete mode 100644 components/filesystem/lockhandler.rst diff --git a/components/filesystem/filesystem.rst b/components/filesystem/filesystem.rst deleted file mode 100644 index e41dfd0b98b..00000000000 --- a/components/filesystem/filesystem.rst +++ /dev/null @@ -1,253 +0,0 @@ -Filesystem -========== - -Usage ------ - -The :class:`Symfony\\Component\\Filesystem\\Filesystem` class is the unique -endpoint for filesystem operations:: - - use Symfony\Component\Filesystem\Filesystem; - use Symfony\Component\Filesystem\Exception\IOExceptionInterface; - - $fs = new Filesystem(); - - try { - $fs->mkdir('/tmp/random/dir/' . mt_rand()); - } catch (IOExceptionInterface $e) { - echo "An error occurred while creating your directory at ".$e->getPath(); - } - -.. versionadded:: 2.4 - The ``IOExceptionInterface`` and its ``getPath`` method were introduced in - Symfony 2.4. Prior to 2.4, you would catch the ``IOException`` class. - -.. note:: - - Methods :method:`Symfony\\Component\\Filesystem\\Filesystem::mkdir`, - :method:`Symfony\\Component\\Filesystem\\Filesystem::exists`, - :method:`Symfony\\Component\\Filesystem\\Filesystem::touch`, - :method:`Symfony\\Component\\Filesystem\\Filesystem::remove`, - :method:`Symfony\\Component\\Filesystem\\Filesystem::chmod`, - :method:`Symfony\\Component\\Filesystem\\Filesystem::chown` and - :method:`Symfony\\Component\\Filesystem\\Filesystem::chgrp` can receive a - string, an array or any object implementing :phpclass:`Traversable` as - the target argument. - -Mkdir -~~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::mkdir` creates a directory. -On posix filesystems, directories are created with a default mode value -`0777`. You can use the second argument to set your own mode:: - - $fs->mkdir('/tmp/photos', 0700); - -.. note:: - - You can pass an array or any :phpclass:`Traversable` object as the first - argument. - -Exists -~~~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::exists` checks for the -presence of all files or directories and returns ``false`` if a file is missing:: - - // this directory exists, return true - $fs->exists('/tmp/photos'); - - // rabbit.jpg exists, bottle.png does not exists, return false - $fs->exists(array('rabbit.jpg', 'bottle.png')); - -.. note:: - - You can pass an array or any :phpclass:`Traversable` object as the first - argument. - -Copy -~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::copy` is used to copy -files. If the target already exists, the file is copied only if the source -modification date is later than the target. This behavior can be overridden by -the third boolean argument:: - - // works only if image-ICC has been modified after image.jpg - $fs->copy('image-ICC.jpg', 'image.jpg'); - - // image.jpg will be overridden - $fs->copy('image-ICC.jpg', 'image.jpg', true); - -Touch -~~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::touch` sets access and -modification time for a file. The current time is used by default. You can set -your own with the second argument. The third argument is the access time:: - - // set modification time to the current timestamp - $fs->touch('file.txt'); - // set modification time 10 seconds in the future - $fs->touch('file.txt', time() + 10); - // set access time 10 seconds in the past - $fs->touch('file.txt', time(), time() - 10); - -.. note:: - - You can pass an array or any :phpclass:`Traversable` object as the first - argument. - -Chown -~~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::chown` is used to change -the owner of a file. The third argument is a boolean recursive option:: - - // set the owner of the lolcat video to www-data - $fs->chown('lolcat.mp4', 'www-data'); - // change the owner of the video directory recursively - $fs->chown('/video', 'www-data', true); - -.. note:: - - You can pass an array or any :phpclass:`Traversable` object as the first - argument. - -Chgrp -~~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::chgrp` is used to change -the group of a file. The third argument is a boolean recursive option:: - - // set the group of the lolcat video to nginx - $fs->chgrp('lolcat.mp4', 'nginx'); - // change the group of the video directory recursively - $fs->chgrp('/video', 'nginx', true); - -.. note:: - - You can pass an array or any :phpclass:`Traversable` object as the first - argument. - -Chmod -~~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::chmod` is used to change -the mode of a file. The fourth argument is a boolean recursive option:: - - // set the mode of the video to 0600 - $fs->chmod('video.ogg', 0600); - // change the mod of the src directory recursively - $fs->chmod('src', 0700, 0000, true); - -.. note:: - - You can pass an array or any :phpclass:`Traversable` object as the first - argument. - -Remove -~~~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::remove` is used to remove -files, symlinks, directories easily:: - - $fs->remove(array('symlink', '/path/to/directory', 'activity.log')); - -.. note:: - - You can pass an array or any :phpclass:`Traversable` object as the first - argument. - -Rename -~~~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::rename` is used to rename -files and directories:: - - // rename a file - $fs->rename('/tmp/processed_video.ogg', '/path/to/store/video_647.ogg'); - // rename a directory - $fs->rename('/tmp/files', '/path/to/store/files'); - -symlink -~~~~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::symlink` creates a -symbolic link from the target to the destination. If the filesystem does not -support symbolic links, a third boolean argument is available:: - - // create a symbolic link - $fs->symlink('/path/to/source', '/path/to/destination'); - // duplicate the source directory if the filesystem - // does not support symbolic links - $fs->symlink('/path/to/source', '/path/to/destination', true); - -makePathRelative -~~~~~~~~~~~~~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::makePathRelative` returns -the relative path of a directory given another one:: - - // returns '../' - $fs->makePathRelative( - '/var/lib/symfony/src/Symfony/', - '/var/lib/symfony/src/Symfony/Component' - ); - // returns 'videos/' - $fs->makePathRelative('/tmp/videos', '/tmp') - -mirror -~~~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::mirror` mirrors a -directory:: - - $fs->mirror('/path/to/source', '/path/to/target'); - -isAbsolutePath -~~~~~~~~~~~~~~ - -:method:`Symfony\\Component\\Filesystem\\Filesystem::isAbsolutePath` returns -``true`` if the given path is absolute, ``false`` otherwise:: - - // return true - $fs->isAbsolutePath('/tmp'); - // return true - $fs->isAbsolutePath('c:\\Windows'); - // return false - $fs->isAbsolutePath('tmp'); - // return false - $fs->isAbsolutePath('../dir'); - -dumpFile -~~~~~~~~ - -.. versionadded:: 2.3 - The ``dumpFile()`` was introduced in Symfony 2.3. - -:method:`Symfony\\Component\\Filesystem\\Filesystem::dumpFile` allows you to -dump contents to a file. It does this in an atomic manner: it writes a temporary -file first and then moves it to the new file location when it's finished. -This means that the user will always see either the complete old file or -complete new file (but never a partially-written file):: - - $fs->dumpFile('file.txt', 'Hello World'); - -The ``file.txt`` file contains ``Hello World`` now. - -A desired file mode can be passed as the third argument. - -Error Handling --------------- - -Whenever something wrong happens, an exception implementing -:class:`Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface` or -:class:`Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface` is thrown. - -.. note:: - - An :class:`Symfony\\Component\\Filesystem\\Exception\\IOException` is - thrown if directory creation fails. - -.. _`Packagist`: https://packagist.org/packages/symfony/filesystem diff --git a/components/filesystem/index.rst b/components/filesystem/index.rst index b3629ef0af9..e643f5a90f4 100644 --- a/components/filesystem/index.rst +++ b/components/filesystem/index.rst @@ -5,5 +5,4 @@ Filesystem :maxdepth: 2 introduction - filesystem - lockhandler + lock_handler diff --git a/components/filesystem/introduction.rst b/components/filesystem/introduction.rst index 15c8d46628a..8990198aa41 100644 --- a/components/filesystem/introduction.rst +++ b/components/filesystem/introduction.rst @@ -1,3 +1,6 @@ +.. index:: + single: Filesystem + The Filesystem Component ======================== @@ -7,6 +10,12 @@ The Filesystem Component The Filesystem component was introduced in Symfony 2.1. Previously, the ``Filesystem`` class was located in the HttpKernel component. + +.. tip:: + + A lock handler feature was introduce in symfony 2.6. + :doc:`See the documentation for more information `. + Installation ------------ @@ -14,3 +23,254 @@ You can install the component in 2 different ways: * :doc:`Install it via Composer ` (``symfony/filesystem`` on `Packagist`_); * Use the official Git repository (https://github.com/symfony/Filesystem). + +Usage +----- + +The :class:`Symfony\\Component\\Filesystem\\Filesystem` class is the unique +endpoint for filesystem operations:: + + use Symfony\Component\Filesystem\Filesystem; + use Symfony\Component\Filesystem\Exception\IOExceptionInterface; + + $fs = new Filesystem(); + + try { + $fs->mkdir('/tmp/random/dir/' . mt_rand()); + } catch (IOExceptionInterface $e) { + echo "An error occurred while creating your directory at ".$e->getPath(); + } + +.. versionadded:: 2.4 + The ``IOExceptionInterface`` and its ``getPath`` method were introduced in + Symfony 2.4. Prior to 2.4, you would catch the ``IOException`` class. + +.. note:: + + Methods :method:`Symfony\\Component\\Filesystem\\Filesystem::mkdir`, + :method:`Symfony\\Component\\Filesystem\\Filesystem::exists`, + :method:`Symfony\\Component\\Filesystem\\Filesystem::touch`, + :method:`Symfony\\Component\\Filesystem\\Filesystem::remove`, + :method:`Symfony\\Component\\Filesystem\\Filesystem::chmod`, + :method:`Symfony\\Component\\Filesystem\\Filesystem::chown` and + :method:`Symfony\\Component\\Filesystem\\Filesystem::chgrp` can receive a + string, an array or any object implementing :phpclass:`Traversable` as + the target argument. + +Mkdir +~~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::mkdir` creates a directory. +On posix filesystems, directories are created with a default mode value +`0777`. You can use the second argument to set your own mode:: + + $fs->mkdir('/tmp/photos', 0700); + +.. note:: + + You can pass an array or any :phpclass:`Traversable` object as the first + argument. + +Exists +~~~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::exists` checks for the +presence of all files or directories and returns ``false`` if a file is missing:: + + // this directory exists, return true + $fs->exists('/tmp/photos'); + + // rabbit.jpg exists, bottle.png does not exists, return false + $fs->exists(array('rabbit.jpg', 'bottle.png')); + +.. note:: + + You can pass an array or any :phpclass:`Traversable` object as the first + argument. + +Copy +~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::copy` is used to copy +files. If the target already exists, the file is copied only if the source +modification date is later than the target. This behavior can be overridden by +the third boolean argument:: + + // works only if image-ICC has been modified after image.jpg + $fs->copy('image-ICC.jpg', 'image.jpg'); + + // image.jpg will be overridden + $fs->copy('image-ICC.jpg', 'image.jpg', true); + +Touch +~~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::touch` sets access and +modification time for a file. The current time is used by default. You can set +your own with the second argument. The third argument is the access time:: + + // set modification time to the current timestamp + $fs->touch('file.txt'); + // set modification time 10 seconds in the future + $fs->touch('file.txt', time() + 10); + // set access time 10 seconds in the past + $fs->touch('file.txt', time(), time() - 10); + +.. note:: + + You can pass an array or any :phpclass:`Traversable` object as the first + argument. + +Chown +~~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::chown` is used to change +the owner of a file. The third argument is a boolean recursive option:: + + // set the owner of the lolcat video to www-data + $fs->chown('lolcat.mp4', 'www-data'); + // change the owner of the video directory recursively + $fs->chown('/video', 'www-data', true); + +.. note:: + + You can pass an array or any :phpclass:`Traversable` object as the first + argument. + +Chgrp +~~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::chgrp` is used to change +the group of a file. The third argument is a boolean recursive option:: + + // set the group of the lolcat video to nginx + $fs->chgrp('lolcat.mp4', 'nginx'); + // change the group of the video directory recursively + $fs->chgrp('/video', 'nginx', true); + +.. note:: + + You can pass an array or any :phpclass:`Traversable` object as the first + argument. + +Chmod +~~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::chmod` is used to change +the mode of a file. The fourth argument is a boolean recursive option:: + + // set the mode of the video to 0600 + $fs->chmod('video.ogg', 0600); + // change the mod of the src directory recursively + $fs->chmod('src', 0700, 0000, true); + +.. note:: + + You can pass an array or any :phpclass:`Traversable` object as the first + argument. + +Remove +~~~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::remove` is used to remove +files, symlinks, directories easily:: + + $fs->remove(array('symlink', '/path/to/directory', 'activity.log')); + +.. note:: + + You can pass an array or any :phpclass:`Traversable` object as the first + argument. + +Rename +~~~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::rename` is used to rename +files and directories:: + + // rename a file + $fs->rename('/tmp/processed_video.ogg', '/path/to/store/video_647.ogg'); + // rename a directory + $fs->rename('/tmp/files', '/path/to/store/files'); + +symlink +~~~~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::symlink` creates a +symbolic link from the target to the destination. If the filesystem does not +support symbolic links, a third boolean argument is available:: + + // create a symbolic link + $fs->symlink('/path/to/source', '/path/to/destination'); + // duplicate the source directory if the filesystem + // does not support symbolic links + $fs->symlink('/path/to/source', '/path/to/destination', true); + +makePathRelative +~~~~~~~~~~~~~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::makePathRelative` returns +the relative path of a directory given another one:: + + // returns '../' + $fs->makePathRelative( + '/var/lib/symfony/src/Symfony/', + '/var/lib/symfony/src/Symfony/Component' + ); + // returns 'videos/' + $fs->makePathRelative('/tmp/videos', '/tmp') + +mirror +~~~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::mirror` mirrors a +directory:: + + $fs->mirror('/path/to/source', '/path/to/target'); + +isAbsolutePath +~~~~~~~~~~~~~~ + +:method:`Symfony\\Component\\Filesystem\\Filesystem::isAbsolutePath` returns +``true`` if the given path is absolute, ``false`` otherwise:: + + // return true + $fs->isAbsolutePath('/tmp'); + // return true + $fs->isAbsolutePath('c:\\Windows'); + // return false + $fs->isAbsolutePath('tmp'); + // return false + $fs->isAbsolutePath('../dir'); + +dumpFile +~~~~~~~~ + +.. versionadded:: 2.3 + The ``dumpFile()`` was introduced in Symfony 2.3. + +:method:`Symfony\\Component\\Filesystem\\Filesystem::dumpFile` allows you to +dump contents to a file. It does this in an atomic manner: it writes a temporary +file first and then moves it to the new file location when it's finished. +This means that the user will always see either the complete old file or +complete new file (but never a partially-written file):: + + $fs->dumpFile('file.txt', 'Hello World'); + +The ``file.txt`` file contains ``Hello World`` now. + +A desired file mode can be passed as the third argument. + +Error Handling +-------------- + +Whenever something wrong happens, an exception implementing +:class:`Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface` or +:class:`Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface` is thrown. + +.. note:: + + An :class:`Symfony\\Component\\Filesystem\\Exception\\IOException` is + thrown if directory creation fails. + +.. _`Packagist`: https://packagist.org/packages/symfony/filesystem diff --git a/components/filesystem/lock_handler.rst b/components/filesystem/lock_handler.rst new file mode 100644 index 00000000000..d57889190ef --- /dev/null +++ b/components/filesystem/lock_handler.rst @@ -0,0 +1,69 @@ +LockHandler +=========== + +.. versionadded:: 2.6 + The lock handler feature was introduced in Symfony 2.6 + +What is a Lock? +--------------- + +File locking is a mechanism that restricts access to a computer file by allowing +only one user or process access at any specific time. This mechanism was +introduced a few decades ago for mainframes, but continues being useful for +modern applications. + +Symfony provides a LockHelper to help you use locks in your project. + +Usage +----- + +.. caution:: + + The lock handler only works if you're using just one server. If you have + several hosts, you must not use this helper. + +A lock can be used, for example, to allow only one instance of a command to run. + +.. code-block:: php + + use Symfony\Component\Filesystem\LockHandler; + + $lockHandler = new LockHandler('hello.lock'); + if (!$lockHandler->lock()) { + // the resource "hello" is already locked by another process + + return 0; + } + +The first argument of the constructor is a string that it will use as part of +the name of the file used to create the lock on the local filesystem. A best +practice for Symfony commands is to use the command name, such as ``acme:my-command``. +``LockHandler`` sanitizes the contents of the string before creating +the file, so you can pass any value for this argument. + +.. tip:: + + The ``.lock`` extension is optional, but it's a common practice to include + it. This will make it easier to find lock files on the filesystem. Moreover, + to avoid name collisions, ``LockHandler`` also appends a hash to the name of + the lock file. + +By default, the lock will be created in the temporary directory, but you can +optionally select the directory where locks are created by passing it as the +second argument of the constructor. + +The :method:`Symfony\\Component\\Filesystem\\LockHandler::lock` method tries to +acquire the lock. If the lock is acquired, the method returns ``true``, +``false`` otherwise. If the ``lock`` method is called several times on the same +instance it will always return ``true`` if the lock was acquired on the first +call. + +You can pass an optional blocking argument as the first argument to the +``lock()`` method, which defaults to ``false``. If this is set to ``true``, your +PHP code will wait indefinitely until the lock is released by another process. + +The resource is automatically released by PHP at the end of the script. In +addition, you can invoke the +:method:`Symfony\\Component\\Filesystem\\LockHandler::release` method to release +the lock explicitly. Once it's released, any other process can lock the +resource. diff --git a/components/filesystem/lockhandler.rst b/components/filesystem/lockhandler.rst deleted file mode 100644 index 30aa687bd9b..00000000000 --- a/components/filesystem/lockhandler.rst +++ /dev/null @@ -1,2 +0,0 @@ -Lockhandler -=========== diff --git a/components/map.rst.inc b/components/map.rst.inc index f9eab711e07..1bccb80fb61 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -70,9 +70,10 @@ * :doc:`/components/expression_language/extending` * :doc:`/components/expression_language/caching` -* **Filesystem** +* :doc:`/components/filesystem/index` - * :doc:`/components/filesystem` + * :doc:`/components/filesystem/introduction` + * :doc:`/components/filesystem/lock_handler` * **Finder** From 126496331e59319842dece5ac5287e9ff07b8771 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 19 Oct 2014 11:19:16 -0400 Subject: [PATCH 0438/1181] [#4204] Fixing slight markup issue --- reference/constraints/Expression.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/constraints/Expression.rst b/reference/constraints/Expression.rst index 01eb69c3493..b3d8f386fa1 100644 --- a/reference/constraints/Expression.rst +++ b/reference/constraints/Expression.rst @@ -221,7 +221,7 @@ more about the expression language syntax, see In Symfony 2.6, the Expression constraint *is* executed if the value is ``null``. Before 2.6, if the value was ``null``, the expression was never executed and the value was considered valid (unless you - also had a constraint like `NotBlank` on the property). + also had a constraint like ``NotBlank`` on the property). For more information about the expression and what variables are available to you, see the :ref:`expression ` From 3caec2169ab5791fd6483ed7939fc093816f21d6 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 7 Jul 2014 16:24:39 +0200 Subject: [PATCH 0439/1181] description for running PHP's built-in web server in the background --- book/installation.rst | 16 ++++++++- cookbook/web_server/built_in.rst | 61 +++++++++++++++++++++++++++----- quick_tour/the_big_picture.rst | 8 ++++- 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/book/installation.rst b/book/installation.rst index 560c4852bb0..837751a87ad 100644 --- a/book/installation.rst +++ b/book/installation.rst @@ -274,7 +274,21 @@ If there are any issues, correct them now before moving on. Note that using the ACL is recommended when you have access to them on your server because changing the umask is not thread-safe. - **4. Use the same user for the CLI and the web server** + **4. Use the built-in web server in development environments** + + The built-in PHP web server - which can be used during development - allows + your web server user and CLI user to be the same. This removes any permissions + issues: + + .. code-block:: bash + + $ php app/console server:start + + .. seealso:: + + Read more about the internal server :doc:`in the cookbook `. + + **5. Use the same user for the CLI and the web server** In development environments, it is a common practice to use the same unix user for the CLI and the web server because it avoids any of these permissions diff --git a/cookbook/web_server/built_in.rst b/cookbook/web_server/built_in.rst index f7ef8d1f039..154ab192c36 100644 --- a/cookbook/web_server/built_in.rst +++ b/cookbook/web_server/built_in.rst @@ -4,6 +4,10 @@ How to Use PHP's built-in Web Server ==================================== +.. versionadded:: 2.6 + The ability to run the server as a background process was introduced + in Symfony 2.6. + Since PHP 5.4 the CLI SAPI comes with a `built-in web server`_. It can be used to run your PHP applications locally during development, for testing or for application demonstrations. This way, you don't have to bother configuring @@ -19,25 +23,46 @@ Starting the Web Server ----------------------- Running a Symfony application using PHP's built-in web server is as easy as -executing the ``server:run`` command: +executing the ``server:start`` command: .. code-block:: bash - $ php app/console server:run + $ php app/console server:start -This starts a server at ``localhost:8000`` that executes your Symfony application. -The command will wait and will respond to incoming HTTP requests until you -terminate it (this is usually done by pressing Ctrl and C). +This starts the web server at ``localhost:8000`` in the background that serves +your Symfony application. By default, the web server listens on port 8000 on the loopback device. You -can change the socket passing an ip address and a port as a command-line argument: +can change the socket passing an IP address and a port as a command-line argument: .. code-block:: bash $ php app/console server:run 192.168.0.1:8080 +.. note:: + + You can use the ``server:status`` command to check if a web server is + listening on a certain socket: + + .. code-block:: bash + + $ php app/console server:status + + $ php app/console server:status 192.168.0.1:8080 + + The first command shows if your Symfony application will be server through + ``localhost:8000``, the second one does the same for ``192.168.0.1:8080``. + +.. note:: + + Before Symfony 2.6, the ``server:run`` command was used to start the built-in + web server. This command is still available and behaves slightly different. + Instead of starting the server in the background, it will block the current + terminal until you terminate it (this is usually done by pressing Ctrl + and C). + Command Options ---------------- +~~~~~~~~~~~~~~~ The built-in web server expects a "router" script (read about the "router" script on `php.net`_) as an argument. Symfony already passes such a router @@ -47,14 +72,32 @@ script: .. code-block:: bash - $ php app/console server:run --env=test --router=app/config/router_test.php + $ php app/console server:start --env=test --router=app/config/router_test.php If your application's document root differs from the standard directory layout, you have to pass the correct location using the ``--docroot`` option: .. code-block:: bash - $ php app/console server:run --docroot=public_html + $ php app/console server:start --docroot=public_html + +Stopping the Server +------------------- + +When you are finished, you can simply stop the web server using the ``server:stop`` +command: + +.. code-block:: bash + + $ php app/console server:stop + +Like with the start command, if you omit the socket information, Symfony will +stop the web server bound to ``localhost:8000``. Just pass the socket information +when the web server listens to another IP address or to another port: + +.. code-block:: bash + + $ php app/console server:stop 192.168.0.1:8080 .. _`built-in web server`: http://www.php.net/manual/en/features.commandline.webserver.php .. _`php.net`: http://php.net/manual/en/features.commandline.webserver.php#example-401 diff --git a/quick_tour/the_big_picture.rst b/quick_tour/the_big_picture.rst index 7d6728775fa..28704ef5633 100644 --- a/quick_tour/the_big_picture.rst +++ b/quick_tour/the_big_picture.rst @@ -70,7 +70,13 @@ to run Symfony: .. code-block:: bash - $ php app/console server:run + $ php app/console server:start + +When you are finished, you can stop it with the ``server:stop`` command: + +.. code-block:: bash + + $ php app/console server:stop .. seealso:: From d02c7c4663b82bd34683be828b0f12f74de88e5f Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sun, 19 Oct 2014 22:59:02 +0200 Subject: [PATCH 0440/1181] Updates according to GH feedback --- cookbook/controller/error_pages.rst | 37 ++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/cookbook/controller/error_pages.rst b/cookbook/controller/error_pages.rst index b087bd69fab..83b8c0b4d0d 100644 --- a/cookbook/controller/error_pages.rst +++ b/cookbook/controller/error_pages.rst @@ -169,6 +169,32 @@ To use this feature, you need to have a definition in your resource: "@TwigBundle/Resources/config/routing/errors.xml" prefix: /_error + .. code-block:: xml + + + + + + + + + .. code-block:: php + + // app/config/routing_dev.php + use Symfony\Component\Routing\RouteCollection; + + $collection = new RouteCollection(); + $collection->addCollection( + $loader->import("@AcmeHelloBundle/Resources/config/routing.php") + ); + $collection->addPrefix("/error"); + + return $collection; + If you're coming from an older version of Symfony, you might need to add this to your ``routing_dev.yml`` file. If you're starting from scratch, the `Symfony Standard Edition`_ already contains it for you. @@ -183,15 +209,6 @@ With this route added, you can use URLs like to preview the *error* page for a given status code as HTML or for a given status code and format. -.. tip:: - - You should not set ``kernel.debug`` to ``false`` in order to see your - error pages during development. This will also stop - Symfony from recompiling your twig templates, among other things. - -.. _`WebfactoryExceptionsBundle`: https://github.com/webfactory/exceptions-bundle -.. _`Symfony Standard Edition`: https://github.com/symfony/symfony-standard/ - .. _custom-exception-controller: Replacing the Default ExceptionController @@ -329,4 +346,6 @@ several) listeners deal with them. Good luck! +.. _`WebfactoryExceptionsBundle`: https://github.com/webfactory/exceptions-bundle +.. _`Symfony Standard Edition`: https://github.com/symfony/symfony-standard/ .. _`ExceptionListener`: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php From 9838438bdf6908cbb67cb5fda20e026202da9912 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 19 Oct 2014 19:22:04 -0400 Subject: [PATCH 0441/1181] [#4293] Fixing bad path --- cookbook/controller/error_pages.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/controller/error_pages.rst b/cookbook/controller/error_pages.rst index 83b8c0b4d0d..951a02fa823 100644 --- a/cookbook/controller/error_pages.rst +++ b/cookbook/controller/error_pages.rst @@ -189,7 +189,7 @@ To use this feature, you need to have a definition in your $collection = new RouteCollection(); $collection->addCollection( - $loader->import("@AcmeHelloBundle/Resources/config/routing.php") + $loader->import('@TwigBundle/Resources/config/routing/errors.xml') ); $collection->addPrefix("/error"); From 16daca4ec053cb6ddcd038a3b71767f1f54ee538 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 20 Oct 2014 21:11:07 +0200 Subject: [PATCH 0442/1181] fix route prefix in PHP code example --- cookbook/controller/error_pages.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cookbook/controller/error_pages.rst b/cookbook/controller/error_pages.rst index 951a02fa823..35199483430 100644 --- a/cookbook/controller/error_pages.rst +++ b/cookbook/controller/error_pages.rst @@ -191,7 +191,7 @@ To use this feature, you need to have a definition in your $collection->addCollection( $loader->import('@TwigBundle/Resources/config/routing/errors.xml') ); - $collection->addPrefix("/error"); + $collection->addPrefix("/_error"); return $collection; @@ -326,7 +326,7 @@ another page or rendering specialized error pages. If your listener calls ``setResponse()`` on the :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent`, - event propagation will be stopped and the response will be sent to + event propagation will be stopped and the response will be sent to the client. This approach allows you to create centralized and layered error @@ -338,7 +338,7 @@ several) listeners deal with them. To see an example, have a look at the `ExceptionListener`_ in the Security Component. - + It handles various security-related exceptions that are thrown in your application (like :class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException`) and takes measures like redirecting the user to the login page, From 1a1476ecad140af03e5145b9c8f6391eea32f792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 6 Oct 2014 18:13:48 +0200 Subject: [PATCH 0443/1181] [Serializer] Handle circular references. symfony/symfony#12098. --- components/serializer.rst | 97 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/components/serializer.rst b/components/serializer.rst index 872c5936e8b..4508482f88f 100644 --- a/components/serializer.rst +++ b/components/serializer.rst @@ -238,6 +238,101 @@ When serializing, you can set a callback to format a specific object property:: $serializer->serialize($person, 'json'); // Output: {"name":"cordoval", "age": 34, "createdAt": "2014-03-22T09:43:12-0500"} +Handling Circular References +---------------------------- + +.. versionadded:: 2.6 + Handling of circular references was introduced in Symfony 2.6. In previous + versions of Symfony, circular references led to infinite loops. + +Circular references are common when dealing with entity relations:: + + class Organization + { + private $name; + private $members; + + public function setName($name) + { + $this->name = $name; + } + + public function getName() + { + return $this->name; + } + + public function setMembers(array $members) + { + $this->members = $members; + } + + public function getMembers() + { + return $this->members; + } + } + + class Member + { + private $name; + private $organization; + + public function setName($name) + { + $this->name = $name; + } + + public function getName() + { + return $this->name; + } + + public function setOrganization(Organization $organization) + { + $this->organization = $organization; + } + + public function getOrganization() + { + return $this->organization; + } + } + +To avoid infinite loops, :class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer` +throws a :class:`Symfony\\Component\\Serializer\\Exception\\CircularReferenceException` +when such case is encountered:: + + $member = new Member(); + $member->setName('Kévin'); + + $org = new Organization(); + $org->setName('Les-Tilleuls.coop'); + $org->setMembers(array($member)); + + $member->setOrganization($kevin); + + echo $serializer->serialize($org, 'json'); // Throws a CircularReferenceException + +The ``setCircularReferenceLimit()`` method of this normalizer sets the number +of times serializing the same object must occur before considering being +in a circular reference. Its default value is ``1``. + +Instead of throwing an exception, circular references can also be handled +by custom callables. This is especially useful when serializing entities +having unique identifiers:: + + $encoder = new JsonEncoder(); + $normalizer = new GetSetMethodNormalizer(); + + $normalizer->setCircularReferenceHandler(function ($object) { + return $object->getName(); + }); + + $serializer = new Serializer(array($normalizer), array($encoder)); + echo $serializer->serialize($org, 'json'); + // {"name":"Les-Tilleuls.coop","members":[{"name":"K\u00e9vin", organization: "Les-Tilleuls.coop"]} + JMSSerializer ------------- @@ -245,7 +340,7 @@ A popular third-party library, `JMS serializer`_, provides a more sophisticated albeit more complex solution. This library includes the ability to configure how your objects should be serialized/deserialized via annotations (as well as YAML, XML and PHP), integration with the Doctrine ORM, -and handling of other complex cases (e.g. circular references). +and handling of other complex cases. .. _`JMS serializer`: https://github.com/schmittjoh/serializer .. _Packagist: https://packagist.org/packages/symfony/serializer From b5b45bccfe74d3c7a13660f01d4388240bd0f114 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 21 Oct 2014 08:52:28 +0200 Subject: [PATCH 0444/1181] move Dumper section above the Caster one --- components/var_dumper/advanced.rst | 116 ++++++++++++++--------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/components/var_dumper/advanced.rst b/components/var_dumper/advanced.rst index d1c1609a229..bf15c1bfe79 100644 --- a/components/var_dumper/advanced.rst +++ b/components/var_dumper/advanced.rst @@ -27,6 +27,64 @@ Before cloning, you can configure the limits with:: They will be applied when calling ``->cloneVar()`` afterwards. +Dumpers +~~~~~~~ + +A dumper is responsible for outputting a string representation of a PHP variable, +using a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object as input. +The destination and the formatting of this output vary with dumpers. + +This component comes with an :class:`Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper` +for HTML output and a :class:`Symfony\\Component\\VarDumper\\Dumper\\CliDumper` +for optionally colored command line output. + +For example, if you want to dump some ``$variable``, just do:: + + $cloner = new VarCloner(); + $dumper = new CliDumper(); + + $dumper->dump($cloner->cloneVar($variable)); + +By using the first argument of the constructor, you can select the output +stream where the dump will be written. By default, the ``CliDumper`` writes +on ``php://stdout`` and the ``HtmlDumper`` on ``php://output``, but any PHP +stream (resource or URL) is acceptable. + +Instead of a stream destination, you can also pass it a ``callable`` that +will be called repeatedly for each line generated by a dumper. This +callable can be configured using the first argument of a dumper's constructor, +but also using the +:method:`Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper::setLineDumper` +method or the second argument of the +:method:`Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper::dump` method. + +For example, to get a dump as a string in a variable, you can do:: + + $cloner = new VarCloner(); + $dumper = new CliDumper(); + $output = ''; + + $dumper->dump( + $cloner->cloneVar($variable), + function ($line, $depth) use (&$output) { + // A negative depth means "end of dump" + if ($depth >= 0) { + // Adds a two spaces indentation to the line + $output .= str_repeat(' ', $depth).$line."\n"; + } + } + ); + + // $output is now populated with the dump representation of $variable + +Dumpers implement the :class:`Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface` +interface that specifies the +:method:`dump(Data $data) ` +method. They also typically implement the +:class:`Symfony\\Component\\VarDumper\\Cloner\\DumperInterface` that frees +them from re-implementing the logic required to walk through a +:class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object's internal structure. + Casters ~~~~~~~ @@ -98,61 +156,3 @@ properties not in the class declaration). .. note:: Although you can, it is best advised not to alter the state of an object while casting it in a Caster. - -Dumpers -~~~~~~~ - -A dumper is responsible for outputting a string representation of a PHP variable, -using a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object as input. -The destination and the formatting of this output vary with dumpers. - -This component comes with an :class:`Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper` -for HTML output and a :class:`Symfony\\Component\\VarDumper\\Dumper\\CliDumper` -for optionally colored command line output. - -For example, if you want to dump some ``$variable``, just do:: - - $cloner = new VarCloner(); - $dumper = new CliDumper(); - - $dumper->dump($cloner->cloneVar($variable)); - -By using the first argument of the constructor, you can select the output -stream where the dump will be written. By default, the ``CliDumper`` writes -on ``php://stdout`` and the ``HtmlDumper`` on ``php://output``, but any PHP -stream (resource or URL) is acceptable. - -Instead of a stream destination, you can also pass it a ``callable`` that -will be called repeatedly for each line generated by a dumper. This -callable can be configured using the first argument of a dumper's constructor, -but also using the -:method:`Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper::setLineDumper` -method or using the second argument of the -:method:`Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper::dump` method. - -For example, to get a dump in a variable, you can do:: - - $cloner = new VarCloner(); - $dumper = new CliDumper(); - $output = ''; - - $dumper->dump( - $cloner->cloneVar($variable), - function ($line, $depth) use (&$output) { - // A negative depth means "end of dump" - if ($depth >= 0) { - // Adds a two spaces indentation to the line - $output .= str_repeat(' ', $depth).$line."\n"; - } - } - ); - - // $output is now populated with the dump representation of $variable - -Dumpers implement the :class:`Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface` -interface that specifies the -:method:`dump(Data $data) ` -method. They also typically implement the -:class:`Symfony\\Component\\VarDumper\\Cloner\\DumperInterface` that frees -them from re-implementing the logic required to walk through a -:class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object's internal structure. From 575c32055fe03ff69bf50c56c1bd6640f505592b Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 14 Oct 2014 17:42:35 +0200 Subject: [PATCH 0445/1181] Updated OptionsResolver documentation: removed static methods --- components/options_resolver.rst | 802 ++++++++++++++++---------------- 1 file changed, 409 insertions(+), 393 deletions(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index 22b1943f9e9..ea1372f4ea6 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -5,7 +5,7 @@ The OptionsResolver Component ============================= - The OptionsResolver component helps you to easily process option arrays. + The OptionsResolver component is `array_replace()` on steroids. Installation ------------ @@ -15,14 +15,17 @@ You can install the component in 2 different ways: * :doc:`Install it via Composer ` (``symfony/options-resolver`` on `Packagist`_); * Use the official Git repository (https://github.com/symfony/OptionsResolver). -Usage ------ +Notes on Previous Versions +-------------------------- .. versionadded:: 2.6 This documentation was written for Symfony 2.6 and later. If you use an older version, please read the corresponding documentation using the version drop-down on the upper right. +Usage +----- + Imagine you have a ``Mailer`` class which has four options: ``host``, ``username``, ``password`` and ``port``:: @@ -62,8 +65,39 @@ check which options are set:: } This boilerplate is hard to read and repetitive. Also, the default values of the -options are buried in the business logic of your code. Let's use -:method:`Symfony\\Component\\OptionsResolver\\Options::resolve` to fix that:: +options are buried in the business logic of your code. We can use +:phpfunction:`array_replace` to fix that:: + + class Mailer + { + // ... + public function __construct(array $options = array()) + { + $this->options = array_replace(array( + 'host' => 'smtp.example.org', + 'username' => 'user', + 'password' => 'pa$$word', + 'port' => 25, + ), $options); + } + } + +Now all four options are guaranteed to be set. But what happens if the user of +the ``Mailer`` class does a mistake? + +.. code-block:: php + + $mailer = new Mailer(array( + 'usernme' => 'johndoe', + )); + +No error will be shown. In the best case, the bug will be appear during testing. +The developer will possibly spend a lot of time looking for the problem. In the +worst case, however, the bug won't even appear and will be deployed to the live +system. + +Let's use the :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` +class to fix this problem:: use Symfony\Component\OptionsResolver\Options; @@ -72,29 +106,31 @@ options are buried in the business logic of your code. Let's use // ... public function __construct(array $options = array()) { - $this->options = Options::resolve($options, array( + $resolver = new OptionsResolver(); + $resolver->setDefaults(array( 'host' => 'smtp.example.org', 'username' => 'user', 'password' => 'pa$$word', 'port' => 25, )); + + $this->options = $resolver->resolve($options); } } -Now all options are guaranteed to be set. Any option that wasn't passed through -``$options`` will be set to the specified default value. Additionally, an -:class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException` +Like before, all options will be guaranteed to be set. Additionally, an +:class:`Symfony\\Component\\OptionsResolver\\Exception\\UndefinedOptionsException` is thrown if an unknown option is passed:: $mailer = new Mailer(array( 'usernme' => 'johndoe', )); - // InvalidOptionsException: The option "usernme" does not exist. Known - // options are: "host", "password", "username" + // UndefinedOptionsException: The option "usernme" does not exist. Known + // options are: "host", "password", "port", "username" -The rest of your code can now access the values of the options without -boilerplate code:: +The rest of your code can access the values of the options without boilerplate +code:: // ... class Mailer @@ -111,12 +147,7 @@ boilerplate code:: } } -Required Options -~~~~~~~~~~~~~~~~ - -If an option must be set by the caller, pass that option to -:method:`Symfony\\Component\\OptionsResolver\\Options::validateRequired`. -For example, let's make the ``host`` option required:: +It's a good practice to split the option configuration into a separate method:: // ... class Mailer @@ -124,17 +155,64 @@ For example, let's make the ``host`` option required:: // ... public function __construct(array $options = array()) { - Options::validateRequired($options, 'host'); + $resolver = new OptionsResolver(); + $this->configureOptions($resolver); + + $this->options = $resolver->resolve($options); + } - $this->options = Options::resolve($options, array( - 'host' => null, + protected function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults(array( + 'host' => 'smtp.example.org', 'username' => 'user', 'password' => 'pa$$word', - 'port' => 25, + 'port' => 25, + 'encryption' => null, )); } } +First, your code becomes easier to read, especially if the constructor does more +than processing options. Second, sub-classes may now override the +``configureOptions()`` method to adjust the configuration of the options:: + + // ... + class GoogleMailer extends Mailer + { + protected function configureOptions(OptionsResolver $resolver) + { + parent::configureOptions($resolver); + + $resolver->setDefaults(array( + 'host' => 'smtp.google.com', + 'encryption' => 'ssl', + )); + } + } + +Required Options +~~~~~~~~~~~~~~~~ + +If an option must be set by the caller, pass that option to +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setRequired`. +For example, let's make the ``host`` option required:: + + // ... + class Mailer + { + // ... + protected function configureOptions(OptionsResolver $resolver) + { + // ... + $resolver->setRequired('host'); + } + } + +.. versionadded:: 2.6 + Before Symfony 2.6, `setRequired()` accepted only arrays. Since then, single + option names can be passed as well. + If you omit a required option, a :class:`Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException` will be thrown:: @@ -143,42 +221,110 @@ will be thrown:: // MissingOptionsException: The required option "host" is missing. -The :method:`Symfony\\Component\\OptionsResolver\\Options::validateRequired` +The :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setRequired` method accepts a single name or an array of option names if you have more than -one required option. +one required option:: -.. note:: + // ... + class Mailer + { + // ... + protected function configureOptions(OptionsResolver $resolver) + { + // ... + $resolver->setRequired(array('host', 'username', 'password')); + } + } - As you can see, the ``host`` option must still be passed to - :method:`Symfony\\Component\\OptionsResolver\\Options::resolve`, - otherwise the method will not accept that option. The default value, - however, can be omitted as the option must be set by the caller. +.. versionadded:: 2.6 + The methods :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isRequired` + and :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::getRequiredOptions` + were introduced in Symfony 2.6. + +Use :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isRequired` to find +out if an option is required. You can use +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::getRequiredOptions` to +retrieve the names of all required options:: + + // ... + class GoogleMailer extends Mailer + { + protected function configureOptions(OptionsResolver $resolver) + { + parent::configureOptions($resolver); + + if ($resolver->isRequired('host')) { + // ... + } + + $requiredOptions = $resolver->getRequiredOptions(); + } + } + +.. versionadded:: 2.6 + The methods :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isMissing` + and :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::getMissingOptions` + were introduced in Symfony 2.6. + +If you want to check whether a required option is still missing from the default +options, you can use :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isMissing`. +The difference to :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isRequired` +is that this method will return false for required options that have already +been set:: + + // ... + class Mailer + { + // ... + protected function configureOptions(OptionsResolver $resolver) + { + // ... + $resolver->setRequired('host'); + } + } + + // ... + class GoogleMailer extends Mailer + { + protected function configureOptions(OptionsResolver $resolver) + { + parent::configureOptions($resolver); + + $resolver->isRequired('host'); + // => true + + $resolver->isMissing('host'); + // => true + + $resolver->setDefault('host', 'smtp.google.com'); + + $resolver->isRequired('host'); + // => true + + $resolver->isMissing('host'); + // => false + } + } + +The method :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::getMissingOptions` +lets you access the names of all missing options. Type Validation ~~~~~~~~~~~~~~~ You can run additional checks on the options to make sure they were passed correctly. To validate the types of the options, call -:method:`Symfony\\Component\\OptionsResolver\\Options::validateTypes`:: - +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedTypes`:: + // ... class Mailer { // ... - public function __construct(array $options = array()) + protected function configureOptions(OptionsResolver $resolver) { // ... - Options::validateTypes($options, array( - 'host' => 'string', - 'port' => array('null', 'int'), - )); - - $this->options = Options::resolve($options, array( - 'host' => null, - 'username' => 'user', - 'password' => 'pa$$word', - 'port' => 25, - )); + $resolver->setAllowedTypes('host', 'string'); + $resolver->setAllowedTypes('port', array('null', 'int')); } } @@ -186,7 +332,8 @@ For each option, you can define either just one type or an array of acceptable types. You can pass any type for which an ``is_()`` method is defined. Additionally, you may pass fully qualified class or interface names. -If you pass an invalid option now, an :class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException` +If you pass an invalid option now, an +:class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException` is thrown:: $mailer = new Mailer(array( @@ -196,34 +343,40 @@ is thrown:: // InvalidOptionsException: The option "host" with value "25" is expected to // be of type "string" +In sub-classes, you can use :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::addAllowedTypes` +to add additional allowed types without erasing the ones already set. + +.. versionadded:: 2.6 + Before Symfony 2.6, `setAllowedTypes()` and `addAllowedTypes()` expected + the values to be given as an array mapping option names to allowed types: + + .. code-block:: php + + $resolver->setAllowedTypes(array('port' => array('null', 'int'))); + Value Validation ~~~~~~~~~~~~~~~~ Some options can only take one of a fixed list of predefined values. For example, suppose the ``Mailer`` class has a ``transport`` option which can be one of ``sendmail``, ``mail`` and ``smtp``. Use the method -:method:`Symfony\\Component\\OptionsResolver\\Options::validateValues` to verify +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedValues` to verify that the passed option contains one of these values:: // ... class Mailer { // ... - public function __construct(array $options = array()) + protected function configureOptions(OptionsResolver $resolver) { // ... - Options::validateValues($options, array( - 'transport' => array('sendmail', 'mail', 'smtp'), - )); - - $this->options = Options::resolve($options, array( - // ... - 'transport' => 'sendmail', - )); + $resolver->setDefault('transport', 'sendmail'); + $resolver->setAllowedValues('transport', array('sendmail', 'mail', 'smtp')); } } -If you pass an invalid transport, an :class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException` +If you pass an invalid transport, an +:class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException` is thrown:: $mailer = new Mailer(array( @@ -233,467 +386,330 @@ is thrown:: // InvalidOptionsException: The option "transport" has the value "send-mail", // but is expected to be one of "sendmail", "mail", "smtp" -For options with more complicated validation schemes, pass a callback which +For options with more complicated validation schemes, pass a closure which returns ``true`` for acceptable values and ``false`` for invalid values:: - Options::validateValues($options, array( + $resolver->setAllowedValues(array( // ... - 'transport' => function ($value) { + $resolver->setAllowedValues('transport', function ($value) { // return true or false - }, + }); )); -Default Values that Depend on another Option -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In sub-classes, you can use :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::addAllowedValues` +to add additional allowed values without erasing the ones already set. -Suppose you want to set the default value of the ``port`` option based on the -encryption chosen by the user of the ``Mailer`` class. More precisely, we want -to set the port to ``465`` if SSL is used and to ``25`` otherwise. +.. versionadded:: 2.6 + Before Symfony 2.6, `setAllowedValues()` and `addAllowedValues()` expected + the values to be given as an array mapping option names to allowed values: -You can implement this feature by passing a closure as default value of the -``port`` option. The closure receives the options as argument. Based on these -options, you can return the desired default value:: + .. code-block:: php + + $resolver->setAllowedValues(array('transport' => array('sendmail', 'mail', 'smtp'))); + +Option Normalization +~~~~~~~~~~~~~~~~~~~~ + +Sometimes, option values need to be normalized before you can use them. For +instance, assume that the ``host`` should always start with ``http://``. To do +that, you can write normalizers. Normalizers are executed after validating an +option. You can configure a normalizer by calling +:method:`Symfony\\Components\\OptionsResolver\\OptionsResolver::setNormalizer`:: // ... class Mailer { // ... - public function __construct(array $options = array()) + protected function configureOptions(OptionsResolver $resolver) { // ... + $resolver->setNormalizer('host', function ($options, $value) { + if ('http://' !== substr($value, 0, 7)) { + $value = 'http://'.$value; + } - $this->options = Options::resolve($options, new Options(array( - // ... - 'encryption' => null, - 'port' => function (Options $options) { - if ('ssl' === $options['encryption']) { - return 465; - } - - return 25; - }, - ))); + return $value; + }); } } -Instead of a simple array, we now pass the default options as -:class:`Symfony\\Component\\OptionsResolver\\Options` instance to -:method:`Symfony\\Component\\OptionsResolver\\Options::resolve`. This class -makes sure that the closure stored in the default value of the ``port`` option -is called. In the closure, you can use the -:class:`Symfony\\Component\\OptionsResolver\\Options` instance just like a -normal option array. - -.. caution:: - - The first argument of the closure must be type hinted as ``Options``. - Otherwise, the closure is considered as the default value of the option. - If the closure is still not called, double check that you passed the default - options as :class:`Symfony\\Component\\OptionsResolver\\Options` instance. - -.. note:: - - The closure is only executed if the ``port`` option isn't set by the user. - -Coding Patterns -~~~~~~~~~~~~~~~ +.. versionadded:: 2.6 + The method :method:`Symfony\\Components\\OptionsResolver\\OptionsResolver::setNormalizer` + was introduced in Symfony 2.6. Before, you had to use + :method:`Symfony\\Components\\OptionsResolver\\OptionsResolver::setNormalizers`. -If you have a large list of options, the option processing code can take up a -lot of space of your method. To make your code easier to read and maintain, it -is a good practice to put the option definitions into static class properties:: +The normalizer receives the actual ``$value`` and returns the normalized form. +You see that the closure also takes an ``$options`` parameter. This is useful +if you need to use other options during normalization:: // ... class Mailer { - private static $defaultOptions = array( - 'host' => null, - 'username' => 'user', - 'password' => 'pa$$word', - 'port' => 25, - 'encryption' => null, - ); - - private static $requiredOptions = array( - 'host', - ); - - private static $optionTypes = array( - 'host' => 'string', - 'username' => 'string', - 'password' => 'string', - 'port' => 'int', - ); - - private static $optionValues = array( - 'encryption' => array(null, 'ssl', 'tls'), - ); - - protected $options; - - public function __construct(array $options = array()) + // ... + protected function configureOptions(OptionsResolver $resolver) { - Options::validateRequired($options, static::$requiredOptions); - Options::validateTypes($options, static::$optionTypes); - Options::validateValues($options, static::$optionValues); + // ... + $resolver->setNormalizer('host', function ($options, $value) { + if (!in_array(substr($value, 0, 7), array('http://', 'https://'))) { + if ('ssl' === $options['encryption']) { + $value = 'https://'.$value; + } else { + $value = 'http://'.$value; + } + } - $this->options = Options::resolve($options, static::$defaultOptions); + return $value; + }); } } -In this way, the class remains easy to read and maintain even with a lot of -options being processed and validated. +Default Values that Depend on another Option +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Suppose you want to set the default value of the ``port`` option based on the +encryption chosen by the user of the ``Mailer`` class. More precisely, we want +to set the port to ``465`` if SSL is used and to ``25`` otherwise. -.. caution:: +You can implement this feature by passing a closure as default value of the +``port`` option. The closure receives the options as argument. Based on these +options, you can return the desired default value:: - PHP does not support closures in property definitions. In such cases, you - must move your closure to a static method:: + use Symfony\Component\OptionsResolver\Options; - private static $defaultOptions = array( + // ... + class Mailer + { + // ... + protected function configureOptions(OptionsResolver $resolver) + { // ... - 'port' => array(__CLASS__, 'getDefaultPort'), - ); + $resolver->setDefault('encryption', null); - public static function getDefaultPort(Options $options) - { - if ('ssl' === $options['encryption']) { - return 465; - } + $resolver->setDefault('port', function (Options $options) { + if ('ssl' === $options['encryption']) { + return 465; + } - return 25; + return 25; + }); } + } -Decoupling the Option Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. caution:: -So far, the configuration of the options, their allowed types etc. was very -tightly coupled to the code that resolves the options. This is fine in most cases. -In some cases, however, the configuration of options must be distributed across -multiple classes. An example is a class hierarchy that supports the addition of -options by subclasses. In those cases, you can create an -:class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` object and pass that -object everywhere that you want to adjust the option configuration. Then, call -:method:`Symfony\\Component\\OptionsResolver\\Options::resolve` with the -configuration object to resolve the options. + The argument of the callable must be type hinted as ``Options``. Otherwise, + the callable is considered as the default value of the option. -The following code demonstrates how to write our previous ``Mailer`` class with -an :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` object:: +.. note:: - // ... - use Symfony\Component\OptionsResolver\OptionsConfig; + The closure is only executed if the ``port`` option isn't set by the user + or overwritten in a sub-class. + +A previously set default value can be accessed by adding a second argument to +the closure:: + // ... class Mailer { - protected $options; - - public function __construct(array $options = array()) - { - $config = new OptionsConfig(); - $this->configureOptions($config); - - $this->options = Options::resolve($options, $config); - } - - protected function configureOptions(OptionsConfig $config) + // ... + protected function configureOptions(OptionsResolver $resolver) { - $config->setDefaults(array( - 'host' => null, - 'username' => 'user', - 'password' => 'pa$$word', - 'port' => 25, + // ... + $resolver->setDefaults(array( 'encryption' => null, - )); - - $config->setRequired(array( - 'host', - )); - - $config->setAllowedTypes(array( - 'host' => 'string', - 'username' => 'string', - 'password' => 'string', - 'port' => 'int', - )); - - $config->setAllowedValues(array( - 'encryption' => array(null, 'ssl', 'tls'), + 'host' => 'example.org', )); } } -As you can see, the code is very similar as before. However, the performance -is marginally worse, since the creation of an additional object is required: -the :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` instance. - -Nevertheless, this design also has a benefit: We can extend the ``Mailer`` -class and adjust the options of the parent class in the subclass:: - - // ... class GoogleMailer extends Mailer { - protected function configureOptions(OptionsConfig $config) + protected function configureOptions(OptionsResolver $resolver) { - $config->setDefaults(array( - 'host' => 'smtp.google.com', - 'port' => 25, - 'encryption' => 'ssl', - )); + parent::configureOptions($resolver); - $config->setRequired(array( - 'username', - 'password', - )); + $options->setDefault('host', function (Options $options, $previousValue) { + if ('ssl' === $options['encryption']) { + return 'secure.example.org' + } + + // Take default value configured in the base class + return $previousValue; + }); } } -The ``host`` option is no longer required now, but defaults to "smtp.google.com". -The ``username`` and ``password`` options, however, are required in the -subclass. - -The :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` has various -useful methods to find out which options are set or required. Check out the -API documentation to find out more about these methods. +As seen in the example, this feature is mostly useful if you want to reuse the +default values set in parent classes in sub-classes. -.. note:: +Options without Default Values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` class used - by the Form Component inherits from - :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig`. All the - documentation for ``OptionsConfig`` applies to ``OptionsResolver`` as well. - -Optional Options -~~~~~~~~~~~~~~~~ - -The :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` has one feature -that is not available when not using this class: You can specify optional -options. Optional options will be accepted and validated when set. When not set, -however, *no default value* will be added to the options array. Pass the names -of the optional options to -:method:`Symfony\\Component\\OptionsResolver\\OptionsConfig::setOptional`:: +In some cases, it is useful to define an option without setting a default value. +Mostly, you will need this when you want to know whether an option was passed +or not. If you set a default value for that option, this is not possible:: // ... class Mailer { // ... - protected function configureOptions(OptionsConfig $config) + protected function configureOptions(OptionsResolver $resolver) { // ... + $resolver->setDefault('port', 25); + } - $config->setOptional(array('port')); + // ... + public function sendMail($from, $to) + { + // Is this the default value or did the caller of the class really + // set the port to 25? + if (25 === $this->options['port']) { + // ... + } } } -This is useful if you need to know whether an option was explicitly passed. If -not, it will be missing from the options array:: +.. versionadded:: 2.6 + The method :method:`Symfony\\Components\\OptionsResolver\\OptionsResolver::setDefined` + was introduced in Symfony 2.6. Before, you had to use + :method:`Symfony\\Components\\OptionsResolver\\OptionsResolver::setOptional`. + +You can use :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setDefined` +to define an option without setting a default value. Then the option will only +be included in the resolved options if it was actually passed to +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::resolve`:: // ... class Mailer { // ... - public function __construct(array $options = array()) + protected function configureOptions(OptionsResolver $resolver) { // ... + $resolver->setDefined('port'); + } + // ... + public function sendMail($from, $to) + { if (array_key_exists('port', $this->options)) { - echo "Set!"; + echo 'Set!'; } else { - echo "Not Set!"; + echo 'Not Set!'; } } } + $mailer = new Mailer(); + $mailer->sendMail($from, $to); + // => Not Set! + $mailer = new Mailer(array( 'port' => 25, )); - // Set! - - $mailer = new Mailer(); - // Not Set! - -.. tip:: + $mailer->sendMail($from, $to); + // => Set! - If you need this functionality when not using an - :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` object, check - the options before calling - :method:`Symfony\\Component\\OptionsResolver\\Options::resolve`:: - - // ... - class Mailer - { - // ... - public function __construct(array $options = array()) - { - // ... - - if (array_key_exists('port', $options)) { - echo "Set!"; - } else { - echo "Not Set!"; - } - - $this->options = Options::resolve($options, array( - // ... - )); - } - } - -Overwriting Default Values -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A previously set default value can be overwritten by invoking -:method:`Symfony\\Component\\OptionsResolver\\OptionsConfig::setDefaults` -again. When using a closure as the new value it is passed 2 arguments: - -* ``$options``: an :class:`Symfony\\Component\\OptionsResolver\\Options` - instance with all the other default options -* ``$previousValue``: the previously set default value - -.. code-block:: php +You can also pass an array of option names if you want to define multiple +options in one go:: // ... class Mailer { // ... - protected function configureOptions(OptionsConfig $config) + protected function configureOptions(OptionsResolver $resolver) { // ... - $config->setDefaults(array( - 'encryption' => 'ssl', - 'host' => 'localhost', - )); - - // ... - $config->setDefaults(array( - 'encryption' => 'tls', // simple overwrite - 'host' => function (Options $options, $previousValue) { - return 'localhost' == $previousValue - ? '127.0.0.1' - : $previousValue; - }, - )); + $resolver->setDefined(array('port', 'encryption')); } } -.. tip:: +.. versionadded:: 2.6 + The method :method:`Symfony\\Components\\OptionsResolver\\OptionsResolver::isDefined` + and :method:`Symfony\\Components\\OptionsResolver\\OptionsResolver::getDefinedOptions` + were introduced in Symfony 2.6. - If the previous default value is calculated by an expensive closure and - you don't need access to it, use the - :method:`Symfony\\Component\\OptionsResolver\\OptionsConfig::replaceDefaults` - method instead. It acts like ``setDefaults`` but erases the previous value - to improve performance. This means that the previous default value is not - available when overwriting with another closure:: +The methods :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isDefined` +and :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::getDefinedOptions` +let you find out which options are defined:: - // ... - class Mailer + // ... + class GoogleMailer extends Mailer + { + protected function configureOptions(OptionsResolver $resolver) { - // ... - protected function configureOptions(OptionsConfig $config) - { - // ... - $config->setDefaults(array( - 'encryption' => 'ssl', - 'heavy' => function (Options $options) { - // Some heavy calculations to create the $result - - return $result; - }, - )); - - $config->replaceDefaults(array( - 'encryption' => 'tls', // simple overwrite - 'heavy' => function (Options $options) { - // $previousValue not available - // ... - - return $someOtherResult; - }, - )); - } - } + parent::configureOptions($resolver); -.. note:: + if ($resolver->isDefined('host')) { + // One of the following was called: - Existing option keys that you do not mention when overwriting are preserved. + // $resolver->setDefault('host', ...); + // $resolver->setRequired('host'); + // $resolver->setDefined('host'); + } -Option Normalization -~~~~~~~~~~~~~~~~~~~~ + $definedOptions = $resolver->getDefinedOptions(); + } + } + +Performance Tweaks +~~~~~~~~~~~~~~~~~~ -Some values need to be normalized before you can use them. For instance, -assume that the ``host`` should always start with ``http://``. To do that, -you can write normalizers. Normalizers are executed after all options were -processed. You can configure these normalizers by calling -:method:`Symfony\\Components\\OptionsResolver\\OptionsConfig::setNormalizers`:: +With the current implementation, the ``configureOptions()`` method will be +called for every single instance of the ``Mailer`` class. Depending on the +amount of option configuration and the number of created instances, this may add +noticeable overhead to your application. If that overhead becomes a problem, you +can change your code to do the configuration only once per class:: // ... class Mailer { - // ... - protected function configureOptions(OptionsConfig $config) + private static $resolversByClass = array(); + + protected $options; + + public function __construct(array $options = array()) { - // ... + // Are we a Mailer, a GoogleMailer, ... ? + $class = get_class($this); - $config->setNormalizers(array( - 'host' => function (Options $options, $value) { - if ('http://' !== substr($value, 0, 7)) { - $value = 'http://'.$value; - } + // Did we call configureOptions() before for this class? + if (!isset(self::$resolversByClass[$class])) { + self::$resolversByClass[$class] = new OptionsResolver(); + $this->configureOptions(self::$resolversByClass[$class]); + } - return $value; - }, - )); + $this->options = self::$resolversByClass[$class]->resolve($options); } - } -The normalizer receives the actual ``$value`` and returns the normalized form. -You see that the closure also takes an ``$options`` parameter. This is useful -if you need to use other options for the normalization:: - - // ... - class Mailer - { - // ... - protected function configureOptions(OptionsConfig $config) + protected function configureOptions(OptionsResolver $resolver) { // ... - - $config->setNormalizers(array( - 'host' => function (Options $options, $value) { - if (!in_array(substr($value, 0, 7), array('http://', 'https://'))) { - if ($options['ssl']) { - $value = 'https://'.$value; - } else { - $value = 'http://'.$value; - } - } - - return $value; - }, - )); } } -.. tip:: +Now the :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` instance +will be created once per class and reused from that on. Be aware that this may +lead to memory leaks in long-running applications, if the default options contain +references to objects or object graphs. If that's the case for you, implement a +method ``clearDefaultOptions()`` and call it periodically:: - When not using an :class:`Symfony\\Component\\OptionsResolver\\OptionsConfig` - object, perform normalization after the call to - :method:`Symfony\\Component\\OptionsResolver\\Options::resolve`:: + // ... + class Mailer + { + private static $resolversByClass = array(); - // ... - class Mailer + public static function clearDefaultOptions() { - // ... - public function __construct(array $options = array()) - { - $this->options = Options::resolve($options, array( - // ... - )); - - if ('http://' !== substr($this->options['host'], 0, 7)) { - $this->options['host'] = 'http://'.$this->options['host']; - } - } + self::$resolversByClass = array(); } + // ... + } + That's it! You now have all the tools and knowledge needed to easily process options in your code. .. _Packagist: https://packagist.org/packages/symfony/options-resolver +.. _Form component: http://symfony.com/doc/current/components/form/introduction.html From 1a410e496c004de866de35367d785c6a80258b85 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Thu, 23 Oct 2014 11:26:28 +0200 Subject: [PATCH 0446/1181] Fixed sentence --- components/console/changing_default_command.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/console/changing_default_command.rst b/components/console/changing_default_command.rst index 1c191ba8571..757a0c9f88c 100644 --- a/components/console/changing_default_command.rst +++ b/components/console/changing_default_command.rst @@ -8,9 +8,9 @@ Changing the Default Command The :method:`Symfony\\Component\\Console\\Application::setDefaultCommand` method was introduced in Symfony 2.5. -will always run the ``ListCommand`` when no command name is passed. In order to change -the default command you just need to pass the command name you want to run by -default to the ``setDefaultCommand`` method:: +The Console component will always run the ``ListCommand`` when no command name is +passed. In order to change the default command you just need to pass the command +name to the ``setDefaultCommand`` method:: namespace Acme\Console\Command; From d190831c8918a17126588aa75960c8f6f2647b91 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 25 Oct 2014 12:50:50 -0400 Subject: [PATCH 0447/1181] Tweaks after proofreading the 2.6 OptionsResolver stuff --- components/options_resolver.rst | 36 ++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index ea1372f4ea6..d11c4965752 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -5,7 +5,9 @@ The OptionsResolver Component ============================= - The OptionsResolver component is `array_replace()` on steroids. + The OptionsResolver component is `array_replace()` on steroids. It + allows you to create an options system with required options, defaults, + validation (type, value), normalization and more. Installation ------------ @@ -21,7 +23,7 @@ Notes on Previous Versions .. versionadded:: 2.6 This documentation was written for Symfony 2.6 and later. If you use an older version, please read the corresponding documentation using the version - drop-down on the upper right. + drop-down on the upper right. For a list of changes, see the `CHANGELOG`_ Usage ----- @@ -65,7 +67,7 @@ check which options are set:: } This boilerplate is hard to read and repetitive. Also, the default values of the -options are buried in the business logic of your code. We can use +options are buried in the business logic of your code. We can use the :phpfunction:`array_replace` to fix that:: class Mailer @@ -91,10 +93,9 @@ the ``Mailer`` class does a mistake? 'usernme' => 'johndoe', )); -No error will be shown. In the best case, the bug will be appear during testing. -The developer will possibly spend a lot of time looking for the problem. In the -worst case, however, the bug won't even appear and will be deployed to the live -system. +No error will be shown. In the best case, the bug will appear during testing, +but the developer will spend time looking for the problem. In the worst case, +the bug might not appear until it's deployed to the live system. Let's use the :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` class to fix this problem:: @@ -268,8 +269,8 @@ retrieve the names of all required options:: If you want to check whether a required option is still missing from the default options, you can use :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isMissing`. -The difference to :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isRequired` -is that this method will return false for required options that have already +The difference between this and :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isRequired` +is that this method will return false if a required option has already been set:: // ... @@ -360,8 +361,8 @@ Value Validation Some options can only take one of a fixed list of predefined values. For example, suppose the ``Mailer`` class has a ``transport`` option which can be one of ``sendmail``, ``mail`` and ``smtp``. Use the method -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedValues` to verify -that the passed option contains one of these values:: +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedValues` +to verify that the passed option contains one of these values:: // ... class Mailer @@ -470,9 +471,9 @@ Suppose you want to set the default value of the ``port`` option based on the encryption chosen by the user of the ``Mailer`` class. More precisely, we want to set the port to ``465`` if SSL is used and to ``25`` otherwise. -You can implement this feature by passing a closure as default value of the -``port`` option. The closure receives the options as argument. Based on these -options, you can return the desired default value:: +You can implement this feature by passing a closure as the default value of +the ``port`` option. The closure receives the options as argument. Based on +these options, you can return the desired default value:: use Symfony\Component\OptionsResolver\Options; @@ -546,8 +547,10 @@ Options without Default Values ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In some cases, it is useful to define an option without setting a default value. -Mostly, you will need this when you want to know whether an option was passed -or not. If you set a default value for that option, this is not possible:: +This is useful if you need to know whether or not the user *actually* set +an option or not. For example, if you set the default value for an option, +it's not possible to know whether the user passed this value or if it simply +comes from the default:: // ... class Mailer @@ -713,3 +716,4 @@ options in your code. .. _Packagist: https://packagist.org/packages/symfony/options-resolver .. _Form component: http://symfony.com/doc/current/components/form/introduction.html +.. _CHANGELOG: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/OptionsResolver/CHANGELOG.md From 59fd436a5705702d71e3bfbf2f9b3aad0abca0bb Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sat, 25 Oct 2014 19:54:56 +0200 Subject: [PATCH 0448/1181] Also did a quick proofread --- components/options_resolver.rst | 63 +++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index d11c4965752..dd6229e0a78 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -5,8 +5,8 @@ The OptionsResolver Component ============================= - The OptionsResolver component is `array_replace()` on steroids. It - allows you to create an options system with required options, defaults, + The OptionsResolver component is :phpfunction:`array_replace` on steroids. + It allows you to create an options system with required options, defaults, validation (type, value), normalization and more. Installation @@ -23,7 +23,7 @@ Notes on Previous Versions .. versionadded:: 2.6 This documentation was written for Symfony 2.6 and later. If you use an older version, please read the corresponding documentation using the version - drop-down on the upper right. For a list of changes, see the `CHANGELOG`_ + drop-down on the upper right. For a list of changes, see the `CHANGELOG`_. Usage ----- @@ -50,29 +50,35 @@ check which options are set:: public function sendMail($from, $to) { $mail = ...; + $mail->setHost(isset($this->options['host']) ? $this->options['host'] : 'smtp.example.org'); + $mail->setUsername(isset($this->options['username']) ? $this->options['username'] : 'user'); + $mail->setPassword(isset($this->options['password']) ? $this->options['password'] : 'pa$$word'); + $mail->setPort(isset($this->options['port']) ? $this->options['port'] : 25); + // ... } } This boilerplate is hard to read and repetitive. Also, the default values of the -options are buried in the business logic of your code. We can use the +options are buried in the business logic of your code. You could use the :phpfunction:`array_replace` to fix that:: class Mailer { // ... + public function __construct(array $options = array()) { $this->options = array_replace(array( @@ -85,7 +91,7 @@ options are buried in the business logic of your code. We can use the } Now all four options are guaranteed to be set. But what happens if the user of -the ``Mailer`` class does a mistake? +the ``Mailer`` class makes a mistake? .. code-block:: php @@ -97,14 +103,15 @@ No error will be shown. In the best case, the bug will appear during testing, but the developer will spend time looking for the problem. In the worst case, the bug might not appear until it's deployed to the live system. -Let's use the :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` -class to fix this problem:: +Fortunately, the :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` +class helps you to fix this problem:: use Symfony\Component\OptionsResolver\Options; class Mailer { // ... + public function __construct(array $options = array()) { $resolver = new OptionsResolver(); @@ -137,6 +144,7 @@ code:: class Mailer { // ... + public function sendMail($from, $to) { $mail = ...; @@ -154,6 +162,7 @@ It's a good practice to split the option configuration into a separate method:: class Mailer { // ... + public function __construct(array $options = array()) { $resolver = new OptionsResolver(); @@ -165,10 +174,10 @@ It's a good practice to split the option configuration into a separate method:: protected function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( - 'host' => 'smtp.example.org', - 'username' => 'user', - 'password' => 'pa$$word', - 'port' => 25, + 'host' => 'smtp.example.org', + 'username' => 'user', + 'password' => 'pa$$word', + 'port' => 25, 'encryption' => null, )); } @@ -197,12 +206,13 @@ Required Options If an option must be set by the caller, pass that option to :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setRequired`. -For example, let's make the ``host`` option required:: +For example, to make the ``host`` option required, you can do:: // ... class Mailer { // ... + protected function configureOptions(OptionsResolver $resolver) { // ... @@ -211,8 +221,8 @@ For example, let's make the ``host`` option required:: } .. versionadded:: 2.6 - Before Symfony 2.6, `setRequired()` accepted only arrays. Since then, single - option names can be passed as well. + As of Symfony 2.6, ``setRequired()`` accepts both an array of options or a + single option. Prior to 2.6, you could only pass arrays. If you omit a required option, a :class:`Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException` @@ -230,6 +240,7 @@ one required option:: class Mailer { // ... + protected function configureOptions(OptionsResolver $resolver) { // ... @@ -277,6 +288,7 @@ been set:: class Mailer { // ... + protected function configureOptions(OptionsResolver $resolver) { // ... @@ -321,6 +333,7 @@ correctly. To validate the types of the options, call class Mailer { // ... + protected function configureOptions(OptionsResolver $resolver) { // ... @@ -330,8 +343,8 @@ correctly. To validate the types of the options, call } For each option, you can define either just one type or an array of acceptable -types. You can pass any type for which an ``is_()`` method is defined. -Additionally, you may pass fully qualified class or interface names. +types. You can pass any type for which an ``is_()`` function is defined +in PHP. Additionally, you may pass fully qualified class or interface names. If you pass an invalid option now, an :class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException` @@ -349,9 +362,7 @@ to add additional allowed types without erasing the ones already set. .. versionadded:: 2.6 Before Symfony 2.6, `setAllowedTypes()` and `addAllowedTypes()` expected - the values to be given as an array mapping option names to allowed types: - - .. code-block:: php + the values to be given as an array mapping option names to allowed types:: $resolver->setAllowedTypes(array('port' => array('null', 'int'))); @@ -368,6 +379,7 @@ to verify that the passed option contains one of these values:: class Mailer { // ... + protected function configureOptions(OptionsResolver $resolver) { // ... @@ -421,9 +433,11 @@ option. You can configure a normalizer by calling class Mailer { // ... + protected function configureOptions(OptionsResolver $resolver) { // ... + $resolver->setNormalizer('host', function ($options, $value) { if ('http://' !== substr($value, 0, 7)) { $value = 'http://'.$value; @@ -468,7 +482,7 @@ Default Values that Depend on another Option ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Suppose you want to set the default value of the ``port`` option based on the -encryption chosen by the user of the ``Mailer`` class. More precisely, we want +encryption chosen by the user of the ``Mailer`` class. More precisely, you want to set the port to ``465`` if SSL is used and to ``25`` otherwise. You can implement this feature by passing a closure as the default value of @@ -499,7 +513,7 @@ these options, you can return the desired default value:: .. caution:: The argument of the callable must be type hinted as ``Options``. Otherwise, - the callable is considered as the default value of the option. + the callable itself is considered as the default value of the option. .. note:: @@ -587,6 +601,7 @@ be included in the resolved options if it was actually passed to class Mailer { // ... + protected function configureOptions(OptionsResolver $resolver) { // ... @@ -640,6 +655,8 @@ let you find out which options are defined:: // ... class GoogleMailer extends Mailer { + // ... + protected function configureOptions(OptionsResolver $resolver) { parent::configureOptions($resolver); @@ -674,10 +691,10 @@ can change your code to do the configuration only once per class:: public function __construct(array $options = array()) { - // Are we a Mailer, a GoogleMailer, ... ? + // What type of Mailer is this, a Mailer, a GoogleMailer, ... ? $class = get_class($this); - // Did we call configureOptions() before for this class? + // Was configureOptions() executed before for this class? if (!isset(self::$resolversByClass[$class])) { self::$resolversByClass[$class] = new OptionsResolver(); $this->configureOptions(self::$resolversByClass[$class]); From 0db5e03b288d1154957768721347e7938101dc6a Mon Sep 17 00:00:00 2001 From: Eugene Leonovich Date: Mon, 27 Oct 2014 12:16:41 +0100 Subject: [PATCH 0449/1181] [OptionsResolver] Fix wrong namespace in example --- components/options_resolver.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index ea1372f4ea6..e0d354ba4fd 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -99,7 +99,7 @@ system. Let's use the :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` class to fix this problem:: - use Symfony\Component\OptionsResolver\Options; + use Symfony\Component\OptionsResolver\OptionsResolver; class Mailer { From f179ec7f6df63e8f76962d8165f14d4d66b42ef6 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 28 Oct 2014 07:17:26 -0700 Subject: [PATCH 0450/1181] A few more tweaks from comments --- components/options_resolver.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index dd6229e0a78..3cb4c42cd1b 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -22,8 +22,8 @@ Notes on Previous Versions .. versionadded:: 2.6 This documentation was written for Symfony 2.6 and later. If you use an older - version, please read the corresponding documentation using the version - drop-down on the upper right. For a list of changes, see the `CHANGELOG`_. + version, please `read the Symfony 2.5 documentation`_. For a list of changes, + see the `CHANGELOG`_. Usage ----- @@ -72,7 +72,7 @@ check which options are set:: } This boilerplate is hard to read and repetitive. Also, the default values of the -options are buried in the business logic of your code. You could use the +options are buried in the business logic of your code. Use the :phpfunction:`array_replace` to fix that:: class Mailer @@ -734,3 +734,4 @@ options in your code. .. _Packagist: https://packagist.org/packages/symfony/options-resolver .. _Form component: http://symfony.com/doc/current/components/form/introduction.html .. _CHANGELOG: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/OptionsResolver/CHANGELOG.md +.. _`read the Symfony 2.5 documentation`: http://symfony.com/doc/2.5/components/options_resolver.html From a1badc5716553ec3e6cb110aa999c67f74d37f20 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 28 Oct 2014 07:17:57 -0700 Subject: [PATCH 0451/1181] Renaming a method at the suggestion of my friend Bernhard --- components/options_resolver.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index 3cb4c42cd1b..4af7e757e68 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -713,14 +713,14 @@ Now the :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` instance will be created once per class and reused from that on. Be aware that this may lead to memory leaks in long-running applications, if the default options contain references to objects or object graphs. If that's the case for you, implement a -method ``clearDefaultOptions()`` and call it periodically:: +method ``clearOptionsConfig()`` and call it periodically:: // ... class Mailer { private static $resolversByClass = array(); - public static function clearDefaultOptions() + public static function clearOptionsConfig() { self::$resolversByClass = array(); } From 28eefe22b4aa2be70e3d0863a4e2e54391fef2cb Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 28 Oct 2014 07:23:22 -0700 Subject: [PATCH 0452/1181] [#4299] Very minor language tweak --- components/serializer.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/serializer.rst b/components/serializer.rst index 4508482f88f..0d26457d0aa 100644 --- a/components/serializer.rst +++ b/components/serializer.rst @@ -301,7 +301,7 @@ Circular references are common when dealing with entity relations:: To avoid infinite loops, :class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer` throws a :class:`Symfony\\Component\\Serializer\\Exception\\CircularReferenceException` -when such case is encountered:: +when such a case is encountered:: $member = new Member(); $member->setName('Kévin'); @@ -315,8 +315,8 @@ when such case is encountered:: echo $serializer->serialize($org, 'json'); // Throws a CircularReferenceException The ``setCircularReferenceLimit()`` method of this normalizer sets the number -of times serializing the same object must occur before considering being -in a circular reference. Its default value is ``1``. +of times it will serialize the same object before considering it a circular +reference. Its default value is ``1``. Instead of throwing an exception, circular references can also be handled by custom callables. This is especially useful when serializing entities From b49731bc179d3fa16f48c0525b232444e9c30dd8 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 28 Oct 2014 07:24:54 -0700 Subject: [PATCH 0453/1181] Linking to the 2.6 headline thanks to a suggestion from @xabbuh --- components/options_resolver.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index 4af7e757e68..7e85bf3c3cf 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -733,5 +733,5 @@ options in your code. .. _Packagist: https://packagist.org/packages/symfony/options-resolver .. _Form component: http://symfony.com/doc/current/components/form/introduction.html -.. _CHANGELOG: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/OptionsResolver/CHANGELOG.md +.. _CHANGELOG: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/OptionsResolver/CHANGELOG.md#260 .. _`read the Symfony 2.5 documentation`: http://symfony.com/doc/2.5/components/options_resolver.html From 5f8b13c461a10eff10fb5744e7e9e7d5153ba9fa Mon Sep 17 00:00:00 2001 From: luciantugui Date: Tue, 28 Oct 2014 21:32:11 +0100 Subject: [PATCH 0454/1181] Update custom_constraint.rst --- cookbook/validation/custom_constraint.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/cookbook/validation/custom_constraint.rst b/cookbook/validation/custom_constraint.rst index caf582a4eee..f95d311ed20 100644 --- a/cookbook/validation/custom_constraint.rst +++ b/cookbook/validation/custom_constraint.rst @@ -69,7 +69,6 @@ The validator class is also simple, and only has one required method ``validate( $this->context->buildViolation($constraint->message) ->setParameter('%string%', $value) ->addViolation(); - ); // If you're using the old 2.4 validation API /* From ee2d7e473df3fea1929ca44bff1559cfb4b03276 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 29 Oct 2014 10:10:58 +0100 Subject: [PATCH 0455/1181] section for DebugBundle/Twig integration --- components/var_dumper/advanced.rst | 12 +++++++ components/var_dumper/introduction.rst | 48 +++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/components/var_dumper/advanced.rst b/components/var_dumper/advanced.rst index bf15c1bfe79..c0b3dd9c953 100644 --- a/components/var_dumper/advanced.rst +++ b/components/var_dumper/advanced.rst @@ -77,6 +77,18 @@ For example, to get a dump as a string in a variable, you can do:: // $output is now populated with the dump representation of $variable +An other option for doing the same could be:: + + $output = fopen('php://memory', 'r+b'); + cloner = new VarCloner(); + $dumper = new CliDumper($output); + + $dumper->dump($cloner->cloneVar($variable)); + fseek($output, 0); + $output = stream_get_contents($output); + + // $output is now populated with the dump representation of $variable + Dumpers implement the :class:`Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface` interface that specifies the :method:`dump(Data $data) ` diff --git a/components/var_dumper/introduction.rst b/components/var_dumper/introduction.rst index 1b4669cc83c..bd48be2809d 100644 --- a/components/var_dumper/introduction.rst +++ b/components/var_dumper/introduction.rst @@ -45,6 +45,52 @@ The advantages of this function are: so can you also use it directly. You can change the behavior of this function by calling :method:`VarDumper::setHandler($callable) `: -calls to ``dump()`` will then be forwarded to ``$callable``, given as first argument. +calls to ``dump()`` will then be forwarded to ``$callable``. + +Where does the output go? +------------------------- + +If you read the advanced documentation, you'll learn how to change the +format or redirect the output to wherever you want. + +By default, these are selected based on your current PHP SAPI: + +- on the command line (CLI SAPI), the output is written on `STDERR`. This + can be surprising to some because this bypasses PHP's output buffering + mechanism. On the other hand, this give the possibility to easily split + dumps from regular output by using pipe redirection. +- on other SAPIs, dumps are written as HTML on the regular output. + +DebugBundle and Twig integration +-------------------------------- + +The `DebugBundle` allows greater integration of the component into the +Symfony full stack framework. It is enabled by default in the dev +environement of the standard edition since version 2.6. + +Since generating (even debug) output in the controller or in the model +of your application may just break it by e.g. sending HTTP headers or +corrupting your view, the bundle configures the `dump()` function so that +variables are dumped in the web debug toolbar. + +But if the toolbar can not be displayed because you e.g. called `die`/`exit` +or a fatal error occurred, then dumps are written on the regular output. + +In a Twig template, two constructs are available for dumping a variable. +Choosing between both is generally only a matter of personal taste: + +- `{% dump foo.bar %}` is the way to go when the original template output + shall not be modified: variables are not dumped inline, but in the web + debug toolbar. +- on the contrary, `{{ dump(foo.bar) }}` dumps inline and thus may or not + be suited to your use case (e.g. you shouldn't use it in an HTML + attribute or a `script` tag). + +Reading a dump +-------------- + +For simple variables, reading the output should be straightforward:: + + dump(array(true, 1.1, "string")); .. _Packagist: https://packagist.org/packages/symfony/var-dumper From 4e6256b565b2e4de8f30f334ff22e60bd1e100ee Mon Sep 17 00:00:00 2001 From: Warnar Boekkooi Date: Wed, 29 Oct 2014 16:50:48 +0800 Subject: [PATCH 0456/1181] Removed unused use UsernameNotFoundException --- cookbook/security/api_key_authentication.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/cookbook/security/api_key_authentication.rst b/cookbook/security/api_key_authentication.rst index 0feefca9a4b..8fb6dfbdb38 100644 --- a/cookbook/security/api_key_authentication.rst +++ b/cookbook/security/api_key_authentication.rst @@ -31,7 +31,6 @@ value and then a User object is created:: use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\User\UserProviderInterface; - use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\BadCredentialsException; class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface From cb0ee899f51df62e72063e54f833ea33dcd5637b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 29 Oct 2014 20:30:04 +0100 Subject: [PATCH 0457/1181] =?UTF-8?q?=C2=A7=20about=20Data::getLimitedClon?= =?UTF-8?q?e()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/var_dumper/advanced.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/components/var_dumper/advanced.rst b/components/var_dumper/advanced.rst index c0b3dd9c953..70bf85e5198 100644 --- a/components/var_dumper/advanced.rst +++ b/components/var_dumper/advanced.rst @@ -27,6 +27,23 @@ Before cloning, you can configure the limits with:: They will be applied when calling ``->cloneVar()`` afterwards. +Before dumping it, you can further limit the resulting +:class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object by calling its +:method:`Symfony\\Component\\VarDumper\\Cloner\\Data::getLimitedClone` +method: +- the first `$maxDepth` argument allows limiting dumps in the depth dimension, +- the second `$maxItemsPerDepth` limits the number of items per depth level, +- and the last `$useRefHandles` defaults to `true` but allows removing internal + objects' handles for sparser output, +- but unlike the previous limits on cloners that remove data on purpose, these + limits can be changed back and forth before dumping since they do not affect + the intermediate representation internally. + +.. note:: + When no limit is applied, a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` + object is as accurate as the native :phpfunction:`serialize` function and thus + could have a wider purpose than strictly dumping for debugging. + Dumpers ~~~~~~~ From 6a3e17088332f9dc499aa765fe6877584893b4d3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 30 Oct 2014 09:51:00 +0100 Subject: [PATCH 0458/1181] =?UTF-8?q?=C2=A7=20about=20DebugBundle=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/var_dumper/advanced.rst | 7 ++-- components/var_dumper/introduction.rst | 56 +++++++++++++++++--------- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/components/var_dumper/advanced.rst b/components/var_dumper/advanced.rst index 70bf85e5198..29aff0c31da 100644 --- a/components/var_dumper/advanced.rst +++ b/components/var_dumper/advanced.rst @@ -31,9 +31,10 @@ Before dumping it, you can further limit the resulting :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object by calling its :method:`Symfony\\Component\\VarDumper\\Cloner\\Data::getLimitedClone` method: -- the first `$maxDepth` argument allows limiting dumps in the depth dimension, -- the second `$maxItemsPerDepth` limits the number of items per depth level, -- and the last `$useRefHandles` defaults to `true` but allows removing internal + +- the first ``$maxDepth`` argument allows limiting dumps in the depth dimension, +- the second ``$maxItemsPerDepth`` limits the number of items per depth level, +- and the last ``$useRefHandles`` defaults to ``true`` but allows removing internal objects' handles for sparser output, - but unlike the previous limits on cloners that remove data on purpose, these limits can be changed back and forth before dumping since they do not affect diff --git a/components/var_dumper/introduction.rst b/components/var_dumper/introduction.rst index bd48be2809d..2c2ae679899 100644 --- a/components/var_dumper/introduction.rst +++ b/components/var_dumper/introduction.rst @@ -23,11 +23,8 @@ You can install the component in 2 different ways: The dump() function ------------------- -The VarDumper component creates a global ``dump()`` function that is -configured out of the box: HTML or CLI output is automatically selected based -on the current PHP SAPI. - -The advantages of this function are: +The VarDumper component creates a global ``dump()`` function that you can +use instead of e.g. :phpfunction:`var_dump`. By using it, you'll gain: - per object and resource types specialized view to e.g. filter out Doctrine internals while dumping a single proxy entity, or get more @@ -47,44 +44,67 @@ You can change the behavior of this function by calling :method:`VarDumper::setHandler($callable) `: calls to ``dump()`` will then be forwarded to ``$callable``. -Where does the output go? -------------------------- +Output format and destination +----------------------------- -If you read the advanced documentation, you'll learn how to change the -format or redirect the output to wherever you want. +If you read the `advanced documentation `, you'll learn how to +change the format or redirect the output to wherever you want. By default, these are selected based on your current PHP SAPI: -- on the command line (CLI SAPI), the output is written on `STDERR`. This +- on the command line (CLI SAPI), the output is written on ``STDERR``. This can be surprising to some because this bypasses PHP's output buffering - mechanism. On the other hand, this give the possibility to easily split + mechanism. On the other hand, it give the possibility to easily split dumps from regular output by using pipe redirection. - on other SAPIs, dumps are written as HTML on the regular output. DebugBundle and Twig integration -------------------------------- -The `DebugBundle` allows greater integration of the component into the +The ``DebugBundle`` allows greater integration of the component into the Symfony full stack framework. It is enabled by default in the dev environement of the standard edition since version 2.6. Since generating (even debug) output in the controller or in the model of your application may just break it by e.g. sending HTTP headers or -corrupting your view, the bundle configures the `dump()` function so that +corrupting your view, the bundle configures the ``dump()`` function so that variables are dumped in the web debug toolbar. -But if the toolbar can not be displayed because you e.g. called `die`/`exit` +But if the toolbar can not be displayed because you e.g. called ``die``/``exit`` or a fatal error occurred, then dumps are written on the regular output. In a Twig template, two constructs are available for dumping a variable. -Choosing between both is generally only a matter of personal taste: +Choosing between both is mostly a matter of personal taste, still: -- `{% dump foo.bar %}` is the way to go when the original template output +- ``{% dump foo.bar %}`` is the way to go when the original template output shall not be modified: variables are not dumped inline, but in the web debug toolbar. -- on the contrary, `{{ dump(foo.bar) }}` dumps inline and thus may or not +- on the contrary, ``{{ dump(foo.bar) }}`` dumps inline and thus may or not be suited to your use case (e.g. you shouldn't use it in an HTML - attribute or a `script` tag). + attribute or a ``