Skip to content

Commit 7bb2785

Browse files
committed
Merge branch '2.8'
* 2.8: (35 commits) [#5922] Tweaks thanks to reviewers Many tweaks thanks to a great review language tweak several other tweaks Completely updating the form type reference section for the text -> TextType changes Use path() and url() PHP templating helpers Update voter section of best practices Added minimal cookbook article about shared Document deprecation of supports{Attribute,Class}() methods Document Security key to secret renamings Use new Simple{Form,Pre}AuthenticatorInterface namespaces tweaks thanks to Javier adding a section about calling isGranted() from within a voter Reworking the voter article for the new Voter class fixing build error Another huge batch of changes for the form type changes in 2.8 minor tweaks #5834 Fixing bad merge removing link to an old, non-existent article Many fixes thanks to great review from ogizanagi, javiereguiluz and others ...
2 parents af97ce1 + 41670b0 commit 7bb2785

File tree

91 files changed

+2268
-939
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+2268
-939
lines changed

best_practices/forms.rst

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,20 @@ form in its own PHP class::
2222
use Symfony\Component\Form\AbstractType;
2323
use Symfony\Component\Form\FormBuilderInterface;
2424
use Symfony\Component\OptionsResolver\OptionsResolver;
25+
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
26+
use Symfony\Component\Form\Extension\Core\Type\EmailType;
27+
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
2528

2629
class PostType extends AbstractType
2730
{
2831
public function buildForm(FormBuilderInterface $builder, array $options)
2932
{
3033
$builder
3134
->add('title')
32-
->add('summary', 'textarea')
33-
->add('content', 'textarea')
34-
->add('authorEmail', 'email')
35-
->add('publishedAt', 'datetime')
35+
->add('summary', TextareaType::class)
36+
->add('content', TextareaType::class)
37+
->add('authorEmail', EmailType::class)
38+
->add('publishedAt', DateTimeType::class)
3639
;
3740
}
3841

@@ -42,22 +45,17 @@ form in its own PHP class::
4245
'data_class' => 'AppBundle\Entity\Post'
4346
));
4447
}
45-
46-
public function getName()
47-
{
48-
return 'post';
49-
}
5048
}
5149

52-
To use the class, use ``createForm`` and instantiate the new class::
50+
To use the class, use ``createForm`` and pass the fully qualified class name::
5351

5452
use AppBundle\Form\PostType;
5553
// ...
5654

5755
public function newAction(Request $request)
5856
{
5957
$post = new Post();
60-
$form = $this->createForm(new PostType(), $post);
58+
$form = $this->createForm(PostType::class, $post);
6159

6260
// ...
6361
}
@@ -97,7 +95,7 @@ directly in your form class, this would effectively limit the scope of that form
9795
{
9896
$builder
9997
// ...
100-
->add('save', 'submit', array('label' => 'Create Post'))
98+
->add('save', SubmitType::class, array('label' => 'Create Post'))
10199
;
102100
}
103101
@@ -112,6 +110,7 @@ some developers configure form buttons in the controller::
112110

113111
use Symfony\Component\HttpFoundation\Request;
114112
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
113+
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
115114
use AppBundle\Entity\Post;
116115
use AppBundle\Form\PostType;
117116

@@ -122,8 +121,8 @@ some developers configure form buttons in the controller::
122121
public function newAction(Request $request)
123122
{
124123
$post = new Post();
125-
$form = $this->createForm(new PostType(), $post);
126-
$form->add('submit', 'submit', array(
124+
$form = $this->createForm(PostType::class, $post);
125+
$form->add('submit', SubmitType::class, array(
127126
'label' => 'Create',
128127
'attr' => array('class' => 'btn btn-default pull-right')
129128
));
@@ -207,21 +206,3 @@ Second, we recommend using ``$form->isSubmitted()`` in the ``if`` statement
207206
for clarity. This isn't technically needed, since ``isValid()`` first calls
208207
``isSubmitted()``. But without this, the flow doesn't read well as it *looks*
209208
like the form is *always* processed (even on the GET request).
210-
211-
Custom Form Field Types
212-
-----------------------
213-
214-
.. best-practice::
215-
216-
Add the ``app_`` prefix to your custom form field types to avoid collisions.
217-
218-
Custom form field types inherit from the ``AbstractType`` class, which defines the
219-
``getName()`` method to configure the name of that form type. These names must
220-
be unique in the application.
221-
222-
If a custom form type uses the same name as any of the Symfony's built-in form
223-
types, it will override it. The same happens when the custom form type matches
224-
any of the types defined by the third-party bundles installed in your application.
225-
226-
Add the ``app_`` prefix to your custom form field types to avoid name collisions
227-
that can lead to hard to debug errors.

best_practices/security.rst

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -264,37 +264,66 @@ the same ``getAuthorEmail`` logic you used above:
264264
265265
namespace AppBundle\Security;
266266
267-
use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter;
267+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
268+
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
269+
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
268270
use Symfony\Component\Security\Core\User\UserInterface;
271+
use AppBundle\Entity\Post;
269272
270-
// AbstractVoter class requires Symfony 2.6 or higher version
271-
class PostVoter extends AbstractVoter
273+
// Voter class requires Symfony 2.8 or higher version
274+
class PostVoter extends Voter
272275
{
273276
const CREATE = 'create';
274277
const EDIT = 'edit';
275278
276-
protected function getSupportedAttributes()
279+
/**
280+
* @var AccessDecisionManagerInterface
281+
*/
282+
private $decisionManager;
283+
284+
public function __construct(AccessDecisionManagerInterface $decisionManager)
277285
{
278-
return array(self::CREATE, self::EDIT);
286+
$this->decisionManager = $decisionManager;
279287
}
280288
281-
protected function getSupportedClasses()
289+
protected function supports($attribute, $subject)
282290
{
283-
return array('AppBundle\Entity\Post');
291+
if (!in_array($attribute, array(self::CREATE, self::EDIT))) {
292+
return false;
293+
}
294+
295+
if (!$subject instanceof Post) {
296+
return false;
297+
}
298+
299+
return true;
284300
}
285301
286-
protected function isGranted($attribute, $post, $user = null)
302+
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
287303
{
304+
$user = $token->getUser();
305+
/** @var Post */
306+
$post = $subject; // $subject must be a Post instance, thanks to the supports method
307+
288308
if (!$user instanceof UserInterface) {
289309
return false;
290310
}
291311
292-
if ($attribute === self::CREATE && in_array('ROLE_ADMIN', $user->getRoles(), true)) {
293-
return true;
294-
}
295-
296-
if ($attribute === self::EDIT && $user->getEmail() === $post->getAuthorEmail()) {
297-
return true;
312+
switch ($attribute) {
313+
case self::CREATE:
314+
// if the user is an admin, allow them to create new posts
315+
if ($this->decisionManager->decide($token, array('ROLE_ADMIN'))) {
316+
return true;
317+
}
318+
319+
break;
320+
case self::EDIT:
321+
// if the user is the author of the post, allow them to edit the posts
322+
if ($user->getEmail() === $post->getAuthorEmail()) {
323+
return true;
324+
}
325+
326+
break;
298327
}
299328
300329
return false;
@@ -310,6 +339,7 @@ To enable the security voter in the application, define a new service:
310339
# ...
311340
post_voter:
312341
class: AppBundle\Security\PostVoter
342+
arguments: ['@security.access.decision_manager']
313343
public: false
314344
tags:
315345
- { name: security.voter }
@@ -337,7 +367,7 @@ via the even easier shortcut in a controller:
337367
*/
338368
public function editAction($id)
339369
{
340-
$post = // query for the post ...
370+
$post = ...; // query for the post
341371
342372
$this->denyAccessUnlessGranted('edit', $post);
343373

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