(alors que je pensais être un pitre)



J'ai hacké puis contribué à Symfony
Mais en fait, t'es qui ?




Mais en fait t'es qui ?

Andoni Larzabal

Dev back PHP/Symfony
Devops à mes heures perdues
Monomaniaque de la dette technique
Artisan des internets
Depuis 2018

AndoniLarz



Mais en fait t'es qui ?
Le sponsor du jour




Il était une fois :
le non respect des standards

La génèse

Mais sans CDATA
Une refacto
Un endpoint qui renvoie du XML
Le legacy

La génèse

Le CDATA ?

# mon-fichier-de-previsions.xml
<?xml version="1.0" encoding="utf-8"?>
<LIEUX>
<LIEU Nom="Acigné">
<ID>216652</ID>
<DEPARTEMENT>Ille-et-Vilaine</DEPARTEMENT>
<CODE_POSTAL>35690</CODE_POSTAL>
<URL_COURTE><![CDATA[lcm://?view=car&id=216652&t_e=101]]></URL_COURTE>
</LIEU>
</LIEUX>
La génèse

Interdit de mettre du CDATA
Pas de budget ou de temps alloué
Les contraintes


La génèse

Refacto d'abord en JSON
A la fin, on normalisera en XML
Le plan
Petit détail : on a des URLs dans nos données




Bienvenue en l'an 2000 :
Le XML

Le XML

Un ensemble de composants
Le XmlEncoder
Le Serializer
(Json, CSV, XML...)


Le XML

La serialization


📍
Le XML

needsCdataWrapping
# vendor/symfony/Component/Serializer/Encoder/XmlEncoder.php
class XmlEncoder
{
// ...
private function needsCdataWrapping(string $val): bool
{
return preg_match('/[<>&]/', $val);
}
}

Le XML

Pas de décoration possible
# vendor/symfony/Component/Serializer/Encoder/XmlEncoder.php
class XmlEncoder
{
// ...
private function needsCdataWrapping(string $val): bool
{
return preg_match('/[<>&]/', $val);
}
}

Le XML

Pas d'extend possible non plus
# vendor/symfony/Component/Serializer/Encoder/XmlEncoder.php
class XmlEncoder
{
// ...
private function needsCdataWrapping(string $val): bool
{
return preg_match('/[<>&]/', $val);
}
}





J'suis coincé

Modifier directement le code dans les vendor
Ecrasé si je réinstalle les vendors
Première solution
Fonctionne que sur mon PC


J'suis coincé

Ouvrir une issue sur le Github Symfony
Client moyen chaud
Deuxième solution
Proposer une PR, demande du temps à priori


J'suis coincé

Hacker le XmlEncoder
Troisième solution




On devient le hacker


Le hacker

C'est possible ???
# vendor/symfony/Component/Serializer/Encoder/XmlEncoder.php
<?php
namespace Symfony\Component\Serializer\Encoder;
// use classes...
class XmlEncoder
{
// other methods...
private function needsCdataWrapping(string $val): bool
{
return preg_match('/[<>&]/', $val);
}
}

Le hacker

Utiliser le \
# vendor/symfony/Component/Serializer/Encoder/XmlEncoder.php
<?php
namespace Symfony\Component\Serializer\Encoder;
// use classes...
class XmlEncoder
{
// other methods...
private function needsCdataWrapping(string $val): bool
{
return \preg_match('/[<>&]/', $val);
}
}

Le hacker

Utiliser le use_function
# vendor/symfony/Component/Serializer/Encoder/XmlEncoder.php
<?php
namespace Symfony\Component\Serializer\Encoder;
// use classes...
use function preg_match;
class XmlEncoder
{
// other methods...
private function needsCdataWrapping(string $val): bool
{
return preg_match('/[<>&]/', $val);
}
}

Le hacker

C'est possible ???
# functions/functions.php
namespace Symfony\Component\Serializer\Encoder;
function preg_match(
string $pattern,
string $subject,
array &$matches = null,
int $flags = 0,
int $offset = 0
): int|false {
// Notre code custom
if ('/[<>&]/' === $pattern) {
return false;
}
return \preg_match($pattern, $subject, $matches, $flags, $offset);
}

Le hacker

C'est pas fini !



Notre première contribution !

On contribue

Par où on commence ?
Proposer une PR
Trouver ou créer l'issue


On contribue

Comment ça se passe ?
Attendre la relecture
Forker le projet
Changes + tests + documentation


(créez une branche)
On contribue

Oui, mais j'ai peur
Trouver un mentor
Chercher dans la commu (Slack, Bluesky, etc.)


On contribue

Le slack




Vous aussi vous pouvez contribuer !

Contribuez vous aussi !


Bonus




AndoniLarz




J'ai contribué à Symfony - polite version
By Andoni Larzabal
J'ai contribué à Symfony - polite version
- 49