Jak zainstalować moduł, który zawiera inną wersję Symfony?

17

Jestem programistą i opiekunem projektu CiviCRM. Próbowaliśmy stworzyć CiviCRM w wersji Drupal 8 i przeszliśmy długą drogę. Uderzamy głowami w klawisze kolektywne, próbując znaleźć główny bloker dla tego projektu.

CiviCRM od jakiegoś czasu używa Symfony, a dołączona wersja jest inna niż ta, która jest dostarczana z Drupalem.

Możemy zainstalować CiviCRM z Drupal 8, ale po jego zainstalowaniu nie możemy zainstalować żadnego innego modułu Drupal.

Wierzę, że sprowadza się to do sytuacji, w której wersja Symfony CiviCRM ładuje się przed wersją Drupala, co powoduje problemy.

Czy ktoś wie o module Drupal 8, który zawiera inną wersję Symfony niż ten dostarczany z Drupalem?

Ostatnio natknąłem się na projekt Ludwig. Ten moduł umożliwia rejestrację przestrzeni nazw w rozszerzonej klasieServiceProviderBase .

Czy byłoby możliwe, aby wersja CiviCRM w wersji Drupal 8 zawierała plik CivicrmServiceProvider.php, który definiuje CivicrmServiceProviderklasę, oraz register()metodę, która dodaje przestrzeń nazw kontenera, aby to działało?

Wiele plików CiviCRM ma usetakie instrukcje, jak Drupal zaczynające się od Symfony, jak tutaj .

W rzeczywistości umieszczamy CiviCRM Core w folderze Drupal doc_root / libraries i używamy modułu bibliotek.

To jest repozytorium dla wersji CiviCRM Drupal w wersji 8.x. , jeśli ktoś chce spojrzeć na to, co do tej pory mamy. Jeśli ktoś ma do tego magiczny eliksir, mogę powiedzieć, że w naszej społeczności byłoby wielu szczęśliwych ludzi. Jeśli więc wiesz, jak nam pomóc, zrób to.

CiviCRM się instaluje, a strony CiviCRM działają. Nie działa to, że po zainstalowaniu CiviCRM nie możemy instalować innych modułów za pośrednictwem strony admin / moduły. O ile wiem, to jedyna zepsuta rzecz. Działa także instalacja modułów z Drush, po zainstalowaniu CiviCRM.

Próba zainstalowania innego modułu po zainstalowaniu CiviCRM powoduje następujący błąd:

Błąd krytyczny PHP: Wywołanie niezdefiniowanej metody Symfony \ Component \ DependencyInjection \ Definition :: setFactory () w /var/www/html/civi-for-d8/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php w linii 206

To jest w Drupal 8.3.5. Próba zainstalowania CiviCRM dla Drupala 8 w czystej instancji Drupala 8.4-dev powoduje następujący błąd:

Drupal \ Component \ Serialization \ Exception \ InvalidDataTypeException: Zarezerwowany wskaźnik „@” nie może uruchomić zwykłego skalara; musisz zacytować skalar w linii 8 (w pobliżu „argumentów: [@string_translation, @ civicrm.page_state]”). w Drupal \ Component \ Serialization \ YamlSymfony :: decode () (wiersz 40 /var/www/html/drupal84/core/lib/Drupal/Component/Serialization/YamlSymfony.php).

jackrabbithanna
źródło
Na telefonie komórkowym, ale jaka wersja Symfony? 8.4 użyje 3.x, skoku z v2.
Matt Glaman
Jesteśmy w wersji 2.5.0 w CiviCRM
jackrabbithanna
Dokumentacja problemu: Issues.civicrm.org/jira/browse/CRM-17652 .... Jedna osoba zgłasza, że ​​nie widział problemu, ale nie jestem tego pewien, wszyscy inni, którzy próbują dostać błąd jak donosi tam
jackrabbithanna
4
Nie sądzę, żeby to było możliwe. Drupal 8.4 faktycznie przeszedł już na Symfony3, chociaż wciąż istnieją podobne dyskusje dotyczące drusha, który ma ten sam problem. Nie można załadować dwóch różnych wersji symfony, albo przerwiesz integrację, albo złamiesz Drupala. Być może symfony3 nie będzie jeszcze w wersji 8.4, ale wsparcie bezpieczeństwa dla symfony2 zakończy się przed obsługą bezpieczeństwa Drupal8, więc w pewnym momencie będziemy musieli się przełączyć
Berdir
1
@Berdir, który może być dobrą odpowiedzią?
Clive

Odpowiedzi:

8

Tak więc myślę, że gdyby CiviCRM został zainstalowany w Drupal 8 za pośrednictwem kompozytora (tj. composer require civicrm/civicrm-coreW katalogu głównym Drupal), a użycie Symfony przez CiviCRM było kompatybilne z Symfony 2.8 lub 3.x (tj. Nieużywanie przestarzałej funkcjonalności), mogłoby to działać.

Spowodowałoby to zainstalowanie wszystkiego w katalogu producenta Drupala, zamiast posiadania dwóch, i oznaczałoby, że CiviCRM używałby wersji Symfony w Drupal 8. Ale gdyby CiviCRM był kompatybilny z późniejszymi wersjami Symfony (nawet gdyby zawierał starszą wersję dla Drupal 6 i 7 oraz inne CMS-y) powinno być w porządku.

Myślę?

ZAKTUALIZOWANO: Tak, działa - próbowałem. :-) Pierwotnie zamieściłem poniżej w kolejce problemów CiviCRM ( CRM-17652 ), ale ponownie opublikowałem tutaj, aby uzyskać kompletność.

Wielki pomysł:

Ponieważ kompozytor jest całkiem nowy dla wielu osób, spróbuję przejść krok po kroku, od niektórych rzeczy kompozytora na wysokim poziomie, aż do jednego sposobu, w jaki można to zrobić w CiviCRM:

  • Composer pozwala aplikacjom wymagać bibliotek, których potrzebuje (i biblioteki mogą oczywiście wymagać innych bibliotek).
  • Biblioteki mają plik composer.json, który mówi, jakich innych bibliotek potrzebuje i z którymi wersjami jest kompatybilny (ale niekoniecznie konkretna pojedyncza wersja - zwykle zakres wersji, na przykład ^2.4.3co najmniej 2.4.3 i do (ale nie w tym) 3.0.0)
  • Aplikacje mają plik composer.json, który podobnie opisuje potrzebne biblioteki i zgodność z wieloma wersjami, ale ten zakres naprawdę pomaga w aktualizacji. Aplikacja będzie miała także composer.lock, który jest określonym zestawem poszczególnych wersji
  • Biblioteki mogą również mieć plik composer.lock do własnego testowania lub dystrybucji (np. Budowanie archiwum wydania z dołączonymi zależnościami), ale jest to ignorowane, gdy aplikacja wymaga danej biblioteki (patrz https://getcomposer.org/doc/02 -libraries.md # plik-blokady )
  • Gdy aplikacja chce wymagać nowej biblioteki, kompozytor znajduje skrzyżowanie kompatybilności wersji między wszystkimi wymaganymi przez nią aplikacjami (w tym wszystkimi bibliotekami już zainstalowanymi i ich zależnościami) a nową biblioteką, prawdopodobnie wykonując pewne aktualizacje, aby wszystko wyrównać ( lub pomyłka, jeśli nie można znaleźć kompatybilnego zestawu wersji)
  • W tym przypadku CiviCRM jest biblioteką, a konkretną witryną Drupal 8 jest aplikacja (sam rdzeń Drupala jest biblioteką)
  • CiviCRM może powiedzieć, że „wymaga” Symfony ^2.5w pliku composer.json, co oznacza, że ​​jest kompatybilny z wersjami od 2.5.0 do (ale nie włącznie) 3.0.0
  • Gdy witryna Drupal 8 chce korzystać z CiviCRM, administrator witryny korzysta composer require civicrm/civicrm-corez biblioteki CiviCRM i wszystkich jej zależności. Jeśli CiviCRM jest kompatybilny z Symfony 2.8 (podobnie jak w Drupal 8.3.x) wszystko zainstaluje się i będzie działać poprawnie, używając pojedynczego Symfony 2.8 z Drupal. Wszystkie zależności kończą się w katalogu dostawców Drupala.
  • Jednak CiviCRM może przechowywać Symfony 2.5 w swoim pliku composer.lock, co oznacza, że ​​testy by tego użyły, a pakiety tar dla Drupala 6 i 7 oraz innych CMS-ów dołączą Symfony 2.5

Propozycja:

  1. Zaktualizuj composer.json CiviCRM, aby mógł być używany jako biblioteka przez CMS-y oparte na kompozytorach, takie jak Drupal 8 (ale prawdopodobnie inni mogą się w ten sposób przenieść w przyszłości - kompozytor staje się dość popularny)
  2. Upewnij się, że rdzeń CiviCRM jest kompatybilny z Symfony 2.8 i 3.0 (używanymi odpowiednio przez Drupal 8.3.xi 8.4.x), ale zachowaj wersję „oficjalnie obsługiwaną” (obecnie Symfony 2.5) w composer.lock do testowania i archiwum do dystrybucji. Kompatybilność z wieloma wersjami Symfony może nie być tak trudna, jak się wydaje - istnieje wiele bibliotek kompatybilnych zarówno z Symfony 2.8, jak i 3.0. Może to być tylko kwestia unikania przestarzałych metod / klas / funkcji! Composer.json będzie musiał zostać zaktualizowany, aby to odzwierciedlić
  3. Użyj kompozytora, aby zainstalować bibliotekę CiviCRM na Drupal 8 zamiast kopiować do katalogu bibliotek. To staje się normalnym sposobem instalowania bibliotek PHP stron trzecich w Drupal 8 (jest to na przykład szeroko wykorzystywane przez Drupal Commerce)

W przypadku CMS-ów opartych na kompozytorach naprawdę uważam, że jest to właściwy sposób. Chociaż ten problem dotyczy obecnie Symfony i Drupal, ponieważ społeczność PHP zaczyna korzystać z coraz większej liczby bibliotek stron trzecich za pośrednictwem kompozytora, może to bardzo dobrze wpłynąć na inne CMS z innymi konfliktami wersji.

Niektóre działające kody do testowania:

Tak więc, jak obiecałem, faktycznie udało mi się to zrobić w ograniczonym stopniu :-) Całkowicie podchodzę do tego z perspektywy Drupala / Kompozytora / Symfony - nie mam ogromnego doświadczenia w CiviCRM, więc prawdopodobnie jest trochę lepsze sposoby na wykonanie mojego procesu poniżej. Cieszę się z każdej porady!

  1. Pobierz i zainstaluj Drupal 8.3.5 (lub najnowszy program Drupal 8.4.x!)
  2. Przejdź do katalogu głównego w powłoce i uruchom te polecenia, aby zainstalować CiviCRM za pośrednictwem kompozytora: https://gist.github.com/dsnopek/56311dbea347874e75180883efabb620
  3. Jeśli używasz Apache, usuń plik vendor / .htacess. Jest to środek bezpieczeństwa Drupala, który zapobiega ładowaniu zasobów takich jak CSS / JS. Będzie to wymagało współpracy z projektem Drupal, aby znaleźć właściwe rozwiązanie, ponieważ całkowite usunięcie tego pliku jest złym pomysłem na produkcji. Zobacz: dostawca / .htaccess blokujący zasoby CSS / JS z bibliotek kompozytora .
  4. Przejdź do katalogu / modules i zrób git clone https://github.com/dsnopek/civicrm-drupal.git --branch composer-library
  5. Przejdź do strony „Rozszerz” ( /admin/modules) i zainstaluj moduł CiviCRM
  6. Wyczyść pamięć podręczną drupal za pomocą Drush ( drush cr)
  7. Wyloguj się i zaloguj ponownie zgodnie z CRM-19878
  8. CiviCRM działa! :-)

Po tym wszystkim CiviCRM używa Symfony 2.8 z Drupala i zależności w katalogu dostawców Drupala i nie ładuje niczego z własnego katalogu dostawców. Huzzah!

Testowałem włączenie modułu „Telefon”, który zawiódł przed wprowadzeniem tych zmian (zobacz moje kroki do odtworzenia ), ale działa z nimi dobrze. :-)

David Snopek
źródło
Oto pytanie związane z tym wszystkim, używając kompozytora .... czy możliwe jest, aby jeden pakiet korzystał z Symfony 2.8, a drugi pakiet korzystał z Symfony 3.2 ....
jackrabbithanna
Jest dość trudny instytucjonalny opór przed CiviCRM, aby zawsze używać tej wersji Symfony, którą robi Drupal 8/9.
jackrabbithanna
1
„przy użyciu kompozytora… czy możliwe jest, aby jeden pakiet korzystał z Symfony 2.8, a inny pakiet korzystał z Symfony 3.2” -> Nie, PHP nie może mieć dwóch klas o tej samej nazwie. To nie jest tak naprawdę sprawa kompozytora.
David Snopek
„Jest dość trudny instytucjonalny opór wobec CiviCRM, aby zawsze używać tej wersji Symfony, którą robi Drupal 8/9” -> Wszystko, co byłoby wymagane od wcześniejszego rdzenia CiviCRM, to zgodność kodu z późniejszą Symfony używaną w Drupal. Nie musiałby go wiązać ani używać domyślnie, wystarczy być kompatybilnym, tj. unikaj przestarzałych metod / klas / funkcji.
David Snopek
Rozumiem, dlaczego ktoś byłby zainteresowany uruchomieniem dwóch głównych wersji Symfony obok siebie - SemVer sorta implikuje konieczność. Ale myślę, że ważne jest, aby duże obszary komponentów Symfony były podobne w v2 / v3 i że integracja Civi z v2 była dość skromna. Dlatego jestem optymistycznie nastawiony do posiadania lub uzyskania kodu PHP, który jest kompatybilny z obydwoma. IMHO, prawdziwą pracą jest aktualizacja struktury kanału dystrybucji i katalogu.
Tim Otten
5

Nie sądzę, żeby to było możliwe.

Drupal 8.4 faktycznie przeszedł już na Symfony 3, chociaż wciąż istnieją podobne dyskusje dotyczące drusha, który ma ten sam problem. zobacz Drush 8.x nie instaluje Drupal 8.4.x i Drush master nie instaluje Drupal 8.3.x, a komponenty Symfony są aktualizowane do 3.2.6

Nie można załadować dwóch różnych wersji symfony, albo przerwiesz integrację, albo złamiesz Drupala. Być może symfony3 nie będzie jeszcze w wersji 8.4, ale obsługa bezpieczeństwa symfony2 zakończy się przed obsługą bezpieczeństwa Drupal8, więc w pewnym momencie będziemy musieli się przełączyć.

Berdir
źródło
Cóż ... Wszystko działa oprócz instalacji modułów z poziomu administratora / modułów .... instalacja modułów z Drush działa ... Wszystkie strony CiviCRM działają. Więc nie jestem przekonany, że to niemożliwe. Dlaczego byłoby to niemożliwe?
jackrabbithanna
1
Nie można załadować dwóch różnych wersji tej samej klasy w tym samym czasie, co nie jest możliwe. Błąd brzmi dokładnie tak, jak się spodziewałem. Najpierw załadowałeś wersję 2.5 klasy Definition, a następnie Drupal się psuje, ponieważ oczekuje on metody, która tak naprawdę nie istnieje. Różnice będą się nasilać, gdy Drupal przejdzie na Symfony 3. Nie do końca rozumiem, dlaczego utknąłeś w wersji 2.5, 2.8 to niewielka aktualizacja i powinna być kompatybilna wstecz (ale nie na odwrót, jak się dowiedziałeś). Więc powinieneś być w stanie zaktualizować CiviCRM, aby wymagał 2.8?
Berdir,
1
Jak wspomniałem w moim komentarzu, założyłem, że nie spodoba ci się moja odpowiedź, ale to nie zmienia tego. Żaden z wymienionych przez ciebie projektów nie używa symfony (joomal wydaje się używać garści składników, które mogą nie powodować konfliktów, ale prawdopodobnie ostatecznie), więc nie możesz tego porównać. Założenie dwóch sprzecznych wersji tej samej klasy jest technicznie niemożliwe, nic nie może tego zmienić. Właśnie dlatego zależności są złożonym biznesem i dlatego istnieje kompozytor. Zamiast używać bibliotek, powinieneś prawdopodobnie rozważyć użycie kompozytora i uczynienie CiviCRM kompatybilnym z wieloma wersjami symfony
Berdir
2
Ponadto wsparcie bezpieczeństwa dla Symfony 2.5 zakończyło się w 2015 roku zgodnie z symfony.com/roadmap?version=2.5#checker , co oznacza, że ​​CiviCRM jest zbudowany na niepewnej i nieaktualnej wersji symfony. Samo to powinno wystarczyć, aby przekonać ich, że konieczna jest aktualizacja, przynajmniej do wersji 2.8, nie chodzi tylko o Drupal8.
Berdir
1
@DavidSnopek racja, to, co napisałeś w odpowiedzi, jest w zasadzie również tym, o czym wspomniałem w moich komentarzach, ale tak długo jak composer.json z CiviCRM specyfikuje „~ 2.5.0” dla komponentów symfony, to nie zadziała. Zobacz github.com/civicrm/civicrm-core/blob/master/composer.json . Więc moja odpowiedź „nie możesz użyć dwóch różnych wersji” jest nadal poprawna IMHO, możesz tylko poprawić / zaktualizować ograniczenia wersji w programie civicrm, a następnie zainstalować go za pośrednictwem kompozytora i użyć tej samej wersji.
Berdir,
1

Teoretycznie jedynymi problemami są tutaj lokalizacja pliku i przestrzeń nazw klas. Niestety, jedyne narzędzia, które znam w kompozytorze do robienia tego, nie pozwalają na określenie dla WERSJI, tylko dla nazwy pakietu.

Czy próbowałeś skonfigurować go jako całkowicie oddzielny moduł ładujący automatycznie?

Ohthehugemanatee
źródło
Czy możesz wyjaśnić bardziej szczegółowo, co masz na myśli?
jackrabbithanna
getcomposer.org/doc/faqs/… to sposób wykonania niestandardowej lokalizacji. Widziałem, jak ludzie rozwidlają projekt, aby było to możliwe ... Również getcomposer.org/doc/06-config.md#prepend-autoloader dla opcji oddzielenia autoloadera kompozytora. W końcu autoloader jest po prostu plikiem php, więc możesz napisać własny autoloader, który decyduje, który z nich wybrać w zależności od dowolnych czynników.
Ohthehugemanatee
Również istotne: stackoverflow.com/questions/30000063/…
Ohthehugemanatee
Bądź jasne, ATM nie ma metody instalacji opartej na kompozytorze, aby zainstalować Civi z D8. Myślałem, że może to był jeden ze sposobów na osiągnięcie tego. Właśnie o to chodziło w obiekcie ServiceProvider wspomnianym w pytaniu, jak dodanie przestrzeni nazw PSR-4 do Drupala w celu wskazania biblioteki CiviCRM ... Gdybym to zrobił, Civi musiałby zmienić wszystkie swoje pliki z „use Symfony \ .... „używać” Civicrm \ Symfony \ .. ”? Przepraszam za ignorancję kompozytora.
jackrabbithanna