¿Cómo instalar un módulo que incluye una versión diferente de Symfony?

17

Soy desarrollador y mantenedor del proyecto CiviCRM. Hemos estado tratando de hacer una versión de Drupal 8 CiviCRM, y hemos recorrido un largo camino. Estamos golpeando nuestras cabezas contra nuestros teclados colectivos tratando de encontrar un bloqueador importante para el proyecto.

CiviCRM ha usado Symfony por un tiempo, y la versión que se incluye es diferente a la que se incluye con Drupal.

Podemos instalar CiviCRM con Drupal 8, pero después de instalarlo, no podemos instalar ningún otro módulo de Drupal.

Creo que se reduce a una situación en la que de alguna manera la versión CiviCRM de Symfony se carga antes que la versión Drupal, y esto causa problemas.

¿Alguien sabe de un módulo Drupal 8 que incluya una versión diferente de Symfony que la que se entrega con Drupal?

Recientemente me encontré con el proyecto Ludwig. Este módulo permite el registro de espacios de nombres en una clase que se extiendeServiceProviderBase .

¿Sería posible que la versión Drupal 8 del módulo CiviCRM incluya un archivo CivicrmServiceProvider.php, que define una CivicrmServiceProviderclase y un register()método que agrega un espacio de nombres de contenedor para permitir que esto funcione?

Muchos archivos CiviCRM tienen usedeclaraciones como Drupal que comienzan con Symfony, como aquí .

De hecho, colocamos CiviCRM Core en la carpeta Drupal doc_root / collections, y usamos el módulo de bibliotecas.

Este es el repositorio para la versión 8.x del módulo CiviCRM Drupal , si alguien quiere ver lo que tenemos hasta ahora. Si alguien tiene el elixir mágico para esto, puedo decirte que habría mucha gente feliz en nuestra comunidad. Entonces, si sabe cómo ayudarnos, hágalo.

CiviCRM se instala y las páginas de CiviCRM funcionan. Lo que no funciona es que después de instalar CiviCRM, no podemos instalar otros módulos a través de la página admin / modules. Que yo sepa, eso es lo único que está roto. También instalar módulos con Drush, después de instalar CiviCRM, funciona.

Intentar instalar otro módulo después de instalar CiviCRM provoca el siguiente error:

Error fatal de PHP: Llame al método indefinido Symfony \ Component \ DependencyInjection \ Definition :: setFactory () en /var/www/html/civi-for-d8/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php en la línea 206

Eso está en Drupal 8.3.5. Intentar instalar CiviCRM para Drupal 8 en una instancia limpia de Drupal 8.4-dev causa el siguiente error:

Drupal \ Component \ Serialization \ Exception \ InvalidDataTypeException: el indicador reservado "@" no puede iniciar un escalar simple; debe citar el escalar en la línea 8 (cerca de "argumentos: [@string_translation, @ civicrm.page_state]"). en Drupal \ Component \ Serialization \ YamlSymfony :: decode () (línea 40 de /var/www/html/drupal84/core/lib/Drupal/Component/Serialization/YamlSymfony.php).

jackrabbithanna
fuente
En dispositivos móviles, pero ¿qué versión de Symfony? 8.4 usará 3.x, un salto desde v2.
Matt Glaman
Estamos en la versión 2.5.0 en CiviCRM
jackrabbithanna
Alguna documentación del problema: issues.civicrm.org/jira/browse/CRM-17652 ... Una persona informa que no vio el problema, pero no estoy seguro de eso, todos los demás que intentan obtener un error como se informó allí
jackrabbithanna
44
No creo que esto sea posible. Drupal 8.4 en realidad ya cambió a Symfony3, aunque todavía hay discusiones similares relacionadas con drush, que tiene el mismo problema. No es posible cargar dos versiones diferentes de Symfony, ya sea que rompas tu integración o rompas Drupal. Quizás symfony3 aún no esté en 8.4, pero el soporte de seguridad para symfony2 finalizará antes del soporte de seguridad de Drupal8, por lo que en algún momento, tendremos que cambiar
Berdir
1
@Berdir que podría ser una buena respuesta?
Clive

Respuestas:

8

Por lo tanto, creo que si CiviCRM se instalara en Drupal 8 a través del compositor (es decir, composer require civicrm/civicrm-coreen la raíz de Drupal) y el uso de Symfony por parte de CiviCRM fuera compatible con Symfony 2.8 o 3.x (es decir, sin usar una funcionalidad obsoleta), esto podría funcionar.

Esto instalaría todo en el directorio de proveedores de Drupal, en lugar de tener dos, y significaría que CiviCRM usaría la versión de Symfony en Drupal 8. Pero si CiviCRM fuera compatible con versiones posteriores de Symfony (incluso si incluye una versión anterior para Drupal). 6 y 7 y otros CMS) debería estar bien.

¿Yo creo que?

ACTUALIZADO: Sí, funciona, lo probé. :-) Originalmente publiqué lo siguiente en la cola de problemas de CiviCRM ( CRM-17652 ), pero volví a publicar aquí para completar.

La gran idea:

Dado que el compositor es bastante nuevo para mucha gente, voy a intentar ir paso a paso, desde algunas cosas de compositores de alto nivel hasta una forma en que se podría hacer en CiviCRM:

  • Composer permite que las aplicaciones requieran las bibliotecas que necesita (y las bibliotecas, por supuesto, pueden requerir otras bibliotecas).
  • Las bibliotecas tienen un archivo composer.json que dice qué otras bibliotecas necesita y con qué versiones es compatible (pero no necesariamente una versión única específica, generalmente una gama de versiones, como ^2.4.3 que dice un mínimo de 2.4.3 y hasta (pero no incluido) 3.0.0)
  • Las aplicaciones tienen un composer.json que describe de manera similar las bibliotecas necesarias y la compatibilidad con una variedad de versiones, pero el rango es realmente para ayudar con la actualización. Una aplicación también tendrá un composer.lock que es un conjunto específico de versiones individuales
  • Las bibliotecas también pueden tener un composer.lock para sus propias pruebas o distribución (como construir el tarball de lanzamiento con las dependencias incluidas), pero esto se ignora cuando una aplicación requiere la biblioteca dada (consulte https://getcomposer.org/doc/02 -libraries.md # archivo de bloqueo )
  • Cuando una aplicación quiere requerir una nueva biblioteca, el compositor encuentra una intersección de compatibilidad de versiones entre todas las cosas que requiere la aplicación (incluidas todas las bibliotecas ya instaladas y sus dependencias) y la nueva biblioteca, posiblemente haciendo algunas actualizaciones para alinear todo ( o error si no puede encontrar una combinación compatible de versiones)
  • En este caso, CiviCRM es una biblioteca, y un sitio particular de Drupal 8 es la aplicación (el núcleo de Drupal es una biblioteca)
  • CiviCRM podría decir que "requiere" Symfony ^2.5 en su composer.json, lo que significa que es compatible con las versiones 2.5.0 hasta (pero sin incluir) 3.0.0
  • Cuando un sitio Drupal 8 quiere usar CiviCRM, el administrador del sitio usa composer require civicrm/civicrm-corepara requerir la biblioteca CiviCRM y todas sus dependencias. Si CiviCRM es compatible con Symfony 2.8 (como se usa en Drupal 8.3.x), todo se instalará y funcionará bien, utilizando el único Symfony 2.8 de Drupal. Todas las dependencias terminan en el directorio de proveedores de Drupal.
  • Sin embargo, CiviCRM podría mantener Symfony 2.5 en su composer.lock, lo que significa que las pruebas lo usarían, y los tarballs para Drupal 6 y 7 y otros CMS agruparían Symfony 2.5

La propuesta:

  1. Actualice el composer.json de CiviCRM para que pueda ser utilizado como biblioteca por CMS basados ​​en compositores como Drupal 8 (pero probablemente otros podrían moverse de esa manera en el futuro; el compositor se está volviendo bastante popular)
  2. Asegúrese de que el núcleo CiviCRM sea compatible con Symfony 2.8 y 3.0 (utilizado por Drupal 8.3.xy 8.4.x respectivamente) pero mantenga la versión "oficialmente compatible" (actualmente Symfony 2.5) en el composer.lock para pruebas y el tarball para distribución. Ser compatible con múltiples versiones de Symfony puede no ser tan difícil como parece: hay varias bibliotecas compatibles con Symfony 2.8 y 3.0. ¡Puede ser solo una cuestión de evitar métodos / clases / características obsoletas! El composer.json deberá actualizarse para reflejar esto
  3. Use el compositor para instalar la biblioteca CiviCRM en Drupal 8 en lugar de copiar en el directorio de bibliotecas. Esta se está convirtiendo en la forma normal de instalar bibliotecas PHP de terceros en Drupal 8 (esto es ampliamente utilizado por Drupal Commerce, por ejemplo)

Para los CMS basados ​​en compositores, realmente creo que esta es la forma correcta. Si bien este problema afecta actualmente a Symfony y Drupal, a medida que la comunidad PHP comienza a usar más y más bibliotecas de terceros a través del compositor, esto podría afectar a otros CMS con otros conflictos de versiones.

Algún código de trabajo para probar:

Entonces, como prometí, en realidad conseguí que esto funcionara en un grado limitado :-) Estoy llegando a esto desde una perspectiva de Drupal / Compositor / Symfony: no tengo mucha experiencia en CiviCRM, así que probablemente haya algo de mejores formas de hacer mi proceso a continuación. Agradezco cualquier consejo!

  1. Descargue e instale Drupal 8.3.5 (¡o el último desarrollador de Drupal 8.4.x!)
  2. Vaya al directorio raíz en el shell y ejecute estos comandos para instalar CiviCRM a través del compositor: https://gist.github.com/dsnopek/56311dbea347874e75180883efabb620
  3. Si usa Apache, elimine el archivo del proveedor / .htacess. Esta es una medida de seguridad de Drupal, que evita que se carguen recursos como CSS / JS. Esto necesitará algo de colaboración con el proyecto Drupal para encontrar una solución adecuada porque eliminar este archivo por completo es una mala idea en la producción. Ver: vendedor / .htaccess que bloquea los activos CSS / JS de las bibliotecas del compositor .
  4. Ve al directorio / modules y haz git clone https://github.com/dsnopek/civicrm-drupal.git --branch composer-library
  5. Vaya a la página "Extender" ( /admin/modules) e instale el módulo CiviCRM
  6. Borrar caché de drupal a través de Drush ( drush cr)
  7. Cierre la sesión y vuelva a iniciarla de acuerdo con CRM-19878
  8. ¡CiviCRM funciona! :-)

Después de todo esto, CiviCRM está utilizando Symfony 2.8 de Drupal y las dependencias en el directorio de proveedores de Drupal, y no está cargando nada de su propio directorio de proveedores. Huzzah!

Probé habilitar el módulo "Teléfono" que falló antes de estos cambios (vea mis pasos para reproducir ), pero funciona bien con ellos. :-)

David Snopek
fuente
Así que aquí hay una pregunta relacionada con todo esto, usando el compositor .... ¿Es posible tener un solo paquete el uso de Symfony 2.8, y otro usar paquete de Symfony 3.2 ....
jackrabbithanna
Hay una resistencia institucional bastante difícil a que se requiera CiviCRM para usar siempre qué versión de Symfony que hace Drupal 8/9.
jackrabbithanna
1
"usando composer .... es posible que un paquete use Symfony 2.8 y otro paquete use Symfony 3.2" -> No, PHP no puede tener dos clases con el mismo nombre. Esto no es realmente una cosa del compositor.
David Snopek
"Hay una resistencia institucional bastante difícil a que se requiera CiviCRM para usar siempre qué versión de Symfony que hace Drupal 8/9" -> Todo lo que se requeriría del núcleo de CiviCRM ascendente es que el código es compatible con el Symfony posterior utilizado en Drupal. No tendría que agruparlo o usarlo por defecto, solo ser compatible, es decir. evitar métodos / clases / características obsoletas.
David Snopek
Entiendo por qué uno estaría interesado en ejecutar las dos versiones principales de Symfony en paralelo: SemVer sorta implica la necesidad. Pero creo que es importante que grandes extensiones de componentes de Symfony sean similares en v2 / v3, y que la integración de Civi en v2 haya sido bastante modesta. Entonces soy optimista sobre tener o lograr un código PHP que sea compatible con ambos. En mi humilde opinión, el trabajo real es actualizar el canal de distribución y la estructura de directorios.
Tim Otten
5

No creo que esto sea posible.

Drupal 8.4 en realidad ya cambió a Symfony 3, aunque todavía hay discusiones similares relacionadas con drush, que tiene el mismo problema. ver Drush 8.x no se instala Drupal 8.4.x y Drush maestro no instalar Drupal 8.3.x y componentes de Symfony se actualiza a 3.2.6

No es posible cargar dos versiones diferentes de Symfony, ya sea que rompas tu integración o rompas Drupal. Quizás symfony3 aún no esté en 8.4, pero el soporte de seguridad para symfony2 finalizará antes del soporte de seguridad de Drupal8, por lo que en algún momento, tendremos que cambiar.

Berdir
fuente
Bueno ... Todo funciona excepto instalar módulos desde admin / modules ... instalar módulos con Drush funciona ... Todas las páginas de CiviCRM funcionan. Así que no estoy convencido de que sea imposible. ¿Por qué sería imposible?
jackrabbithanna
1
No puede cargar dos versiones diferentes de la misma clase al mismo tiempo, eso no es posible. El error suena exactamente como lo que esperaría que sucediera. Primero logró cargar la versión 2.5 de la clase Definición y luego Drupal se rompe porque espera que exista un método que realmente no existe. Y las diferencias aumentarán a medida que Drupal cambie a Symfony 3. No entiendo por qué estás atrapado con 2.5, 2.8 es una actualización menor y debería ser compatible con versiones anteriores (pero no al revés como descubriste). ¿Entonces debería poder actualizar CiviCRM para requerir 2.8?
Berdir
1
Como mencioné en mi comentario, supuse que no le gustaría que respondiera, pero eso no lo cambia. Ninguno de esos proyectos que mencionas usa Symfony (joomal parece usar un puñado de componentes que podrían no entrar en conflicto pero posiblemente lo harán eventualmente), por lo que no puedes comparar eso. Es técnicamente imposible cargar dos versiones en conflicto de la misma clase, nada puede cambiar eso. Es por eso que las dependencias son un negocio complejo y por qué existe el compositor. En lugar de usar bibliotecas, probablemente debería considerar usar compositor y hacer que CiviCRM sea compatible con múltiples versiones de Symfony
Berdir
2
Además, el soporte de seguridad para Symfony 2.5 finalizó en 2015 según symfony.com/roadmap?version=2.5#checker , lo que significa que CiviCRM se basa en una versión de Symfony insegura y desactualizada. Eso solo debería ser suficiente para convencerlos de que es necesaria una actualización, al menos para la versión 2.8, no se trata solo de Drupal8.
Berdir
1
@DavidSnopek correcto, lo que escribiste en tu respuesta es básicamente lo que mencioné en mis comentarios también, pero mientras composer.json de CiviCRM especifique "~ 2.5.0" para sus componentes de Symfony, eso no va a funcionar. Ver github.com/civicrm/civicrm-core/blob/master/composer.json . Entonces mi respuesta "no puedes usar dos versiones diferentes" sigue siendo correcta en mi humilde opinión, solo puedes mejorar / actualizar las restricciones de versión en civicrm y luego instalarlo a través del compositor y usar la misma versión.
Berdir
1

Teóricamente, los únicos problemas aquí son la ubicación del archivo y el espacio de nombres de clase. Desafortunadamente, las únicas herramientas que conozco en Composer para hacer eso no te permiten especificar por VERSIÓN, solo por nombre de paquete.

¿Has intentado configurarlo como un autocargador completamente separado?

Ohthehugemanateetee
fuente
¿Puedes explicar con más detalle lo que quieres decir?
jackrabbithanna
getcomposer.org/doc/faqs/… es cómo hacer la ubicación personalizada. He visto a personas bifurcar un proyecto solo para hacer esto posible ... También getcomposer.org/doc/06-config.md#prepend-autoloader para la opción de mantener separado el autocargador del compositor. Al final, el cargador automático es solo un archivo php, por lo que puede escribir su propio cargador automático que decida cuál incluir según los factores que desee.
Ohthehugemanatee
También relevante: stackoverflow.com/questions/30000063/…
Ohthehugemanatee
Sea claro, ATM no hay un método de instalación basado en compositor para instalar Civi con D8. Pensé que tal vez esa era una forma de lograr esto. De eso se trataba el objeto ServiceProvider mencionado en la pregunta, como agregar un espacio de nombre PSR-4 a Drupal para apuntar a la biblioteca CiviCRM ... Si hiciera esto, Civi necesitaría cambiar todos sus archivos de 'use Symfony \ .... 'para' usar Civicrm \ Symfony \ .. '? Perdón por mi ignorancia del compositor por favor.
jackrabbithanna