New! Checkout our new Forums homepage! Follow the latest activity in eZ Publish Forums on Share.ez.no, Projects.ez.no and StackOverflow.com


Web Summer Camp 2018 is slowly but surely closing in. We have defined the tracks (a few surprises there!), finished the speaker selection process, and are working on the track programs and extras – read on!

04/26/2018 10:19 am   www.netgen.hr/eng/Blog   Mirror   Link   @20

Deprecate some uses of Request::getSession()

Contributed by
Florent Mata
in #26564.

Using Request::getSession() when no session exists has been deprecated in Symfony 4.1 and it will throw an exception in Symfony 5.0. The solution is to always check first if a session exists with the Request::hasSession() method:

1
2
3
4
// ...
if ($request->hasSession() && ($session = $request->getSession())) {
    $session->set('some_key', 'some_value');
}

Allow to cache requests that use sessions

Contributed by
Yanick Witschi
in #26681.

Whenever the session is started during a request, Symfony turns the response into a private non-cacheable response to prevent leaking private information. However, even requests making use of the session can be cached under some circumstances.

For example, information related to some user group could be cached for all the users belonging to that group. Handling these advanced caching scenarios is out of the scope of Symfony, but they can be solved with the FOSHttpCacheBundle.

In order to disable the default Symfony behavior that makes requests using the session uncacheable, in Symfony 4.1 we added the NO_AUTO_CACHE_CONTROL_HEADER header that you can add to responses:

1
2
3
use Symfony\Component\HttpKernel\EventListener\AbstractSessionListener;

$response->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, 'true');

Allow to migrate sessions

Contributed by
Ross Motley
in #26096.

Migrating sessions (e.g. from the filesystem to the database) is a tricky operation that usually ends up losing all the existing sessions. That's why in Symfony 4.1 we've introduced a new MigratingSessionHandler class to allow migrate between old and new save handlers without losing session data.

It's recommended to do the migration in three steps:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
use Symfony\Component\HttpFoundation\Session\Storage\Handler\MigratingSessionHandler;

$oldSessionStorage = ...;
$newSessionStorage = ...;

// The constructor of the migrating class are: MigratingSessionHandler($currentHandler, $writeOnlyHandler)
// Step 1. Do this during the "garbage collection period of time" to get all sessions in the new storage
$sessionStorage = new MigratingSessionHandler($oldSessionStorage, $newSessionStorage);

// Step 2. Do this while you verify that the new storage handler works as expected
$sessionStorage = new MigratingSessionHandler($newSessionStorage, $oldSessionStorage);

// Step 3. Your app is now ready to switch to the new storage handler
$sessionStorage = $newSessionStorage;

Be trained by Symfony experts - 2018-05-14 Paris - 2018-05-14 Paris - 2018-05-16 Paris
04/26/2018 06:33 am   Symfony Blog   Mirror   Link   @4
@ezecosystem
ezecosystem pushed to master in ezecosystem/launchpad Apr 26, 2018
04/26/2018 12:02 am   eZecosystem @ GitHub   Mirror   Link   @8
@ezecosystem
ezecosystem pushed to master in ezecosystem/ezplatform-xmltext-fieldtype Apr 26, 2018
  • @vidarl 9ffe1e7
    Fix EZP-29116 : Conversions from ezxmltext to ezrichtext fails if ezx…
04/25/2018 11:59 pm   eZecosystem @ GitHub   Mirror   Link   @10
@ezpublishlegacy
ezpublishlegacy pushed to master in ezpublishlegacy/phpunit Apr 25, 2018
04/25/2018 12:30 pm   eZPublishLegacy @ GitHub   Mirror   Link   @6
@ezecosystem
ezecosystem pushed to master in ezecosystem/Sylius Apr 25, 2018
04/25/2018 12:07 pm   eZecosystem @ GitHub   Mirror   Link   @6

What is GDPR?

General Data Protection Regulation (GDPR) is a new regulation on data protection and data privacy for all European Union (EU) citizens. The regulation is set to go into effect on May 25, 2018. GDPR’s goal is to strengthen data privacy by securing EU citizens' rights to be forgotten or their right to inquire about personal data that is collected on their behalf by different entities that they come in contact with. GDPR requires that data controllers and data processors implement certain measures to meet new data protection requirements.

Data Controller vs Data Processor

A data controller is any entity that decides the purpose and means of personal data processing . On the other hand, a data processor is the entity that is responsible for processing the data on behalf of the controller. It is necessary to understand the distinction between these two roles. Gdpreu.org uses the following example to distinguish between the two roles: “Acme Co. sells widgets to consumers and uses Email Automation Co. to email consumers on their behalf and track their engagement activity, then with regard to such email activity data, Acme Co. is the data controller, and Email Automation Co. is the data processor.” According to GDPR the data controller is the principal party responsible for collecting consents, managing the revoking of consents and the deletion of personal data. The data processor implements these actions on behalf of the controller’s request.

What Are the Ramifications of Breaching GDPR?

The law states that any entity that collects personal data of EU citizens will be responsible and accountable for how that data is handled. According to Article 4 of the GDPR, ‘personal data’ means “any information relating to an identified or identifiable natural person (‘data subject’); an identifiable natural person is one who can be identified, directly or indirectly, in particular by reference to an identifier such as a name, an identification number, location data, an online identifier or to one or more factors specific to the physical, physiological, genetic, mental, economic, cultural or social identity of that natural person.”

A breach of the GDPR regulation can cause a company to be fined up to €20 million or 4% of its worldwide annual revenue (the biggest being applied).

Now that we have provided some context for those who are not familiar with GDPR, let’s look at how to comply.

How to Address GDPR with eZ Platform

GDPR is a complex legislation that for many is still difficult to understand and prepare for. Since the legislation is often vague, it is difficult to understand how it will be enforced starting May 25th. Although we are not experts on the matter, we have done great amounts of research on this topic. Here we share with you some guidance on how to implement the right features on your eZ Platform or eZ Publish website to ensure you comply with these upcoming policies. This past week I interviewed our rockstar Technical Product Manager, Bertrand Dunogier about steps eZ clients who use eZ Platform can take to address the GDPR predicament.

Question: What is the first step organizations should consider when preparing for GDPR?

BD: The first steps are actually not about technology or about eZ Platform at all. Organizations need to first take a good look at themselves and begin to understand and document what data they are collecting and how it is being stored. Companies must ask themselves the following questions:

  • What type of data are we collecting?
  • How relevant is the data we have collected?
  • Are we communicating to our users/visitors the type of data we are collecting?
  • Did we ask visitors for permission to collect data?
  • What is our consent management process?
  • What is the purpose of the data we have collected?
  • How will this data be utilized?

One of the best measures companies can take is to eliminate old and irrelevant data. We need to understand that 95% of data collected holds no relevance. Therefore, the best thing a company can do is to get rid of irrelevant data. The second measure companies can take is to begin documenting all personal data that is collected and its purpose as well as the processes on how it is collected.

Question: How can you ask for consent with eZ Platform?

The places where personal data is collected using eZ Platform or eZ Publish are user profile creation, forms using user generated content (UGC) in eZ content repository and forms independent of the content repository using our form builder, some forms developed custom by the developer of the site or even a third-party solution or library. Let’s first define how personal data is collected using these different instances.

User Profile Creation

A person creating a user profile on eZ Platform or eZ Publish. Depending on the projects, you might have pre-defined personal fields that users must fill out such as email and their first and last names.

UGC Form

On a UGC form a user creates content in the repository. For example, posting a review or listing a product for sale on a community based e-Commerce site.

Independent Form

Example of form builder in eZ Platform or eZ Survey extension in eZ Publish. In all three of these scenarios you can (and should) implement a consent management solution that will allow your organization to comply with GDPR regulations. We recommend that you add a new field description that is mandatory. For new registrants who create user profiles, we suggest that you implement an email field. Requiring users to provide you with an email will allow you, as the controller, to send a follow-up email to users that details the type of information you are collecting on them and the purpose of collecting that data. Secondly, a follow-up email will allow you to authenticate the user. This allows you to create a double opt-mechanism.

Another solution that can address all three scenarios is the addition of a checkbox field. The checkbox field will require users to check the consent box prior to registration. This will provide you with proof that the user has provided you with his consent/permission to gather data on them. The checkbox should also be used to confirm in a UGC scenario that the user has agreed to use the license and contribute content on the platform.

Additionally, make sure to be explicit about the purpose for which you collect data in your consent request and not to conceal what type of information you will be collecting on your user.

Question: What can be done if a user requests to be deleted?

BD: A registered user can ask for his account and personal data to be deleted. Deleting the account and the personal data (user fields) stored within the user profile is not a problem. However, in the case of UGC, it can be tricky. If the contributions from the user are personal data (and in many case they will be), erasing them is, of course, possible but this could lead to undesired broken links and loss of content on the website for other users—and you should be aware of this.

If the contributions are not to be handled as personal data (maybe the user signed an agreement granting specific rights to this content), then deleting the user account might lead to broken links and orphan content. In this case, we recommend to disable the user account and anonymize all its fields by replacing them with dummy values, which lead to the same result without deleting the account itself.

To erase personal data, site administrators can simply use the Administration Interface by going to the User Management section to delete or disable a user as well as doing a filtered search to identify all content related to a specific user/author. And of course all of this can also be done by using lower level APIs.

Question: How can you use eZ Platform to export data?

BD: Currently we do not have an exporting button. However, we are looking to develop an out-of-the-box capability that allows users to “retrieve data” in the click of a button. This button will allow you to download and export personal data. Currently developers can customize the system using the API. The API allows you to query the content repository for all content published by an author, and can then be exported. We are also considering creating a simple “forget me” button that once pressed, will lead to all the personal data collected on a certain user to be deleted automatically.

Conclusion

GDPR can be a very confusing piece of legislation. The good news is that a lot can be done about it with on eZ Platform and eZ Publish, thanks to APIs and architecture. The final word on what needs to be done to comply will depends a lot on your specific installation and how you use the platform. It will require you to adjust how you address data collection and data privacy.

In the near future we hope to introduce some features that will go beyond the current capabilities for reaching GDPR compliance, making it easier and faster to implement. For example, we are looking into various features such as a consent management panel, a data export panel and a consent withdrawal tool bar.

We recommend that you learn more about this topic by reading Bozho’s Tech Blog post: GDPR – A Practical Guide for Developers or Smashing Magazines article: GDPR for Web Developers.

And stay tuned, we’ll post more about GDPR here as well. In the meantime, you can provide any comments or questions about how eZ Platform or eZ Publish can help you be GDPR compliant in the comment section below or our discussion forum at discuss.ezplatform.com.

04/25/2018 10:31 am   ez.no/About-eZ/Blog   Mirror   Link   @8

What is GDPR?

General Data Protection Regulation (GDPR) is a new regulation on data protection and data privacy for all European Union (EU) citizens. The regulation is set to go into effect on May 25, 2018. GDPR’s goal is to strengthen data privacy by securing EU citizens' rights to be forgotten or their right to inquire about personal data that is collected on their behalf by different entities that they come in contact with. GDPR requires that data controllers and data processors implement certain measures to meet new data protection requirements.

Data Controller vs Data Processor

A data controller is any entity that decides the purpose and means of personal data processing. On the other hand, a data processor is the entity that is responsible for processing data on behalf of the controller. It is necessary to understand the distinction between these two roles. Gdpreu.org uses the following example to distinguish between the two roles: “Acme Co. sells widgets to consumers and uses Email Automation Co. to email consumers on their behalf and track their engagement activity, then with regard to such email activity data, Acme Co. is the data controller, and Email Automation Co. is the data processor.” According to GDPR the data controller is the principal party responsible for collecting consents, managing the revoking of consents and the deletion of personal data. The data processor implements these actions on behalf of the controller’s request.

What Are the Ramifications of Breaching GDPR?

The law states that any entity that collects personal data of EU citizens will be responsible and accountable for how that data is handled. According to Article 4 of the GDPR, ‘personal data’ means “any information relating to an identified or identifiable natural person (‘data subject’); an identifiable natural person is one who can be identified, directly or indirectly, in particular by reference to an identifier such as a name, an identification number, location data, an online identifier or to one or more factors specific to the physical, physiological, genetic, mental, economic, cultural or social identity of that natural person.”

A breach of the GDPR regulation can cause a company to be fined up to €20 million or 4% of its worldwide annual revenue (the biggest being applied).

Now that we have provided some context for those who are not familiar with GDPR, let’s look at how to comply.

How to Address GDPR with eZ Platform

GDPR is a complex legislation that for many is still difficult to understand and prepare for. Since the legislation is often vague, it is difficult to understand how it will be enforced starting May 25th. Although we are not experts on the matter, we have done great amounts of research on this topic. Here we share with you some guidance on how to implement the right features on your eZ Platform or eZ Publish website to ensure you comply with these upcoming policies.

This past week I interviewed our rockstar Technical Product Manager, Bertrand Dunogier about steps eZ clients who use eZ Platform can take to address the GDPR predicament.

Question: What is the first step organizations should consider when preparing for GDPR?

BD: The first steps are actually not about technology or about eZ Platform at all. Organizations need to first take a good look at themselves and begin to understand and document what data they are collecting and how it is being stored. Companies must ask themselves the following questions:

  • What type of data are we collecting?
  • How relevant is the data we have collected?
  • Are we communicating to our users/visitors the type of data we are collecting?
  • Did we ask visitors for permission to collect data?
  • What is our consent management process?
  • What is the purpose of the data we have collected?
  • How will this data be utilized?

One of the best measures companies can take is to eliminate old and irrelevant data. We need to understand that 95% of data collected holds no relevance. Therefore, the best thing a company can do is to get rid of irrelevant data. The second measure companies can take is to begin documenting all personal data that is collected and its purpose as well as the processes on how it is collected.

Question: How can you ask for consent with eZ Platform?

The places where personal data is collected using eZ Platform or eZ Publish are user profile creation, forms using user generated content (UGC) in eZ content repository and forms independent of the content repository using our form builder, some forms developed custom by the developer of the site or even a third-party solution or library. Let’s first define how personal data is collected using these different instances.

  • User Profile Creation - A person creating a user profile on eZ Platform or eZ Publish. Depending on the projects, you might have pre-defined personal fields that users must fill out such as email and their first and last names.
  • UGC Form - On a UGC form a user creates content in the repository. For example, posting a review or listing a product for sale on a community based e-Commerce site.
  • Independent Form - For example, a form builder in eZ Platform or eZ Survey extension in eZ Publish.

In all three of these scenarios you can (and should) implement a consent management solution that will allow your organization to comply with GDPR regulations. We recommend that you add a new field description that is mandatory. For new registrants who create user profiles, we suggest that you implement an email field. Requiring users to provide you with an email will allow you, as the controller, to send a follow-up email to users that details the type of information you are collecting on them and the purpose of collecting that data. Secondly, a follow-up email lets you authenticate the user, allowing you to create a double opt-in mechanism.

Another solution that can address all three scenarios is the addition of a checkbox field. The checkbox field will require users to check the consent box prior to registration. This will provide you with proof that the user has provided you with his consent/permission to gather data on them. The checkbox should also be used to confirm in a UGC scenario that the user has agreed to use the license and contribute content on the platform.

Additionally, make sure to be explicit about the purpose for which you collect data in your consent request and not to conceal what type of information you will be collecting on your user.

Question: What can be done if a user requests to be deleted?

BD: A registered user can ask for his account and personal data to be deleted. Deleting the account and the personal data (user fields) stored within the user profile is not a problem. However, in the case of UGC, it can be tricky. If the contributions from the user are personal data (and in many case they will be), erasing them is, of course, possible but this could lead to undesired broken links and loss of content on the website for other users—and you should be aware of this.

If the contributions are not to be handled as personal data (maybe the user signed an agreement granting specific rights to this content), then deleting the user account might lead to broken links and orphan content. In this case, we recommend to disable the user account and anonymize all its fields by replacing them with dummy values, which lead to the same result without deleting the account itself.

To erase personal data, site administrators can simply use the Administration Interface by going to the User Management section to delete or disable a user as well as doing a filtered search to identify all content related to a specific user/author. And of course all of this can also be done by using lower level APIs.

Question: How can you use eZ Platform to export data?

BD: Currently we do not have an exporting button. However, we are looking to develop an out-of-the-box capability that allows users to “retrieve data” in the click of a button. This button will allow you to download and export personal data. Currently developers can customize the system using the API. The API allows you to query the content repository for all content published by an author, and can then be exported. We are also considering creating a simple “forget me” button that once pressed, will lead to all the personal data collected on a certain user to be deleted automatically.

Conclusion

GDPR can be a very confusing piece of legislation. The good news is that a lot can be done about it with on eZ Platform and eZ Publish, thanks to APIs and architecture. The final word on what needs to be done to comply will depends a lot on your specific installation and how you use the platform. It will require you to adjust how you address data collection and data privacy.

In the near future we hope to introduce some features that will go beyond the current capabilities for reaching GDPR compliance, making it easier and faster to implement. For example, we are looking into various features such as a consent management panel, a data export panel and a consent withdrawal tool bar.

We recommend that you learn more about this topic by reading Bozho’s Tech Blog post: GDPR – A Practical Guide for Developers or Smashing Magazines article: GDPR for Web Developers.

And stay tuned, we’ll post more about GDPR here as well. In the meantime, you can provide any comments or questions about how eZ Platform or eZ Publish can help you be GDPR compliant in the comment section below or our discussion forum at discuss.ezplatform.com.

04/25/2018 10:31 am   eZ Systems News   Mirror   Link   @10

Mugo Web puts emphasis on keeping its employees connected -- through good times and bad.

04/24/2018 02:54 pm   Mugo Web Blog   Mirror   Link   @17
@ezecosystem
ezecosystem pushed to master in ezecosystem/ezpublish-kernel Apr 24, 2018
04/24/2018 12:00 pm   eZecosystem @ GitHub   Mirror   Link   @14
@ezecosystem
ezecosystem pushed to master in ezecosystem/ezplatform-xmltext-fieldtype Apr 24, 2018
  • @vidarl 4f71a7f
    Adding new options to conversion cmd : --dry-run and --contentobject …
04/24/2018 11:59 am   eZecosystem @ GitHub   Mirror   Link   @6

FlattenException now unwraps errors

Contributed by
Alexander M. Turek
in #26028.

Symfony wraps errors thrown by the application inside a FatalThrowableError. This makes the actual error class to not be displayed in the exception pages, where you see for example Symfony's FatalThrowableError instead of PHP's DivisionByZeroError when your code tries to divide by 0.

In Symfony 4.1, FlattenException now unwraps FatalThrowableError instances and logs the wrapped error. In consequence, the real error class is now always displayed in the exception page:

Introduced new exception classes

Contributed by
Sullivan Senechal and Florent Mata
in #25775 and #26475.

In Symfony 4.1 we've introduced a new ProcessSignaledException class in the Process component to properly catch signaled process errors. Also, in the HttpFoundation component, we've introduced new detailed exception classes for file upload handling to replace the generic catch-all FileException:

1
2
3
4
5
6
7
use Symfony\Component\HttpFoundation\File\Exception\CannotWriteFileException;
use Symfony\Component\HttpFoundation\File\Exception\ExtensionFileException;
use Symfony\Component\HttpFoundation\File\Exception\FormSizeFileException;
use Symfony\Component\HttpFoundation\File\Exception\IniSizeFileException;
use Symfony\Component\HttpFoundation\File\Exception\NoFileException;
use Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException;
use Symfony\Component\HttpFoundation\File\Exception\PartialFileException;

Moreover, now that PHP 7.1 supports multi catch exception handling, you can process several exceptions with the same catch() block:

1
2
3
4
5
try {
    // ...
} catch (FormSizeFileException | IniSizeFileException $e) {
    // ...
}

Improved the exception page design

Contributed by
Javier Eguiluz
in #26671.

The exception pages have been improved in Symfony 4.1 to display less information about "vendor code". If some code belongs to the vendor/ folder, we compact its information to fit in a single line and we no longer display its arguments. The other code remains the same, which helps you focus more easily on your own application code:


Be trained by Symfony experts - 2018-05-14 Paris - 2018-05-14 Paris - 2018-05-16 Paris
04/24/2018 06:17 am   Symfony Blog   Mirror   Link  
@ezecosystem
ezecosystem pushed to master in ezecosystem/Sylius Apr 23, 2018
04/23/2018 12:06 pm   eZecosystem @ GitHub   Mirror   Link   @4

Introduced a HeaderUtils class

Contributed by
Christian Schmidt
in #24699.

Parsing HTTP headers is not as trivial as some may think. It requires parsing quoted strings with backslash escaping and ignoring white-space in certain places. We did that in some methods of the HttpFoundation component but the repeated logic was starting to make the code hard to maintain.

That's why in Symfony 4.1 we've introduced a new HeaderUtils class that provides the most common utilities needed when parsing HTTP headers. This is not an internal class, so you can use it in your own code too:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
use Symfony\Component\HttpFoundation\HeaderUtils;

// Splits an HTTP header by one or more separators
HeaderUtils::split('da, en-gb;q=0.8', ',;')
// => array(array('da'), array('en-gb'), array('q', '0.8'))

// Combines an array of arrays into one associative array
HeaderUtils::combineParts(array(array('foo', 'abc'), array('bar')))
// => array('foo' => 'abc', 'bar' => true)

// Joins an associative array into a string for use in an HTTP header
HeaderUtils::joinAssoc(array('foo' => 'abc', 'bar' => true, 'baz' => 'a b c'), ',')
// => 'foo=abc, bar, baz="a b c"'

// Encodes a string as a quoted string, if necessary
HeaderUtils::quote('foo "bar"')
// => 'foo \"bar\"'

// Decodes a quoted string
HeaderUtils::unquote('foo \"bar\"')
// => 'foo "bar"'

Allow to bypass headers when submitting forms in tests

Contributed by
cfjulien
in #26791.

An issue reported by the Mink browser testing project made us realize that you cannot bypass HTTP header information when submitting forms in tests which use the BrowserKit component.

That's why in Symfony 4.1 the submit() method now accepts a third optional argument called $serverParameters which allows you to do things like this:

1
2
3
4
$crawler = $client->request('GET', 'http://www.example.com/foo');
$form = $crawler->filter('input')->form();
$client->submit($form, [], ['HTTP_ACCEPT_LANGUAGE' => 'de']);
// => $client->getRequest()->getServer()['HTTP_ACCEPT_LANGUAGE'] = 'de'

Added support for default values in Accept headers

Contributed by
Javier Eguiluz
in #26036.

When using the Accept HTTP header it's common to use expressions like .../*, */* and even * to define the default values:

1
Accept: text/plain;q=0.5, text/html, text/*;q=0.8, */*

However, in Symfony versions previous to 4.1 these default values weren't supported:

1
2
3
4
5
6
use Symfony\Component\HttpFoundation\AcceptHeader;

$acceptHeader = AcceptHeader::fromString('text/plain;q=0.5, text/html, text/*;q=0.8, */*');
$quality = $acceptHeader->get('text/xml')->getQuality();
// instead of returning '0.8', this code displays the following error message:
//   Call to a member function getQuality() on null

In Symfony 4.1 all these default values are now properly supported:

1
2
3
4
$acceptHeader = AcceptHeader::fromString('text/plain;q=0.5, text/html, text/*;q=0.8, */*');
$acceptHeader->get('text/xml')->getQuality();        // => 0.8 (because of text/*)
$acceptHeader->get('text/html')->getQuality();       // => 1.0
$acceptHeader->get('application/xml')->getQuality(); // => 1.0 (because of */*)

Be trained by Symfony experts - 2018-05-14 Paris - 2018-05-14 Paris - 2018-05-16 Paris
04/23/2018 06:03 am   Symfony Blog   Mirror   Link  

This week, Symfony improved the performance of the Cache component inlining some function calls and simplified the usage of the new Messenger component allowing to omit the sender tag name and to use the adapter name instead of the service name. In addition, we added a new dd() helper which is useful when you can't or don't want to use a debugger.

Symfony development highlights

2.7 changelog:

  • a3af3d3: [Form] fixed trimming choice values
  • d17d38d: [HttpKernel] fix that ESI/SSI processing can turn a private response public
  • b0410d4: [HttpFoundation] don't assume that file binary exists on *nix OS

3.4 changelog:

  • baeb1bf: [TwigBundle] fixed rendering exception stack traces
  • 8f2132f: [Routing] fixed loading multiple class annotations for invokable classes
  • 2a52963: [Console] fixed PSR exception context key
  • e984546: [TwigBundle] fixed formatting arguments in plaintext format
  • bf871f4: [Cache] inline some hot function calls
  • 09d1a2b: [TwigBridge] fixed PercentType error rendering in Bootstrap 4 theme
  • 733e813: [DoctrineBridge] fixed bug when indexBy is meta key in PropertyInfo\DoctrineExtractor

Master changelog:

  • 7e4de96: [Messenger] use the adapter name instead of the service name
  • d2f8df8: [Config] fix the valid placeholder types for variable node
  • 4af9003: [Messenger] allow sender tag name omission
  • fe19931: [Messenger] allow to configure the transport
  • 4429c9b: [Messenger] allow disabling the auto-setup of the AmqpExt connection
  • a59d0f6: [VarDumper] added dd() helper
  • 8c4fd12: [Security] made security.providers optional
  • 3450e47: [TwigBundle] do not normalize array keys in twig globals
  • 028e1e5: Declare type for arguments of anonymous functions
  • 1b1bbd4: [HttpKernel] Added support for timings in ArgumentValueResolvers
  • 306c599: [DependencyInjection] allow autoconfigured calls in PHP
  • d0db387: [HttpKernel] split logs on different sub-requests in LoggerDataCollector
  • 833909b: [DependencyInjection] hide service ids that start with a dot
  • 2ceef59: [Form] added choice_translation_locale option for Intl choice types
  • 9cb1f14: [BrowserKit] allow to bypass HTTP header information
  • cbc2376: [HttpFoundation] added a HeaderUtils class

Newest issues and pull requests

They talked about us


Be trained by Symfony experts - 2018-05-14 Paris - 2018-05-14 Paris - 2018-05-16 Paris
04/22/2018 02:55 am   Symfony Blog   Mirror   Link  

Added a ConstraintViolationListNormalizer

Contributed by
Grégoire Pineau
in #22150.

When working on APIs with Symfony, it's common to use code like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
/**
 * @Route("/blog/new", name="api_blog_new")
 * @Method("POST")
 * @Security("is_granted('ROLE_ADMIN')")
 */
public function new(Request $request, SerializerInterface $serializer, ValidatorInterface $validator)
{
    $data = $request->getContent();
    $post = $serializer->deserialize($data, Post::class, 'json', ['groups' => ['post_write']]);
    $post->setAuthor($this->getUser());

    $violations = $validator->validate($post);
    if (count($violations) > 0) {
        $repr = $serializer->serialize($violations, 'json');

        return JsonResponse::fromJsonString($repr, 400);
    }

    // ...
}

The $violations variable contains a ConstraintViolationList object and it's common to transform it into a list of errors and serialize the list to include it in a JSON response. That's why in Symfony 4.1 we've added a ConstraintViolationListNormalizer which does that for you automatically. The normalizer follows the RFC 7807 specification to generate the list of errors.

Getting the XML and CSV results as a collection

Contributed by
Hamza Amrouche
in #25218 and #25369.

The CsvEncoder and XmlEncoder now define a new config option called as_collection. If you pass that option as part of the context argument and set it to true, the results will be a collection.

Default constructor arguments for denormalization

Contributed by
Maxime Veber
in #25493.

If the constructor of a class defines arguments, as usually happens when using Value Objects, the serializer won't be able to create the object. In Symfony 4.1 we've introduced a new default_constructor_arguments context option to solve this problem.

In the following example, both foo and bar are required constructor arguments but only foo is provided. The value of bar is taken from the default_constructor_arguments option:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

class MyObj
{
    private $foo;
    private $bar;

    public function __construct($foo, $bar)
    {
        $this->foo = $foo;
        $this->bar = $bar;
    }
}

$normalizer = new ObjectNormalizer($classMetadataFactory);
$serializer = new Serializer(array($normalizer));

// this is equivalent to $data = new MyObj('Hello', '');
$data = $serializer->denormalize(['foo' => 'Hello'], 'MyObj', [
    'default_constructor_arguments' => [
        'MyObj' => ['foo' => '', 'bar' => ''],
    ]
]);

Added a MaxDepth handler

Contributed by
Kévin Dunglas
in #26108.

Sometimes, instead of just stopping the serialization process when the configured max depth is reached, it's better to let the developer handle this situation to return something (e.g. the identifier of the entity).

In Symfony 4.1 you can solve this problem defining a custom handler with the new setMaxDepthHandler() method:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Annotation\MaxDepth;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

class Foo
{
    public $id;

    /** @MaxDepth(1) */
    public $child;
}

$level1 = new Foo();
$level1->id = 1;

$level2 = new Foo();
$level2->id = 2;
$level1->child = $level2;

$level3 = new Foo();
$level3->id = 3;
$level2->child = $level3;

$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$normalizer = new ObjectNormalizer($classMetadataFactory);
$normalizer->setMaxDepthHandler(function ($foo) {
    return '/foos/'.$foo->id;
});

$serializer = new Serializer(array($normalizer));
$result = $serializer->normalize($level1, null, array(ObjectNormalizer::ENABLE_MAX_DEPTH => true));
/*
$result = array[
    'id' => 1,
    'child' => [
        'id' => 2,
        'child' => '/foos/3',
    ]
];
*/

Ignore comments when decoding XML

Contributed by
James Sansbury
in #26445.

In previous Symfony versions, XML comments were processed when decoding contents. Also, if the first line of the XML content was a comment, it was used as the root node of the decoded XML.

In Symfony 4.1, XML comments are removed by default but you can control this behavior with the new optional third constructor argument:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class XmlEncoder
{
    public function __construct(
        string $rootNodeName = 'response',
        int $loadOptions = null,
        array $ignoredNodeTypes = array(XML_PI_NODE, XML_COMMENT_NODE)
    ) {
        // ...
    }
}

Be trained by Symfony experts - 2018-04-23 Lyon - 2018-04-23 Lyon - 2018-04-25 Clichy
04/20/2018 03:54 am   Symfony Blog   Mirror   Link   @20
@ezpublishlegacy
ezpublishlegacy pushed to master in ezpublishlegacy/repository-forms Apr 19, 2018
04/19/2018 12:30 pm   eZPublishLegacy @ GitHub   Mirror   Link   @10
@ezpublishlegacy
ezpublishlegacy pushed to master in ezpublishlegacy/ezpublish-kernel Apr 19, 2018
04/19/2018 12:12 pm   eZPublishLegacy @ GitHub   Mirror   Link   @6
@ezecosystem
ezecosystem pushed to master in ezecosystem/Sylius Apr 19, 2018
04/19/2018 12:07 pm   eZecosystem @ GitHub   Mirror   Link   @10
@ezecosystem
ezecosystem pushed to master in ezecosystem/repository-forms Apr 19, 2018
04/19/2018 12:06 pm   eZecosystem @ GitHub   Mirror   Link   @8
@ezecosystem
ezecosystem pushed to master in ezecosystem/ezstudio-installer Apr 19, 2018
04/19/2018 12:00 pm   eZecosystem @ GitHub   Mirror   Link   @8
@ezecosystem
ezecosystem pushed to master in ezecosystem/ezpublish-kernel Apr 19, 2018
04/19/2018 11:59 am   eZecosystem @ GitHub   Mirror   Link   @8
@ezecosystem
ezecosystem pushed to master in ezecosystem/ezplatform-com Apr 19, 2018
  • @SylvainGuittard c8e94c3
    EZP-26809: Unify installation instructions (#131)
04/19/2018 11:59 am   eZecosystem @ GitHub   Mirror   Link   @8

A simpler way to test Ajax requests

Contributed by
Hamza Amrouche
in #26381.

The BrowserKit component used in Symfony functional tests provides lots of utilities to simulate the behavior of a web browser. In Symfony 4.1 we've added a new utility to make Ajax requests simpler: xmlHttpRequest().

This method works the same as the current request() method and accepts the same arguments, but it adds the required HTTP_X_REQUESTED_WITH header automatically so you don't have to do that yourself:

1
2
3
4
5
6
7
// Before
$crawler = $client->request('GET', '/some/path', [], [], [
    'HTTP_X-Requested-With' => 'XMLHttpRequest',
]);

// After
$crawler = $client->xmlHttpRequest('GET', '/some/path');

Improved the Ajax panel in the debug toolbar

The first minor but noticeable change is that the link to the Ajax request profile has been moved to the first column of the table, so it's easier to click on it.

In addition, when the Ajax request results in an exception (HTTP status of 400 or higher) the profiler link points to the exception profiler panel instead of the default request/response panel:

In any case, the biggest new feature of the Ajax panel is that requests now display their duration in real-time, so you always know which requests are still pending to finish:


Be trained by Symfony experts - 2018-04-23 Lyon - 2018-04-23 Lyon - 2018-04-25 Clichy
04/19/2018 03:15 am   Symfony Blog   Mirror   Link   @6
@ezecosystem
ezecosystem pushed to master in ezecosystem/ezplatform-com Apr 19, 2018
  • @SylvainGuittard e404bbb
    CSS fix for the new homepage banner
04/18/2018 11:58 pm   eZecosystem @ GitHub   Mirror   Link   @10
@ezpublishlegacy
ezpublishlegacy pushed to master in ezpublishlegacy/ezstudio Apr 18, 2018
04/18/2018 12:15 pm   eZPublishLegacy @ GitHub   Mirror   Link   @8