2017-02-28 76 views
1

我有以下情況:如何在Sulu CMS中動態創建和更新頁面?

  • 數據庫存儲有關房屋(地址,房間數,建造日期,上次銷售價格等)
  • 這個數據庫正在通過一個應用程序操縱的信息(讓我們稱該應用爲「後端應用」),無法直接集成到Sulu驅動的應用中。我可以通過一個API來訪問存儲的數據,這個API給了我一些House對象的JSON表示。當房屋被創建,更新或刪除時,我也可以讓應用啓動某種對Sulu驅動應用的調用。
  • 蘇祿驅動的應用程序(我們稱之爲的「前端房子的應用程序」)與「房子」,「房間」等模板,連接到不同的數據庫不同的服務器上。這款蘇魯驅動的應用程序的網站環境顯示了帶有網頁的網頁,其中一些內容通過與「後端應用程序」連接預先填充。根據Sulu-templates的配置方面,其他內容僅存在於「前端房屋應用」的數據庫中,如用戶評論,室內設計評估等。

我想達到的目標,是實現自動化「前端房子程序」的創建,更新和刪除的方式-pages基於「後端房子程序」活動。

例如,當在「後端房屋應用程序」中添加新房屋時,我希望它通知「前端房屋應用程序」,以便「前端房屋應用程序」自動創建整個節點樹新增房子。含義:具有填寫所需數據的「房屋」頁面,每個房間的「房間」頁面等,以使「前端房屋應用」的內容管理者可以看到新增房屋的整個樹工作區並可以開始操作已有模板中的內容。除了自動創建這些頁面,我也想預先設定的更新和創造的權利,因爲「前端家應用」 不能能夠創建新的房間或換房子的名字的內容管理, 例如。

我沒有設法讓它工作,我只是添加我已經做了什麼來顯示我卡住了。

我開始了下面的代碼,在擴展蘇祿自己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(); 

現在,當我火了控制器動作,我第一次得到的異常

屬性「網址「在結構」房子「是必需的,但沒有給出任何價值。

我試圖通過用值'/huizen/' . $house->getId()只是手動綁定屬性'url'$structure,在點在哪裏結合其他值來解決此問題。但是這並不能解決這個問題,顯然這個url值被覆蓋在persist事件鏈的某個地方,我還沒有找到

不過,我可以,只是爲了測試目的,手動替換處理映射這個特殊的持續事件StructureSubscriber的URL。如果我這樣做,在Sulu-app-database中創建 - 歡呼!

我的phpcr_nodes表中列出了兩個額外的記錄,一個用於RouteDocument,指的是/cmf/immo/routes/nl/huizen/1,另一個用於PageDocument指/cmf/immo/contents/huizen/smurfhouseworkspace_name列都填寫了值default_live。但是,只要沒有與這兩個記錄完全重複的記錄(workspace_name中的值default除外),則網頁將不會顯示在Sulu管理CMS內部環境中。不用說,他們也會不會出現在公共網站本身

此外,當我讓我的控制器操作中的DocumentManager嘗試->find我新創建的文檔時,我得到了類UnknownDocument的文檔。因此,我不能讓DocumentManager去->publish;異常發生。如果我訪問Sulu管理環境中的頁面,它們因此不會發布;一旦我在那裏發佈它們,它們可以由DocumentManager在控制器操作中找到 - 即使我稍後取消發佈它們。由於某種原因,他們不再是UnknownDocument。但是,即使可以找到它們,我也無法讓DocumentManager轉到->unpublish->publish - 這對實際文檔沒有任何影響。

我希望能有一個蘇祿食譜配方或另一個廣泛描述如何動態創建完全發佈的頁面的文檔,因此不需要通過實際的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; 
} 

回答

0

第一所有的我想你希望它加載哪些以下行不加載:

$parentHousesDocument = $documentManager->find('/cmf/immo/routes/nl/huizen', 'nl'); 

它加載的路線,而不是頁面的文件,所以它看起來應該像下面這樣:

$parentHousesDocument = $documentManager->find('/cmf/immo/contents/nl/huizen', 'nl'); 

關於你的錯誤的URL,而不是重寫StructureSubscriber你應該使用簡單的文件,這不正是你所需要的:-)

而且default_live工作空間是錯誤的setResourceSegment方法,它是您可能在網站內核上運行這些命令?問題是,WebsiteKernel的default_live工作區是默認的,因此將內容寫入這個工作區。如果使用AdminKernel運行命令,它應該登錄到default工作區,並且您應該能夠使用DocumentManager的publish方法將其複製到default_live工作區。

我希望有幫助:-)

+0

是的,'default_live'來自WebsiteController。我通過將它重構爲一個在AdminKernel中運行的控制檯命令來解決這個問題。但鑑於我現在知道AdminKernel是我所需要的,我可以專門爲整個update-a-new-house-part創建一個新的前端控制器,並讓它運行AdminKernel - hooray :) 我確實設法將流程重寫爲不再需要URL的內容,並使用路由文檔(我會將其添加到我的問題中),但是我會直接以任一方式嘗試使用頁面文檔 - 謝謝! –