Como instalar um módulo que inclui uma versão diferente do Symfony?

17

Sou desenvolvedor e mantenedor do projeto CiviCRM. Estamos tentando criar uma versão do Drupal 8 CiviCRM e percorremos um longo caminho. Estamos batendo nossas cabeças contra nossos teclados coletivos, tentando descobrir um grande bloqueador para o projeto.

O CiviCRM usa o Symfony há algum tempo, e a versão incluída é diferente da que acompanha o Drupal.

Podemos instalar o CiviCRM com o Drupal 8, mas após a instalação, não podemos instalar nenhum outro módulo do Drupal.

Eu acredito que tudo se resume a uma situação em que, de alguma forma, a versão CiviCRM do Symfony carrega antes da versão Drupal, e isso causa problemas.

Alguém conhece um módulo do Drupal 8 que inclui uma versão diferente do Symfony do que a que acompanha o Drupal?

Recentemente, deparei-me com o projeto Ludwig. Este módulo permite o registro de espaços para nome em uma classe que se estendeServiceProviderBase .

Seria possível para a versão Drupal 8 do módulo CiviCRM incluir um arquivo CivicrmServiceProvider.php, que define uma CivicrmServiceProviderclasse e um register()método que adiciona um espaço para nome do contêiner para permitir que isso funcionasse?

Muitos arquivos do CiviCRM têm useinstruções como Drupal começando com Symfony, como aqui .

Na verdade, colocamos o CiviCRM Core na pasta doc_root / libraries do Drupal e usamos o módulo de bibliotecas.

Este é o repositório para o módulo 8.x do CiviCRM Drupal , se alguém quiser ver o que conseguimos até agora. Se alguém tiver o elixir mágico para isso, posso dizer que haveria muitas pessoas felizes em nossa comunidade. Então, se você sabe como nos ajudar, por favor.

O CiviCRM é instalado e as páginas do CiviCRM funcionam. O que não funciona é que, após a instalação do CiviCRM, não podemos instalar outros módulos na página admin / modules. Tanto quanto sei, é a única coisa que está quebrada. A instalação de módulos com o Drush, após a instalação do CiviCRM, funciona.

Tentar instalar outro módulo após a instalação do CiviCRM causa o seguinte erro:

Erro fatal do PHP: Ligue para o método indefinido Symfony \ Component \ DependencyInjection \ Definition :: setFactory () em /var/www/html/civi-for-d8/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php na linha 206

Isso está no Drupal 8.3.5. Tentar instalar o CiviCRM for Drupal 8 em uma instância limpa do Drupal 8.4-dev causa o seguinte erro:

Drupal \ Component \ Serialization \ Exception \ InvalidDataTypeException: o indicador reservado "@" não pode iniciar um escalar simples; é necessário citar o escalar na linha 8 (próximo a "argumentos: [@string_translation, @ civicrm.page_state]"). em Drupal \ Component \ Serialization \ YamlSymfony :: decode () (linha 40 de /var/www/html/drupal84/core/lib/Drupal/Component/Serialization/YamlSymfony.php).

jackrabbithanna
fonte
No celular, mas qual versão do Symfony? 8.4 usará 3.x, um salto da v2.
Matt Glaman
Estamos na versão 2.5.0 em CiviCRM
jackrabbithanna
Alguma documentação do problema: issues.civicrm.org/jira/browse/CRM-17652 .... Uma pessoa relata que não viu o problema, mas não tenho certeza, todos os outros que tentam obter um erro como relatado lá
jackrabbithanna
4
Eu não acho que isso seja possível. O Drupal 8.4 já mudou para o Symfony3, embora ainda haja discussões semelhantes relacionadas ao drush, que tem o mesmo problema. Não é possível carregar duas versões diferentes do symfony, você interrompe sua integração ou o Drupal. Talvez symfony3 não estará em 8,4 ainda, mas o suporte de segurança para Symfony2 vai acabar antes de suporte de segurança Drupal8, por isso em algum momento, vamos ter que mudar
Berdir
1
@Berdir que pode ser uma boa resposta?
Clive

Respostas:

8

Então, acho que se o CiviCRM fosse instalado no Drupal 8 via compositor (ou seja, composer require civicrm/civicrm-corena raiz do Drupal) e o uso do Symfony pelo CiviCRM fosse compatível com o Symfony 2.8 ou 3.x (ou seja, sem a funcionalidade obsoleta), isso poderia funcionar.

Isso instalaria tudo no diretório de fornecedores do Drupal, em vez de ter dois, e isso significaria que o CiviCRM usaria a versão do Symfony no Drupal 8. Mas se o CiviCRM fosse compatível com as versões posteriores do Symfony (mesmo que empacotasse uma versão mais antiga do Drupal 6 e 7 e outros CMSs) deve ficar bem.

Eu acho que?

ATUALIZADO: Sim, funciona - eu tentei. :-) Eu originalmente publiquei o abaixo na fila de problemas do CiviCRM ( CRM-17652 ), mas publiquei novamente aqui para garantir a integridade.

A grande ideia:

Como o compositor é bastante novo para muitas pessoas, vou tentar ir passo a passo, de alguns compositores de alto nível até uma maneira que poderia ser feita no CiviCRM:

  • O Composer permite que os aplicativos exijam as bibliotecas necessárias (e as bibliotecas, é claro, podem exigir outras bibliotecas).
  • As bibliotecas têm um arquivo composer.json que diz de que outras bibliotecas ele precisa e com quais versões é compatível (mas não necessariamente uma versão única específica - geralmente um intervalo de versões, como o ^2.4.3que indica um mínimo de 2.4.3 e até (mas não incluindo) 3.0.0)
  • Os aplicativos têm um composer.json que descreve similarmente as bibliotecas necessárias e a compatibilidade com um intervalo de versões, mas o intervalo é realmente para ajudar na atualização. Um aplicativo também terá um composer.lock, que é um conjunto específico de versões individuais
  • As bibliotecas também podem ter um composer.lock para seus próprios testes ou distribuição (como compilar o tarball de release com as dependências incluídas), mas isso é ignorado quando um aplicativo requer a biblioteca especificada (consulte https://getcomposer.org/doc/02 -libraries.md # lock-file )
  • Quando um aplicativo deseja exigir uma nova biblioteca, o compositor encontra uma interseção da compatibilidade de versão entre tudo o que o aplicativo requer (incluindo todas as bibliotecas já instaladas e suas dependências) e a nova biblioteca, possivelmente fazendo algumas atualizações para alinhar tudo ( ou erro se não encontrar uma mistura compatível de versões)
  • Nesse caso, o CiviCRM é uma biblioteca e um site Drupal 8 específico é o aplicativo (o próprio núcleo do Drupal é uma biblioteca)
  • O CiviCRM poderia dizer que "requer" o Symfony ^2.5em seu compositor.json, o que significa que é compatível com as versões 2.5.0 até (mas não incluindo) 3.0.0
  • Quando um site do Drupal 8 deseja usar o CiviCRM, o administrador do site usa composer require civicrm/civicrm-corepara exigir a biblioteca do CiviCRM e todas as suas dependências. Se o CiviCRM for compatível com o Symfony 2.8 (como usado no Drupal 8.3.x), tudo será instalado e funcionará bem, usando o único Symfony 2.8 do Drupal. Todas as dependências acabam no diretório de fornecedores do Drupal.
  • No entanto, o CiviCRM poderia manter o Symfony 2.5 em seu compositor.lock, o que significa que os testes usariam isso, e os tarballs para Drupal 6 e 7 e outros CMSs agrupariam o Symfony 2.5

A proposta:

  1. Atualize o compositer.json do CiviCRM para que ele possa ser usado como uma biblioteca por CMSs baseados no compositor como o Drupal 8 (mas provavelmente outros poderão se mover dessa maneira no futuro - o compositor está ficando bastante popular)
  2. Certifique-se de que o núcleo do CiviCRM seja compatível com o Symfony 2.8 e 3.0 (usado pelo Drupal 8.3.xe 8.4.x respectivamente), mas mantenha a versão "oficialmente suportada" (atualmente Symfony 2.5) no compositer.lock para teste e tarball para distribuição. Ser compatível com várias versões do Symfony pode não ser tão difícil quanto parece - existem várias bibliotecas compatíveis com o Symfony 2.8 e 3.0. Pode ser apenas uma questão de evitar métodos / classes / recursos obsoletos! O compositer.json precisará ser atualizado para refletir isso
  3. Use o compositor para instalar a biblioteca CiviCRM no Drupal 8 em vez de copiar no diretório de bibliotecas. Isso está se tornando a maneira normal de instalar bibliotecas PHP de terceiros no Drupal 8 (isso é usado extensivamente pelo Drupal Commerce, por exemplo)

Para CMSs baseados em compositores, eu realmente acho que esse é o caminho certo. Embora esse problema atualmente esteja afetando o Symfony e o Drupal, como a comunidade PHP começa a usar cada vez mais bibliotecas de terceiros por meio do compositor, isso pode muito bem afetar outros CMSs com outros conflitos de versão.

Algum código de trabalho para testar:

Então, como prometido, eu realmente consegui que isso funcionasse em um grau limitado :-) Estou aproveitando totalmente isso da perspectiva do Drupal / Composer / Symfony - eu não tenho muita experiência com o CiviCRM, então provavelmente há algumas melhores maneiras de executar meu processo abaixo. Congratulo-me com qualquer conselho!

  1. Baixe e instale o Drupal 8.3.5 (ou o mais recente desenvolvedor do Drupal 8.4.x!)
  2. Vá para o diretório raiz no shell e execute estes comandos para instalar o CiviCRM via compositor: https://gist.github.com/dsnopek/56311dbea347874e75180883efabb620
  3. Se você usa o Apache, remova o arquivo vendor / .htacess. Esta é uma medida de segurança do Drupal, que impede que recursos como CSS / JS sejam carregados. Isso precisará de alguma colaboração com o projeto Drupal para descobrir uma solução adequada, pois remover esse arquivo completamente é uma má idéia para a produção. Consulte: vendor / .htaccess bloqueando ativos CSS / JS das bibliotecas do compositor .
  4. Vá para o diretório / modules e faça git clone https://github.com/dsnopek/civicrm-drupal.git --branch composer-library
  5. Vá para a página "Estender" ( /admin/modules) e instale o módulo CiviCRM
  6. Limpar cache do drupal via Drush ( drush cr)
  7. Efetue logout e logon novamente conforme CRM-19878
  8. O CiviCRM funciona! :-)

Depois de tudo isso, o CiviCRM está usando o Symfony 2.8 do Drupal e as dependências no diretório de fornecedores do Drupal, e não está carregando nada do seu próprio diretório de fornecedores. Huzzah!

Eu testei habilitando o módulo "Telefone", que falhou antes dessas alterações (veja minhas etapas para reproduzir ), mas funciona bem com elas. :-)

David Snopek
fonte
Então aqui está uma pergunta relacionada a tudo isso, usando compositor .... é possível ter um pacote de uso Symfony 2.8, e um outro uso pacote Symfony 3.2 ....
jackrabbithanna
Existe uma resistência institucional bastante difícil ao CiviCRM, que sempre usa a versão do Symfony que o Drupal 8/9 faz.
precisa
1
"usando o compositor .... é possível ter um pacote usando o Symfony 2.8 e outro pacote usando o Symfony 3.2" -> Não, o PHP não pode ter duas classes com o mesmo nome. Isso não é realmente uma coisa de compositor.
David Snopek 17/07/19
"Existe uma resistência institucional bastante difícil para o CiviCRM ser obrigado a sempre usar a versão do Symfony que o Drupal 8/9 faz" -> Tudo o que seria necessário no núcleo de CiviCRM upstream é que o código é compatível com o Symfony posterior usado no Drupal. Não seria necessário agrupá-lo ou usá-lo por padrão, apenas ser compatível, ou seja. evite métodos / classes / recursos obsoletos.
David Snopek 17/07/19
Entendo por que alguém estaria interessado em executar as duas principais versões do Symfony lado a lado - o SemVer meio implica a necessidade. Mas acho importante que grandes quantidades de componentes do Symfony sejam semelhantes na v2 / v3 e que a integração da Civi na v2 tenha sido bastante modesta. Então, eu estou otimista em ter ou obter código PHP compatível com ambos. IMHO, o verdadeiro trabalho está atualizando o canal de distribuição e a estrutura de diretórios.
Tim Otten
5

Eu não acho que isso seja possível.

O Drupal 8.4 já mudou para o Symfony 3, embora ainda haja discussões semelhantes relacionadas ao drush, que tem o mesmo problema. veja Drush 8.x não instala Drupal 8.4.x e Drush mestre não instalar o Drupal 8.3.x e componentes Symfony são atualizados para 3.2.6

Não é possível carregar duas versões diferentes do symfony, você interrompe sua integração ou o Drupal. Talvez o symfony3 ainda não esteja na versão 8.4, mas o suporte de segurança do symfony2 terminará antes do suporte de segurança do Drupal8, portanto, em algum momento, teremos que mudar.

Berdir
fonte
Bem ... Tudo funciona, exceto a instalação de módulos de admin / modules .... a instalação de módulos com Drush funciona ... Todas as páginas do CiviCRM funcionam. Portanto, não estou convencido de que seja impossível. Por que isso seria impossível?
precisa
1
Você não pode carregar duas versões diferentes da mesma classe ao mesmo tempo, isso não é possível. O erro soa exatamente como o que eu esperaria que acontecesse. Você conseguiu carregar a versão 2.5 da classe Definition primeiro e, em seguida, o Drupal quebra porque espera que exista um método que realmente não existe. E as diferenças ficarão maiores à medida que o Drupal passa para o Symfony 3. Não entendo por que você está preso com o 2.5, 2.8 é uma pequena atualização e deve ser compatível com versões anteriores (mas não o contrário, como você descobriu). Portanto, você deve poder atualizar o CiviCRM para exigir o 2.8?
Berdir 16/07/19
1
Como mencionei no meu comentário, presumi que você não gostaria que eu respondesse, mas isso não muda. Nenhum desses projetos que você menciona usa o symfony (o joomal parece usar um punhado de componentes que podem não entrar em conflito, mas possivelmente acabarão eventualmente), então você não pode comparar isso. É tecnicamente impossível carregar duas versões conflitantes da mesma classe, nada pode mudar isso. É por isso que as dependências são um negócio complexo e o compositor existe. Em vez de usar as bibliotecas, você provavelmente deve olhar em usar compositor e fazendo CiviCRM compatível com várias versões do symfony
Berdir
2
Além disso, o suporte de segurança para o Symfony 2.5 foi encerrado em 2015, de acordo com symfony.com/roadmap?version=2.5#checker , o que significa que o CiviCRM é construído em uma versão symfony insegura e desatualizada. Isso por si só deve ser suficiente para convencê-los de que uma atualização é necessária, pelo menos para a versão 2.8, não é apenas sobre o Drupal8.
22417 Berdir
1
@DavidSnopek certo, o que você escreveu na sua resposta também é basicamente o que mencionei nos meus comentários, mas enquanto o composer.json do CiviCRM especificar "~ 2.5.0" para seus componentes do symfony, isso não vai funcionar. Consulte github.com/civicrm/civicrm-core/blob/master/composer.json . Portanto, minha resposta "você não pode usar duas versões diferentes" ainda está correta, IMHO, você só pode melhorar / atualizar as restrições de versão no civicrm e instalá-lo através do compositor e usar a mesma versão.
21817 Berdir
1

Teoricamente, os únicos problemas aqui são o local do arquivo e o namespace da classe. Infelizmente, as únicas ferramentas que conheço no compositor para fazer isso não permitem que você especifique por VERSION, apenas por nome do pacote.

Você já tentou configurá-lo como um carregador automático completamente separado?

Ohthehugemanatee
fonte
Você pode explicar com mais detalhes o que você quer dizer?
jackrabbithanna
getcomposer.org/doc/faqs/… é como fazer o local personalizado. Vi pessoas trabalhando em um projeto apenas para tornar isso possível ... Também getcomposer.org/doc/06-config.md#prepend-autoloader para a opção de manter o carregador automático do compositor separado. No final, o autoloader é apenas um arquivo php, então você pode escrever seu próprio autoloader que decide qual incluir, dependendo dos fatores que desejar.
Ohthehugemanatee
Também relevante: stackoverflow.com/questions/30000063/…
Ohthehugemanatee
Seja claro, o caixa eletrônico não existe um método de instalação baseado em compositor para instalar o Civi com D8. Eu pensei que talvez essa fosse uma maneira de conseguir isso. Era sobre isso que o objeto ServiceProvider mencionado na pergunta era, como adicionar um namespace PSR-4 ao Drupal para apontar para a biblioteca CiviCRM ... Se eu fizesse isso, o Civi precisaria alterar todos os seus arquivos de 'use Symfony \ .... 'usar' Civicrm \ Symfony \ .. '? Perdoe minha ignorância do compositor pls.
21417 jackdabbithanna