ComponentLink в качестве метаданных на уровне публикации, найдите страницу, на которой используется соответствующий компонент.

В TBB я пытаюсь найти страницу, используя критерии и запрос, который использует компонент с определенным TcmUri.

Я искал пример на sdllive, но не нашел.

Может ли кто-нибудь дать мне пример того, как я могу это сделать?

Полный сценарий таков:

У меня есть ComponentLink, установленный как поле метаданных в публикации. Этот ComponentLink является компонентом входа. Страница, на которой используется компонент, обеспечивает возможность входа на веб-сайт. Теперь я читаю метаданные из публикации при публикации мастера сайта, беру tcmId компонента, используемого в качестве ComponentLink (я уже сделал это), и нахожу страницу, которая использует компонент (страница входа), чтобы получить путь к эту страницу входа и запишите ее в web.config.


person IonutC    schedule 13.06.2012    source источник


Ответы (4)


Если компонент находится на странице как презентация компонента, то почему бы вам просто не использовать связывание компонентов, чтобы найти его? Сохраните URI компонента в Web.Config, если это проще всего для вас, используйте что-то вроде этого:

const string currentPageId = "tcm:6-123-64";
TcmUri itemUri = new TcmUri(ConfigurationManager.AppSettings["MyLoginComponent"]);
ComponentLink componentLink = new ComponentLink(itemUri.PublicationId);

string loginUrl =
    componentLink.GetLink(currentPageId, itemUri.ToString(), "tcm:0-0-0", "", "",
                          false, false).Url;

Если вы предпочитаете найти это во время публикации с помощью TBB:

RepositoryLocalObject context = null;
if (package.GetByName(Package.ComponentName) == null)
    context = (RepositoryLocalObject)engine.GetObject(
               package.GetByName(Package.ComponentName));
else
    context = (RepositoryLocalObject)engine.GetObject(
               package.GetByName(Package.ComponentName));

Repository contextPublication = context.ContextRepository;
if (contextPublication.Metadata == null) return;
ItemFields metadata = 
     new ItemFields(contextPublication.Metadata, contextPublication.MetadataSchema);
if (!metadata.Contains("MyLoginComponentField")) return;

ComponentLinkField myLoginComponentField = (ComponentLinkField)metadata["MyLoginComponentField"];
Component loginTarget = myLoginComponentField.Value;

UsingItemsFilter filter = new UsingItemsFilter(engine.GetSession())
                                {
                                    InRepository = contextPublication, 
                                    ItemTypes = new[] {ItemType.Page}
                                };

foreach (Page page in component.GetUsingItems(filter))
{
    string url = page.PublishLocationUrl;
}

Если компонент используется более чем на одной странице, то это будет содержать URL-адрес ПОСЛЕДНЕЙ страницы в списке - убедитесь, что это не так... Я мог бы правильно обработать это в коде, но я подумал, что я должен не делать всю домашнюю работу.

person Nuno Linhares    schedule 13.06.2012
comment
Спасибо Нуно за ответ. Я не знал о таком подходе, класс UsingItemsFilter и метод GetUsingItems() были мне неизвестны. Я новичок в мире Tridion, и мне еще предстоит многому научиться. - person IonutC; 15.06.2012

Нуно прав - функция динамического связывания компонентов Tridion точно удовлетворит ваши потребности. В примере Nuno используются данные конфигурации приложения, но вы можете так же легко использовать данные публикации для ссылки на свой компонент входа в систему, как вы предложили в своем вопросе.

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

person Dominic Cronin    schedule 14.06.2012

Мне удалось отфильтровать версию, реализуя этот метод:

public static bool IsPageLastVersion(Page page)
    {
        bool isLastVersion = false;
        if (page != null)
        {
            List<VersionedItem> pageVersions = page.GetVersions().ToList();
            pageVersions.Sort((v1, v2) => v1.Version.CompareTo(v2.Version));
            int lastVersion = pageVersions.Last().Version;
            isLastVersion = lastVersion == page.Version;
        }
        return isLastVersion;
    }
person IonutC    schedule 18.06.2012

Я воспользовался подходом, предложенным Нуно, и теперь у меня есть следующее:

        StringBuilder url = new StringBuilder();
        RepositoryLocalObject context = null;
        if (package.GetByName(Package.ComponentName) == null)
            context = (RepositoryLocalObject)engine.GetObject(
                       package.GetByName(Package.PageName));
        else
            context = (RepositoryLocalObject)engine.GetObject(
                       package.GetByName(Package.ComponentName));

        Repository contextPublication = context.ContextRepository;

        _log.Debug("Starting checking the metadata");
        if (contextPublication.Metadata != null)
        {
            ItemFields metadata =
             new ItemFields(contextPublication.Metadata, contextPublication.MetadataSchema);
            if (metadata.Contains("LoginPage"))
            {
                _log.Debug("LoginPage metadata field found in " + metadata.ToXml().OuterXml);
                ComponentLinkField myLoginComponentField = (ComponentLinkField)metadata["LoginPage"];
                Component loginTarget = myLoginComponentField.Value;

                UsingItemsFilter filter = new UsingItemsFilter(engine.GetSession())
                {

                   // InRepository = contextPublication,
                    ItemTypes = new[] { ItemType.Page }

                };

                foreach (comm.Page page in loginTarget.GetUsingItems(filter))
                {
                    if(PublishEngine.IsPublished(page))
                    {
                        url.Append(" url: ").Append(page.PublishLocationUrl);
                    }
                }
            }
        }
        return url.ToString();

Пока я просто читаю все пути к страницам как одну строку.

person IonutC    schedule 15.06.2012
comment
Проверьте параметры фильтра, должен быть способ указать OnlyCurrentVersions или что-то в этом роде. Однако рекомендуемым подходом для получения ссылок на страницы/компоненты является использование динамической ссылки. Что произойдет, если я отменю публикацию одной из этих страниц сейчас? - person Nuno Linhares; 15.06.2012