Cómo utilizar symplify/vendor-patches en proyectos php
Es posible que alguna vez hayan encontrado un bug en una dependencia de un proyecto de php que utiliza composer, y el arreglo es simple y lo único que se requiere es cambiar 1 o 2 líneas de código en el paquete referenciado es decir en /vendor/usuario/paquete-con-error
.
Como buen ciudadano del mundo open source, lo primero que se debe hacer es abrir un issue y crear un pull request con los cambios en el proyecto dependencia para que el dueño lo pueda aceptar y se arregle para todos los usuarios de ese paquete, pero no vamos a negar que este proceso toma bastante tiempo, y si necesitamos arreglar lo más pronto hay otras opciones.
Puedes crear un fork del proyecto en tu github y usar ese url de github en la version de composer.json, pero estarías tomando una responsabilidad manual de actualizar y aplicar el cambio cada vez que haya actualizaciones. Se puede copiar el paquete localmente que es más rápido pero con esto ya no hay actualizaciones.
O la mejor opción se puede usar “composer patches”.
Hace un tiempo estaba trabajando en un proyecto laravel con el paquete de administración nova, y un addon para manejo de archivos infinety-es/nova-filemanager
el paquete funcionaba muy bien con archivos públicos, pero para mi proyecto necesitaba guardar los archivos en un bucket privado de S3 y para descargarlos debía generar una url temporal con un tiempo de expiración máximo.
Analizando el código del paquete encontré 2 lugares donde se generaba la url del archivo para descarga en el archivo fuente src/Http/Services/NormalizeFile.php
en la función toArray y en la función getImage lo único que había que hacer es realizar el siguiente cambio:
--- /dev/null
+++ ../src/Http/Services/NormalizeFile.php
@@ -50,7 +50,7 @@
'mime' => $this->getCorrectMimeFileType(),
'path' => $this->storagePath,
'size' => $this->getFileSize(),
- 'url' => $this->cleanSlashes($this->storage->url($this->storagePath)),
+ 'url' => $this->cleanSlashes($this->storage->temporaryUrl($this->storagePath, '+5 minutes')),
'date' => $this->modificationDate(),
'ext' => $this->file->getExtension(),
]);
@@ -145,7 +145,7 @@
private function getImage($mime, $extension = false)
{
if (Str::contains($mime, 'image') || $extension == 'svg') {
- return $this->storage->url($this->storagePath);
+ return $this->storage->temporaryUrl($this->storagePath, '+5 minutes');
}
$fileType = new FileTypesImages();
Cómo se cambia esas 2 líneas en /vendor?
Se hace en 4 simples pasos:
- Instalar el paquete que controla los parches
composer require cweagans/composer-patches symplify/vendor-patches --dev
- Se crea una copia del archivo a cambiar en /vendor por la extensión
.old
Por ejemplo en mi caso cambie vendor/infinety-es/nova-filemanager/src/Http/Services/NormalizeFile.php
a
vendor/infinety-es/nova-filemanager/src/Http/Services/NormalizeFile.php.old
-
Abrir el archivo original
vendor/infinety-es/nova-filemanager/src/Http/Services/NormalizeFile.php
y realizar los cambios necesarios. Se verifica que los cambios funcionen ya que solo el archivo*.php
funciona no el*.php.old
. -
Generar el parche usando el comando:
vendor/bin/vendor-patches generate
La herramienta de symplify genera todos los parches en el directorio /patches/
:
ls -l patches
.rw-r--r-- 883 marcelo 30 Apr 7:16 infinety-es-nova-filemanager-src-http-services-normalizefile-php.patch
Y también genera la configuración de parches al composer.json:
...
"extra": {
"laravel": [],
"patches": {
"infinety-es/nova-filemanager": [
"patches/infinety-es-nova-filemanager-src-http-services-normalizefile-php.patch"
]
}
},
...
Y eso es todo, la siguiente vez que realicen composer install
, el parche se aplica automáticamente.
Referencias: