4

A Better way to attach custom SP2010 event receivers

I recently decided to take a deeper look into code which is used to programmatically attach or remove a SharePoint event receiver against a SharePoint list.

Using the SharePoint 2010 Object Model to programmatically add or remove an event receiver is really simple….and that is exactly the problem I came across. As developers we sometimes tend to have a ‘get the job done’ attitude and we do exactly that…we write code which executes without any problems and which delivers the expected results, so we consider the job done and we move on. If we want to build robust code we have to consider the different syntax options and implement what we believe is most relevant in the particular scenario.

So I took the C# code and made slight changes to it and now I get much better (and more granular) control. I am now able to programmatically set the SharePoint custom event receiver properties.

Scenario: I have a SharePoint 2010 site which contains a number of custom event receivers. These event receivers can be web scoped, site scoped, or list scoped (this example). Based on a specific action (trigger) I want to programmatically attach or remove the custom event receivers to / from their target. Examples of triggers are: a business rule (workflow), a custom page code behind (like a settings page), provisioning logic, etc. So, the code which manages the event receivers can live almost anywhere. In this example I make use of a custom provisioning feature to manage the event receivers. In other words if my custom provisioning feature is activated it will attach my custom event receivers and when the feature is deactivated it will remove the event receivers.

This is the old code before I made changes:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    using (SPWeb web = properties.Feature.Parent as SPWeb)
    {
        SPList list = web.Lists.TryGetList("test");
        if (list != null)
        {
            string classname = "SharePointDemoCode.Custom.EventReceivers.SetDealValuesReceiver";
            string assembly = "SharePointDemoCode, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1ee7eff4c43a8776";
            web.AllowUnsafeUpdates = true;
            list.EventReceivers.Add(SPEventReceiverType.ItemAdded, assembly, classname);
            web.AllowUnsafeUpdates = false;
        }
    }
}

This code will attach the event receiver without any problems but if I use SharePointEventReceiverManager.exe to analyse the event receiver association I can see that the event sequence number set to 10000 (default value) and the event receiver name is empty.

image

So to have control over the above mentioned properties one can rather use the following code:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    using (SPWeb web = properties.Feature.Parent as SPWeb)
    {
        SPList list = web.Lists.TryGetList("test");
        if (list != null)
        {
            string classname = "SharePointDemoCode.Custom.EventReceivers.SetDealValuesReceiver";
            string assembly = "SharePointDemoCode, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1ee7eff4c43a8776";

            SPEventReceiverDefinitionCollection eventReceivers = list.EventReceivers;
            SPEventReceiverDefinition neweventReceiver = eventReceivers.Add();
            neweventReceiver.Name = "Set Deal Values Receiver";
            neweventReceiver.Synchronization = SPEventReceiverSynchronization.Default;
            neweventReceiver.Type = SPEventReceiverType.ItemAdded;
            neweventReceiver.SequenceNumber = 25001;
            neweventReceiver.Assembly = assembly;
            neweventReceiver.Class = classname;
            neweventReceiver.Update();
        }
    }
}

From the image below you can see that the event sequence number set to 25001  and the event receiver name is ‘Set Deal Values Receiver’ – this is exactly what I wanted to have control over.

image

To remove / detach an event receiver use the following code:

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
    string classname = "SharePointDemoCode.Custom.EventReceivers.SetDealValuesReceiver";

    using (SPWeb web = properties.Feature.Parent as SPWeb)
    {
        SPList list = web.Lists.TryGetList("test");
        if (list != null)
        {
            IEnumerable<SPEventReceiverDefinition> eventReceiverResults = list.EventReceivers.Cast<SPEventReceiverDefinition>().Where(receiver => string.Equals(receiver.Class, classname, StringComparison.OrdinalIgnoreCase));

            if (eventReceiverResults.Any())
            {
                foreach (SPEventReceiverDefinition eventReceiver in eventReceiverResults.ToList())
                {
                    list.EventReceivers[eventReceiver.Id].Delete();
                }
            }
        }
    }
}

For a complete list of SPEventReceiverDefinition Members go to: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.speventreceiverdefinition_members(v=office.14).aspx

3

Field with name … was not found - SPFieldCollection

A booby trap is a device or setup that is intended to kill, harm or surprise a person, unknowingly triggered by the presence or actions of the victim.

The SharePoint 2010 Object Model has a couple of ‘booby traps’ and if you don’t pay careful attention you might end up wasting precious time trying to troubleshoot code which should be working.

The following issue is a classic example of syntax which is really easy to implement and descriptive enough to prevent us from making mistakes…but it can be a little misleading.

If you want to retrieve an existing site column (field) from a SPWeb and you know what the internal name of the field is you can use the following to get the field:

SPField newField = web.Fields.GetField(fieldname);

If you don’t know the internal name of the field but you know what the display name of the field is you can use the following to get the field:

SPField newField = web.Fields.GetField(fieldname);

or

SPField newField = web.Fields[fieldname];

Now, imagine you want to programmatically (C#) add a site column (field) to a SharePoint list, library or content type.

First you want to check if the field exists, then you want to retrieve the field and finally you want to add the field to a list, library or content type.

1-You can use the display name of the field to check if it exists:

image

The result is = true so

2-You want to use the display name of the field to fetch the field from the web:

image

You can see from the two screenshots (above) that the comments indicate that the ‘display name’ can be used in both functions so by looking at it one would assume that if web.Fields.ContainsField(“SolutionExpert”) is true then you will be able to retrieve the field by using SPField newfield = web.Fields[“SolutionExpert”] ... but there is a problem!!!

The internal name of my field is ‘SolutionExpert’ and the display name is ‘Solution Expert’ so I made a mistake!!

If you look closely at web.Fields.ContainsField(string fieldName) you will see that the method accepts either the display name or the internal name of the field, so you might find yourself in a situation where you passed in the internal name of a field to web.Fields.ContainsField and the result was true, but when you then use the same field name to try access the field with newfield = web.Fields[fieldname] you will get an error because newfield = web.Fields[fieldname] only accepts the display name of the field and not the internal name.

Example:

image

So, remember that it is much safer to reference fields by its internal name and instead of using

SPField newField = web.Fields[fieldname]

rather use:

SPField newField = web.Fields.GetField(fieldname);

image

Also see: http://msdn.microsoft.com/en-us/library/ms196070.aspx

1

Get / Set field order for SharePoint 2010 list or library

When you build custom SharePoint solutions there are times when you need to create lists/libraries and fields (site columns or list fields) during run-time.

Using the SharePoint 2010 object model to programmatically create site columns, content types or list and library fields is really easy but you will find that the order in which the new fields appear on the item's view- and edit forms depends on the execution order of the code which provisioned the fields.

To illustrate this, imagine you have a document library called ‘Technology’ which contains 2 fields called ‘Name’ and ‘Title’.

An event triggers your code to add 2 new fields to the document library. First the code adds the field ‘Product’ to the library and then the code adds the field ‘Document Summary’ to the library. At this point your library will contain 4 fields in the following order: 1-Name, 2-Title, 3-Product, 4-Document Summary.

Later another event triggers your code to add a field called ‘Product Version’ to the same library. The result will be that the new field will be displayed in position 5 on the view and edit forms.  This is not ideal – as you can see from the image below, the position of the ‘Document Summary’ field should rather be below ‘Product Version’.

image

Fortunately there is an easy way to programmatically control the order in which fields appear on the list item view- and edit forms.

Many thanks to Rahul Sharma for his original post on this topic – I used the basics from his post http://www.directsharepoint.com/2011/11/change-column-order-in-new-and-edit.html and extended it to fit my needs.

The following code illustrates three functions:

  1. Get the display order of all visible fields for a specified list/library
  2. Get the display order of a specific list of fields for a specified list/library
  3. Set the display order of a specific list of fields on a list/library item’ view- and edit forms.

(The code is written in a simple console app. Remember to add a reference to Microsoft.SharePoint.dll and change your console app platform target to 64bit – and add proper exception management)

1-Get the display order of all visible fields for a specified list/library

Based on the scenario described above the result from the code below is:

image

static void Main(string[] args)
{
   using (SPSite site = new SPSite(args[0]))
   {
       Dictionary<string, int> actualfieldsorder = FetchFieldOrder(site.OpenWeb(), "Technology", "Document");
      
       foreach (KeyValuePair<string, int> pair in actualfieldsorder)
       {
          Console.WriteLine(pair.Key + " : " + pair.Value);
       }

       Console.WriteLine("");
       Console.WriteLine("Done");
       Console.ReadKey();
   }
}

private static Dictionary<string, int> FetchFieldOrder(SPWeb web, string listname, string contenttypename)
{
    Dictionary<string, int> fieldsorder = new Dictionary<string, int>();
    SPList list = web.Lists.TryGetList(listname);
    if (list != null)
    {
        SPContentType spct = list.ContentTypes[contenttypename];
            int positionindex = 0;
            foreach (SPField field in spct.Fields)
            {
                if (!field.Hidden && field.Reorderable)
                {
                        if (field.ShowInEditForm == null)
                        {
                                positionindex++;
                                fieldsorder.Add(field.InternalName, positionindex);
                        }
                        else
                        {
                            if ((bool)field.ShowInEditForm)
                            {
                                positionindex++;
                                fieldsorder.Add(field.InternalName, positionindex);
                            }
                        }
                }
            }
    }

    return fieldsorder;
}

2-Get the display order of a specific list of fields for a specified list/library

There might also be situations whereby you want to determine the display order for a specific list of fields in relation to each other. Example, I want to determine whether the ‘Product’ field will appear above the ‘Product Version’ field. I am not interested in any of the other fields.

The code below will return the following result:

image

static void Main(string[] args)
        {
            using (SPSite site = new SPSite(args[0]))
            {
                List<string> fields = new List<string>();
                fields.Add("Product");
                fields.Add("Product_x0020_Version");
                Dictionary<string, int> actualfieldsorder = FetchFieldOrder(site.OpenWeb(), "Technology", "Document",fields);

                foreach (KeyValuePair<string, int> pair in actualfieldsorder)
                {
                    Console.WriteLine(pair.Key + " : " + pair.Value);
                }

                Console.WriteLine("");
                Console.WriteLine("Done");
                Console.ReadKey();
            }
        }

private static Dictionary<string, int> FetchFieldOrder(SPWeb web, string listname, string contenttypename, List<string> checkfields)
{
    Dictionary<string, int> fieldsorder = new Dictionary<string, int>();
    foreach (string fieldname in checkfields)
    {
        fieldsorder.Add(fieldname, 0);
    }
    SPList list = web.Lists.TryGetList(listname);
    if (list != null)
    {
        SPContentType spct = list.ContentTypes[contenttypename];
        int positionindex = 0;
        foreach (SPField field in spct.Fields)
        {
            if (!field.Hidden && field.Reorderable)
            {
                if (field.ShowInEditForm == null)
                {
                    if (fieldsorder.ContainsKey(field.InternalName))
                    {
                        positionindex++;
                        fieldsorder[field.InternalName] = positionindex;
                    }
                }
                else
                {
                    if ((bool)field.ShowInEditForm)
                    {
                        if (fieldsorder.ContainsKey(field.InternalName))
                        {
                            positionindex++;
                            fieldsorder[field.InternalName] = positionindex;
                        }
                    }
                }
            }
        }
    }

    return fieldsorder;
}

3-Set the display order of a specific list of fields on a list/library item’ view- and edit forms

The following code will set the display order of the specified fields. Please note that the parameter ‘CustomOrder’ contains the fields which you want to reorder. The order in which the fields will appear on the view and edit forms is determined by the order in which you programmatically add the fields to the List variable '(CustomOrder). If you want you can change to code to have even more granular control.

image

The code below will result in the following:

image

static void Main(string[] args)
       {
           using (SPSite site = new SPSite(args[0]))
           {
               List<string> CustomOrder = new List<string>();
               CustomOrder.Add("FileLeafRef");
               CustomOrder.Add("Title");
               CustomOrder.Add("Product");
               CustomOrder.Add("Product_x0020_Version");
               CustomOrder.Add("DocumentSummary");

               SetFieldOrder(site.OpenWeb(), "Technology", "Document", CustomOrder);

               Console.WriteLine("");
               Console.WriteLine("Done");
               Console.ReadKey();
           }
       
       }

private static void SetFieldOrder(SPWeb web, string listname, string contenttypename, List<String> CustomOrder)
{
    try
    {
        SPList list = web.Lists.TryGetList(listname);
        if(list!=null)
        {
            Dictionary<Int32, String> listColumnReorder = new Dictionary<Int32, String>();
            int iCounter = 0;
            foreach (string item in CustomOrder)
            {
                if (list.Fields.ContainsField(item))
                {
                    SPField field = list.Fields.GetFieldByInternalName(item);
                    if (field != null)
                    {
                        if (!field.Hidden && field.Reorderable)
                        {
                            if (field.ShowInEditForm == null || (bool)field.ShowInEditForm)
                                {
                                    listColumnReorder.Add(iCounter, field.InternalName);
                                    iCounter++;
                                }
                        }
                    }
                }
            }
            String[] sFields = new String[listColumnReorder.Count];
            foreach (Int32 order in listColumnReorder.Keys)
            {
                sFields[order] = listColumnReorder[order];
            }
            ReOrderColumn(sFields, list.ContentTypes[contenttypename]);
       }
    }
    catch (Exception ex)
    {
        // add your own exception management here...
    }
}

private static void ReOrderColumn(String[] fieldInternalNameArray, SPContentType objContentType)
{
     try
     {
         SPFieldLinkCollection fldLinks = objContentType.FieldLinks;
         fldLinks.Reorder(fieldInternalNameArray);

         objContentType.Update();
     }
     catch (Exception ex)
     {
         // add your own exception management here...
     }
}

6

Show or Hide SharePoint Ribbon Tab based on User Permissions

This week I wanted to figure out how to show or hide a custom developed SharePoint Ribbon Tab based on the permissions of a logged in SharePoint user.

I have a custom SharePoint 2010 Ribbon Tab with the title ‘Show or Hide Tab’ and I want to hide the tab if a current logged in user is a member of the ‘Root Visitors’ security group.

I do not want to hide the entire ribbon and I also do not want to hide only the inactive buttons. The ribbon with the ‘Documents’ and ‘Library’ tabs must be visible for all users and audience targeting must be applied to the new custom ribbon tab.

I can imagine that the requirement is quite a common one. You might want to develop a set of custom tabs which are only visible to users who are members of a specific SharePoint group.

I assume that you know how to develop a custom ribbon – if not please follow the great blog series by Chris O’Brien on Ribbon Customizations and ensure that your custom ribbon tab works before you continue with this tutorial.

clip_image001

I could not find a blog with an appropriate example on the web so I used a combination of a few blog posts and added my own logic.

I want to thank Chris O’Brien for his series on Ribbon Customizations and Tobias Lekman for his helpful blog post . Their contributions were extremely helpful during my research.

How it works:

I have a custom ribbon with the title ‘Show or Hide Tab’.I also have a SharePoint Group Called ‘Root Visitors’. I log in to SharePoint as a user who is not a member of this group.

clip_image002

I navigate to the Shared Documents library and do not see the custom ribbon tab.

clip_image003

Now I add the user to the security group

clip_image004

 …and I navigate back to the Shared Documents library. Now the custom ribbon tab is visible.

clip_image005

 Ok, so Let’s Get Started

Prerequisites (…you need the following in place before you start coding):

    1. the ID of the Ribbon Tab which you want to hide ( I created a custom ribbon tab –see elements file contents below)
    2. the name of the SharePoint Security Group which can see the ribbon item
    3. jquery-1.6.2.min.js (download from http://docs.jquery.com/Downloading_jQuery)
    4. jquery.SPServices-0.6.2.js - this is a jQuery library which abstracts SharePoint’s Web Services and makes them easier to use. It also includes functions which use the various Web Service operations to provide more useful (and cool) capabilities. It works entirely client side and requires no server install. http://spservices.codeplex.com

Development Tasks (…you will code the following):

    1. Construct the JQuery to hide the ribbon tab
    2. Register the JQuery to hide the ribbon tab
    3. Verify that it all works fine

 

Prerequisites:

1.       Get the ID of the Ribbon Tab which you want to hide:

If you have a custom ribbon tab then you can get the ID value from the Elements.xml file. In the example below the ID of my custom ribbon is ‘DemoHideRibbonTab’

       ?xml version="1.0" encoding="utf-8"?>

       <Elements xmlns="http://schemas.microsoft.com/sharepoint/">

        <CustomAction

         Id="DemoHideRibbonTab"

As an alternative you can use the following handy piece of JQuery to view the IDs of all the Ribbon Tabs on a page.

Copy the JQuery code below and paste it inside a Content Editor Web Part on the SharePoint library AllItems.aspx page and save the page. 

<script type="text/javascript">

   $("a.ms-cui-tt-a").each(function ()

   {

     var objTabTitle = $(this).parent().attr("id");

     alert( objTabTitle );

   });

</script>

When you refresh the page the JQuery will iterate through all the ribbon tabs and display their IDs.

You should see the IDs of the different ribbon tabs:

clip_image006 

2.       Get the name of the SharePoint Security Group:

The security group for which you must hide the ribbon tab must be a SharePoint group –it’s simple, you must have the name of the group. 

3.       Download and distribute jquery-1.6.2.min.js

The jQuery library is a single JavaScript file, containing all of its common DOM, event, effects, and Ajax functions. It can be included within a SharePoint page by linking to a local copy.

Download jquery-1.6.2.min.js from http://docs.jquery.com/Downloading_jQuery and distribute into the 14-hive of your SharePoint web-front-end server.

Example: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\HideRibbonSample\Scripts\ jquery-1.6.2.min.js

4.       Download and distribute jquery.SPServices-0.6.2.js

This is a jQuery library which abstracts SharePoint’s Web Services and makes them easier to use. It also includes functions which use the various Web Service operations to provide more useful (and cool) capabilities. It works entirely client side and requires no server install.

Download jquery.SPServices-0.6.2.js from http://spservices.codeplex.com and distribute into the 14-hive of your SharePoint web-front-end server.

Exanple: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\HideRibbonSample\Scripts\ jquery.SPServices-0.6.2.js

 

Development Tasks:

1.       Construct the JQuery to hide the ribbon tab

We now have all the prerequisites in place and we can start coding the JQuery which will hide the ribbon tab.

Create a new empty file and save the file to the 14-hive of your SharePoint web-front-end server.

Exanple: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\HideRibbonSample\Scripts\HideRibbonSample.js 

Add the following JQuery to the file.

function checkIfUserIsInGroup()

{

$(document).ready(function() { $().SPServices({ 

      operation: "GetGroupCollectionFromUser", 

      userLoginName: $().SPServices.SPGetCurrentUser(), 

      async: false, 

      completefunc: function(xData, Status) { 

      if($(xData.responseXML).find("Group[Name='Root Visitors']").length == 1) 

         { 

                       return "true";

         } 

      else

         {

HideTab();

                       return "false";

         }

       } 

     });

     });

}

 

function HideTab()

{

$("a.ms-cui-tt-a").each(function ()

{

var objTabTitle = $(this).parent().attr("id");

if(objTabTitle == "DemoHideRibbonTab-title")

{

$(this).parent().hide();

}

});

}

 

var ribbonSelected;

function checkRibbonState() {

       var id = $("li.ms-cui-tt-s").attr("id");

        if (ribbonSelected != id)

       { 

              ribbonSelected = id;

              checkIfUserIsInGroup();

       }

}

 

function beginCheckRibbon()

{

var checkRibbonStateInterval = setInterval("checkRibbonState()", 10);

 }

$(document).ready(function ()

{

        setTimeout("beginCheckRibbon()", 1000);

});

 

2.       Register the JQuery as a custom action on the relevant ribbon tab

Open the elements.xml file in which your custom ribbon tab is defined.

You have to register the JQuery scripts in the correct sequence.

Use the ScriptLink class to register the following scripts:

1.       The jquery-1.6.2.min.js script.

2.       The jquery.SPServices-0.6.2.js script.

3.       Your custom JQuery Hide Ribbon script. 

 

<CustomAction Id="JohanJQuery.Script" Location="ScriptLink" ScriptSrc ="/_layouts/HideRibbonSample/Scripts/jquery-1.6.2.min.js" Sequence="100"/>

 

<CustomAction Id="SPS_SERVICE_JohanJQuery.Script" Location="ScriptLink" ScriptSrc ="/_layouts/HideRibbonSample/Scripts/jquery.SPServices-0.6.2.js" Sequence="101"/>

 

<CustomAction Id="JohanHideTab_JohanJQuery.Script" Location="ScriptLink" ScriptSrc ="/_layouts/HideRibbonSample/Scripts/HideRibbonSample.js" Sequence="102"/> 

 

My complete Ribbon Tab definition with the script registration is as follows:

<?xml version="1.0" encoding="utf-8"?>

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <CustomAction

    Id="DemoHideRibbonTab"

    Location="CommandUI.Ribbon"

    RegistrationId="101"

    RegistrationType="List">

    <CommandUIExtension>

      <CommandUIDefinitions>

        <CommandUIDefinition

          Location="Ribbon.Tabs._children">

          <Tab Id="DemoHideRibbonTab" Title="Show or Hide Tab" Description="Show or Hide Tab" Sequence="501">

            <Scaling

              Id="DemoHideRibbonTab.Scaling">

              <MaxSize

                Id="DemoHideRibbonTab.OneLargeGroupMaxSize"

                GroupId="DemoHideRibbonTab.OneLargeGroupExample"

                Size="OneLarge"/>

            </Scaling>

         

            <Groups Id="DemoHideRibbonTab.GeneralControls.Groups">

              <Group

                Id="DemoHideRibbonTab.OneLargeGroupExample"

                Description="Contains custom controls"

                Title="Show Message"

                Sequence="55"

                Template="Ribbon.Templates.OneLarge">

                <Controls Id="DemoHideRibbonTab.OneLargeGroupExample.Controls">

                  <Button

                      Id="DemoHideRibbonTab.OneLargeGroupExample.Controls.Button"

                      LabelText="Show Message"

                      Image16by16="/_layouts/images/newtargetapp16.png"

                      Image32by32="/_layouts/images/newtargetapp32.png"

                      Command="COB.Command.SayHello"

                      Sequence="10"

                      TemplateAlias="custLarge1" />

                </Controls>

              </Group>

            </Groups>

          </Tab>

        </CommandUIDefinition>

        <CommandUIDefinition Location="Ribbon.Templates._children">

          <GroupTemplate Id="Ribbon.Templates.OneLarge">

            <Layout

              Title="OneLarge"

              LayoutTitle="OneLarge">

              <Section Alignment="Top" Type="OneRow">

                <Row>

                  <ControlRef DisplayMode="Large" TemplateAlias="custLarge1" />

                </Row>

              </Section>

            </Layout>

          </GroupTemplate>

        </CommandUIDefinition>

      </CommandUIDefinitions>

      <CommandUIHandlers>

        <CommandUIHandler

       Command="COB.Command.SayHello"

       CommandAction="javascript:alert('Hello World');" />

      </CommandUIHandlers>

    </CommandUIExtension>

  </CustomAction>

 

  <CustomAction Id="JohanJQuery.Script" Location="ScriptLink" ScriptSrc ="/_layouts/HideRibbonSample/Scripts/jquery-1.6.2.min.js" Sequence="100"/>

  <CustomAction Id="SPS_SERVICE_JohanJQuery.Script" Location="ScriptLink" ScriptSrc ="/_layouts/HideRibbonSample/Scripts/jquery.SPServices-0.6.2.js" Sequence="101"/>

  <CustomAction Id="JohanHideTab_JohanJQuery.Script" Location="ScriptLink" ScriptSrc ="/_layouts/HideRibbonSample/Scripts/HideRibbonSample.js" Sequence="102"/>

</Elements>

 

3.       Verify that it works fine

Build, Package and Deploy your custom ribbon feature.

Deactivate and Activate the feature in your site and refresh the SharePoint page on which the ribbon should appear (because the registration ID of my ribbon is ‘101’ the page which I should see the ribbon tab is http://demoweb/Shared%20Documents/Forms/AllItems.aspx.

If I am a member of the ‘Root Visitors’ group then the tab is visible.

clip_image005 

If I am not a member of the ‘Root Visitors’ group then the tab is not visible.

clip_image003

 

Enjoy!!

 

References:

Once again, thanks for the contributions made by members of the community.

Chris O’Brien: Ribbon Customizations

Tobias Lekman: Hiding Inactive Ribbon Commands in SharePoint 2010