У меня следующая ситуация:
- В базе данных хранится информация о домах (адрес, количество комнат, дата постройки, цена последней продажи и т.д.)
- Управление этой базой данных осуществляется через приложение (назовем это приложение «внутренним приложением»), которое нельзя напрямую интегрировать в приложение, управляемое Sulu. Я могу получить доступ к сохраненным данным через API, который дает мне JSON-представление House-объектов. Я также могу заставить приложение запускать какой-то вызов к приложению, управляемому Sulu, когда дом создается, обновляется или удаляется.
- Приложение, управляемое Sulu (назовем его «домашнее приложение внешнего интерфейса») с шаблонами для «дома», «комнаты» и т. д., подключено к другой базе данных на другом сервере. Среда веб-сайта этого приложения, управляемого Sulu, показывает домашние страницы со страницами комнат, где некоторый контент предварительно заполняется через подключение к «внутреннему домашнему приложению». Другой контент существует только в базе данных «приложения внешнего интерфейса», например, комментарии пользователей, оценки дизайна интерьера и т. Д., В соответствии с настроенными аспектами шаблонов Sulu.
Чего я хочу достичь, так это способа автоматизировать создание, обновление и удаление страниц "собственного внешнего интерфейса" на основе действий в "собственном внутреннем приложении".
Например, когда новый дом добавляется в «внутреннее приложение дома», я хочу, чтобы он уведомлял «приложение внешнего интерфейса», чтобы «приложение внешнего интерфейса» автоматически создавало все дерево узлов для вновь добавленного дома. Значение: "дом"-страница с заполненными необходимыми данными, "комната"-страницы для каждой комнаты и т. д., чтобы контент-менеджер "интерфейсного приложения дома" мог видеть все дерево вновь добавленного дома в рабочей области и может начать манипулировать содержимым в уже доступных шаблонах. В дополнение к автоматическому созданию этих страниц, я также хочу предварительно установить права на обновление и создание, так как контент-менеджер «приложения для внешнего интерфейса» не должен иметь возможность создавать новые комнаты или изменять например, название дома.
Мне не удалось заставить его работать, я просто добавлю то, что уже сделал, чтобы показать, где я застрял.
Я начал со следующего кода в контроллере, который расширяет собственный WebsiteController Sulu:
$documentManager = $this->get('sulu_document_manager.document_manager');
$nodeManager = $this->get('sulu_document_manager.node_manager');
$parentHousesDocument = $documentManager->find('/cmf/immo/routes/nl/huizen', 'nl');
$newHouseDocument = $documentManager->create('page');
// The backendApi just gives a House object with data from the backend
// In this case we get an existing House with id 1
$house = $backendApi->getHouseWithId(1);
$newHouseDocument->setTitle($house->getName()); // For instance 'Smurfhouse'
$newHouseDocument->setLocale('nl'); // Nl is the only locale we have
$newHouseDocument->setParent($parentHouseDocument); // A default page where all the houses are listed
$newHouseDocument->setStructureType('house'); // Since we have a house.xml template
// I need to grab the structure to fill it with values from the House object
$structure = $newHouseDocument->getStructure();
$structure->bind([
'title' => $house->getName(),
'houseId' => $house->getId(),
]);
$newHouseDocument->setWorkflowStage(WorkflowStage::PUBLISHED); // You would expect this to automatically publish the document, but apparently it doesn't... I took it from a test I reverse-engineered in trying to create a page, I have no clue what it is supposed to change.
$nodeManager->createPath('/cmf/immo/routes/nl/huizen/' . $house->getId());
$documentManager->persist(
$newHouseDocument,
'nl',
[
'path' => '/cmf/immo/contents/huizen/' . Slugifier::slugify($house->getName()), // Assume for argument's sake that the Slugifier just slugifies the name...
'auto_create' => true, // Took this value from a test that creates pages, don't know whether it is necessary
'load_ghost_content' => false, // Idem
]
);
$documentManager->flush();
Теперь, когда я запускаю действие контроллера, я сначала получаю исключение
Свойство "url" в структуре "дом" является обязательным, но не имеет значения.
Я попытался исправить это, просто вручную привязав свойство 'url'
со значением '/huizen/' . $house->getId()
к $structure
в том месте, где я привязываю другие значения. Но это не исправит ситуацию, поскольку, очевидно, значение url перезаписывается где-то в цепочке событий сохранения, и я еще не нашел, где.
Однако я могу, только в целях тестирования, вручную переопределить URL-адрес в StructureSubscriber
, который обрабатывает сопоставление для этого конкретного события сохранения. Если я это сделаю, что-то будет создано в базе данных Sulu-app-database — ура!
В моей таблице phpcr_nodes
есть две дополнительные записи: одна для RouteDocument, относящаяся к /cmf/immo/routes/nl/huizen/1
, и одна для PageDocument, относящаяся к /cmf/immo/contents/huizen/smurfhouse
. У обоих столбец workspace_name
заполнен значением default_live
. Однако если нет записей, полностью дублирующих эти две записи, за исключением значений default
в столбце workspace_name
, страницы не будут отображаться в среде CMS администрирования Sulu. Излишне говорить, что они также не будут отображаться на общедоступном веб-сайте.
Кроме того, когда я позволяю DocumentManager в действии моего контроллера попытаться ->find
создать мой вновь созданный документ, я получаю документ класса UnknownDocument
. Следовательно, я не могу заставить DocumentManager работать ->publish
на нем; возникает Исключение. Если я посещаю страницы в административной среде Sulu, они, следовательно, не публикуются; как только я опубликую их там, Менеджер документов сможет их найти в действии контроллера, даже если я позже отменю их публикацию. По какой-то причине им больше не UnknownDocument
. Однако, даже если их можно найти, я не могу заставить DocumentManager идти ->unpublish
или ->publish
- это просто НЕ влияет на фактические документы.
Я надеялся, что появится кулинарная книга-рецепт Sulu или другая документация, подробно описывающая, как динамически создавать полностью опубликованные страницы, не прибегая к «ручному труду» фактической среды CMS, но до сих пор я не нашел один ... Вся помощь очень ценится :)
PS: Для полноты: мы запускаем Sulu в среде сервера Windows на PHP 7.1; dbase — это PostgreSQL, а Sulu — это локальная разветвленная версия тега выпуска 1.4.7, потому что мне пришлось внести некоторые изменения в способ, которым Sulu обрабатывает загруженные файлы, чтобы заставить его работать в среде Windows.
РЕДАКТИРОВАТЬ: частичное решение для создания новой домашней страницы, если она еще не существует (явно не используя AdminKernel, но, конечно, ее следует запускать в контексте, где AdminKernel активен):
public function getOrCreateHuisPagina(Huis $huis)
{
$parent = $this->documentManager->find('/cmf/immo/routes/nl/huizen', 'nl'); // This is indeed the route document for the "collector page" of all the houses, but this doesn't seem to give any problems (see below)
try {
$document = $this->documentManager->find('/cmf/immo/routes/nl/huizen/' . $huis->id(), 'nl'); // Here I'm checking whether the page already exists
} catch(DocumentNotFoundException $e) {
$document = $this->setupPublishedPage();
$document->setTitle($huis->naam());
$document->setStructureType('huis_detail');
$document->setResourceSegment('/huizen');
$document->setParent($parent);
$document->getStructure()->bind([
'title' => $huis->naam(), // Not sure if this is required seeing as I already set the title
'huis_id' => $huis->id(),
]);
$this->documentManager->persist(
$document,
'nl',
[
'parent_path' => '/cmf/immo/contents/huizen', // Explicit path to the content document of the parnt
]
);
}
$this->documentManager->publish($document, 'nl');
return $document;
}