1
votes

Here's the scenario: I have a page in Sitecore 7 (Update-4) that displays a list of recently updated content and media. For media items, I need to display a list of content item paths that use the recently updated media item. What is the best approach to doing this?

My code below uses Sitecore fast query because originally this was supposed to be a simple page listing a few fields from each item. We have not fully implemented our search indexes (or indices if you prefer) but if I need to add a custom search index with a computed field to accomplish this then so be it! We have also not implemented an ORM (hence the need to get the duration setting item by id). Also keep in mind I inherited this project from someone else who did not know Sitecore so I have had to apply "virtual duct tape" to get the job done in some places.

<div id="content">
  <h1>Recently Updated Content</h1>
  <asp:Repeater id="rptRecentlyUpdatedContent" runat="server">
    <HeaderTemplate>
      <Table class="gridtable">
        <tr>
           <th>Name</th>
           <th>Section</th>
           <th>Type</th>
           <th>Last Updated</th>
        </tr>
    </HeaderTemplate>

    <ItemTemplate>
      <tr>
        <td><%# DataBinder.Eval(Container.DataItem, "Name") %></td>
        <td><%# DataBinder.Eval(Container.DataItem, "Paths.ContentPath") %></td>
        <td>Content</td>
        <td><%# Sitecore.DateUtil.IsoDateToDateTime(DataBinder.Eval(Container.DataItem, "Fields[\"__Updated\"]").ToString()) %></td>
      </tr>
    </ItemTemplate>
  </asp:Repeater>

  <asp:Repeater id="rptRecentlyUpdatedFiles" runat="server">
    <ItemTemplate>
      <tr>
        <td><%# DataBinder.Eval(Container.DataItem, "Name") %></td>
        <td></td>
        <td><%# DataBinder.Eval(Container.DataItem, "TemplateName") %></td>
        <td><%# Sitecore.DateUtil.IsoDateToDateTime(DataBinder.Eval(Container.DataItem, "Fields[\"__Updated\"]").ToString()) %></td>
      </tr>
    </ItemTemplate>

    <FooterTemplate>
      </Table>
    </FooterTemplate>
  </asp:Repeater>
</div>

Codebehind:

using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace RJ.Sitecore.Web.layouts.controls
{
    public partial class RecentUpdates : BaseControl
    {     

        protected void Page_Load(object sender, EventArgs e)
        {
            int duration = GetRecentlyUpdatedDuration();
            GetRecentlyUpdatedItems(duration);
        }

        protected void GetRecentlyUpdatedItems(int duration) 
        {
            try
            {
                DateTime dtEndDate = DateTime.Now.AddDays(1);
                DateTime dtStartDate = dtEndDate.AddDays(-duration);
                string endDate = dtEndDate.ToString("yyyyMMdd");
                string startDate = dtStartDate.ToString("yyyyMMdd");
                string sitecoreContentQuery = string.Format("fast:/sitecore/content/Home//*[@__Updated >= '{0}T000000' and @__Updated < '{1}T000000']", startDate, endDate);
                string sitecoreMediaQuery = string.Format("fast:/sitecore/media library//*[@__Updated >= '{0}T000000' and @__Updated < '{1}T000000']", startDate, endDate);

                global::Sitecore.Data.Items.Item[] contentItems = global::Sitecore.Context.Database.SelectItems(sitecoreContentQuery);
                var orderedContentItems = contentItems.OrderByDescending(x => x[global::Sitecore.FieldIDs.Updated]);

                global::Sitecore.Data.Items.Item[] mediaItems = global::Sitecore.Context.Database.SelectItems(sitecoreMediaQuery);
                var orderedMediaItems = mediaItems.OrderByDescending(x => x[global::Sitecore.FieldIDs.Updated]);

                rptRecentlyUpdatedContent.DataSource = orderedContentItems;
                rptRecentlyUpdatedContent.DataBind();
                rptRecentlyUpdatedFiles.DataSource = orderedMediaItems;
                rptRecentlyUpdatedFiles.DataBind();
            }
            catch (Exception ex)
            {
                global::Sitecore.Diagnostics.Log.Error("ERROR: ", ex); 
            }
        }

        protected int GetRecentlyUpdatedDuration()
        {
            Item durationItem = global::Sitecore.Context.Database.GetItem("{05A9B5E8-C9D3-4532-B3E1-301546BB17BC}");
            if (durationItem == null)
            {
                return 0;
            }

            global::Sitecore.Data.Fields.TextField duration = durationItem.Fields["duration"];
            if (duration == null)
            {
                return 0;
            }

            return Convert.ToInt32(duration.Value);        
        }
    }
}
1
Are you using, or considered using, Sitecore Powershell Extensions module? There's a report in there will will get recently updated media, it would not be hard to extend that to content as well.jammykam

1 Answers

1
votes

This is a large topic, so "What is the best approach to doing this?" doesn't really have a simple answer. So I'm hoping a short and functional answer will suffice :)

I don't think you'll need a computed field. The base SearchResultItem class used for search has properties that represent the last updated date and the path of the item. So a really basic search could look like this:

using (var context = ContentSearchManager.GetIndex("your_index_name").CreateSearchContext()) 
{ 
    var results = context.GetQueryable<SearchResultItem>().
                          Where(item => item.Updated > startDate && 
                                        item.Updated < endDate && 
                                        item.Path.StartsWith(mediaLibraryRootPath)).
                          .GetResults();
}

There are different ways to handle the results, but for simplicity's sake I'll just show you how to get a list of item ID's that you can work with

results.Hits.Select(hit => hit.Document.ItemId);