Skip to content
Extraits de code Groupes Projets

Comparer les révisions

Les modifications sont affichées comme si la révision source était fusionnée avec la révision cible. En savoir plus sur la comparaison des révisions.

Source

Sélectionner le projet cible
No results found

Cible

Sélectionner le projet cible
  • spip/images
  • RealET/filtres_images_warnings
  • bricebou/filtres_images
3 résultats
Afficher les modifications
Validations sur la source (41)
Affichage de
avec 612 ajouts et 1524 suppressions
......@@ -2,7 +2,6 @@
/.gitattributes export-ignore
/.gitignore export-ignore
/ecs.php export-ignore
/phpcs.xml.dist export-ignore
/phpstan.neon.dist export-ignore
/phpstan-baseline.neon export-ignore
/rector.php export-ignore
......
/vendor/
/composer.phar
/composer.lock
/phpcs.xml
/phpstan.neon
/.php_cs.cache
/.php_cs.txt
# Changelog
## Unreleased
## 5.0.1 - 2025-12-02
### Added
- !4735 Implémenter les variantes `convert` et `imagick` de `image_rotation`
## 5.0.0 - 2025-11-27
### Added
......@@ -12,8 +19,14 @@
### Fixed
- !4718 Optimisation des filtres `image_flip_vertical()` & `image_flip_horizontal()`
- !4720 Optimisation du filtre `image_nb()`
- !4719 Optimisation du filtre `image_gamma()`
- #4716 Optimisation du filtre `image_rotation()`
- #4716 Correction du paramètre `crop` de `image_rotation()`
- #4722 check existance de `exif_read_data()`
- spip/spip#5974 Éviter des warnings sur `image_oriente_selon_exif()` en absence d’image
### Removed
- #4723 Filtre `|image_typo`, installer le plugin `Image typographique`
- #4723 Function `rtl_mb_ord()`, installer le plugin `Image typographique`
- #4723 Function `rtl_reverse()`, installer le plugin `Image typographique`
- #4723 Function `rtl_visuel()`, installer le plugin `Image typographique`
- #4723 Function `printWordWrapped()`, installer le plugin `Image typographique`
- #4723 Function `produire_image_typo()`, installer le plugin `Image typographique`
......@@ -11,33 +11,46 @@
}
],
"require": {
"php": "^8.1"
"php": "^8.2"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"phpcompatibility/php-compatibility": "dev-develop",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.1",
"rector/rector": "^0.15.23",
"spip/coding-standards": "^1.3",
"symplify/easy-coding-standard": "^11.4"
"rector/rector": "^2.0",
"spip-league/easy-coding-standard": "^1.1",
"spip-league/sdk": "^1.0"
},
"suggest": {
"ext-exif": "*"
},
"repositories": {
"spip": {
"type": "composer",
"url": "https://get.spip.net/composer"
}
},
"autoload-dev": {
"psr-4": {
"Spip\\Test\\Images\\": "tests/"
}
},
"files": [
"vendor/spip-league/sdk/src/Stub/functions_autoloading.php",
"vendor/spip-league/sdk/src/Stub/functions_compiler.php",
"vendor/spip-league/sdk/src/Stub/functions_i18n.php",
"vendor/spip-league/sdk/src/Stub/functions_image_processing.php",
"vendor/spip-league/sdk/src/Stub/functions_filesystem.php",
"vendor/spip-league/sdk/src/Stub/functions_logger.php",
"vendor/spip-league/sdk/src/Stub/functions_templating.php",
"vendor/spip-league/sdk/src/Stub/functions_text_processing.php"
]
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
},
"platform": {
"php": "8.1.17"
"php": "8.2.26"
}
},
"extra": {
"branch-alias": {
"dev-master": "4.3.x-dev"
"dev-master": "5.0.x-dev"
}
}
}
<?php
// ecs.php
use PhpCsFixer\Fixer\Basic\CurlyBracesPositionFixer;
use PhpCsFixer\Fixer\Operator\NotOperatorWithSpaceFixer;
use PhpCsFixer\Fixer\Operator\NotOperatorWithSuccessorSpaceFixer;
use PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer;
use PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocAnnotationRemoveFixer;
use PhpCsFixer\Fixer\Phpdoc\PhpdocNoPackageFixer;
use PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer;
use PhpCsFixer\Fixer\Strict\StrictComparisonFixer;
use PhpCsFixer\Fixer\StringNotation\ExplicitStringVariableFixer;
use PhpCsFixer\Fixer\Whitespace\NoExtraBlankLinesFixer;
use PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays\DisallowLongArraySyntaxSniff;
use PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\AssignmentInConditionSniff;
use Symplify\CodingStandard\Fixer\ArrayNotation\ArrayListItemNewlineFixer;
use Symplify\CodingStandard\Fixer\ArrayNotation\ArrayOpenerAndCloserNewlineFixer;
use Symplify\CodingStandard\Fixer\Spacing\MethodChainingNewlineFixer;
use Symplify\CodingStandard\Fixer\Spacing\SpaceAfterCommaHereNowDocFixer;
use SpipLeague\EasyCodingStandard\Set\SetList;
use Symplify\EasyCodingStandard\Config\ECSConfig;
use Symplify\EasyCodingStandard\ValueObject\Set\SetList;
return static function (ECSConfig $ecsConfig): void {
// A. full sets
$ecsConfig->sets([SetList::PSR_12, SetList::SYMPLIFY, SetList::COMMON, SetList::CLEAN_CODE]);
$ecsConfig->rule(NoExtraBlankLinesFixer::class);
$ecsConfig->rule(DisallowLongArraySyntaxSniff::class);
$ecsConfig->ruleWithConfiguration(CurlyBracesPositionFixer::class, [
'functions_opening_brace' => 'same_line',
'anonymous_functions_opening_brace' => 'same_line',
]);
$ecsConfig->ruleWithConfiguration(GeneralPhpdocAnnotationRemoveFixer::class, [
'annotations' => ['throws', 'group', 'covers', 'category']
]);
$ecsConfig->indentation('tab');
$ecsConfig->paths([
__DIR__ . '/images_fonctions.php',
__DIR__ . '/filtres',
__DIR__ . '/tests',
]);
$ecsConfig->skip([
__DIR__ . '/lang',
ArrayListItemNewlineFixer::class,
ArrayOpenerAndCloserNewlineFixer::class,
AssignmentInConditionSniff::class,
DeclareStrictTypesFixer::class,
ExplicitStringVariableFixer::class,
MethodChainingNewlineFixer::class,
NotOperatorWithSuccessorSpaceFixer::class,
NotOperatorWithSpaceFixer::class,
UnaryOperatorSpacesFixer::class,
PhpdocNoPackageFixer::class,
SpaceAfterCommaHereNowDocFixer::class,
StrictComparisonFixer::class,
]);
};
return ECSConfig::configure()
->withSets([SetList::SPIP])
->withPaths([__DIR__])
->withRootFiles()
->withSkip([__DIR__ . '/lang', __DIR__ . '/vendor', __DIR__ . '/tests'])
;
......@@ -37,9 +37,9 @@ function couleur_web($couleur) {
}
function couleur_4096($couleur) {
$r = (substr($couleur, 0, 1));
$v = (substr($couleur, 2, 1));
$b = (substr($couleur, 4, 1));
$r = (substr((string) $couleur, 0, 1));
$v = (substr((string) $couleur, 2, 1));
$b = (substr((string) $couleur, 4, 1));
return "$r$r$v$v$b$b";
}
......
<?php
/**
* La fonction de base qui déclare le process et detecte si il est utilisable
* - si non renvoie null
* - si oui renvoie les formats qu'il sait traiter en entrée et en sortie
* @return string[]
*/
function filtres_image_process_convert_dist(): ?array {
if (proces_convert_disponible()) {
return [
'input' => ['gif', 'jpg', 'png', 'webp', 'avif'],
'output' => ['gif', 'jpg', 'png', 'webp', 'avif'],
];
}
return null;
}
function proces_convert_disponible() {
if (!defined('_CONVERT_COMMAND')) {
define('_CONVERT_COMMAND', 'convert');
}
if (!defined('_IMG_CONVERT_QUALITE')) {
define('_IMG_CONVERT_QUALITE', _IMG_QUALITE);
}
if (function_exists('exec') && _CONVERT_COMMAND !== '') {
return true;
}
return false;
}
/**
* La fonction qui cree la vignette avec le process extérieur
*/
function filtres_image_process_convert_vignette_dist(
string $fichier_source,
string $format_source,
string $fichier_dest,
string $format_dest,
int $width,
int $height
): ?string {
// Securite : mes_options.php peut preciser le chemin absolu
if (!proces_convert_disponible()) {
return null;
}
if (!defined('_RESIZE_COMMAND')) {
define(
'_RESIZE_COMMAND',
_CONVERT_COMMAND . ' -quality ' . _IMG_CONVERT_QUALITE . ' -orient Undefined %src -resize %xx%y! %dest'
);
}
$commande = str_replace(
['%x', '%y', '%src', '%dest'],
[$width, $height, escapeshellcmd($fichier_source), escapeshellcmd($fichier_dest)],
(string) _RESIZE_COMMAND
);
spip_logger('images')
->info($commande);
exec($commande, $output, $result_code);
if (!@file_exists($fichier_dest) || filemtime($fichier_dest) < filemtime($fichier_source)) {
spip_logger('images')->error("echec convert sur $fichier_dest");
return null; // echec commande
}
// renvoyer le chemin relatif car c'est ce qu'attend SPIP pour la suite (en particlier action/tester)
return $fichier_dest;
}
/**
* Version "convert" du filtre image_rotation si la librairie convert a été selectionnée dans l'admin
* @see image_rotation()
*
* @param string $im
* @param float $angle
* @param bool $crop
* @return string
*/
function image_rotation__process_convert($im, $angle, $crop = false) {
$fonction = ['image_rotation__process_convert', func_get_args()];
$image = _image_valeurs_trans($im, "rot-$angle", 'png', $fonction, false, _SVG_SUPPORTED);
if (!$image) {
return '';
}
if (
!proces_convert_disponible()
|| $image['format_source'] === 'svg'
|| (defined('_ROTATE_COMMAND') && _ROTATE_COMMAND === '')
) {
return image_rotation($im, $angle, $crop);
}
$im = $image['fichier'];
$dest = $image['fichier_dest'];
$creer = $image['creer'];
if ($creer) {
spip_timer('image_rotation__process_convert');
if (!defined('_ROTATE_COMMAND')) {
define('_ROTATE_COMMAND', _CONVERT_COMMAND . ' -background none %src -rotate %t %dest');
}
spip_logger('images')
->debug($log = "image_rotation: $im avec convert");
$commande = str_replace(
['%t', '%src', '%dest'],
[$angle, escapeshellcmd($im), escapeshellcmd($dest)],
_ROTATE_COMMAND
);
spip_logger('images')
->debug($commande);
exec($commande);
// si echec, fallback sur le filtre natif gd2
if (!file_exists($dest) || filemtime($dest) < filemtime($im)) {
spip_logger('images')->error("echec image_rotation: $im avec convert");
return image_rotation($im, $angle, $crop);
}
$t = spip_timer('image_rotation__process_convert');
spip_logger('images')
->debug("$log en $t");
}
[$src_y, $src_x] = taille_image($dest);
$image_tournee = _image_ecrire_tag($image, ['src' => $dest, 'width' => $src_x, 'height' => $src_y]);
if ($crop) {
$image_tournee = image_recadre($image_tournee, $image['largeur'], $image['hauteur'], 'center', 'transparent');
}
return $image_tournee;
}
<?php
/**
* La fonction de base qui déclare le process et detecte si il est utilisable
* - si non renvoie null
* - si oui renvoie les formats qu'il sait traiter en entrée et en sortie
* @return string[]
*/
function filtres_image_process_imagick_dist(): ?array {
if (method_exists(\Imagick::class, 'readImage')) {
return [
'input' => ['gif', 'jpg', 'png', 'webp', 'avif'],
'output' => ['gif', 'jpg', 'png', 'webp', 'avif'],
];
}
return null;
}
/**
* La fonction qui cree la vignette avec le process extérieur
*/
function filtres_image_process_imagick_vignette_dist(
string $fichier_source,
string $format_source,
string $fichier_dest,
string $format_dest,
int $width,
int $height
): ?string {
// Historiquement la valeur pour imagick semble differente. Si ca n'est pas necessaire, il serait preferable de garder _IMG_QUALITE
if (!defined('_IMG_IMAGICK_QUALITE')) {
define('_IMG_IMAGICK_QUALITE', 75);
}
if (!class_exists(\Imagick::class)) {
spip_logger('images')->error('Classe Imagick absente !');
return null;
}
// chemin compatible Windows
$dir_output = realpath(dirname($fichier_dest));
if (!$dir_output) {
return null;
}
$vignette = $dir_output . DIRECTORY_SEPARATOR . basename($fichier_dest);
try {
$imagick = new Imagick();
$imagick->readImage(realpath($fichier_source));
$imagick->resizeImage(
$width,
$height,
Imagick::FILTER_LANCZOS,
1
); //, IMAGICK_FILTER_LANCZOS, _IMG_IMAGICK_QUALITE / 100);
$imagick->writeImage($vignette);
} catch (\ImagickException $e) {
spip_logger('images')->error("echec imagick sur $vignette : " . $e->getMessage());
return null;
}
// $image_dest et $vignette sont normalement equivalents, mais on teste bien les deux
if (!@file_exists($vignette) || !@file_exists($fichier_dest)) {
spip_logger('images')->error("echec imagick sur $vignette");
return null;
}
// renvoyer le chemin relatif car c'est ce qu'attend SPIP pour la suite (en particlier action/tester)
return $fichier_dest;
}
......@@ -288,7 +288,7 @@ function _image_couleur_extraire($img, $x = 10, $y = 6) {
$color_tran = imagecolorsforindex($thumb, $color_index);
$x++;
$y++;
} while ($color_tran['alpha'] == 127 and $x < $newwidth and $y < $newheight);
} while ($color_tran['alpha'] == 127 && $x < $newwidth && $y < $newheight);
$couleur = _couleur_dec_to_hex($color_tran['red'], $color_tran['green'], $color_tran['blue']);
}
......
Ce diff est replié.
<?php
/**
* SPIP, Système de publication pour l'internet
*
* Copyright © avec tendresse depuis 2001
* Arnaud Martin, Antoine Pitrou, Philippe Rivière, Emmanuel Saint-James
*
* Ce programme est un logiciel libre distribué sous licence GNU/GPL.
*/
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
// librairie de base du core
include_spip('inc/filtres_images_mini');
// Image typographique
// Fonctions pour l'arabe
function rtl_mb_ord($char) {
if (($c = ord($char)) < 216) {
return $c;
}
return 256 * rtl_mb_ord(substr($char, 0, -1)) + ord(substr($char, -1));
/* return (strlen($char) < 2) ?
ord($char) : 256 * mb_ord(substr($char, 0, -1))
+ ord(substr($char, -1));
*/
}
function rtl_reverse($mot, $rtl_global) {
$res = null;
$rtl_prec = $rtl_global;
$ponctuations = ['/', '-', '«', '»', '“', '”', ',', '.', ' ', ':', ';', '(', ')', '،', '؟', '?', '!', ' '];
foreach ($ponctuations as $ponct) {
$ponctuation[$ponct] = true;
}
for ($i = 0; $i < spip_strlen($mot); $i++) {
$lettre = spip_substr($mot, $i, 1);
$code = rtl_mb_ord($lettre);
# echo "<li>$lettre - $code";
if (($code >= 54928 && $code <= 56767) || ($code >= 15_707_294 && $code <= 15_711_164)) {
$rtl = true;
} else {
$rtl = false;
}
if (
$lettre == '٠' || $lettre == '١' || $lettre == '٢' || $lettre == '٣' || $lettre == '٤' || $lettre == '٥'
|| $lettre == '٦' || $lettre == '٧' || $lettre == '٨' || $lettre == '٩'
) {
$rtl = false;
}
if ($ponctuation[$lettre]) {
# le truc mega casse-gueule de l'inversion unicode:
# traiter le sens de placement en fonction de la lettre precedente
# (et non automatiquement le rtl_global)
$rtl = $rtl_prec;
if ($rtl) {
switch ($lettre) {
case '(':
$lettre = ')';
break;
case ')':
$lettre = '(';
break;
case '«':
$lettre = '»';
break;
case '»':
$lettre = '«';
break;
case '“':
$lettre = '”';
break;
case '”':
$lettre = '“';
break;
}
}
}
if ($rtl) {
$res = $lettre . $res;
} else {
$res = $res . $lettre;
}
$rtl_prec = $rtl;
}
return $res;
}
function rtl_visuel($texte, $rtl_global) {
// hebreu + arabe: 54928 => 56767
// hebreu + presentation A: 15707294 => 15710140
// arabe presentation: 15708336 => 15711164
# echo hexdec("efb7bc");
// premiere passe pour determiner s'il y a du rtl
// de facon a placer ponctuation et mettre les mots dans l'ordre
$arabic_letters = [
[
'ي', // lettre 0
'ﻱ', // isolee 1
'ﻳ', // debut 2
'ﻴ', // milieu 3
'ﻲ',
],
[
'ب', // lettre 0
'ﺏ', // isolee 1
'ﺑ', // debut 2
'ﺒ', // milieu 3
'ﺐ',
],
[
'ا', // lettre 0
'ا', // isolee 1
'ﺍ', // debut 2
'ﺍ', // milieu 3
'ﺎ',
],
[
'إ', // lettre 0
'إ', // isolee 1
'إ', // debut 2
'ﺈ', // milieu 3
'ﺈ',
],
[
'ل', // lettre 0
'ﻝ', // isolee 1
'ﻟ', // debut 2
'ﻠ', // milieu 3
'ﻞ',
],
[
'خ', // lettre 0
'ﺥ', // isolee 1
'ﺧ', // debut 2
'ﺨ', // milieu 3
'ﺦ',
],
[
'ج', // lettre 0
'ﺝ', // isolee 1
'ﺟ', // debut 2
'ﺠ', // milieu 3
'ﺞ',
],
[
'س', // lettre 0
'ﺱ', // isolee 1
'ﺳ', // debut 2
'ﺴ', // milieu 3
'ﺲ',
],
[
'ن', // lettre 0
'ﻥ', // isolee 1
'ﻧ', // debut 2
'ﻨ', // milieu 3
'ﻦ',
],
[
'ش', // lettre 0
'ﺵ', // isolee 1
'ﺷ', // debut 2
'ﺸ', // milieu 3
'ﺶ',
],
[
'ق', // lettre 0
'ﻕ', // isolee 1
'ﻗ', // debut 2
'ﻘ', // milieu 3
'ﻖ',
],
[
'ح', // lettre 0
'ﺡ', // isolee 1
'ﺣ', // debut 2
'ﺤ', // milieu 3
'ﺢ',
],
[
'م', // lettre 0
'ﻡ', // isolee 1
'ﻣ', // debut 2
'ﻤ', // milieu 3
'ﻢ',
],
[
'ر', // lettre 0
'ر', // isolee 1
'ﺭ', // debut 2
'ﺮ', // milieu 3
'ﺮ',
],
[
'ع', // lettre 0
'ع', // isolee 1
'ﻋ', // debut 2
'ﻌ', // milieu 3
'ﻊ',
],
[
'و', // lettre 0
'و', // isolee 1
'ﻭ', // debut 2
'ﻮ', // milieu 3
'ﻮ',
],
[
'ة', // lettre 0
'ة', // isolee 1
'ة', // debut 2
'ﺔ', // milieu 3
'ﺔ',
],
[
'ف', // lettre 0
'ﻑ', // isolee 1
'ﻓ', // debut 2
'ﻔ', // milieu 3
'ﻒ',
],
[
'ﻻ', // lettre 0
'ﻻ', // isolee 1
'ﻻ', // debut 2
'ﻼ', // milieu 3
'ﻼ',
],
[
'ح', // lettre 0
'ﺡ', // isolee 1
'ﺣ', // debut 2
'ﺤ', // milieu 3
'ﺢ',
],
[
'ت', // lettre 0
'ﺕ', // isolee 1
'ﺗ', // debut 2
'ﺘ', // milieu 3
'ﺖ',
],
[
'ض', // lettre 0
'ﺽ', // isolee 1
'ﺿ', // debut 2
'ﻀ', // milieu 3
'ﺾ',
],
[
'ك', // lettre 0
'ك', // isolee 1
'ﻛ', // debut 2
'ﻜ', // milieu 3
'ﻚ',
],
[
'ه', // lettre 0
'ﻩ', // isolee 1
'ﻫ', // debut 2
'ﻬ', // milieu 3
'ﻪ',
],
[
'ي', // lettre 0
'ي', // isolee 1
'ﻳ', // debut 2
'ﻴ', // milieu 3
'ﻲ',
],
[
'ئ', // lettre 0
'ﺉ', // isolee 1
'ﺋ', // debut 2
'ﺌ', // milieu 3
'ﺊ',
],
[
'ص', // lettre 0
'ﺹ', // isolee 1
'ﺻ', // debut 2
'ﺼ', // milieu 3
'ﺺ',
],
[
'ث', // lettre 0
'ﺙ', // isolee 1
'ﺛ', // debut 2
'ﺜ', // milieu 3
'ﺚ',
],
[
'ﻷ', // lettre 0
'ﻷ', // isolee 1
'ﻷ', // debut 2
'ﻸ', // milieu 3
'ﻸ',
],
[
'د', // lettre 0
'ﺩ', // isolee 1
'ﺩ', // debut 2
'ﺪ', // milieu 3
'ﺪ',
],
[
'ذ', // lettre 0
'ﺫ', // isolee 1
'ﺫ', // debut 2
'ﺬ', // milieu 3
'ﺬ',
],
[
'ط', // lettre 0
'ﻁ', // isolee 1
'ﻃ', // debut 2
'ﻄ', // milieu 3
'ﻂ',
],
[
'آ', // lettre 0
'آ', // isolee 1
'آ', // debut 2
'ﺂ', // milieu 3
'ﺂ',
],
[
'أ', // lettre 0
'أ', // isolee 1
'أ', // debut 2
'ﺄ', // milieu 3
'ﺄ',
],
[
'ؤ', // lettre 0
'ؤ', // isolee 1
'ؤ', // debut 2
'ﺆ', // milieu 3
'ﺆ',
],
[
'ز', // lettre 0
'ز', // isolee 1
'ز', // debut 2
'ﺰ', // milieu 3
'ﺰ',
],
[
'ظ', // lettre 0
'ظ', // isolee 1
'ﻇ', // debut 2
'ﻈ', // milieu 3
'ﻆ',
],
[
'غ', // lettre 0
'غ', // isolee 1
'ﻏ', // debut 2
'ﻐ', // milieu 3
'ﻎ',
],
[
'ى', // lettre 0
'ى', // isolee 1
'ﯨ', // debut 2
'ﯩ', // milieu 3
'ﻰ',
],
[
'پ', // lettre 0
'پ', // isolee 1
'ﭘ', // debut 2
'ﭙ', // milieu 3
'ﭗ',
],
[
'چ', // lettre 0
'چ', // isolee 1
'ﭼ', // debut 2
'ﭽ', // milieu 3
'ﭻ',
],
];
if (init_mb_string() and mb_regex_encoding() !== 'UTF-8') {
echo 'Attention: dans php.ini, il faut indiquer:<br /><strong>mbstring.internal_encoding = UTF-8</strong>';
}
$texte = explode(' ', $texte);
foreach ($texte as $mot) {
$res = '';
// Inserer des indicateurs de debut/fin
$mot = '^' . $mot . '^';
$mot = preg_replace(',&nbsp;,u', ' ', $mot);
$mot = preg_replace(',&#171;,u', '«', $mot);
$mot = preg_replace(',&#187;,u', '»', $mot);
// ponctuations
$ponctuations = ['/', '-', '«', '»', '“', '”', ',', '.', ' ', ':', ';', '(', ')', '،', '؟', '?', '!', ' '];
foreach ($ponctuations as $ponct) {
$mot = str_replace("$ponct", "^$ponct^", $mot);
}
// lettres forcant coupure
$mot = preg_replace(',ا,u', 'ا^', $mot);
$mot = preg_replace(',د,u', 'د^', $mot);
$mot = preg_replace(',أ,u', 'أ^', $mot);
$mot = preg_replace(',إ,u', 'إ^', $mot);
$mot = preg_replace(',أ,u', 'أ^', $mot);
$mot = preg_replace(',ر,u', 'ر^', $mot);
$mot = preg_replace(',ذ,u', 'ذ^', $mot);
$mot = preg_replace(',ز,u', 'ز^', $mot);
$mot = preg_replace(',و,u', 'و^', $mot);
$mot = preg_replace(',و,u', 'و^', $mot);
$mot = preg_replace(',ؤ,u', 'ؤ^', $mot);
$mot = preg_replace(',ة,u', 'ة^', $mot);
// $mot = preg_replace(",ل,u", "^ل", $mot);
// $mot = preg_replace(",,", "^", $mot);
$mot = preg_replace(',٠,u', '^٠^', $mot);
$mot = preg_replace(',١,u', '^١^', $mot);
$mot = preg_replace(',٢,u', '^٢^', $mot);
$mot = preg_replace(',٣,u', '^٣^', $mot);
$mot = preg_replace(',٤,u', '^٤^', $mot);
$mot = preg_replace(',٥,u', '^٥^', $mot);
$mot = preg_replace(',٦,u', '^٦^', $mot);
$mot = preg_replace(',٧,u', '^٧^', $mot);
$mot = preg_replace(',٨,u', '^٨^', $mot);
$mot = preg_replace(',٩,u', '^٩^', $mot);
// Ligatures
$mot = preg_replace(',لا,u', 'ﻻ', $mot);
$mot = preg_replace(',لأ,u', 'ﻷ', $mot);
foreach ($arabic_letters as $a_l) {
$mot = preg_replace(',([^\^])' . $a_l[0] . '([^\^]),u', '\\1' . $a_l[3] . '\\2', $mot);
$mot = preg_replace(',\^' . $a_l[0] . '([^\^]),u', '^' . $a_l[2] . '\\1', $mot);
$mot = preg_replace(',([^\^])' . $a_l[0] . '\^,u', '\\1' . $a_l[4] . '^', $mot);
// il semble qu'il ne soit pas necessaire de remplacer
// la lettre isolee
// $mot = preg_replace(",\^".$a_l[0]."\^,u", "^".$a_l[1]."^", $mot);
}
$mot = preg_replace(',\^,u', '', $mot);
$res = $mot;
$res = rtl_reverse($mot, $rtl_global);
/*
$rtl = false;
for ($i = 0; $i < spip_strlen($mot); $i++) {
$lettre = spip_substr($mot, $i, 1);
$code = rtl_mb_ord($lettre);
if (($code >= 54928 && $code <= 56767) || ($code >= 15708336 && $code <= 15711164)) $rtl = true;
}
*/
if ($rtl_global) {
$retour = $res . ' ' . $retour;
} else {
$retour = $retour . ' ' . $res;
}
}
return $retour;
}
function printWordWrapped(
$image,
$top,
$left,
$maxWidth,
$font,
$couleur,
$text,
$textSize,
$align = 'left',
$hauteur_ligne = 0
) {
$line = null;
$retour = [];
static $memps = [];
$fontps = false;
// Normalisation du chemin de la police en chemin absolu (pour Windows cf https://bugs.php.net/bug.php?id=75656)
$font = realpath($font);
// imageftbbox exige un float, et settype aime le double pour php < 4.2.0
settype($textSize, 'double');
// calculer les couleurs ici, car fonctionnement different selon TTF ou PS
$black = imagecolorallocatealpha(
$image,
hexdec(substr($couleur, 0, 2)),
hexdec(substr($couleur, 2, 2)),
hexdec(substr($couleur, 4, 2)),
0
);
$grey2 = imagecolorallocatealpha(
$image,
hexdec(substr($couleur, 0, 2)),
hexdec(substr($couleur, 2, 2)),
hexdec(substr($couleur, 4, 2)),
127
);
$rtl_global = false;
for ($i = 0; $i < spip_strlen($text); $i++) {
$lettre = spip_substr($text, $i, 1);
$code = rtl_mb_ord($lettre);
if (($code >= 54928 && $code <= 56767) || ($code >= 15_707_294 && $code <= 15_711_164)) {
$rtl_global = true;
}
}
// split the text into an array of single words
$words = explode(' ', $text);
// les espaces
foreach ($words as $k => $v) {
$words[$k] = str_replace(['~'], [' '], $v);
}
if ($hauteur_ligne == 0) {
$lineHeight = floor($textSize * 1.3);
} else {
$lineHeight = $hauteur_ligne;
}
$dimensions_espace = imageftbbox($textSize, 0, $font, ' ', []);
if ($dimensions_espace[2] < 0) {
$dimensions_espace = imageftbbox($textSize, 0, $font, $line, []);
}
$largeur_espace = $dimensions_espace[2] - $dimensions_espace[0];
$retour['espace'] = $largeur_espace;
$line = '';
$lines = [];
while (count($words) > 0) {
$mot = $words[0];
if ($rtl_global) {
$mot = rtl_visuel($mot, $rtl_global);
}
$dimensions = imageftbbox($textSize, 0, $font, $line . ' ' . $mot, []);
$lineWidth = $dimensions[2] - $dimensions[0]; // get the length of this line, if the word is to be included
if ($lineWidth > $maxWidth) { // if this makes the text wider that anticipated
$lines[] = $line; // add the line to the others
$line = ''; // empty it (the word will be added outside the loop)
}
$line .= ' ' . $words[0]; // add the word to the current sentence
$words = array_slice($words, 1); // remove the word from the array
}
if ($line != '') {
$lines[] = $line;
} // add the last line to the others, if it isn't empty
$height = count($lines) * $lineHeight; // the height of all the lines total
// do the actual printing
$i = 0;
// Deux passes pour recuperer, d'abord, largeur_ligne
// necessaire pour alignement right et center
$largeur_max = 0;
foreach ($lines as $line) {
if ($rtl_global) {
$line = rtl_visuel($line, $rtl_global);
}
$dimensions = imageftbbox($textSize, 0, $font, $line, []);
$largeur_ligne = $dimensions[2] - $dimensions[0];
if ($largeur_ligne > $largeur_max) {
$largeur_max = $largeur_ligne;
}
}
foreach ($lines as $i => $line) {
if ($rtl_global) {
$line = rtl_visuel($line, $rtl_global);
}
$dimensions = imageftbbox($textSize, 0, $font, $line, []);
$largeur_ligne = $dimensions[2] - $dimensions[0];
if ($align == 'right') {
$left_pos = $largeur_max - $largeur_ligne;
} else {
if ($align == 'center') {
$left_pos = floor(($largeur_max - $largeur_ligne) / 2);
} else {
$left_pos = 0;
}
}
imagefttext($image, $textSize, 0, $left + $left_pos, $top + $lineHeight * $i, $black, $font, trim($line), []);
}
$retour['height'] = $height; # + round(0.3 * $hauteur_ligne);
$retour['width'] = $largeur_max;
return $retour;
}
//array imagefttext ( resource image, float size, float angle, int x, int y, int col, string font_file, string text [, array extrainfo] )
//array imagettftext ( resource image, float size, float angle, int x, int y, int color, string fontfile, string text )
function produire_image_typo() {
/*
arguments autorises:
$texte : le texte a transformer; attention: c'est toujours le premier argument, et c'est automatique dans les filtres
$couleur : la couleur du texte dans l'image - pas de dieze
$police: nom du fichier de la police (inclure terminaison)
$largeur: la largeur maximale de l'image ; attention, l'image retournee a une largeur inferieure, selon les limites reelles du texte
$hauteur_ligne: la hauteur de chaque ligne de texte si texte sur plusieurs lignes
(equivalent a "line-height")
$padding: forcer de l'espace autour du placement du texte; necessaire pour polices a la con qui "depassent" beaucoup de leur boite
$align: alignement left, right, center
*/
/**
* On définit les variables par défaut
*/
$variables_defaut = [
'align' => false,
'police' => '',
'largeur' => 0,
'hauteur_ligne' => 0,
'padding' => 0,
];
$variable = [];
// Recuperer les differents arguments
$variable = [];
$numargs = func_num_args();
$arg_list = func_get_args();
$texte = $arg_list[0];
for ($i = 1; $i < $numargs; $i++) {
if (($p = strpos($arg_list[$i], '=')) !== false) {
$nom_variable = substr($arg_list[$i], 0, $p);
$val_variable = substr($arg_list[$i], $p + 1);
$variable["$nom_variable"] = $val_variable;
}
}
$variable = [...$variables_defaut, ...$variable];
// Construire requete et nom fichier
$text = str_replace('&nbsp;', '~', $texte);
$text = preg_replace(",(\r|\n)+,ms", ' ', $text);
include_spip('inc/charsets');
$text = html2unicode(strip_tags($text));
if (strlen($text) == 0) {
return '';
}
$taille = $variable['taille'];
if ($taille < 1) {
$taille = 16;
}
if (isset($variable['couleur'])) {
$couleur = couleur_html_to_hex($variable['couleur']);
} else {
$couleur = '';
}
if (strlen($couleur) < 6) {
$couleur = '000000';
}
$alt = $texte;
$align = $variable['align'];
if (!$variable['align']) {
$align = 'left';
}
$police = $variable['police'];
if (strlen($police) < 2) {
$police = 'dustismo.ttf';
}
$largeur = $variable['largeur'];
if ($largeur < 5) {
$largeur = 600;
}
if ($variable['hauteur_ligne'] > 0) {
$hauteur_ligne = $variable['hauteur_ligne'];
} else {
$hauteur_ligne = 0;
}
if ($variable['padding'] > 0) {
$padding = $variable['padding'];
} else {
$padding = 0;
}
// Normalisation de la couleur pour ne pas produire 2 hash différents pour le nom du fichier cache
$string = "$text-$taille-" . strtoupper($couleur) . "-$align-$police-$largeur-$hauteur_ligne-$padding";
$query = md5($string);
$dossier = sous_repertoire(_DIR_VAR, 'cache-texte');
$fichier = "$dossier$query.png";
$flag_gd_typo = function_exists('imageftbbox')
&& function_exists('imageCreateTrueColor');
if (@file_exists($fichier)) {
$image = $fichier;
} else {
if (!$flag_gd_typo) {
return $texte;
}
$font = find_in_path('polices/' . $police);
if (!$font) {
spip_log(_T('fichier_introuvable', ['fichier' => $police]));
$font = find_in_path('polices/' . 'dustismo.ttf');
}
// Normalisation du chemin de la police en chemin absolu (pour Windows cf https://bugs.php.net/bug.php?id=75656)
$font = realpath($font);
$imgbidon = imageCreateTrueColor($largeur, 45);
$retour = printWordWrapped(
$imgbidon,
$taille + 5,
0,
$largeur,
$font,
$couleur,
$text,
$taille,
'left',
$hauteur_ligne
);
$hauteur = $retour['height'];
$largeur_reelle = $retour['width'];
$espace = $retour['espace'];
imagedestroy($imgbidon);
$im = imageCreateTrueColor($largeur_reelle - $espace + (2 * $padding), $hauteur + 5 + (2 * $padding));
imagealphablending($im, false);
imagesavealpha($im, true);
// Creation de quelques couleurs
$grey2 = imagecolorallocatealpha(
$im,
hexdec(substr($couleur, 0, 2)),
hexdec(substr($couleur, 2, 2)),
hexdec(substr($couleur, 4, 2)),
127
);
ImageFilledRectangle($im, 0, 0, $largeur_reelle + (2 * $padding), $hauteur + 5 + (2 * $padding), $grey2);
// Le texte a dessiner
printWordWrapped(
$im,
$taille + 5 + $padding,
$padding,
$largeur,
$font,
$couleur,
$text,
$taille,
$align,
$hauteur_ligne
);
// Utiliser imagepng() donnera un texte plus claire,
// compare a l'utilisation de la fonction imagejpeg()
_image_gd_output($im, ['fichier_dest' => $fichier, 'format_dest' => 'png']);
imagedestroy($im);
$image = $fichier;
}
$dimensions = spip_getimagesize($image);
$largeur = $dimensions[0];
$hauteur = $dimensions[1];
return inserer_attribut(
"<img src='$image' width='$largeur' height='$hauteur' style='width:" . $largeur . 'px;height:' . $hauteur . "px;' />",
'alt',
$alt
);
}
......@@ -59,18 +59,3 @@ $GLOBALS['spip_matrice']['_couleur_hex_to_dec'] = 'filtres/images_lib.php';
$GLOBALS['spip_matrice']['_image_distance_pixel'] = 'filtres/images_lib.php';
$GLOBALS['spip_matrice']['_image_decale_composante'] = 'filtres/images_lib.php';
*/
/**
* Créer une image typo
*
* @note
* Cas particulier historique : son nom commence par "image_"
* mais s'applique sur un texte…
* @return string
*/
function image_typo() {
include_spip('inc/filtres_images_mini.php');
include_spip('filtres/images_typo');
$tous = func_get_args();
return call_user_func_array('produire_image_typo', $tous);
}
......@@ -6,7 +6,7 @@
source="https://git.spip.net/spip/filtres_images.git"
reference="fr">
<langue code="ar" url="https://trad.spip.net/tradlang_module/paquet-images?lang_cible=ar" total="2" traduits="2" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
<traducteur nom="George" lien="https://trad.spip.net/auteur/جورج-قندلفت" />
<traducteur nom="George" lien="https://trad.spip.net/auteur/george" />
</langue>
<langue code="br" url="https://trad.spip.net/tradlang_module/paquet-images?lang_cible=br" total="2" traduits="2" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
<traducteur nom="nonobreizh" lien="https://trad.spip.net/auteur/nonobreizh" />
......@@ -42,6 +42,9 @@
<langue code="lb" url="https://trad.spip.net/tradlang_module/paquet-images?lang_cible=lb" total="2" traduits="2" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
<traducteur nom="Jim Wanderscheid" lien="https://trad.spip.net/auteur/jwander" />
</langue>
<langue code="mg" url="https://trad.spip.net/tradlang_module/paquet-images?lang_cible=mg" total="2" traduits="2" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
<traducteur nom="iBesorongola" lien="https://trad.spip.net/auteur/ibesorongola" />
</langue>
<langue code="nl" url="https://trad.spip.net/tradlang_module/paquet-images?lang_cible=nl" total="2" traduits="2" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
<traducteur nom="Suske" lien="https://trad.spip.net/auteur/suske" />
</langue>
......
<?php
// This is a SPIP language file -- Ceci est un fichier langue de SPIP
// extrait automatiquement de https://trad.spip.net/tradlang_module/paquet-images?lang_cible=mg
// ** ne pas modifier le fichier **
return [
// I
'images_description' => 'Filtres de transformation d’images et de couleurs',
'images_slogan' => 'Filtres de transformation d’images et de couleurs',
];
<paquet
prefix="images"
categorie="multimedia"
version="4.3.0-dev"
etat="dev"
version="5.0.1"
etat="stable"
compatibilite="[5.0.0-dev;5.0.*]"
logo="images/image_filtre-xx.svg"
>
......
<?xml version="1.0"?>
<ruleset>
<file>.</file>
<exclude-pattern>vendor/*</exclude-pattern>
<exclude-pattern>lang/*</exclude-pattern>
<exclude-pattern>tests/*</exclude-pattern>
<rule ref="SPIP50"/>
<config name="ignore_warnings_on_exit" value="1"/>
<arg name="cache" value=".php_cs.cache"/>
<arg name="report-full" value=".php_cs.txt"/>
<arg name="report-summary"/>
<arg value="s"/>
</ruleset>
parameters:
ignoreErrors:
-
message: "#^Function _couleur_dec_to_hex not found\\.$#"
count: 4
path: filtres/couleurs.php
-
message: "#^Function _couleur_hex_to_dec not found\\.$#"
count: 6
path: filtres/couleurs.php
-
message: "#^Function _couleur_hsl_to_rgb not found\\.$#"
count: 2
path: filtres/couleurs.php
-
message: "#^Function _couleur_rgb_to_hsl not found\\.$#"
count: 2
path: filtres/couleurs.php
-
message: "#^Function couleur_eclaircir not found\\.$#"
count: 1
path: filtres/couleurs.php
-
message: "#^Function couleur_foncer not found\\.$#"
count: 1
path: filtres/couleurs.php
-
message: "#^Function include_spip not found\\.$#"
count: 7
path: filtres/couleurs.php
-
message: "#^Function _couleur_dec_to_hex not found\\.$#"
count: 3
path: filtres/images_lib.php
-
message: "#^Function _couleur_hsl_to_rgb not found\\.$#"
count: 1
path: filtres/images_lib.php
-
message: "#^Function _couleur_rgb_to_hsl not found\\.$#"
count: 1
path: filtres/images_lib.php
-
message: "#^Function _image_valeurs_trans not found\\.$#"
count: 1
path: filtres/images_lib.php
-
message: "#^Function ecrire_fichier not found\\.$#"
count: 1
path: filtres/images_lib.php
-
message: "#^Function include_spip not found\\.$#"
count: 1
path: filtres/images_lib.php
-
message: "#^Function lire_fichier not found\\.$#"
count: 1
path: filtres/images_lib.php
-
message: "#^Function svg_extract_couleurs not found\\.$#"
count: 1
path: filtres/images_lib.php
-
message: "#^Function _couleur_hex_to_dec not found\\.$#"
count: 4
path: filtres/images_transforme.php
-
message: "#^Function _image_ecrire_tag not found\\.$#"
count: 15
path: filtres/images_transforme.php
-
message: "#^Function _image_gd_output not found\\.$#"
count: 27
path: filtres/images_transforme.php
-
message: "#^Function _image_tag_changer_taille not found\\.$#"
count: 1
path: filtres/images_transforme.php
-
message: "#^Function _image_valeurs_trans not found\\.$#"
count: 22
path: filtres/images_transforme.php
-
message: "#^Function charger_fonction not found\\.$#"
count: 1
path: filtres/images_transforme.php
-
message: "#^Function hauteur not found\\.$#"
count: 1
path: filtres/images_transforme.php
-
message: "#^Function image_reduire not found\\.$#"
count: 1
path: filtres/images_transforme.php
-
message: "#^Function imagick_isopaqueimage not found\\.$#"
count: 1
path: filtres/images_transforme.php
-
message: "#^Function imagick_readimage not found\\.$#"
count: 2
path: filtres/images_transforme.php
-
message: "#^Function imagick_setfillcolor not found\\.$#"
count: 1
path: filtres/images_transforme.php
-
message: "#^Function imagick_writeimage not found\\.$#"
message: '#^Function spip_timer not found\.$#'
identifier: function.notFound
count: 2
path: filtres/images_transforme.php
-
message: "#^Function include_spip not found\\.$#"
count: 6
path: filtres/images_transforme.php
-
message: "#^Function largeur not found\\.$#"
count: 1
path: filtres/images_transforme.php
path: filtres/image_process/convert.php
-
message: "#^Function spip_log not found\\.$#"
count: 2
message: '#^Function spip_timer not found\.$#'
identifier: function.notFound
count: 8
path: filtres/images_transforme.php
-
message: "#^Function spip_unlink not found\\.$#"
count: 1
path: filtres/images_transforme.php
message: '#^Access to an undefined property Spip\\Cli\\Command\\ImagesPurger\:\:\$io\.$#'
identifier: property.notFound
count: 8
path: spip-cli/ImagesPurger.php
-
message: "#^Function svg_ajouter_background not found\\.$#"
message: '#^Access to constant VALUE_REQUIRED on an unknown class Symfony\\Component\\Console\\Input\\InputOption\.$#'
identifier: class.notFound
count: 1
path: filtres/images_transforme.php
path: spip-cli/ImagesPurger.php
-
message: "#^Function svg_ajouter_voile not found\\.$#"
message: '#^Access to undefined constant Spip\\Cli\\Command\\ImagesPurger\:\:FAILURE\.$#'
identifier: classConstant.notFound
count: 2
path: filtres/images_transforme.php
path: spip-cli/ImagesPurger.php
-
message: "#^Function svg_filter_blur not found\\.$#"
message: '#^Access to undefined constant Spip\\Cli\\Command\\ImagesPurger\:\:SUCCESS\.$#'
identifier: classConstant.notFound
count: 1
path: filtres/images_transforme.php
path: spip-cli/ImagesPurger.php
-
message: "#^Function svg_filter_grayscale not found\\.$#"
message: '#^Call to an undefined method Spip\\Cli\\Command\\ImagesPurger\:\:setName\(\)\.$#'
identifier: method.notFound
count: 1
path: filtres/images_transforme.php
path: spip-cli/ImagesPurger.php
-
message: "#^Function svg_filter_sepia not found\\.$#"
message: '#^Parameter \$input of method Spip\\Cli\\Command\\ImagesPurger\:\:execute\(\) has invalid type Symfony\\Component\\Console\\Input\\InputInterface\.$#'
identifier: class.notFound
count: 1
path: filtres/images_transforme.php
path: spip-cli/ImagesPurger.php
-
message: "#^Function svg_flip not found\\.$#"
count: 2
path: filtres/images_transforme.php
-
message: "#^Function svg_recadrer not found\\.$#"
count: 3
path: filtres/images_transforme.php
-
message: "#^Function svg_rotate not found\\.$#"
message: '#^Parameter \$output of method Spip\\Cli\\Command\\ImagesPurger\:\:execute\(\) has invalid type Symfony\\Component\\Console\\Output\\OutputInterface\.$#'
identifier: class.notFound
count: 1
path: filtres/images_transforme.php
-
message: "#^Function svg_transformer not found\\.$#"
count: 1
path: filtres/images_transforme.php
-
message: "#^Function taille_image not found\\.$#"
count: 3
path: filtres/images_transforme.php
-
message: "#^Function _T not found\\.$#"
count: 1
path: filtres/images_typo.php
-
message: "#^Function _image_gd_output not found\\.$#"
count: 1
path: filtres/images_typo.php
-
message: "#^Function couleur_html_to_hex not found\\.$#"
count: 1
path: filtres/images_typo.php
-
message: "#^Function find_in_path not found\\.$#"
count: 2
path: filtres/images_typo.php
-
message: "#^Function html2unicode not found\\.$#"
count: 1
path: filtres/images_typo.php
-
message: "#^Function include_spip not found\\.$#"
count: 2
path: filtres/images_typo.php
-
message: "#^Function init_mb_string not found\\.$#"
count: 1
path: filtres/images_typo.php
-
message: "#^Function inserer_attribut not found\\.$#"
count: 1
path: filtres/images_typo.php
-
message: "#^Function sous_repertoire not found\\.$#"
count: 1
path: filtres/images_typo.php
-
message: "#^Function spip_getimagesize not found\\.$#"
count: 1
path: filtres/images_typo.php
-
message: "#^Function spip_log not found\\.$#"
count: 1
path: filtres/images_typo.php
-
message: "#^Function spip_strlen not found\\.$#"
count: 2
path: filtres/images_typo.php
-
message: "#^Function spip_substr not found\\.$#"
count: 2
path: filtres/images_typo.php
-
message: "#^Function include_spip not found\\.$#"
count: 2
path: images_fonctions.php
path: spip-cli/ImagesPurger.php
......@@ -2,7 +2,7 @@ includes:
- phpstan-baseline.neon
parameters:
phpVersion: 80100
phpVersion: 80200
paths:
- .
excludePaths:
......@@ -10,4 +10,6 @@ parameters:
- vendor
- lang
- tests
- ecs.php
- rector.php
level: 0
......@@ -2,31 +2,13 @@
declare(strict_types=1);
use Rector\CodeQuality\Rector\LogicalAnd\LogicalToBooleanRector;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector;
use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
use Rector\Php71\Rector\FuncCall\CountOnNullRector;
use Rector\Php80\Rector\FunctionLike\MixedTypeRector;
use Rector\Php80\Rector\FunctionLike\UnionTypesRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([
__DIR__ . '/filtres',
__DIR__ . '/images_fonctions.php',
__DIR__ . '/tests',
]);
$rectorConfig->sets([
LevelSetList::UP_TO_PHP_81
]);
$rectorConfig->skip([
__DIR__ . '/lang',
FinalizePublicClassConstantRector::class,
NullToStrictStringFuncCallArgRector::class,
CountOnNullRector::class,
MixedTypeRector::class,
UnionTypesRector::class,
]);
};
return RectorConfig::configure()
->withPaths([__DIR__])
->withRootFiles()
->withPhpSets(php82: true)
->withRules([LogicalToBooleanRector::class])
->withSkip([__DIR__ . '/lang', __DIR__ . '/vendor', __DIR__ . '/tests', NullToStrictStringFuncCallArgRector::class]);
<?php
namespace Spip\Cli\Command;
use Spip\Cli\Console\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class ImagesPurger extends Command
{
protected array $images_obsoletes = [];
protected function configure() {
$this
->setName('images:purger')
->addOption('from', null, InputOption::VALUE_REQUIRED, 'Purger les images plus anciennes que cette date')
->setDescription('Purger les images temporaires de local/ plus anciennes que la date fournie en option from')
->addUsage("--from='-1 year'")
->addUsage("--from='-6 month'")
->addUsage("--from='2024-01-01'")
->addUsage("--from='2024-10'")
;
}
protected function execute(InputInterface $input, OutputInterface $output) {
$this->io->title('Purger les images temporaires obsolètes');
$from = $input->getOption('from');
if (!$from) {
$this->io->error('Option --from requis');
return self::FAILURE;
}
$from = strtotime($from);
if (!$from) {
$this->io->error('Option --from invalide');
return self::FAILURE;
}
$this->io->care(sprintf('Purger avant le <info>%s</info>', date('Y-m-d H:i:s', $from)));
$dir_caches = [_DIR_VAR . 'cache-gd2/', _DIR_VAR . 'cache-vignettes/'];
foreach ($dir_caches as $dir_cache) {
$this->parcourirDossierCacheImages($dir_cache, $from);
}
$this->nettoyerCacheImagesObsoletes();
return self::SUCCESS;
}
protected function parcourirDossierCacheImages($dir, $from, $recurs = true) {
$dir = rtrim($dir, '/') . '/';
$files = glob($dir . '*');
foreach ($files as $file) {
if (is_dir($file)) {
if ($recurs) {
$this->parcourirDossierCacheImages($file, $from, $recurs);
}
} else {
if (filemtime($file) < $from) {
$this->images_obsoletes[] = $file;
}
}
}
}
protected function nettoyerCacheImagesObsoletes() {
include_spip('inc/filtres');
$nb_deleted = 0;
$size_deleted = 0;
foreach ($this->images_obsoletes as $file) {
$nb_deleted++;
$size_deleted += filesize($file);
if (@unlink($file)) {
$this->io->check("Supprimer: $file");
} else {
$this->io->fail("Supprimer: $file");
}
}
$size = taille_en_octets($size_deleted);
if ($nb_deleted) {
$this->io->care($nb_deleted . ' fichiers supprimés' . ($size ? ' (' . $size . ')' : ''));
} else {
$this->io->care('0 fichier supprimé');
}
}
}