Активировать тему для конкретной страницы программно5 5.7

Цель состоит в том, чтобы активировать существующую тему на странице записи в блоге. Обычно пользователь делает это в Раздел Атрибуты страниц вот так:
Атрибуты страницы - & gt; Темы записей блогов - & gt; активировать

Теперь моя цель — сделать это программно. Я не буду публиковать здесь все свои испытания (начиная с 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)? (Как показано на рисунке)

Я знаю это должно быть связано с БД-таблицами CollectionAttributeValues а также atSelectedTopics, Также классы CollectionValue а также CollectionKey должен быть вовлечен.

Я мог бы добавить эти записи вручную в БД, но это не очень хорошая идея, потому что я не знаю, какие данные необходимы для правильной работы. Темы используются для фильтрации записей в блоге, так что я совершенно уверен, что есть другие таблицы, и как сказал разработчик Core: «Это хрупкие мелочи» ;-).

Поскольку эта версия concrete5 является полностью новым запуском, документы для разработчиков не завершены, и после 2 дней копания в основном коде я просто в отчаянии.


Обновить (после недели копания …)

Мне удалось сделать взлом, взятый из метода Controller 🙁/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;

Получить идентификатор атрибута по дескриптору:

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

Так что мне действительно любопытно посмотреть, какой надежный и подходящий для системы способ решить эту проблему.

1

Решение

Вот то, что я придумал, это работает. Вы были довольно близко

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, а не полное пространство имен, как вы это делали, в противном случае вы получите сообщение о невозможности очистки кеша.

2

Другие решения

Других решений пока нет …