Как установить модуль, который включает в себя другую версию Symfony?


17

Я разработчик и сопровождающий проекта CiviCRM. Мы пытались создать версию CiviCRM для Drupal 8 и прошли долгий путь. Мы бьем себя по голове о наших коллективных клавиатурах, пытаясь стать главным блокировщиком для проекта.

CiviCRM какое-то время использовал Symfony, и включенная версия отличается от той, которая поставляется с Drupal.

Мы можем установить CiviCRM с Drupal 8, но после его установки мы не сможем установить любой другой модуль Drupal.

Я полагаю, что это сводится к ситуации, когда версия Symfony на CiviCRM загружается раньше, чем версия Drupal, и это вызывает проблемы.

Кто-нибудь знает модуль Drupal 8, который включает в себя версию Symfony, отличную от той, которая поставляется с Drupal?

Недавно я наткнулся на проект Людвига. Этот модуль позволяет регистрировать пространства имен в расширяемом классеServiceProviderBase .

Возможно ли, чтобы версия Drupal 8 модуля CiviCRM включала файл CivicrmServiceProvider.php, который определяет CivicrmServiceProviderкласс, и register()метод, который добавляет пространство имен контейнера, чтобы это работало?

Многие файлы CiviCRM имеют useтакие выражения, как Drupal, начиная с Symfony, как здесь .

Фактически мы помещаем CiviCRM Core в папку Drupal doc_root / library и используем модуль библиотеки.

Это репозиторий для версии 8.x модуля CiviCRM Drupal , если кто-то хочет взглянуть на то, что мы получили до сих пор. Если у кого-то есть для этого волшебный эликсир, я могу сказать, что в нашем сообществе будет много счастливых людей. Так что, если вы знаете, как помочь нам, пожалуйста.

CiviCRM устанавливает, и страницы CiviCRM работают. Что не работает, так это то, что после установки CiviCRM мы не можем устанавливать другие модули через страницу admin / modules. Насколько я знаю, это единственное, что сломано. Также установка модулей с Drush, после установки CiviCRM, работает.

Попытка установить другой модуль после установки CiviCRM приводит к следующей ошибке:

Неустранимая ошибка PHP: вызов неопределенного метода Symfony \ Component \ DependencyInjection \ Definition :: setFactory () в /var/www/html/civi-for-d8/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php в строке 206

Это в Drupal 8.3.5. Попытка установить CiviCRM для Drupal 8 в чистый экземпляр Drupal 8.4-dev приводит к следующей ошибке:

Drupal \ Component \ Serialization \ Exception \ InvalidDataTypeException: зарезервированный индикатор "@" не может запустить простой скаляр; вам нужно заключить скаляр в строку 8 (рядом с «arguments: [@string_translation, @ civicrm.page_state]»). в Drupal \ Component \ Serialization \ YamlSymfony :: decode () (строка 40 из /var/www/html/drupal84/core/lib/Drupal/Component/Serialization/YamlSymfony.php).


На мобильном, но какая версия Symfony? 8.4 будет использовать 3.x, прыжок с v2.
Мэтт Глэман

Мы в версии 2.5.0 в CiviCRM
jackrabbithanna

Некоторая документация по проблеме: Issues.civicrm.org/jira/browse/CRM-17652 .... Один человек сообщает, что не видел проблемы, но я не уверен в этом, все остальные, кто пытается получить ошибку как сообщалось там
jackrabbithanna

4
Я не думаю, что это возможно. Drupal 8.4 фактически уже переключился на Symfony3, хотя все еще существуют похожие дискуссии, связанные с drush, у которого та же проблема. Невозможно загрузить две разные версии Symfony, либо вы нарушаете интеграцию, либо нарушаете Drupal. Возможно, symfony3 еще не будет в 8.4, но поддержка безопасности для symfony2 прекратится до поддержки безопасности Drupal8, поэтому в какой-то момент нам придется переключиться
Бердир

1
@ Бердир, что может быть хорошим ответом?
Клайв

Ответы:


8

Итак, я думаю, что если CiviCRM был установлен в Drupal 8 через composer (то есть composer require civicrm/civicrm-coreв корне Drupal), и использование CiviCRM Symfony было бы совместимо с Symfony 2.8 или 3.x (то есть без использования устаревших функций), это могло бы работать.

Это позволит установить все в каталоге вендоров Drupal, а не в два, и это будет означать, что CiviCRM будет использовать версию Symfony в Drupal 8. Но если CiviCRM будет совместим с более поздними версиями Symfony (даже если он будет включать более старую версию для Drupal) 6 & 7 и другие CMS) это должно быть хорошо.

Я думаю?

ОБНОВЛЕНО: Да, это работает - я попробовал это. :-) Первоначально я разместил нижеприведенное в очереди на выпуск CiviCRM ( CRM-17652 ), но повторно опубликовал здесь для полноты.

Большая идея:

Поскольку композитор является довольно новым для многих людей, я попытаюсь шаг за шагом перейти от какого-либо высокоуровневого композитора к одному способу, которым это можно сделать в CiviCRM:

  • Composer позволяет приложениям запрашивать библиотеки, в которых он нуждается (а библиотеки, конечно, могут требовать другие библиотеки).
  • В библиотеках есть файл composer.json, в котором указано, какие другие библиотеки ему нужны и с какими версиями он совместим (но не обязательно с конкретной версией - обычно это диапазон версий, например, в ^2.4.3которых указано минимум от 2.4.3 и до (но не в том числе) 3.0.0)
  • В приложениях есть файл composer.json, который аналогичным образом описывает необходимые библиотеки и совместимость с рядом версий, но диапазон действительно помогает в обновлении. Приложение также будет иметь composer.lock, который представляет собой определенный набор отдельных версий.
  • Библиотеки также могут иметь composer.lock для своего собственного тестирования или распространения (например, сборка релиз-архива с связанными зависимостями), но это игнорируется, когда приложению требуется указанная библиотека (см. Https://getcomposer.org/doc/02. -libraries.md # lock-file )
  • Когда приложению требуется новая библиотека, composer находит пересечение совместимости версий между всем, что требуется приложению (включая все уже установленные библиотеки и их зависимости), и новой библиотекой, возможно, делая некоторые обновления, чтобы все выстроилось ( или выдает ошибку, если не может найти совместимое сочетание версий)
  • В этом случае CiviCRM - это библиотека, а конкретный сайт Drupal 8 - это приложение (само ядро ​​Drupal - это библиотека)
  • CiviCRM может сказать, что «требует» Symfony ^2.5в своем composer.json, что означает, что он совместим с версиями 2.5.0 до (но не включая) 3.0.0
  • Когда сайт Drupal 8 хочет использовать CiviCRM, администратор сайта composer require civicrm/civicrm-coreзапрашивает библиотеку CiviCRM и все ее зависимости. Если CiviCRM совместим с Symfony 2.8 (как в Drupal 8.3.x), все будет установлено и будет работать нормально, используя единственный Symfony 2.8 от Drupal. Все зависимости попадают в каталог поставщиков Drupal.
  • Тем не менее, CiviCRM может сохранить Symfony 2.5 в своем composer.lock, что означает, что тесты будут использовать это, а tarballs для Drupal 6 & 7 и других CMS будут включать Symfony 2.5

Предложение:

  1. Обновите composer.json CiviCRM, чтобы он мог использоваться в качестве библиотеки CMS, основанной на композиторе, например Drupal 8 (но, возможно, другие могут двигаться в этом направлении в будущем - композитор становится довольно популярным)
  2. Убедитесь, что ядро CiviCRM совместимо с Symfony 2.8 и 3.0 (используется Drupal 8.3.x и 8.4.x соответственно), но сохраните «официально поддерживаемую» версию (в настоящее время Symfony 2.5) в composer.lock для тестирования и в архиве для распространения. Быть совместимым с несколькими версиями Symfony может быть не так сложно, как кажется - есть несколько библиотек, совместимых с Symfony 2.8 и 3.0. Это может быть просто вопрос избегания устаревших методов / классов / возможностей! Файл composer.json необходимо обновить, чтобы отразить это
  3. Используйте composer для установки библиотеки CiviCRM на Drupal 8, а не для копирования в каталог библиотеки. Это становится обычным способом установки сторонних PHP-библиотек в Drupal 8 (например, широко используется в Drupal Commerce)

Для CMS на основе композиторов я действительно считаю, что это правильный путь. Хотя эта проблема в настоящее время затрагивает Symfony и Drupal, так как сообщество PHP начинает использовать все больше и больше сторонних библиотек через composer, это может очень хорошо повлиять на другие CMS с другими конфликтами версий.

Некоторый рабочий код для тестирования:

Итак, как и было обещано, я действительно заставил это работать в ограниченной степени :-) Я полностью прихожу к этому с точки зрения Drupal / Composer / Symfony - у меня нет тонны опыта CiviCRM, так что, вероятно, есть некоторые Лучшие способы сделать мой процесс ниже. Я приветствую любые советы!

  1. Загрузите и установите Drupal 8.3.5 (или последнюю версию Drupal 8.4.x!)
  2. Перейдите в корневой каталог оболочки и выполните эти команды, чтобы установить CiviCRM через композитор: https://gist.github.com/dsnopek/56311dbea347874e75180883efabb620.
  3. Если вы используете Apache, удалите файл vendor / .htacess. Это мера безопасности от Drupal, которая предотвращает загрузку таких ресурсов, как CSS / JS. Для этого потребуется совместная работа с проектом Drupal, чтобы найти правильное решение, потому что удаление этого файла - плохая идея на производстве. См. Vendor / .htaccess, блокирующий ресурсы CSS / JS из библиотек композитора .
  4. Перейдите в каталог / modules и выполните git clone https://github.com/dsnopek/civicrm-drupal.git --branch composer-library
  5. Перейдите на страницу «Расширить» ( /admin/modules) и установите модуль CiviCRM.
  6. Очистить друпальный кеш через Drush ( drush cr)
  7. Выйдите из системы и войдите снова согласно CRM-19878.
  8. CiviCRM работает! :-)

После всего этого CiviCRM использует Symfony 2.8 из Drupal и зависимости в каталоге вендоров Drupal и ничего не загружает из своего каталога вендоров. Ура!

Я протестировал включение модуля «Телефон», который не прошел до этих изменений (см. Мои шаги по воспроизведению ), но с ними работает нормально. :-)


Итак, вот вопрос, связанный со всем этим, с использованием composer .... возможно ли, чтобы один пакет использовал Symfony 2.8, а другой пакет использовал Symfony 3.2 ....
jackrabbithanna

Существует довольно сложное институциональное сопротивление CiviCRM, требующему всегда использовать версию Symfony, которую использует Drupal 8/9.
jackrabbithanna

1
«используя композер .... возможно ли, чтобы один пакет использовал Symfony 2.8, а другой пакет использовал Symfony 3.2» -> Нет, PHP не может иметь два класса с одинаковым именем. Это на самом деле не композитор.
Дэвид Снопек

«Институциональное сопротивление CiviCRM довольно сложно, чтобы всегда использовать ту версию Symfony, которую делает Drupal 8/9» -> Все, что требовалось от ядра CiviCRM восходящего потока, - это совместимость кода с более поздней версией Symfony, использованной в Drupal. Это не должно было бы связывать это или использовать это по умолчанию, только быть совместимым, т.е. избегать устаревших методов / классов / возможностей.
Дэвид Снопек

Я понимаю, почему кто-то заинтересован в одновременном запуске двух основных версий Symfony - SemVer sorta подразумевает необходимость. Но я думаю, что важно, чтобы крупные компоненты Symfony были похожи в v2 / v3, а интеграция Civi с v2 была довольно скромной. Так что я с оптимизмом смотрю на наличие или достижение кода PHP, который совместим с обоими. ИМХО, настоящая работа - обновление канала распределения и структуры каталогов.
Тим Оттен

5

Я не думаю, что это возможно.

Drupal 8.4 фактически уже переключился на Symfony 3, хотя все еще существуют похожие обсуждения, связанные с drush, у которого есть та же проблема. см. Drush 8.x не устанавливает Drupal 8.4.x, а Drush master не устанавливает Drupal 8.3.x, а компоненты Symfony обновлены до 3.2.6

Невозможно загрузить две разные версии Symfony, либо вы нарушаете интеграцию, либо нарушаете Drupal. Возможно, symfony3 еще не будет в 8.4, но поддержка безопасности для symfony2 прекратится до поддержки безопасности в Drupal8, поэтому в какой-то момент нам придется переключиться.


Хорошо ..... Все работает, кроме установки модулей из admin / modules .... установка модулей с помощью Drush работает ... Все страницы CiviCRM работают. Поэтому я не уверен, что это невозможно. Почему это было бы невозможно?
jackrabbithanna

1
Вы не можете загрузить две разные версии одного и того же класса одновременно, что невозможно. Ошибка звучит именно так, как я и ожидал. Вам удалось сначала загрузить версию 2.5 класса Definition, а затем Drupal, потому что он ожидает, что существует метод, который на самом деле не существует. И различия станут больше, когда Drupal перейдет на Symfony 3. Я не совсем понимаю, почему вы застряли с 2.5, 2.8 - это незначительное обновление и должно быть обратно совместимым (но не наоборот, как вы узнали). Таким образом, вы должны иметь возможность обновить CiviCRM, чтобы требовать 2.8?
Бердир

1
Как я уже упоминал в своем комментарии, я предположил, что вам не понравится мой ответ, но это не изменит его. Ни один из тех проектов, о которых вы упомянули, не использует symfony (кажется, joomal использует несколько компонентов, которые могут не конфликтовать, но, возможно, в конечном итоге), так что вы не можете сравнить это. Технически невозможно загрузить две конфликтующие версии одного и того же класса, ничто не может изменить это. Вот почему зависимости это сложный бизнес и почему существует композитор. Вместо использования библиотек, вы, вероятно, должны изучить использование composer и совместимость
CiviCRM

2
Кроме того, поддержка безопасности для Symfony 2.5 была прекращена в 2015 году в соответствии с symfony.com/roadmap?version=2.5#checker , что означает, что CiviCRM построен на небезопасной и устаревшей версии Symfony. Одного этого должно быть достаточно, чтобы убедить их в необходимости обновления, по крайней мере, до версии 2.8, речь идет не только о Drupal8.
Бердир

1
@DavidSnopek правильно, то, что вы написали в своем ответе, в основном то, что я упоминал и в моих комментариях, но пока composer.json из CiviCRM определяет «~ 2.5.0» для своих компонентов Symfony, это не сработает. См. Github.com/civicrm/civicrm-core/blob/master/composer.json . Так что мой ответ «вы не можете использовать две разные версии» по-прежнему верен ИМХО, вы можете только улучшить / обновить ограничения версии в civicrm, а затем установить его через composer и использовать ту же версию.
Бердир

1

Теоретически единственными проблемами здесь являются местоположение файла и пространство имен класса. К сожалению, единственные инструменты, которые я знаю в composer, которые не позволяют вам указывать для VERSION, только для имени пакета.

Вы пытались настроить его как отдельный автозагрузчик?


Можете ли вы объяснить более подробно, что вы имеете в виду?
jackrabbithanna

getcomposer.org/doc/faqs/… как сделать пользовательское местоположение. Я видел, как люди раскручивали проект только для того, чтобы сделать это возможным ... Также getcomposer.org/doc/06-config.md#prepend-autoloader для опции, позволяющей хранить автозагрузчик компоновщика отдельно. В конце концов, автозагрузчик - это просто файл php, так что вы можете написать свой собственный автозагрузчик, который решит, какой из них включить, в зависимости от того, какие факторы вам нравятся.
Ohthehugemanatee


Прошу прояснить: в банкомате нет способа установки на основе композитора для установки Civi с D8. Хотя, возможно, это был один из способов сделать это. Именно об этом и упоминался объект ServiceProvider, упомянутый в вопросе, например, о добавлении пространства имен PSR-4 в Drupal для указания на библиотеку CiviCRM ... Если бы я сделал это, Civi нужно было бы изменить все свои файлы с 'use Symfony \ .... 'чтобы' использовать Civicrm \ Symfony \ .. '? Прошу прощения за мое невежество композитора, пожалуйста.
jackrabbithanna
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.