1311 private links
J'ai eu quelques soucis avec Travis CI pour des tests de bout en bout d'un outil qui manipule des images en PHP.
En gros, j'ai :
- un dossier avec des images attendues
- un dossier avec les images sources
- des tests unitaires qui passent les images sources dans la moulinette, et s'assurent qu'elles ressortent identiques aux images attendues.
Tout marchait bien en local, mais lors de l'exécution des tests Travis, toutes les images étaient différentes. À l’œil nu, c'était bien les même, mais les binaires n'étaient pas identiques.
Il s'avère qu'il suffit d'avoir une version légèrement différente de php-gd
pour que les images générées soient différentes, par exemple une amélioration de l'encodage. Merci cet article du blog de Piwik pour m'avoir mis sur la piste.
De fait, la solution est assez simple : recréer à la volée les images attendues avec PHP GD (et donc la même version que celle utilisée par la moulinette). Attention, il faut bien ré-utiliser toutes les fonctions utilisée dans la manipulation des images pour arriver au bon résultat.
En bonus, un petit snippet :
/**
* Duplicate expected images using the current GD version.
*
* Different versions of GD will result in slightly different images,
* which would make the comparaison test fail. By regenerating expected thumbs,
* the expected and actual result should be the same.
*
* @param string $image relative path of the expected thumb inside the expected thumb directory.
* @param bool $crop Set to true to apply the crop function.
*
* @throws \Exception couldn't create the image.
*/
public function regenerate($image, $crop = false)
{
$targetFolder = dirname(self::$regenerated . $image);
if (! is_dir($targetFolder)) {
mkdir($targetFolder, 0755, true);
}
$content = file_get_contents(self::$expected . $image);
$sourceImg = @imagecreatefromstring($content);
$width = imagesx($sourceImg);
$height = imagesy($sourceImg);
$targetImg = imagecreatetruecolor($width, $height);
if (! imagecopyresized(
$targetImg, $sourceImg,
0, 0, 0, 0,
$width, $height, $width, $height
)
) {
@imagedestroy($sourceImg);
@imagedestroy($targetImg);
throw new \Exception('Could not generate the expected image from source image.');
}
if ($crop) {
$targetImg = imagecrop($targetImg, [
'x' => 0,
'y' => 0,
'width' => $width,
'height' => $height
]);
}
$target = self::$regenerated . $image;
imagedestroy($sourceImg);
imagepng($targetImg, $target);
imagedestroy($targetImg);
}
Container is a small but powerful dependency injection container that allows you to decouple components in your application in order to write clean and testable code.
C'est bon à savoir. La fonction uniqid()
de PHP s'appuie sur l'heure. Pour éviter les collisions, elle met donc le thread en pause avec une microseconde (usleep(1)). Si vous savez un peu comment fonctionne un CPU, ça peut en fait être un peu plus, en fonction de sa fréquence, ce qu'il fait à côté, etc. Du coup, dans une boucle, une pause de ce genre peut commencer à avoir un impact non négligeable sur les performances.
Conclusion, il faut toujours appeler cette fonction avec le paramètre $more_entropy
pour éviter de passer par cette pause.
La construction d'une page, étape par étape, pour apprendre le web design. J'ai survolé le contenu, mais j'aime bien le format.
Intéressant. Des statistiques sur les conventions de codes appliquées sur un ensemble de projets PHP.
Globalement, je suis dans la majorité, c'est plutôt bon signe.
« Build cross platform desktop apps with JavaScript, HTML, and CSS »
Plein d'exemples sur la syntaxe et l'utilisation du langage Go.
Un petit outil qui permet de télécharger une police Google dans tous les formats, et génère le CSS pour les utiliser en local.
Un émulateur de Gameboy en PHP. Quand même oui.
Un loooong article sur les bonnes pratiques en PHP.
Le début n'est pas passionnant, mais il y a quelques chapitres par la suite qui ont l'air de valoir d'être lu.
Set d'icônes libre basé sur une police. Utilisé ici même.
Un guide CSS pour centrer des éléments, en particulier verticalement, parce que... grumble !
Compatibilité des propriétés CSS3 entre les différentes versions de navigateur.
A lire.
J'ai enfin migré mon Shaarli sur mon « nouveau » serveur, tout docker-ifié. J'en ai profité pour virer mes hacks et le rendre compatible avec la dernière version v0.6.3
et les futures versions proprement.
Ça veut dire mise à jour du thème, qui est maintenant personnalisable. C'est sur Github et c'est libre. Je l'ai appelé Launch, comme le thème Wordpress duquel je me suis inspiré à l'époque.
Et pour personnaliser tout ça, par exemple le menu, j'ai fait un plugin shaarli.
Maintenant je n'ai plus la honte de contribuer activement et d'utiliser une vieille version en prod. 🙂
Un autre outil pour debugger des regex.
"At universities they should make every developer write an app with Node.js, deploy it to production, then try to update the dependencies 3 months later. The only downside is we would have zero new developers coming out of computer science programs.
You see the Node.js philosophy is to take the worst fucking language ever designed and put it on the server."
Ah ah ! C'est vrai que les processus en webdev se complexifient vraiment avec tous les outils existants sur toutes les couches.
Y'a des applications, genre Wekan, que j'ai pas été foutu d'installer sans docker tellement c'est le merdier.
Bon après il faut pas jeter le bébé avec l'eau du bain, y'a de beaux outils, mais AMHA il faut savoir garder les choses suffisement simples.
Des recommandations pour PHP.
Y'a plein de bonnes choses : du coding style (PSR-2) histoire d'avoir un code cohérent, les recommandations d'autoloading, etc.
Dans les drafts, également : une standardisation pour PHPDoc, des conseils de sécurité et surtout...
Huggable Interface :
- A Huggable object expresses affection and support for another object by invoking its hug() method, passing $this as the first parameter.
- An object whose hug() method is invoked MUST hug() the calling object back at least once.
:)
Sympa ce petit soft pour compter les lignes de code. C'est tout simple et ça s'exécute en une commande.
Aller une petite analyse de workspace pro :