CQ - перемещение контента с одной страницы на другую

Я понимаю, что это довольно специфический вопрос, но я думаю, что кто-то сталкивался с этим раньше. Итак, у меня есть около пятидесяти страниц или около того, которые были созданы около года назад. Мы пытаемся обновить страницу новыми компонентами, особенно в верхнем и нижнем колонтитулах. За исключением контента в области основного контента, он останется прежним. Поэтому я пытаюсь перенести все со старых страниц на новые, но просто сохранить область основного контента. Проблема в том, что я не могу просто изменить тип ресурса на старой странице, чтобы он указывал на новые компоненты страницы, потому что содержимое отличается, и у меня будет несколько узлов в верхнем и нижнем колонтитулах, которые мне не нужны. Например, вот моя текущая структура контента:

Старый контент

star-trek
    jcr:content
        header
            nav
            social
            chat
        main-content
            column-one
            column-two
        footer
            sign-up
            mega-menu

Новый контент

star-wars
    jcr:content
        masthead
            mega-menu                                
        main-content
            column-one
            column-two
        bottom-footer
            left-links
            right-links

У кого-нибудь есть идеи о том, как переместить только контент в узле основного контента и каким-то образом удалить другие узлы. Я пытаюсь как-то сделать это программно, потому что я не хочу создавать 50 страниц с нуля. Любая помощь приветствуется!

3 ответа

Решение

Вы можете использовать JCR API для перемещения по желанию, я бы

  1. Запретить пользователям доступ к рассматриваемому контенту. Это можно сделать с помощью временных списков ACL или, если возможно, путем закрытия доступа к интерфейсу.
  2. Запустите скрипт или сервлет, который изменяет содержимое с помощью API-интерфейсов JCR.
  3. Проверьте результаты
  4. Позвольте пользователям снова получить доступ к контенту

Для сценария изменения содержимого я предлагаю сценарий, который изменяет одну страницу (т.е. вы вызываете его с помощью HTTP-запроса, заканчивающегося в /content/star-trek.modify.txt), чтобы вы могли запустить его либо на одной странице, для тестирование или на группе страниц, когда это хорошо.

Сценарий запускается из текущего узла, рекурсивно обращается к нему, чтобы найти узлы, которые он знает, как изменить (на основе их слинга: resourceType), модифицирует их и сообщает, что он сделал, в журналах или на своем выходе.

Чтобы изменить узлы, сценарий использует API-интерфейсы JCR Node для перемещения (и, возможно, Worskpace.move).

Действительно возможно написать код, который делает то, что вам нужно:

package com.test;

import java.io.File;
import java.io.IOException;

import javax.jcr.ItemExistsException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.Node;

import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.core.TransientRepository;
import org.xml.sax.SAXException;

public class test {

    public void test(Document doc) throws RepositoryException {
        try {

            // Create a connection to the CQ repository running on local host 

            Repository repository = JcrUtils
                    .getRepository("http://localhost:4502/crx/server");
            System.out.println("rep is created");

            // Create a Session
            javax.jcr.Session session = repository.login(new SimpleCredentials(
                    "admin", "admin".toCharArray()));
            System.out.println("session is created");

            String starTrekNodePath = "/content/path/";
            String starWarsNodePath = "/content/anotherPath"

            Node starTrekpageJcrNode = null;
            Node starWarstext = null;

            setProperty(java.lang.String name, Node value) 

            boolean starTrekNodeFlag = session.nodeExists(starTrekNodePath);
            boolean starWarsNodeFlag = session.nodeExists(starWarsNodePath);
            if (starTrekNodeFlag && starWarsNodeFlag) {
                System.out.println("to infinity and beyond");
                Node starTrekNode = session.getNode(starTrekNodePath);
                Node starWarsNodeFlag = session.getNode(starWarsNodePath);

                //apply nested looping logic here; to loop through all pages under this node
                //assumption is that you have similar page titles or something

                //on these lines to determine target and destination nodes
                            //2nd assumption is that destination pages exist with the component structures in q
                //once we have the target nodes, the following segment should be all you need

                Node starTrekChildNode = iterator.next();//assuming you use some form of iterator for looping logic
                Node starWarsChildNode = iterator1.next();//assuming you use some form of iterator for looping logic

                //next we get the jcr:content node of the target and child nodes

                Node starTrekChildJcrNode = starTrekChildNode.getNode("jcr:content");
                Node starWarsChildJcrNode = starWarsChildNode.getNode("jcr:content");

                // now we fetch the main-component nodes. 

                Node starTrekChildMCNode = starTrekChildJcrNode.getNode("main-content");
                Node starWarsChildMCNode = starWarsChildJcrNode.getNode("main-content");

                //now we fetch each component node

                Node starTrekChildC1Node = starTrekChildMCNode.getNode("column-one");
                Node starTrekChildC2Node = starTrekChildMCNode.getNode("column-two");

                Node starWarsChildC1Node = starWarsChildMCNode.getNode("column-one");
                Node starWarsChildC2Node = starWarsChildMCNode.getNode("column-two");

                // fetch the properties for each node of column-one and column-two from target
                String prop1;
                String prop2;
                PropertyIterator iterator = starTrekChildC1Node.getProperties(propName);
                while (iterator.hasNext()) {
                    Property prop = iterator.nextProperty();
                    prop1 = prop.getString();
                }

                PropertyIterator iterator = starTrekChildC2Node.getProperties(propName);
                while (iterator.hasNext()) {
                    Property prop = iterator.nextProperty();
                    prop2 = prop.getString();
                }



                // and now we set the values

                starWarsChildC1Node.setProperty("property-name",prop1);
                starWarsChildC2Node.setProperty("property-name",prop2);

                //end loops as appropriate
}

Надеюсь, это должно поставить вас на правильный путь. Вы должны выяснить, как вы хотите определить целевую и целевую страницы, основываясь на структуре вашей папки в /content, но основная логика должна быть такой же

Проблема с результатами, которые я вижу здесь, состоит в том, что вы пишете сервлеты, которые выполняют операции JCR, чтобы перемещать вещи. Хотя технически это работает, на самом деле это не масштабируемый или повторно используемый способ сделать это. Вы должны написать какой-то очень специфический код, развернуть его, выполнить, а затем удалить его (или он существует вечно). Это отчасти непрактично и не совсем ОТЛИЧНО.

Вот два лучших варианта:

Один из моих коллег написал консоль CQ Groovy, которая дает вам возможность использовать Groovy для создания сценариев изменений в репозитории. Мы часто используем его для преобразования контента, как вы описали. Преимущество использования Groovy в том, что это скрипт (а не скомпилированный / развернутый код). У вас по-прежнему есть доступ к JCR API, если вам это нужно, но в консоли есть несколько вспомогательных методов, которые еще больше упрощают работу. Я очень рекомендую этот подход.

https://github.com/Citytechinc/cq-groovy-console

Другой подход заключается в использовании инструмента Bulk Editor в AEM. Вы можете экспортировать TSV контента, внести изменения, а затем повторно импортировать. Вам придется включить функцию импорта с помощью административной функции, но я использовал ее с некоторым успехом. Осторожно, это немного глючит, со свойствами значений массива.

Другие вопросы по тегам