以编程方式具体激活页面主题5 5.7
Activate a Topic for a Page programmaticaly concrete5 5.7
目标是激活博客条目页面中的现有主题。通常,用户在 页面属性部分 中这样做:
现在我的目标是以编程方式执行此操作。我不会 post 我所有的试验(自 2 天以来)都在这里,因为它只是废话,但这是我到目前为止所做的。
首先,我将博客页面添加到选定的父页面 (ID 157):
use Concrete\Core\Page;
$parentPage = Page\Page::getByID(157);
$template = \PageTemplate::getByHandle('blog_entry');
$entry = $parentPage->add($type, array(
'cName' => 'My title',
'cDescription' => 'description',
'cHandle' => 'my_title',
'cvIsApproved' => true,
'cDatePublic' => $publishDate->format('Y-m-d H:i:s')
), $template);
由于新创建的页面是 blog_entry
模板,博客条目主题已经分配。
然后我创建一个主题并将其添加到它的主题树(博客条目主题)中,如下所示:
use \Concrete\Core\Tree\Type\Topic as TopicTree;
use \Concrete\Core\Tree\Node\Type\Topic as TopicTreeNode;
use \Concrete\Core\Tree\Node\Node as TreeNode;
$topicTree = TopicTree::getByName('Blog Entries');
$parentTopic = TreeNode::getByID($topicTree->getRootTreeNodeObject()->treeNodeID);
$item0 = TopicTreeNode::add('udland', $parentTopic);
如何activate/assign这个Topic(Udland)到我的页面($entry)?(如图)
我知道它一定与数据库表 CollectionAttributeValues
和 atSelectedTopics
有关。 类 CollectionValue
和 CollectionKey
也必须涉及。
我可以在数据库中手动添加这些条目,但这不是一个好主意,因为我不知道需要哪些数据才能使其正常工作。这些主题用于过滤博客条目,所以我很确定还涉及其他表格,正如核心开发人员所说:"These are fragile little things" ;-).
由于这个版本的 concrete5 是一个全新的发布,开发人员文档并不完整,在深入研究核心代码 2 天后,我感到很绝望。
更新(经过一周的挖掘...)
我设法从 Controller 方法中提取了一个 hack:(/concrete/controllers/panel/page/attributes.php -> submit()
).
我知道这根本不是办法但这是我迄今为止最好的尝试:
(我只是在此处包含 NameSpaces 以明确 类 我在调用什么)
use Concrete\Core\Page;
use Concrete\Core\Page\Collection\Version\Version;
use Concrete\Core\Workflow\Request\ApprovePageRequest;
use CollectionAttributeKey;
use \Concrete\Core\Tree\Node\Type\Topic as TopicTreeNode;
通过句柄获取属性 ID:
$ak = CollectionAttributeKey::getByHandle('blog_entry_topics');
$attributekID = $ak->getAttributeKeyID();
进入主题
$item_one = TopicTreeNode::getNodeByName('Udland');
然后通过以下方式模拟 posted 表单:
$_POST = array(
'topics_' . $attributekID => array($item_one->treeNodeID)
);
我知道这太丑陋了,而且是个大黑客,而且一点也不可靠,但正如所说,它是从控制器中取出来的……
然后我做一个精简版的submit()
方法:
$c = Page\Page::getByID(157);
$published = new \DateTime();
$nvc = $c->getVersionToModify();
$nvcObj = $nvc->getVersionObject();
$data = array();
$data['cName'] = $nvcObj->cvName;
$data['cDescription'] = $nvcObj->cvDescription;
$data['cDatePublic'] = $published->format('Y-m-d H:i:s');
$data['uID'] = '1';
$nvc->update($data);
$setAttribs = $nvc->getSetCollectionAttributes();
$processedAttributes = array();
$selectedAKIDs = $attributekID;
if (!is_array($selectedAKIDs)) {
$selectedAKIDs = array();
}
$selected = is_array(array($attributekID)) ? array($attributekID) : array();
foreach ($setAttribs as $ak) {
if (in_array($ak->getAttributeKeyID(), $selected)) {
$ak->saveAttributeForm($nvc);
} else {
$nvc->clearAttribute($ak);
}
$processedAttributes[] = $ak->getAttributeKeyID();
}
$newAttributes = array_diff($selectedAKIDs, $processedAttributes);
foreach ($newAttributes as $akID) {
$ak = CollectionAttributeKey::getByID($akID);
$ak->saveAttributeForm($nvc);
}
所以如前所述,这确实很丑陋,但这是迄今为止最好的试验,而且不知何故它起作用了。
然后通过以下方式批准请求:
$pkr = new ApprovePageRequest();
$u = new User();
$pkr->setRequestedPage($c);
$v = Version::get($c, "RECENT");
$pkr->setRequestedVersionID($v->getVersionID());
$pkr->setRequesterUserID($u->getUserID());
$pkr->trigger();
$u->unloadCollectionEdit();
但真正让我感到奇怪的是 /concrete/src/Attribute/Key/Key.php
中的那个方法最终应该发生的地方(以我的拙见):
/**
* Calls the functions necessary to save this attribute to the database. If no passed value is passed, then we save it via the stock form.
* NOTE: this code is screwy because all code ever written that EXTENDS this code creates an attribute value object and passes it in, like
* this code implies. But if you call this code directly it passes the object that you're messing with (Page, User, etc...) in as the $attributeValue
* object, which is obviously not right. So we're going to do a little procedural if/then checks in this to ensure we're passing the right
* stuff
*
* @param CollectionValue|mixed $mixed
* @param mixed $passedValue
*/
protected function saveAttribute($mixed, $passedValue = false)
{
/** @var \Concrete\Core\Attribute\Type $at */
$at = $this->getAttributeType();
$at->getController()->setAttributeKey($this);
if ($mixed instanceof AttributeValue) {
$attributeValue = $mixed;
} else {
// $mixed is ACTUALLY the object that we're setting the attribute against
//todo: figure out what $nvc should really be since it doesn't exist in this scope
$attributeValue = $nvc->getAttributeValueObject($mixed, true);
}
$at->getController()->setAttributeValue($attributeValue);
if ($passedValue) {
$at->getController()->saveValue($passedValue);
} else {
$at->getController()->saveForm($at->getController()->post());
}
$at->__destruct();
unset($at);
}
所以我真的很想知道解决这个问题的可靠且适合系统的方法是什么。
这是我想出的有效方法。你很接近。
use \Concrete\Core\Tree\Type\Topic as TopicTree;
use \Concrete\Core\Tree\Node\Type\Topic as TopicTreeNode;
use \Concrete\Core\Tree\Node\Node as TreeNode;
$parentPage = \Page::getbyPath('/blog');
$template = \PageTemplate::getByHandle('blog_entry');
$entry = $parentPage->add($type, array(
'cName' => 'ooops',
'cDescription' => 'hmmmm',
'cHandle' => 'yay',
'cvIsApproved' => true,
'cDatePublic' => '2015-12-21 00:00:00'
), $template);
$item0 = TopicTreeNode::getNodeByName('udland');
if (!$item0) {
$topicTree = TopicTree::getByName('Blog Entries');
$parentTopic = TreeNode::getByID($topicTree->getRootTreeNodeObject()->treeNodeID);
$item0 = TopicTreeNode::add('udland', $parentTopic);
}
$entry->setAttribute('blog_entry_topics', array($item0->getTreeNodeDisplayPath()));
看起来该属性采用节点显示路径数组,这就是它设置选择的方式。此外,您必须使用 \Page 别名,而不是像您一样使用完全限定的命名空间,否则您会收到无法清除缓存的错误消息。
目标是激活博客条目页面中的现有主题。通常,用户在 页面属性部分 中这样做:
现在我的目标是以编程方式执行此操作。我不会 post 我所有的试验(自 2 天以来)都在这里,因为它只是废话,但这是我到目前为止所做的。
首先,我将博客页面添加到选定的父页面 (ID 157):
use Concrete\Core\Page;
$parentPage = Page\Page::getByID(157);
$template = \PageTemplate::getByHandle('blog_entry');
$entry = $parentPage->add($type, array(
'cName' => 'My title',
'cDescription' => 'description',
'cHandle' => 'my_title',
'cvIsApproved' => true,
'cDatePublic' => $publishDate->format('Y-m-d H:i:s')
), $template);
由于新创建的页面是 blog_entry
模板,博客条目主题已经分配。
然后我创建一个主题并将其添加到它的主题树(博客条目主题)中,如下所示:
use \Concrete\Core\Tree\Type\Topic as TopicTree;
use \Concrete\Core\Tree\Node\Type\Topic as TopicTreeNode;
use \Concrete\Core\Tree\Node\Node as TreeNode;
$topicTree = TopicTree::getByName('Blog Entries');
$parentTopic = TreeNode::getByID($topicTree->getRootTreeNodeObject()->treeNodeID);
$item0 = TopicTreeNode::add('udland', $parentTopic);
如何activate/assign这个Topic(Udland)到我的页面($entry)?(如图)
我知道它一定与数据库表 CollectionAttributeValues
和 atSelectedTopics
有关。 类 CollectionValue
和 CollectionKey
也必须涉及。
我可以在数据库中手动添加这些条目,但这不是一个好主意,因为我不知道需要哪些数据才能使其正常工作。这些主题用于过滤博客条目,所以我很确定还涉及其他表格,正如核心开发人员所说:"These are fragile little things" ;-).
由于这个版本的 concrete5 是一个全新的发布,开发人员文档并不完整,在深入研究核心代码 2 天后,我感到很绝望。
更新(经过一周的挖掘...)
我设法从 Controller 方法中提取了一个 hack:(/concrete/controllers/panel/page/attributes.php -> submit()
).
我知道这根本不是办法但这是我迄今为止最好的尝试:
(我只是在此处包含 NameSpaces 以明确 类 我在调用什么)
use Concrete\Core\Page;
use Concrete\Core\Page\Collection\Version\Version;
use Concrete\Core\Workflow\Request\ApprovePageRequest;
use CollectionAttributeKey;
use \Concrete\Core\Tree\Node\Type\Topic as TopicTreeNode;
通过句柄获取属性 ID:
$ak = CollectionAttributeKey::getByHandle('blog_entry_topics');
$attributekID = $ak->getAttributeKeyID();
进入主题
$item_one = TopicTreeNode::getNodeByName('Udland');
然后通过以下方式模拟 posted 表单:
$_POST = array(
'topics_' . $attributekID => array($item_one->treeNodeID)
);
我知道这太丑陋了,而且是个大黑客,而且一点也不可靠,但正如所说,它是从控制器中取出来的……
然后我做一个精简版的submit()
方法:
$c = Page\Page::getByID(157);
$published = new \DateTime();
$nvc = $c->getVersionToModify();
$nvcObj = $nvc->getVersionObject();
$data = array();
$data['cName'] = $nvcObj->cvName;
$data['cDescription'] = $nvcObj->cvDescription;
$data['cDatePublic'] = $published->format('Y-m-d H:i:s');
$data['uID'] = '1';
$nvc->update($data);
$setAttribs = $nvc->getSetCollectionAttributes();
$processedAttributes = array();
$selectedAKIDs = $attributekID;
if (!is_array($selectedAKIDs)) {
$selectedAKIDs = array();
}
$selected = is_array(array($attributekID)) ? array($attributekID) : array();
foreach ($setAttribs as $ak) {
if (in_array($ak->getAttributeKeyID(), $selected)) {
$ak->saveAttributeForm($nvc);
} else {
$nvc->clearAttribute($ak);
}
$processedAttributes[] = $ak->getAttributeKeyID();
}
$newAttributes = array_diff($selectedAKIDs, $processedAttributes);
foreach ($newAttributes as $akID) {
$ak = CollectionAttributeKey::getByID($akID);
$ak->saveAttributeForm($nvc);
}
所以如前所述,这确实很丑陋,但这是迄今为止最好的试验,而且不知何故它起作用了。
然后通过以下方式批准请求:
$pkr = new ApprovePageRequest();
$u = new User();
$pkr->setRequestedPage($c);
$v = Version::get($c, "RECENT");
$pkr->setRequestedVersionID($v->getVersionID());
$pkr->setRequesterUserID($u->getUserID());
$pkr->trigger();
$u->unloadCollectionEdit();
但真正让我感到奇怪的是 /concrete/src/Attribute/Key/Key.php
中的那个方法最终应该发生的地方(以我的拙见):
/**
* Calls the functions necessary to save this attribute to the database. If no passed value is passed, then we save it via the stock form.
* NOTE: this code is screwy because all code ever written that EXTENDS this code creates an attribute value object and passes it in, like
* this code implies. But if you call this code directly it passes the object that you're messing with (Page, User, etc...) in as the $attributeValue
* object, which is obviously not right. So we're going to do a little procedural if/then checks in this to ensure we're passing the right
* stuff
*
* @param CollectionValue|mixed $mixed
* @param mixed $passedValue
*/
protected function saveAttribute($mixed, $passedValue = false)
{
/** @var \Concrete\Core\Attribute\Type $at */
$at = $this->getAttributeType();
$at->getController()->setAttributeKey($this);
if ($mixed instanceof AttributeValue) {
$attributeValue = $mixed;
} else {
// $mixed is ACTUALLY the object that we're setting the attribute against
//todo: figure out what $nvc should really be since it doesn't exist in this scope
$attributeValue = $nvc->getAttributeValueObject($mixed, true);
}
$at->getController()->setAttributeValue($attributeValue);
if ($passedValue) {
$at->getController()->saveValue($passedValue);
} else {
$at->getController()->saveForm($at->getController()->post());
}
$at->__destruct();
unset($at);
}
所以我真的很想知道解决这个问题的可靠且适合系统的方法是什么。
这是我想出的有效方法。你很接近。
use \Concrete\Core\Tree\Type\Topic as TopicTree;
use \Concrete\Core\Tree\Node\Type\Topic as TopicTreeNode;
use \Concrete\Core\Tree\Node\Node as TreeNode;
$parentPage = \Page::getbyPath('/blog');
$template = \PageTemplate::getByHandle('blog_entry');
$entry = $parentPage->add($type, array(
'cName' => 'ooops',
'cDescription' => 'hmmmm',
'cHandle' => 'yay',
'cvIsApproved' => true,
'cDatePublic' => '2015-12-21 00:00:00'
), $template);
$item0 = TopicTreeNode::getNodeByName('udland');
if (!$item0) {
$topicTree = TopicTree::getByName('Blog Entries');
$parentTopic = TreeNode::getByID($topicTree->getRootTreeNodeObject()->treeNodeID);
$item0 = TopicTreeNode::add('udland', $parentTopic);
}
$entry->setAttribute('blog_entry_topics', array($item0->getTreeNodeDisplayPath()));
看起来该属性采用节点显示路径数组,这就是它设置选择的方式。此外,您必须使用 \Page 别名,而不是像您一样使用完全限定的命名空间,否则您会收到无法清除缓存的错误消息。