String Writer

my tech stuffs…

Posts Tagged ‘Publication

Delete keywords in Tridion

with 5 comments

As posted earlier, I completed the keyword deletion tool. I’ve tried both approaches (explained in my earlier post) to implement this keyword deletion. Finally I’ve decided to go with deleting keywords from bottom to top that’s 2nd approach.

How to call it

All you need is just to create class object with TCM Uri of a parent keyword whose child keywords are to be deleted and call its delete method.


//initialize the class with keyword TCM Uri value
TCMKeywords keywords = new TCMKeywords(ConfigurationManager.AppSettings["TCMURI"]);
//deletes keyword branch
keywords.Delete();

Here we don’t need to pass its publication TCM Uri since that can be retrieved from its keyword TCM Uri. I’ve given TCM Uri in my app.config file so that I can change it whenever I needed.

Call child keywords recursively

Tridion API does not provide direct method to get all child keywords in hierarchical order. But we can write a recursive call just like the way we do it for any other tree structure objects.


/// <summary>
/// Recursive method to navigate all keywords
/// </summary>
/// <param name="parentTCM">TCM Uri of parent keyword</param>
/// <param name="level">Hierarchy level of keyword</param>
private void NavigateKeywords(string parentTCM, int level)
{
   //gets all child keywords from given parent
   XmlNode keyNode = this.GetListChildKeywords(parentTCM);

   foreach (XmlNode key in keyNode.ChildNodes)
   {
      //loops through its next level
      NavigateKeywords(key.Attributes["ID"].Value, level + 1);

      //deletes keyword if it doesn't have any child
      this.DeleteKeyword((Keyword)this.GetObject(key.Attributes["ID"].Value), level);
   }
}

Obviously a keyword cannot be deleted if it is being used by other items. So all other associations should be removed before deleting it. That’s the reason DeleteKeyword(…) is being called after NavigateKeywords(…). That means if keyword (A) do not have any child, keyword (A) will be considered for deletion.

GetListChildKeywords(…) is a private method to retrieve all child keywords in Xml type of object.


/// <summary>
/// Gets all child keywords in xml object
/// </summary>
/// <param name="parentKeywordTCM">Parent <see cref="Keyword">Keyword</see></param>
/// <returns>Child keywords in <see cref="XmlNode">XmlNode</see> object</returns>
private XmlNode GetListChildKeywords(string parentKeywordTCM)
{
   //gets all child keywords
   string keyXML = ((Keyword)this.GetObject(parentKeywordTCM)).GetListChildKeywords(EnumKeywordSortType.SortTypeTitle,ListColumnFilter.XMLListID, (ListRowFilter)TObj.CreateListRowFilter());

   //returns output as xml object
   return this.PopulateXMLNode(keyXML);
}

ListColumnFilter –Other attributes also can be retrieved other than ListID. But we need only list id for this tool.

ListRowFilter – Here we are getting all rows so we are not setting any filter conditions. This can be set based upon our requirements. Let’s look at this code sample if filtering condition is needed.

Deleting a keyword

The keywords in Tridion can be used in following ways.

  1. Classified with other building blocks
  2. Used in component or metadata fields
  3. Localized in its child publications

A keyword should be released from the all above associations before deleting it.


//releases keyword from its all dependencies
if (this.ReleaseKeyword(keyword, keyLevel))
{
   //deletes keyword
   keyword.Delete();

   Console.WriteLine("{0}{1} deleted...", keyLevel, keyword.Title);
}

ReleaseKeyword(…) is a private method to unclassify and unlocalize the keywords.


/// <summary>
/// Releases the keyword from its dependencies
/// </summary>
/// <param name="keyword"><see cref="Keyword">Keyword</see> object to be released</param>
/// <param name="keyLevel">Hirarchical level of a keyword</param>
/// <returns>Returns <see cref="bool">bool</see> if released or not</returns>
private bool ReleaseKeyword(Keyword keyword, string keyLevel)
{
   //default status
   bool released = false;

   //unclassifies the keyword
   released = this.Unclassify(keyword, keyLevel);

   //unlocalizes the keyword from its all child publications
   if (released)
      released = UnLocalize(keyword, keyLevel);

   //returns released status
   return released;
}

Unclassifying keywords

In Tridion, the content or building blocks are generally classified with keywords.

Classified means that it can be in either way,

1) Keyword can be used in any of field values in metadata or components.

2) An Tridion object is classified against keyword.

These two associations should be removed as part of unclassification.

For example, if a keyword is classified with 10 Tridion objects, we need to retrieve those 10 objects and call them separately its own unclassify method.

The problem here is a keyword in one publication would be derived into its child publications. In child publications, these keywords might have classified with other objects. Hence the appropriate keyword from the same publication should be retrieved to unclassify it.


/// <summary>
/// Unclassifies the keyword
/// </summary>
/// <param name="keyword"><see cref="Keyword">Keyword</see> object to be released</param>
/// <param name="keyLevel">Hierarchical level of a keyword</param>
/// <returns>Returns <see cref="bool">bool</see> if unclassified or not</returns>
private bool Unclassify(Keyword keyword, string keyLevel)
{
   try
   {
      //gets all using items from all publications
      string classifiedItemsXML = keyword.Info.GetListUsingItems(ListColumnFilter.XMLListDefault,(ListRowFilter)TObj.CreateListRowFilter());

      //converts xml string to xml object
      XmlNode xmlDoc = this.PopulateXMLNode(classifiedItemsXML);

      string tcmChild = null;
      //default publication is set to current publication

      string pubURI = this.PublicationURI;

      foreach (XmlNode child in xmlDoc.ChildNodes)
      {
         //gets keyword tcm uri
         tcmChild = child.Attributes["ID"].Value;

         //checks if publication of child object is same as its parent keyword
         if (!this.IsSamePublication(tcmChild))
         {
            //gets publication tcm uri from given tcm uri
            pubURI = GeneratePublicationTCM(tcmChild);

            //gets the same keyword object from its child object publication
            keyword = (Keyword)this.GetObject(pubURI, ReplacePublicationID(keyword.ID, this.GetPublicationID(tcmChild)));
         }

         //checks its child object type and unclassify
         switch (child.Attributes["Type"].Value)
         {
            case "2":
               ((Folder)this.GetObject(pubURI, tcmChild)).UnClassify(keyword);
               break;
            case "4":
               ((StructureGroup)this.GetObject(pubURI, tcmChild)).UnClassify(keyword);
               break;
            case "16":
               ((Component)this.GetObject(pubURI, tcmChild)).UnClassify(keyword);
               break;
            case "32":
               ((ComponentTemplate)this.GetObject(pubURI, tcmChild)).UnClassify(keyword);
               break;
            case "64":
               ((Tridion.ContentManager.Interop.TDS.Page)this.GetObject(pubURI, tcmChild)).UnClassify(keyword);
               break;
            case "128":
               ((PageTemplate)this.GetObject(pubURI, tcmChild)).UnClassify(keyword);
               break;
         }
      }

      //display the output if any of child is unclassified
      if (xmlDoc.ChildNodes.Count != 0)
         Console.WriteLine("{0}{1} unclassified...", keyLevel, keyword.Title);

      return true;
   }
   catch (Exception ex)
   {
      Console.WriteLine("Unclassification Failed!");
      Console.WriteLine(ex.Message);
      return false;
   }
}

GetListUsingItems(…) is the common method in all Tridion objects to retrieve its associated items. In this case, this method will return all the objects wherever the keyword is being used.

Here important note is that if a keyword is unclassified, the parent object will not get republished automatically. If you need to republish the parent object while keyword unclassification, you need to set some code and trigger workflow events.

Unlocalizing keywords

Unlocalizing is not a straight forward approach unlike unclassification. There is no method to write all localized keywords.

If there is a keyword in publication, the same keyword has to be checked in its all child publications whether it is localized in child publication level.


/// <summary>
/// Unlocalizes keyword
/// </summary>
/// <param name="keyword"><see cref="Keyword">Keyword</see> object to be released</param>
/// <param name="keyLevel">Hirarchical level of a keyword</param>
/// <returns>Returns <see cref="bool">bool</see> if unlozalized or not</returns>
private bool UnLocalize(Keyword keyword, string keyLevel)
{
   try
   {
      //gets all child publications
      List<string> childPublications = this.GetChildPublications(keyword.Publication.ID);

      foreach (string cPub in childPublications)
      {
         //gets the keyword in each child publication
         Keyword childKey = (Keyword)this.GetObject(cPub, ReplacePublicationID(keyword.ID, this.SplitURI(cPub, 1)));

         //checks if it is localized
         if (childKey.Info.IsLocalized)
         {
             childKey.UnLocalize();
             Console.WriteLine("{0}{1} unlocalized from {2}...", keyLevel, childKey.Title, childKey.Publication.Title);
         }
      }
      return true;
   }
   catch (Exception ex)
   {
      Console.WriteLine(ex.Message);
      return false;
   }
}

GetChildPublications(…) posted earlier (Get Child publications in Tridion)

Output

I created these keywords for my testing. All keywords are classified against a component and two of them are localized in child publications.

clip_image001[1]

I ran the tool and got the following output.

clip_image002[1]

The source code can be copied from this link.

Written by visvabalaji

April 12, 2011 at 10:53 pm

Get Child publications in Tridion

leave a comment »

This code sample will give you all the derived child publications from the specific parent publication. There is no direct method to get all child publications but can be easily retrieved from GetListUsingItems(…).

I needed this method to get a status of a component in all child levels.

/// <summary>
/// Gets all child publications
/// </summary>
/// <param name="parent">TCM Uri of parent publication</param>
/// <returns>Collection of child publications</returns>
private void GetChildPublications(string parentTCM)
{
  //gets current publication object
  Publication pub = tdse.GetPublication(parentTCM);
  //gets row filter object
  ListRowFilter filter = tdse.CreateListRowFilter();
  //filter only publication type
  filter.SetCondition("ItemType", 1);
  //returns using publications as xml
  string itemsXML = pub.Info.GetListUsingItems(ListColumnFilter.XMLListID, filter);

  //initialize xml document object
  XmlDocument xmlDoc = new XmlDocument();
  //loads items xml
  xmlDoc.LoadXml(itemsXML);

  foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
  {
    //loops id attribute in each child node
    Console.WriteLine(node.Attributes["ID"].Value);
  }
}

The below code returns all derived publications and remember that this will return all using items if ItemType is not specified.

  //filter only publication type
  filter.SetCondition("ItemType", 1);
  //returns using publications as xml
  string itemsXML = pub.Info.GetListUsingItems(ListColumnFilter.XMLListID, filter);

Output of above line is,

<?xml version="1.0" encoding="utf-8"?>
<tcm:ListUsingItems xmlns:tcm="http://www.tridion.com/ContentManager/5.0">
  <tcm:Item ID="tcm:0-123-1" />
  <tcm:Item ID="tcm:0-124-1" />
  <tcm:Item ID="tcm:0-125-1" />
  <tcm:Item ID="tcm:0-142-1" />
  <tcm:Item ID="tcm:0-143-1" />
  <tcm:Item ID="tcm:0-144-1" />
</tcm:ListUsingItems>

Written by visvabalaji

April 11, 2011 at 11:38 pm

Tridion: Organizational Items

leave a comment »

 

clip_image002 

 

-          Collection of content and layout items that are used to create a website

-          Contains folders, structure groups and categories

-          Root publication should be defined to overall publications

-          While creation, child publication will be exact copy of parent but virtual copy

-          Usual Practice

o    Empty publication should be created as root to accommodate future changes.


clip_image004

 

 

-          Stores content building blocks (schemas, components, comp templates, page templates, folders and virtual folders)

-          Contains physical copy of building blocks

-          Default folders are Content, Default Building Blocks and System

-          Usual practice

o    Components are stored in Content folder

o    Schemas and Templates are stored in System folder


clip_image006

 

 

-          Organize, manage, and provide a URL structure for Pages

-          Contains Pages with embedded building blocks

-          Can be used for site navigation

-          Can be displayed in order by prefixing 3 digit number, <nnn>_<Title>

-          Title without prefix number will not be shown on page.

-          Usual Practice

o    Prefix numbers are incremental of 10

 


clip_image008

 

 

 

-          Classify the contents using keywords

-          Keywords are unique across categories in a publication

-          Keywords can be used as source for collection controls (ex, dropdown)

-          Two other types of keywords

o    Abstract – defines generic characteristic of an object. It can’t be used for classification.

o    Concrete – defines specific values

-          Only possible through TOM API

o    Category can have another category as parent

o    Keywords can have multiple parents

o    SDL Tridion GUI will only show a single parent

-          Usual Practice

o    Parent keyword name will be appended while trying to add duplicate keyword names (ex, <parentKey>_<keyword>

 

Written by visvabalaji

March 16, 2010 at 6:53 am

Follow

Get every new post delivered to your Inbox.