1

目标是激活博客条目页面中的现有主题。通常,用户在Pages Attributes 部分执行此操作,如下所示: 页面属性 -> 博客条目主题 -> 激活

现在我的目标是以编程方式执行此操作。我不会在这里发布我所有的试验(自 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);

如何激活/分配这个主题(Udland)到我的页面($entry)?(如图所示)

我知道它必须与 DB-tablesCollectionAttributeValuesatSelectedTopics. 还有课程CollectionValueCollectionKey 必须参与。

我可以在数据库中手动添加这些条目,但这不是一个好主意,因为我不知道需要哪些数据才能使其正常工作。这些主题用于过滤博客条目,所以我很确定还涉及其他表格,正如核心开发人员所说:“这些都是脆弱的小东西” ;-)。

由于这个版本的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');

然后通过以下方式模拟发布的表格:

$_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);
}

所以我真的很想知道解决这个问题的可靠和适合系统的方法是什么。

4

1 回答 1

2

这就是我想出的确实有效的方法。你非常接近。

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 别名,而不是像您所做的那样使用完全限定的命名空间,否则您会收到有关它无法清除缓存的错误。

于 2015-12-21T22:07:56.293 回答