【发布时间】:2017-02-28 12:49:53
【问题描述】:
我有以下情况:
- 数据库存储有关房屋的信息(地址、房间数量、建造日期、最后售价等)
- 正在通过一个应用程序(我们称该应用程序为“后端应用程序”)操作此数据库,该应用程序无法直接集成到 Sulu 驱动的应用程序中。我可以通过一个 API 访问存储的数据,该 API 为我提供了房屋对象的 JSON 表示。当房屋被创建、更新或删除时,我还可以让应用启动对 Sulu 驱动的应用的某种调用。
- 带有“house”、“room”等模板的 Sulu 驱动的应用程序(我们称之为“前端房子应用程序”)连接到不同服务器上的不同数据库。这个由 Sulu 驱动的应用程序的网站环境显示带有房间页面的主页,其中一些内容是通过与“后端主页应用程序”的连接预先填充的。其他内容仅存在于“前端房屋应用”的数据库中,如用户cmets、室内设计评价等,根据Sulu-templates的配置方面。
我想要实现的是一种基于“后端应用程序”中的活动自动创建、更新和删除“前端应用程序”页面的方法。
例如,当在“后端房屋应用程序”中添加新房屋时,我希望它通知“前端房屋应用程序”,以便“前端房屋应用程序”自动为新创建的整个节点树加了房子。含义:填写所需数据的“house”-page、“room”-每个房间的pages等,这样“前端house app”的内容管理器就可以看到新添加的house的整棵树工作区,并且可以开始处理已经可用模板中的内容。除了自动创建这些页面之外,我还想预先设置更新和创建的权限,因为“前端应用程序”的内容管理器一定不能能够创建新房间或更改例如房子的名字。
我没有设法让它工作,我将添加我已经完成的内容以显示我卡在哪里。
我从以下代码开始,在一个扩展了 Sulu 自己的 WebsiteController 的控制器中:
$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();
现在,当我触发控制器动作时,我首先得到异常
结构“house”中的属性“url”是必需的,但没有给出值。
我试图通过手动将属性'url' 与值'/huizen/' . $house->getId() 绑定到$structure 来解决这个问题,在我绑定其他值的地方。但这并不能解决问题,显然 url 值在持久事件链中的某处被覆盖,我还没有找到在哪里。
但是,出于测试目的,我可以手动覆盖 StructureSubscriber 中处理此特定持久事件映射的 url。如果我这样做,会在 Sulu-app-database 中创建一些东西 - 万岁!
我的phpcr_nodes 表列出了两条额外记录,一条用于引用/cmf/immo/routes/nl/huizen/1 的RouteDocument,另一条用于引用/cmf/immo/contents/huizen/smurfhouse 的PageDocument。两者都有用值default_live 填充的workspace_name 列。但是,只要没有与这两条记录完全重复的记录,除了 workspace_name 列中的值 default,这些页面将不会出现在 Sulu 管理 CMS 环境中 .不用说,它们也将不会出现在适当的公共网站上。
此外,当我让我的控制器操作中的 DocumentManager 尝试 ->find 我新创建的文档时,我得到了一个 UnknownDocument 类的文档。因此,我不能让 DocumentManager 转到 ->publish 上;出现异常。如果我访问 Sulu 管理环境中的页面,它们因此未发布;一旦我在那里发布它们,DocumentManager 可以在控制器操作中找到它们 - 即使我稍后取消发布它们。出于某种原因,它们不再是UnknownDocument。但是,即使可以找到它们,我也不能让 DocumentManager 转到 ->unpublish 或 ->publish - 这对实际文档没有任何影响。
我希望有一个 Sulu 食谱或另一篇文档来广泛描述如何动态创建完全发布的页面,从而无需经历实际 CMS 环境的“体力劳动”,但到目前为止我还没有'没有找到一个......非常感谢所有帮助:)
PS:为了完整起见:我们在 PHP 7.1 的 Windows 服务器环境中运行 Sulu; 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;
}
【问题讨论】:
标签: sulu