Skip to content

Commit ca653aa

Browse files
committed
Merge branch '3.4' into 4.0
* 3.4: Update sessions.rst Removed some repeated content and minor rewords doc(testing/http_authentication.rst); Update locale_sticky_session.rst Undefined variable $userName in example [Cache] minor tweaks Fixed the code of the custom password authenticator example Documented PHPUnit data providers
2 parents cef13f8 + 3fb163c commit ca653aa

File tree

12 files changed

+169
-123
lines changed

12 files changed

+169
-123
lines changed

best_practices/tests.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ functional tests, you can quickly spot any big errors before you deploy them:
2727
Define a functional test that at least checks if your application pages
2828
are successfully loading.
2929

30-
A functional test can be as easy as this::
30+
A functional test like this is simple to implement thanks to
31+
:ref:`PHPUnit data providers <testing-data-providers>`::
3132

3233
// tests/ApplicationAvailabilityFunctionalTest.php
3334
namespace App\Tests;

components/cache.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ The Cache Component
1010

1111
The Cache component provides an extended `PSR-6`_ implementation as well as
1212
a `PSR-16`_ "Simple Cache" implementation for adding cache to your applications.
13-
It is designed to have a low overhead and it ships with ready to use adapters
14-
for the most common caching backends.
13+
It is designed for performance and resiliency, and ships with ready to use
14+
adapters for the most common caching backends, including proxies for adapting
15+
from/to `Doctrine Cache`_.
1516

1617
Installation
1718
------------
@@ -189,4 +190,4 @@ Advanced Usage (PSR-6)
189190

190191
.. _`PSR-6`: http://www.php-fig.org/psr/psr-6/
191192
.. _`PSR-16`: http://www.php-fig.org/psr/psr-16/
192-
.. _Packagist: https://packagist.org/packages/symfony/cache
193+
.. _Doctrine Cache: https://www.doctrine-project.org/projects/cache.html

components/cache/adapters/pdo_doctrine_dbal_adapter.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ third, and forth parameters::
2727
// until the database table is truncated or its rows are otherwise deleted)
2828
$defaultLifetime = 0,
2929

30-
// an array of options for configuring the database connection
30+
// an array of options for configuring the database table and connection
3131
$options = array()
3232
);
3333

components/cache/cache_invalidation.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ several cached items, keeping them in sync can be difficult.
1212

1313
The Symfony Cache component provides two mechanisms to help solving this problem:
1414

15-
* :ref:`Tags based invalidation <cache-component-tags>` for managing data dependencies;
15+
* :ref:`Tags-based invalidation <cache-component-tags>` for managing data dependencies;
1616
* :ref:`Expiration based invalidation <cache-component-expiration>` for time related dependencies.
1717

1818
.. _cache-component-tags:
1919

2020
Using Cache Tags
2121
----------------
2222

23-
To benefit from tags based invalidation, you need to attach the proper tags to
23+
To benefit from tags-based invalidation, you need to attach the proper tags to
2424
each cached item. Each tag is a plain string identifier that you can use at any
2525
time to trigger the removal of all items associated with this tag.
2626

components/cache/cache_pools.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ allowing manual removal of stale cache items::
170170

171171
The :ref:`ChainAdapter <component-cache-chain-adapter>` implementation does not directly
172172
contain any pruning logic itself. Instead, when calling the chain adapter's
173-
:method:`Symfony\\Component\\Cache\\ChainAdapter::prune` method, the call is delegated to all
173+
:method:`Symfony\\Component\\Cache\\Adapter\\ChainAdapter::prune` method, the call is delegated to all
174174
its compatible cache adapters (and those that do not implement ``PruneableInterface`` are
175175
silently ignored)::
176176

components/http_foundation/sessions.rst

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -94,29 +94,12 @@ Session Workflow
9494
Session Attributes
9595
..................
9696

97-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Session::set`
98-
Sets an attribute by key.
97+
The session attributes are stored internally in a "Bag", a PHP object that acts
98+
like an array. They can be set, removed, checked, etc. using the methods
99+
explained later in this article for the ``AttributeBagInterface`` class. See
100+
:ref:`attribute-bag-interface`.
99101

100-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Session::get`
101-
Gets an attribute by key.
102-
103-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Session::all`
104-
Gets all attributes as an array of key => value.
105-
106-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Session::has`
107-
Returns true if the attribute exists.
108-
109-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Session::replace`
110-
Sets multiple attributes at once: takes a keyed array and sets each key => value pair.
111-
112-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Session::remove`
113-
Deletes an attribute by key.
114-
115-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Session::clear`
116-
Clear all attributes.
117-
118-
The attributes are stored internally in a "Bag", a PHP object that acts like
119-
an array. A few methods exist for "Bag" management:
102+
In addition, a few methods exist for "Bag" management:
120103

121104
:method:`Symfony\\Component\\HttpFoundation\\Session\\Session::registerBag`
122105
Registers a :class:`Symfony\\Component\\HttpFoundation\\Session\\SessionBagInterface`.
@@ -168,19 +151,65 @@ the following API which is intended mainly for internal purposes:
168151
:method:`Symfony\\Component\\HttpFoundation\\Session\\SessionBagInterface::getName`
169152
Returns the name of the session bag.
170153

154+
.. _attribute-bag-interface:
155+
171156
Attributes
172157
~~~~~~~~~~
173158

174159
The purpose of the bags implementing the :class:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface`
175160
is to handle session attribute storage. This might include things like user ID,
176-
and remember me login settings or other user based state information.
161+
and "Remember Me" login settings or other user based state information.
177162

178163
:class:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBag`
179164
This is the standard default implementation.
180165

181166
:class:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\NamespacedAttributeBag`
182167
This implementation allows for attributes to be stored in a structured namespace.
183168

169+
:class:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface`
170+
has a simple API
171+
172+
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::set`
173+
Sets an attribute by name (``set('name', 'value')``).
174+
175+
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::get`
176+
Gets an attribute by name (``get('name')``) and can define a default
177+
value when the attribute doesn't exist (``get('name', 'default_value')``).
178+
179+
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::all`
180+
Gets all attributes as an associative array of ``name => value``.
181+
182+
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::has`
183+
Returns ``true`` if the attribute exists.
184+
185+
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::replace`
186+
Sets multiple attributes at once using an associative array (``name => value``).
187+
If the attributes existed, they are replaced; if not, they are created.
188+
189+
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::remove`
190+
Deletes an attribute by name and returns its value.
191+
192+
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::clear`
193+
Deletes all attributes.
194+
195+
Example::
196+
197+
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
198+
use Symfony\Component\HttpFoundation\Session\Session;
199+
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
200+
201+
$session = new Session(new NativeSessionStorage(), new AttributeBag());
202+
$session->set('token', 'a6c1e0b6');
203+
// ...
204+
$token = $session->get('token');
205+
// if the attribute may or may not exist, you can define a default value for it
206+
$token = $session->get('attribute-name', 'default-attribute-value');
207+
// ...
208+
$session->clear();
209+
210+
Namespaced Attributes
211+
.....................
212+
184213
Any plain key-value storage system is limited in the extent to which
185214
complex data can be stored since each key must be unique. You can achieve
186215
namespacing by introducing a naming convention to the keys so different parts of
@@ -205,35 +234,13 @@ the array::
205234
$session->set('tokens', $tokens);
206235

207236
With structured namespacing, the key can be translated to the array
208-
structure like this using a namespace character (defaults to ``/``)::
209-
210-
$session->set('tokens/c', $value);
211-
212-
This way you can easily access a key within the stored array directly and easily.
213-
214-
:class:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface`
215-
has a simple API
216-
217-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::set`
218-
Sets an attribute by key.
219-
220-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::get`
221-
Gets an attribute by key.
222-
223-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::all`
224-
Gets all attributes as an array of key => value.
225-
226-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::has`
227-
Returns true if the attribute exists.
228-
229-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::replace`
230-
Sets multiple attributes at once: takes a keyed array and sets each key => value pair.
237+
structure like this using a namespace character (which defaults to ``/``)::
231238

232-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::remove`
233-
Deletes an attribute by key.
239+
// ...
240+
use Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag;
234241

235-
:method:`Symfony\\Component\\HttpFoundation\\Session\\Attribute\\AttributeBagInterface::clear`
236-
Clear the bag.
242+
$session = new Session(new NativeSessionStorage(), new NamespacedAttributeBag());
243+
$session->set('tokens/c', $value);
237244

238245
Flash Messages
239246
~~~~~~~~~~~~~~

form/unit_testing.rst

Lines changed: 5 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ widgets you want to display are available in the children property::
107107
$this->assertArrayHasKey($key, $children);
108108
}
109109

110+
.. tip::
111+
112+
Use :ref:`PHPUnit data providers <testing-data-providers>` to test multiple
113+
form conditions using the same test code.
114+
110115
Testings Types from the Service Container
111116
-----------------------------------------
112117

@@ -213,56 +218,3 @@ guessers using the :method:`Symfony\\Component\\Form\\Test\\FormIntegrationTestC
213218
:method:`Symfony\\Component\\Form\\Test\\FormIntegrationTestCase::getTypeExtensions`
214219
and :method:`Symfony\\Component\\Form\\Test\\FormIntegrationTestCase::getTypeGuessers`
215220
methods.
216-
217-
Testing against Different Sets of Data
218-
--------------------------------------
219-
220-
If you are not familiar yet with PHPUnit's `data providers`_, this might be
221-
a good opportunity to use them::
222-
223-
// tests/Form/Type/TestedTypeTest.php
224-
namespace App\Tests\Form\Type;
225-
226-
use App\Form\Type\TestedType;
227-
use Symfony\Component\Form\Test\TypeTestCase;
228-
229-
class TestedTypeTest extends TypeTestCase
230-
{
231-
/**
232-
* @dataProvider getValidTestData
233-
*/
234-
public function testForm($data)
235-
{
236-
// ... your test
237-
}
238-
239-
public function getValidTestData()
240-
{
241-
return array(
242-
array(
243-
'data' => array(
244-
'test' => 'test',
245-
'test2' => 'test2',
246-
),
247-
),
248-
array(
249-
'data' => array(),
250-
),
251-
array(
252-
'data' => array(
253-
'test' => null,
254-
'test2' => null,
255-
),
256-
),
257-
);
258-
}
259-
}
260-
261-
The code above will run your test three times with 3 different sets of
262-
data. This allows for decoupling the test fixtures from the tests and
263-
easily testing against multiple sets of data.
264-
265-
You can also pass another argument, such as a boolean if the form has to
266-
be synchronized with the given set of data or not etc.
267-
268-
.. _`data providers`: https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers

security/custom_password_authenticator.rst

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ the user::
2828
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
2929
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
3030
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
31+
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
3132
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
3233
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
3334
use Symfony\Component\Security\Core\User\UserProviderInterface;
@@ -52,7 +53,20 @@ the user::
5253
throw new CustomUserMessageAuthenticationException('Invalid username or password');
5354
}
5455

55-
$isPasswordValid = $this->encoder->isPasswordValid($user, $token->getCredentials());
56+
$currentUser = $token->getUser();
57+
58+
if ($currentUser instanceof UserInterface) {
59+
if ($currentUser->getPassword() !== $user->getPassword()) {
60+
throw new BadCredentialsException('The credentials were changed from another session.');
61+
}
62+
} else {
63+
if ('' === ($givenPassword = $token->getCredentials())) {
64+
throw new BadCredentialsException('The given password cannot be empty.');
65+
}
66+
if (!$this->encoderFactory->getEncoder($user)->isPasswordValid($user->getPassword(), $givenPassword, $user->getSalt())) {
67+
throw new BadCredentialsException('The given password is invalid.');
68+
}
69+
}
5670

5771
if ($isPasswordValid) {
5872
$currentHour = date('G');

security/custom_provider.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ Here's an example of how this might look::
144144
);
145145
}
146146

147+
$username = $user->getUsername();
148+
147149
return $this->fetchUser($username);
148150
}
149151

session/locale_sticky_session.rst

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -171,19 +171,50 @@ event::
171171
$this->session->set('_locale', $user->getLocale());
172172
}
173173
}
174-
175-
public static function getSubscribedEvents()
176-
{
177-
return array(
178-
SecurityEvents::INTERACTIVE_LOGIN => array(array('onInteractiveLogin', 15)),
179-
);
180-
}
181174
}
182175

183-
If you're using the :ref:`default services.yaml configuration <service-container-services-load-example>`,
184-
you're done! Symfony will automatically know about the event subscriber will pass
185-
your the ``session`` service. Now, when you login, the user's locale will be set
186-
into the session.
176+
Then register the listener:
177+
178+
.. configuration-block::
179+
180+
.. code-block:: yaml
181+
182+
# config/services.yaml
183+
services:
184+
App\EventListener\UserLocaleListener:
185+
tags:
186+
- { name: kernel.event_listener, event: security.interactive_login, method: onInteractiveLogin, priority: 15 }
187+
188+
.. code-block:: xml
189+
190+
<!-- config/services.xml -->
191+
<?xml version="1.0" encoding="UTF-8" ?>
192+
<container xmlns="http://symfony.com/schema/dic/services"
193+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
194+
xsi:schemaLocation="http://symfony.com/schema/dic/services
195+
http://symfony.com/schema/dic/services/services-1.0.xsd">
196+
197+
<services>
198+
<service id="App\EventListener\UserLocaleListener">
199+
<tag name="kernel.event_listener"
200+
event="security.interactive_login"
201+
method="onInteractiveLogin" priority=15 />
202+
</service>
203+
</services>
204+
</container>
205+
206+
.. code-block:: php
207+
208+
// config/services.php
209+
use AppBundle\EventListener\UserLocaleListener;
210+
use Symfony\Component\DependencyInjection\Reference;
211+
212+
$container
213+
->register(UserLocaleListener::class)
214+
->addTag(
215+
'kernel.event_listener',
216+
array('event' => 'security.interactive_login', 'method' => 'onInteractiveLogin', 'priority' => 15)
217+
);
187218
188219
.. caution::
189220

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy