Ir al contenido

Configuración del compilador de backport de NextPDF

Herramientas de compilación, NO una dependencia de tiempo de ejecución. Todo lo descrito en esta página configura cómo se transforma el código fuente en tiempo de compilación. Nada de ello se distribuye a un entorno de ejecución posterior.

La transformación se controla mediante tres archivos de configuración de Rector ubicados en rector/config/ y tres reglas personalizadas ubicadas en rector/rules/. La configuración seleccionada depende del destino. El destino PHP 8.1 requiere una única pasada de Rector. El destino PHP 7.4 usa una canalización de dos pasadas con una etapa de corrección intermedia. La segunda pasada es necesaria porque Rector no puede resolver los valores predeterminados de los casos de enumeración en un solo recorrido.

ArchivoPropósitoUsado por
rector/config/rector-php81.phpDescenso en una sola pasada a PHP 8.1Destino PHP 8.1
rector/config/rector-php74-enums.phpPasada 1 — conversión de enumeraciones en clases de lista de constantesDestino PHP 7.4
rector/config/rector-php74.phpPasada 2 — descenso completo a PHP 7.4Destino PHP 7.4

Cada configuración llama a la cadena de conjuntos de descenso de Rector (withDowngradeSets(php81: true) o withDowngradeSets(php74: true)) para las características que Rector gestiona de forma nativa. A continuación, registra reglas personalizadas para los casos que no gestiona. Verificado con los tres archivos de rector/config/.

Tanto rector-php81.php como rector-php74.php omiten */tests/Benchmark/*. Los scripts de benchmark hacen referencia a bibliotecas externas de PDF que Rector no puede resolver, lo que bloquea su resolutor de parámetros predeterminados. rector-php74.php omite además DowngradeHashAlgorithmXxHashRector. Esa regla integrada se bloquea con las constantes MHASH_XXH* obsoletas en versiones modernas de PHP, y el código fuente no usa xxHash. Verificado con las llamadas a withSkip() de ambos archivos.

El repositorio distribuye exactamente tres reglas personalizadas de Rector. Las tres están registradas en rector-php81.php; las reglas de visibilidad asimétrica, clonación con sustituciones y constantes de trait también están registradas en rector-php74.php. Así lo afirma directamente tests/Rector/RectorRulesMetadataTest.php, que construye cada regla y comprueba su definición y sus tipos de nodo.

Elimina el modificador set de la visibilidad asimétrica. Una propiedad o un parámetro promovido declarado public private(set) pasa a ser simplemente public. El acceso de lectura se conserva; la restricción de escritura en tiempo de compilación se elimina. Si no queda ninguna visibilidad de lectura, la regla toma public por defecto. Transformación respaldada por el código fuente, a partir de tests/Rector/Fixtures/DowngradeAsymmetricVisibility/public_private_set.php.inc:

before
<?php
class Config {
public private(set) float $x = 0.0;
public private(set) string $name = '';
public private(set) int $count = 0;
}
after
<?php
class Config {
public float $x = 0.0;
public string $name = '';
public int $count = 0;
}

Reescribe la forma funcional de clone() con un arreglo de sustituciones, convirtiéndola en una clonación seguida de asignaciones de propiedad explícitas y la devolución de una variable temporal. El contador de variables temporales se reinicia por archivo. Esta regla debe ejecutarse después de la regla de eliminación de propiedades de solo lectura, porque de lo contrario la asignación expandida fallaría contra una propiedad de solo lectura. Transformación respaldada por el código fuente, a partir de tests/Rector/Fixtures/DowngradeCloneWith/return_clone_with.php.inc:

before
<?php
class PageSize {
public float $width = 0.0;
public float $height = 0.0;
public function withDimensions(float $width, float $height): self {
return clone($this, ['width' => $width, 'height' => $height]);
}
}
after
<?php
class PageSize {
public float $width = 0.0;
public float $height = 0.0;
public function withDimensions(float $width, float $height): self
{
$__cloneResult1 = clone $this;
$__cloneResult1->width = $width;
$__cloneResult1->height = $height;
return $__cloneResult1;
}
}

La regla tiene limitaciones documentadas. El emparejamiento de argumentos usa un patrón no recursivo, por lo que no se gestionan los valores de sustitución que contienen paréntesis anidados. Solo las claves de arreglo de tipo cadena se resuelven en nombres de propiedades. Verificado con rector/rules/DowngradeCloneWithRector.php y su conjunto de fixtures.

Convierte las constantes de trait en propiedades estáticas. Una constante de trait es una característica que los entornos de ejecución anteriores rechazan con «Traits cannot have constants». La regla también reescribe las referencias self::CONST y static::CONST a la forma de propiedad estática. La visibilidad se conserva; el modificador final se elimina porque las propiedades no pueden ser final en el destino más antiguo. Una constante de clase tipada pasa a ser una propiedad tipada. Transformación respaldada por el código fuente, a partir de tests/Rector/Fixtures/DowngradeTraitConstants/private_constant.php.inc:

before
<?php
trait HasLimit
{
private const MAX_SIZE = 1024;
public function getLimit(): int
{
return self::MAX_SIZE;
}
}
after
<?php
trait HasLimit
{
private static $MAX_SIZE = 1024;
public function getLimit(): int
{
return self::$MAX_SIZE;
}
}

La canalización de dos pasadas para PHP 7.4

Sección titulada «La canalización de dos pasadas para PHP 7.4»

El descenso a PHP 7.4 no puede ejecutarse en una sola pasada. El resolutor de valores predeterminados de parámetros de Rector se bloquea con los valores predeterminados de los casos de enumeración en la promoción de propiedades del constructor. Por ello, el script de compilación ejecuta:

  1. Pasada 1 — preprocesamiento de enumeraciones. rector-php74-enums.php ejecuta únicamente la regla integrada de conversión de enumeraciones en clases de lista de constantes. Tras esta pasada, los casos de enumeración son constantes de clase simples.
  2. Limpieza de la caché. La caché de Rector se limpia para que la segunda pasada no vea un árbol obsoleto.
  3. Correcciones de posprocesamiento. scripts/build.php reescribe los patrones que la regla de enumeración a clase no cubre. Los métodos que antes eran de instancia en la enumeración pasan a ser estáticos. Los accesos EnumClass::Case->value y ->name se resuelven. Los argumentos con nombre que Rector no pudo vincular se aplanan a posicionales. Son patrones sintácticos que, de otro modo, serían un error de análisis en PHP 7.4.
  4. Pasada 2 — descenso completo. rector-php74.php ejecuta la cadena completa de descenso a PHP 7.4 más las reglas personalizadas.

Verificado con scripts/build.php (runRector(), postProcessFixups()).

scripts/build.php es el orquestador. Sus opciones están verificadas con la llamada getopt() y el constructor Build:

IndicadorPredeterminadoEfecto
--version=<x.y.z>2.0.0Versión escrita en el composer.json y el CHANGELOG.md generados
--source-dir=<path>c:/Users/admin/DocumentsRaíz que contiene los repositorios hermanos de código fuente
--output-dir=<path><repo>/outputLugar donde se escribe la distribución generada
--target=php74 | --target=php81php81Destino de descenso. php74 fuerza solo el núcleo y deshabilita Pro
--dry-rundesactivadoEjecuta cada etapa en modo de solo informe; se omiten las copias y la ejecución de Rector
--no-prodesactivadoExcluye el paquete Pro (solo en el destino PHP 8.1; PHP 7.4 ya lo excluye)

Un valor --target no válido genera InvalidArgumentException antes de iniciar cualquier trabajo. Verificado con Build::__construct() (la protección VALID_TARGETS).

ScriptComandoPropósito
composer testphpunitEjecutar los conjuntos de fixtures de las reglas
composer analysephpstan analyse rector/rules scripts --level=10Analizar estáticamente el código de compilación
composer buildphp scripts/build.phpCompilación completa
composer build:dryphp scripts/build.php --dry-runCompilación en modo de prueba (dry-run)

Verificado con composer.jsonscripts.

  • /integrations/backport/quickstart/ — ejecutar la prueba en seco y la compilación completa.
  • /integrations/backport/troubleshooting/ — qué significa cada etapa de fallo.