Locator Tool and Index Blocks

Justin "JET" Turner's Avatar

Justin "JET" Turner

27 Feb, 2014 03:39 PM

Below is the code I am using to access an index block and the properties I get back. It appears that there isn't a way to find the list of indexed content from an index block. Is this correct, or am I missing something?

#set($profilePhotos = $_.locateBlock("/_blocks/hidden/Profile Photos", $currentPageSiteName))
$_PropertyTool.outputProperties($profilePhotos)
Object type: com.hannonhill.cascade.api.adapters.IndexBlockAPIAdapter
Properties:
 - lastModified: Date
 - identifer: Identifier
 - identifier: PathIdentifier
 - parentFolder: Folder
 - path: String
 - isUserCanWrite(String): boolean
 - lastModifiedBy: String
 - currentUserCanRead: boolean
 - currentUserCanWrite: boolean
 - isUserCanRead(String): boolean
 - createdOn: Date
 - hideSystemName: boolean
 - siteName: String
 - metadata: Metadata
 - siteId: String
 - folderOrder: int
 - name: String
 - parentFolderIdentifier: PathIdentifier
 - createdBy: String

A little bit about what we are doing. We have facstaff profile pages in every site. There are also images uploaded in those sites for those profiles. We are using an index block to gather all the images together, and this index block is attached to each profile page. We use a custom metadata field to match the image with the page. This has been working fairly well, but when building department listings, it is rather slow due to calling the same index block for every page. The department listing index block ends up having 30+ copies of the image index block content, and thus runs rather slowly.

I would like to rewrite everything to use the locator tool to get the images index block, preventing it from needing to be in the page data definition, and thus trimming down the department listing index block.

I would be open to alternatives that allow me to build the same list of images as the index block would using the locator tool if it would be fast enough (find all files in a given folder).

  1. 1 Posted by Ryan Griffith on 27 Feb, 2014 03:58 PM

    Ryan Griffith's Avatar

    Hi Justin,

    You are correct in that the Locator Tool does not return the contents of an Index Block, it can be used to traverse down through the base folder and children, though.

    Looking over your description, I have a couple of possible ideas:

    • Can you simply add file choosers to the faculty pages to choose the image?
    • Could you add the path to the file (or page depending on which way you want to go) and use the Locator Tool to access the asset at that path?
      • Piggy backing on that, if using a path is not feasible, can you build out the path dynamically using the metadata field?

    On a side note, we are currently working on adding search functionality to the Locator Tool and I think that would work wonderfully in this case. Unfortunately, I do not have an ETA on when that will be implemented in a release.

    Please let me know if you have any questions.

    Thanks!

  2. 2 Posted by Justin "JE... on 27 Feb, 2014 04:14 PM

    Justin "JET" Turner's Avatar

    Our asset factory for profile photos does some image resizing, but only forces a specific width.
    So, having the content editors pick both resized versions of the image was determined to be a potential problem, and so they wanted a more automatic version.
    So, the pages and images have an identical metadata field where they input the users email address, and we compare these to match the images with the page, then render the appropriate sized ones in different places.

    So, I know all the images are in _uploads/images/profile/ but the images aren't named consistently enough to programmatically figure out which one to use.

    Example images:

    398-125x175.jpg
    398-62x86.jpg
    398.jpg
    AllisonClapp-3-125x144.jpg
    AllisonClapp-3-62x71.jpg
    AllisonClapp-3.jpg
    

    Would it be possible to use the locator tool to build an array of all the images in that specific folder? Basically building the index block on the fly, or would that be extremely slow with sometimes 90+ images?

  3. 3 Posted by Ryan Griffith on 27 Feb, 2014 04:28 PM

    Ryan Griffith's Avatar

    Thank you for clarifying, Justin. I can definitely see how my wouldn't be feasible.

    Would it be possible to use the locator tool to build an array of all the images in that specific folder?

    You certainly can. Assuming the path for the folder will always be the same, you can loop over the children within the folder (ie the Image assets) and match up the dynamic metadata field with the one from the calling page and maybe record the images that do match. It's not cached like an Index Block, but might still be fairly quick.

    Please let me know if you have any questions.

    Thanks!

  4. 4 Posted by Justin "JE... on 27 Feb, 2014 05:40 PM

    Justin "JET" Turner's Avatar

    Out of 90 images, this produces the 1 I need for a single page without any real lag time.

    I'll probably do a modified version where I store the username and link in an array for the department listing, so I don't use the locator tool 90+ times for each person in the department, as I think searching through an array will be faster than the locator tool is

    #set($profilePhotos = $_.locateFolder("/_uploads/images/profile", $currentPageSiteName))
    #foreach($children in $profilePhotos.children)
        #foreach($dynamic in $children.metadata.dynamicFields)
            #if($dynamic.name == "username" && $username.value.toLowerCase() == $dynamic.value.toLowerCase())
                #set($test = $_StringTool.substringAfter($children.link,"-125x"))
                #if($test != "")
                    ${children.link}
                #end
            #end
        #end
    #end
    
  5. 5 Posted by Ryan Griffith on 27 Feb, 2014 06:44 PM

    Ryan Griffith's Avatar

    Yep, you are definitely on the right track.

    I would suggest using a Map so you can create a lookup table of name and link. Something like the following:

    ## Initialize the map
    #set ($map = {})
    
    ...
    
    ## Add an item to the map. Save the result in a dummy variable so it's not displayed.
    #set($_void = $map.put($name.value, $link.value))
    
    ...
    
    ## Retrieve an item from the map
    #if ($map.containsKey("name"))
        $map.get("name")
    #end
    

    Please let me know if you have any questions.

    Thanks!

  6. 6 Posted by Justin "JE... on 28 Feb, 2014 03:51 PM

    Justin "JET" Turner's Avatar

    For our department listings and main campus directory, we build a PHP include file with the pieces of the profile used in those places. To do this, we aggregate an index block from each site into a single page.

    So, the code to get our images now looks like the following.
    The $subItems[0] is the first page in the index block. We use that to get the site name so we can get all the images for the profiles from that site.
    I then store all 3 images in the $profilePhotos map with an additional tag for the size.

    #set($profilePhotos = {})
    #set($profileFolder = $_.locateFolder("/_uploads/images/profile", $subItems[0].getChild('site').value))
    #foreach($child in $profileFolder.children)
        #foreach($dynamic in $child.metadata.dynamicFields)
            #if($dynamic.name == "username" && $dynamic.value != "")
                #set($tempName = "${dynamic.value.toLowerCase()}")
                #set($test = $_StringTool.substringAfter($child.link,"-125x"))
                #if($test != "")
                    #set($tempName = "${tempName}-125")
                #else
                    #set($test = $_StringTool.substringAfter($child.link,"-62x"))
                    #if($test != "")
                        #set($tempName = "${tempName}-62")
                    #end
                #end
                #set($_void = $profilePhotos.put($tempName, $child.link))
            #end
        #end
    #end
    

    Then, to retrieve the images at the correct place in the process, we use the following. The passthrough commands help prevent extra white space and prevent the system from changing the < and > signs.

    #if($profilePhotos.containsKey("${email.toLowerCase()}-125"))<!--#passthrough-top
        ,"image125" => '[system-asset]${profilePhotos.get("${email.toLowerCase()}-125")}[/system-asset]'#passthrough-top-->
    #end
    #if($profilePhotos.containsKey("${email.toLowerCase()}-62"))<!--#passthrough-top
        ,"image62" => '[system-asset]${profilePhotos.get("${email.toLowerCase()}-62")}[/system-asset]'#passthrough-top-->
    #end
    #if($profilePhotos.containsKey("${email.toLowerCase()}"))<!--#passthrough-top
        ,"image" => '[system-asset]${profilePhotos.get("${email.toLowerCase()}")}[/system-asset]'#passthrough-top-->
    #end
    
  7. 7 Posted by Ryan Griffith on 28 Feb, 2014 04:31 PM

    Ryan Griffith's Avatar

    That looks good, Justin. I am glad to hear the Map direction is working out.

    Hopefully if the search functionality I mentioned is implemented for the Locator Tool you will be able to further simplify all of this.

  8. Justin "JET" Turner closed this discussion on 28 Feb, 2014 06:58 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac