Objectifs de la séance ¶
- Effectuer les contrôles sur le fichier reçu
- Générer dynamiquement des images en
PHP
- Transformer une image reçue, en format et en dimensions
- S'amuser avec les images en
PHP
Consignes ¶
Ce sujet complémentaire est la suite du TP « Envoi de fichiers ». Les questions seront logiquement traitées dans le même dépôt Git
que le sujet principal.
Renforcement des contrôles sur le fichier reçu ¶
La documentation officielle sur les envois de fichiers mentionne l'utilisation d'un champ caché de formulaire nommé « MAX_FILE_SIZE
» qui doit contenir la taille maximale admissible par le serveur Web propulsé par PHP
. Classiquement, cette valeur peut être trouvée dans le fichier de configuration de PHP « php.ini
», plus précisément dans la directive « upload_max_filesize
». Les valeurs sont exprimées en octets ou, plus souvent, en Kio, Mio ou Gio grâce aux suffixes « K
», « M
» et « G
» (par exemple « 2M
» pour 2 Mio, soit 2×1024×1024=2097152 octets). Pour consulter cette valeur programmatiquement, il faut utiliser la function « ini_get()
». Puisque nous sommes dans une démarche de conception et de réutilisation, vous allez développer la classe « ServerConfiguration\Directive
» qui consulte les valeurs de façon fiable et permet également d'effectuer les transformations du type chaîne « 2M
» en entier « 2097152
».
- Créez la classe «
ServerConfiguration\Directive
» - Définissez la méthode «
get()
» qui retourne la valeur de la directive dont le nom lui est passé en paramètre - Définissez la méthode «
getInBytes()
» qui retourne la valeur en octets de la directive dont le nom lui est passé en paramètre :- Récupérez la valeur de la directive demandée
- Utilisez l'expression rationnelle «
'/([0-9]+)([gmk]?)/i'
» avec preg_match() pour capturer (les éléments en parenthèse sont capturés et placés dans le tableau «matches
» en troisième paramètre de la fonction) la valeur numérique et l'éventuel suffixe d'unité («K
», «M
» ou «G
») - Selon le suffixe, effectuer les opérations suivantes dans l'ordre et sans exclusivité des cas (un «
switch
» sans «break
» !) :G
- valeur numérique = valeur numérique × 1024
M
- valeur numérique = valeur numérique × 1024
K
- valeur numérique = valeur numérique × 1024
- Définissez la méthode «
getUploadMaxFilesize()
» qui retourne la valeur en octets de la directive «upload_max_filesize
» - Testez la dernière méthode qui devrait retourner «
2097152
» - Ajoutez une méthode de classe «
maxFileSize()
» à la classe «UserAvatar
» qui retourne la valeur en octets de la taille maximale de la propriété «avatar
» en base de données - Modifiez le formulaire produit dans la méthode «
toHtml()
» de la classe «UserProfileWithAvatar
» afin qu'il intègre un champ caché «MAX_FILE_SIZE
» ayant pour valeur le minimum de «Directive::getUploadMaxFilesize()
» et de «UserAvatar::maxFileSize()
» - Ajoutez une méthode de classe «
isValidFile(string \$filename)
» à la classe «UserAvatar
» contrôle que le fichier dont le chemin est passé en paramètre est bien un fichier de typePNG
et qu'il s'ouvre correctement (lisez simplement ses dimensions avecgetimagesize()
) - Contrôlez que la taille du fichier reçu est bien inférieure à la valeur de «
UserAvatar::maxFileSize()
» et qu'il est valide au sens de la méthode «UserAvatar::isValidFile()
»
Génération dynamique d'images en PHP
¶
PHP, associé à la bibliothèque GD
, permet de manipuler des images. Cependant, la bibliothèque propose uniquement une vision non orientée objet. Afin de vous familiariser avec le développement objet en PHP
, une encapsulation objet des fonctionnalités GD
vous est proposée sous la forme d'une classe MyGdImage
.
Toutes les fonctions GD
qui admettent comme premier paramètre une ressource issue de la création d'une image GD
ont été transformées en méthodes de la classe MyGdImage
.
Par exemple, la fonction GD
bool imageFilledRectangle( resource $image, int $x1, int $y1, int $x2, int $y2, int $color )
devient la méthode bool filledRectangle( int $x1, int $y1, int $x2, int $y2, int $color )
de la classe MyGdImage
.
Notez la disparition du paramètre de type ressource (qui est devenu un attribut de l'instance) ainsi que la suppression du mot 'image' dans le nom de la méthode.
Les fonctions de la bibliothèque GD
qui n'admettent pas une ressource comme premier paramètre sont des méthodes statiques de la classe MyGdImage
. Pour connaître l'ensemble des fonctions GD
, consultez la documentation. Pour finir, la construction d'instances de la classe MyGdImage
est possible grâce à trois méthodes de classe :
MyGdImage::createFromSize(int $sx, int $sy)
pour créer une image vide de taille$sx × $sy
MyGdImage::createFromString(string $data)
pour créer une image à partir d'une chaîne de caractères$data
contenant l'équivalent des données d'un fichier image.MyGdImage::createFromFile(string $file, string $type)
pour créer une image à partir d'un fichier$file
existant sur le serveur. Le type du fichier est donné par$type
qui prend ses valeurs dans les constantes de la classeMyGdImage
:MyGdImage::GD
pour un fichier de type GDMyGdImage::GD2PART
pour un fichier de type GD2PARTMyGdImage::GD2
pour un fichier de type GD2MyGdImage::GIF
pour un fichier de type GIFMyGdImage::JPEG
pour un fichier de type JPEGMyGdImage::PNG
pour un fichier de type PNGMyGdImage::WBMP
pour un fichier de type WBMPMyGdImage::XBM
pour un fichier de type XBMMyGdImage::XPM
pour un fichier de type XPM
Un exemple de code pourrait être :
et le résultat serait :
- Récupérez le code source de la classe «
MyGdImage
» : «MyGdImage.php
» (télécharger)InformationLe code de cette classe fait appel à des possibilités offertes par
PHP
qui seront vues plus tard. - Récupérez le code source de la classe «
MyGdImageException
» : «MyGdImageException.php
» (télécharger)
Transformation de la taille et du type des images reçues ¶
Jusqu'à présent, pour simplifier la réalisation de TP, vous pouvez envoyer des images de type PNG
uniquement. Il serait intéressant de proposer à l'utilisateur de soumettre une image de type PNG
, JPEG
voire GIF
qui sont les formats historiques du Web. De plus, à part la limite de taille de contenu à 65535 octets, l'image n'est pas contrainte dans ses dimensions en pixels. Il serait judicieux de redimensionner, sur le serveur, le fichier reçu de l'utilisateur pour en faire une image aux mêmes proportions avec une dimension maximale de 150 pixels en largeur et en hauteur (cette valeur est arbitraire).
Pour cela, vous devez utiliser « MyGdImage
».
- Consultez la documentation des «
Fonctions de bufferisation de sortie
»InformationLa bibliothèque
GD
propos uniquement d'enregistrer un fichier ou le transmettre au navigateur du client. Il est donc impossible de récupérer directement les données d'une image générée. Dans le cadre de l'exercice demandé, cela impliquerait d'enregistrer l'image résultat dans un fichier pour pouvoir relire son contenu, ce qui est très inefficace. L'alternative est de capturer le flux de sortie pour récupérer son contenu et ainsi ne pas passer par le disque du serveur pour gagner du temps.Afin de vous faciliter la tâche, «
MyGdImage
», l'encapsulation objet de «GdImage
», contient une méthode de capture du tampon de sortie («protected static function captureOutputBuffer(callable $callback): string
») qui est utilisée dans les méthodes «getJpeg()
», «getPng()
» et «getGif()
» pour récupérer le contenu de l'image générée. - Détectez le type d'image reçu et faites en sorte de transformer les types qui ne sont pas
PNG
- Redimensionnez l'image reçue pour que sa dimension la plus grande soit égale à 150 pixels
S'amuser avec les images ¶
Réalisez les scripts permettant d'obtenir les images suivantes :
Réalisez un ciel étoilé avec la lune dont la phase est passée en paramètre (de 0 à 100) :
Pour les plus enthousiastes d'entre-vous, utilisation de filter pour réaliser des convolutions :
avec le noyau
, devient :