20
5 Unbelievable Tricks to Help You COPE Eric L. Epps, Sauk Valley Community College @ericepps #CUC15 #COPEtricks Which Hannon Hill Employee Are You?

5 Unbelievable Tricks to Help You COPE

Embed Size (px)

Citation preview

5 Unbelievable Tricks to Help You COPEEric L. Epps, Sauk Valley Community College@ericepps #CUC15 #COPEtricksWhich Hannon Hill Employee Are You?

COPE, of course, stands for Create Once, Publish Everywhere, one of the core reasons to use a content management system, especially Cascade Server. Today, I want to look at some key concepts and techniques that have helped me COPE with content over the years.

If everything works correctly, Ill be posting links throughout the session with the hashtag #COPEtricks, so feel free to follow along or check those out afterwards

This is going to be part historical, part technical, as I explore some of the key techniques Ive discovered or developed to re-use content--whether that content be traditional web page content or system assets like formats. Its a mix of concepts, techniques, and code, so I hope there will be a little something for everyone. Please feel free to stop me at any time with questions, and I hope we can have some time at the end for you to share your own favorite COPEing mechanisms.

To start off, let me share a little about my context to explain why this has been so critical for me. Im Web Developer at Sauk Valley Community College. Heres a picture of our campus, which looks pretty rural, but if we zoom out a little bit.it looks even more rural. Were definitely one of the smaller Cascade sites.[twitter]Follow #CUC15 or #COPETricks for related links (if it works right!)[/twitter]

To start off, let me share a little about my context to explain why this has been so critical for me. Im Web Developer at Sauk Valley Community College. Heres a picture of our campus, which looks pretty rural, but if we zoom out a little bit.it looks even more rural. Were definitely one of the smaller Cascade sites.

So I wear several different hats--webmaster, campus display signage, mobile app, document imaging system, other duties as assigned--which comes with some challenges and benefits. Since I touch so many areas, I have an ability to look for where content can be re-used. But I also have a real need to make that process as efficient as possible. In larger institutions, you still have a need to be efficient and re-use content, but with the added need to share that content among several developers and departments.

1. Its not about the web page(Cascade as a data warehouse)

When I started using Cascade Server, back in version 4.7 (which boasted Internet Explorer 7 support!), I remember being frustrated by how complicated it was to build a simple web page. So, I love coffee, perhaps a little too much, and roast my own. If I have roasted some coffee beans and want to give you some, the easiest way is for me to put it in a bag and give it to you. Right? No need for any other steps.

But we do have some limitations, dont we? We have to be nearby. We need to be able to carry the package. So, if I have 100,000 pounds of coffee to distribute nationwide, Im going to need to add some steps. If that coffee comes from a hundred different sources, more steps. Im going to need a warehouse, a distribution center.

One of the key realizations for me was when I stopped thinking of Cascade Server as a program to make web pages and started thinking of it as a data warehouse. Im going to be collecting data from a lot of different sources--user generated in Cascade, XML feeds, APIs, user generated from outside Cascade, wherever I can get it. Some of that will need to be repackaged, transformed, filtered, then I can send it out to wherever it needs to go.

In one sense, this is hardly revolutionary, but looking at Cascade this way is a key to unlocking Cascades full potential.

2. Ultimate set of tools(Take advantage of Cascade tools)

Data Definition Smart Fields

First is Smart Fields in Data Definitions. In addition to making Data Definitions much easier to use for the end user, having the ability to hide part of a form makes it easier to reuse that Data Definition elsewhere. The general idea is that you can show or hide sections of a form based on a box, checkbox, or radio button. Again, this makes life much easier for content creators, and since you have to select whether a particular section is shown or hidden, you can easily show or hide that section in your Velocity or XSLT Format based on that value.

Data Definition Smart FieldsContent Types/Content Type Publishing

[twitter]Content Type publish sets: idea http://bit.ly/cuc15-ctpublishidea, code http://bit.ly/cuc15-ctpublishcode #CUC15 #COPETricks[/twitter]Second up is Content Types. Many of you may not been around for the dark ages before the Content Type, but the ability to group together all of a particular type of page regardless of their location is great. So, once you have a content type, you can use a Content Type Index Block or the Query API to get a list of all assets and further filter and display them. I have a listing of committees and their minutes in our Intranet; before Content Types, I had to remember to manually add each index page to the publish set every time a new committee was added. Now, its a Committee Index Content Type, and I can use Web Services to update the publish set automatically whenever a new committee is added. Theres also an idea in the Idea Exchange to make this an option in the native Publish Set, so a shameless plug to vote for that idea and make my Web Services script obsolete.

Data Definition Smart FieldsContent Types/Content Type PublishingXSL Page Transforms

Third is a technique I learned from Jay Mercer in my first ever User Conference session. He talked about XSLT Page Transforms and his Identity Transform. This has eliminated much of my need to write new templates by essentially giving access to the entire page from within the DEFAULT page region. The Identity Transform just loops through and replicates the entire XHTML page *after* all the regions have been processed. You can then add whatever templates you want to modify the processed XHTML. For example, if I want to append the current month and year to the element for all news releases, I just add an element with a class=addToTitle which I move to the element and remove from the DEFAULT region. Or, I can take any link with a class=proxy and run that link through EZ-Proxy. Or I can define an element in any region of the document and move it to the document by adding a class of moveToHead. This dramatically reduces the number of modifications I need to make to Templates and the number of new Templates I have to make. Jay, thank you, thank you, thank you.

Data Definition Smart FieldsContent Types/Content Type PublishingXSL Page TransformsWeb Services

Fourth is too big of a topic to do more than a passing mention, but nothing has supercharged my ability to manage and automate Cascade more than Web Services. Theres just no substitute for being able to set a cron job to create and modify content in batches and daily, weekly, or whatever.

Data Definition Smart FieldsContent Types/Content Type PublishingXSL Page TransformsWeb ServicesVelocity Script Tools(Velocity Includes, Locator Tool, Query API)

[twitter]Cascade Velocity Tools http://www.hannonhill.com/kb/Script-Formats/ #CUC15 #COPETricks[/twitter]Finally in my ultimate set of tools is Velocity Script Tools, especially Includes, Locator Tool, and Query API. Well use this many more times in all the rest of the presentation, but Velocity offers many tools to streamline your code. One of the most useful has been Velocity Includes, allowing me to define code used repeatedly as a Velocimacro in a shared Velocity format. Our course schedules are maintained in Cascade, and include several different filtered views (for example, night classes, friday classes, listing by department) but theyre all displayed in a common format. I used to have to edit each individual Format for every change to that format. Once I rewrote them in Velocity, I can modify that display table code once and update all those pages. Saves a ton of time.Locator Tool often saves me from needing to include a block as part of the Data Definition. Often, to get additional information, Id need to include a huge Block in the Data Definition and hide it from end-users. This way, I can have smaller blocks and reference them just in the Format (which also makes them easier to change out). Again, well be coming back and looking at some more examples later.I havent used the Query API much yet, but it similarly has the ability to be a more efficient way to access pages than attaching an index block and another format. Instead, the results can be filtered ahead of time and all from one Format.

3. Give me all the XML(APIs to XML using Web Services)

One of the things the Locator Tool opened up was the ability to easily open a block from within a script. This means its a lot easier to pull in just the block I want. All I need to know is the name and path--which I can reliably predict if Im using Web Services to create the blocks.

$restURL = 'https://api.somesite.com?apikey={{secret}}';

$returnJSON = file_get_contents($restURL);

createXMLBlock($cascade, $auth,'/parent/folder', 'theAssetName', $siteName, $returnJSON,'json');foreach($values as $value) {

$restURL = https://api.somesite.com?apikey={{secret}}&value=' . $value;

$returnXML = file_get_contents($restURL);

createXMLBlock($cascade, $auth, '/parent/folder', $value, $siteName, $returnXML,'xml');}

[twitter]Idea - Locator Tool access to Feed Block XML http://bit.ly/cuc15-feedblocks[/twitter]At the same time, its becoming more and more common for web apps to expose data via an API. Ive seen REST APIs most commonly, and theyre among the easiest to work with, so well use them for a couple examples. REST usually returns XML, JSON, or text. Of course, Cascade is great with XML, text can easily be wrapped in XML tags, and JSON can be pretty easily converted to XML. So all we need to do is use Web Services to access the REST API and store the result in an XML block. Time for another shameless plug: theres an idea on the Idea Exchange, too, to allow the Locator Tool to access the XML of a Feed Block, which could even eliminate this step in many cases and allow the most up-to-date data at publish time.

$restURL = 'https://api.data.gov/ed/collegescorecard/v1/schools.json? id=148672,147703&_fields=school.name,school.city,school.state,id&api_key={{secret}}';

$scJSON = file_get_contents($restURL);

createXMLBlock($cascade,$auth, '/-blocks/CareerOneStop', 'scorecard', $siteName, $scJSON,'json');foreach($socCodes as $value) {

$socCode = str_replace(-,'',$value);

$restURL = 'http://www.careerinfonet.org/webservices/occwages_webservice/occwagesservice.asmx/GetWagesByZip?userID='.$apiKey.'&soccode='.$socCode.'&zip='.$zipCode;

$wagesXML = file_get_contents($restURL);

createXMLBlock($cascade,$auth, '/-blocks/CareerOneStop/Wage', $value, $siteName, $wagesXML,xml');}http://bit.ly/cuc15-restapi (GitHub)

[twitter]Import REST API results into Cascade http://bit.ly/cuc15-restapi #CUC15 #COPEtricks[/twitter]

[twitter]Import Acalog course catalog into Cascade http://bit.ly/cuc15-acalog #CUC15 #COPEtricks[/twitter]

4. A Brick Within a Block Within a ShortCode(Bricks and ShortCodes)

#set ( $sib = $_XPathTool.selectSingleNode($contentRoot, "/system-index-block) )#set ( $bricks = $_XPathTool.selectNodes($sib, "system-page/system-data-structure/brick") )#macro ( useBricks $contentString ) #set ( $string = $contentString ) #foreach ( $item in $bricks ) #set ( $var = "\[" + $_EscapeTool.xml($item.getChild("name").value) + "\]" ) #set ( $val = $_EscapeTool.xml($item.getChild("value").value) ) #set ( $string = $string.replaceAll($var, $val) ) #end ${string}#end#set ( $page = $_XPathTool.selectSingleNode($sib, "calling-page/system-page") )#set ( $content = $_SerializerTool.serialize($page.getChild("page-xhtml"), true) )#useBricks($content)Bricks

[twitter]Hannon Hill Bricks example http://bit.ly/cuc15-brick #CUC15 #COPEtricks[/twitter]

[getBlock type="xhtml" path="/absolute/path/to/block" site=siteName"][getBlock type="xhtml" path="/absolute/path/to/block" site="siteName" replace="textreplacement1 textreplacement2" textreplacement1="value to display #1" textreplacement2="value to display #2]

(will replace the string "[|[textreplacement1]|]" in the block with "value to display #1" and "[|[textreplacement2]|]" with "value to display #2)http://bit.ly/cuc15-shortcode (GitHub)

5. Better together(Content Layering)

Faculty/Staff Websites

Program Pages

Thank [email protected]/ericepps