Question

We have a project for which we are storing user profile photos in Sitecore. Our user base is going to be integrated with LDAP (meaning that we will have tens of thousands of users, if not more), and profiles will be created the first time a user logs in. Users will be able to change their profile photos later, and we have a customized Sitecore Profile, which has a property to store the ID of the profile photo media item.

What I am trying to do is figure out a way to avoid breaking the 100 item limit and store the photos in the Sitecore Media Library. We do not want to use item buckets, and we want to leverage Sitecore caching, so storing the images externally is out. I was thinking about a ten-level deep folder structure based on the username, but that is a bit dirty.

Does anyone have any suggestions that might help?

Thank you, in advance.

Sitecore 6.6

Was it helpful?

Solution

Avoiding breaking the 100 children limit is a very good practice and you should follow this for sure.

To achieve this in your scenario you definitely need some kind of folder structure. Creating such a kind of structure is not fun. You can automate it by adding you event handler to item:created event and move the newly created item automatically.

I've written quick code that should check if the current folder contains max 50 items and if not it tries to create additional folders with a single char as a name recursively and move the item to the folder.

You wrote that you're storing reference as ID so moving the item will not break reference.

Please have in my that I haven't tested the code so it might need tweaking.

<event name="item:created">
  <handler type="My.Assembly.Namespace.ProfilePhotoHandler, My.Assembly" method="OnItemCreated" />
</event>
protected void OnItemCreated(object sender, EventArgs args)
{
    ItemCreatedEventArgs eventArgs = Event.ExtractParameter(args, 0) as ItemCreatedEventArgs;

    if (eventArgs == null || eventArgs.Item == null)
        return;
    Item item = eventArgs.Item;

    if (item == null
        || !item.Paths.IsMediaItem
        || !item.Paths.FullPath.Contains("/profile-images/")
        || item.TemplateID.ToString() == "{FE5DD826-48C6-436D-B87A-7C4210C7413B}")

        // we want to move only media items in profile-images and not media folders
        return;

    string guid = item.ID.ToShortID().ToString();

    MoveItemToProperDirectory(guid, item, item.Parent, 0);
}

private void MoveItemToProperDirectory(string guid, Item item, Item folder, int level)
{
    if (folder.Children.Count < 1)
    {
        if (item.Parent.ID != folder.ID)
        {
            item.MoveTo(folder);
        }
        return;
    }

    using (new SecurityDisabler())
    {
        // take next letter from the hash or random char if the hash is too short
        string newSubfolderName = (level < guid.Length)
                                        ? guid[level].ToString()
                                        : ('a' + new Random((int)DateTime.Now.Ticks).Next(24)).ToString();

        Item subfolder = folder.Children.FirstOrDefault(c => c.Name == newSubfolderName);
        if (subfolder == null)
        {
            // create new Media Folder and move the item there
            subfolder = folder.Add(newSubfolderName, new TemplateID(ID.Parse("{FE5DD826-48C6-436D-B87A-7C4210C7413B}")));
        }
        MoveItemToProperDirectory(guid, item, subfolder, level + 1);
    }
}

OTHER TIPS

If somehow an update is not an option, you could consider the following: The images are not used by content editors, thus from the content editor, the items are not used. This makes it possible to hide the node that contains the images, just like the buckets do. Combining this with a folder structure (created during import, or in the handles) makes a good solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top