Blog

v5.2

Since the name change from Sava CMS to Mura CMS (effectively the release of Mura CMS 5.1), a lot has gone into making Mura CMS more useful, more usable and more flexible. Today, we're announcing Mura CMS 5.2 to consolidate those improvements with a few new ones, including the first step in migrating the Mura CMS admin from the Fusebox framework to Sean Corfield's FW/1 framework. Here's a list of the most important new features you'll find in the next release of Mura CMS:

  • Improved Front-End Editing - direct access for components, forms, local content indexes and more
  • Copy All/Delete All in the Site Manager - copy/paste entire sections of your site
    This feature has been a long time coming for Mura CMS and it's literally, exactly what it sounds like. It allows you to copy and delete entire sections of content within the Mura CMS Site Manager. Previously, deleting a page (or any other content node) in Mura would only delete the page itself, allowing any child pages to move up to where the parent previously lived in the site structure. This could be both a feature (making it easy to move content by moving a single node and then deleting it) or a bug because there was no way to mass delete content. Since this seemed more bug than feature, we decided to make moving content and deleting content both easier by adding a way to do each.
  • Site Copy - make an exact copy of an existing site, content and all
  • Improved Caching
    This last year we implemented a simple caching strategy for Mura that hooks into Java's soft reference caching. It's chore when enabled is to store display object information on a per page request level. This is very important for those traffic intensive sites.

    Our goal is to supply the common developer with different caching strategies (LRU, memCache, etc) based on their overall needs and goals.
  • H1/H2 to Toggle Page Title Markup for your preferred SEO approach
  • NEW Admin Framework: Sean Corfield’s FW/1
    Many of you developers out there know that Mura's admin is built upon fusebox. Fusebox has been a great framework to use and has suited our needs quite well. But over the last few years as we have implmented Mura in multiple environments we have noticed that fusebox actually caused more harm than good when it came to Mura's needs.

    Noticing this we decided to look at other frameworks out there (Coldbox by Luis Majano, FW/1 by Sean Corfield, etc) in the hope of giving us a new direction to take as well as new patterns to follow. In the end we decided to use Sean Corfields FW/1 framework. It's simple, lightweight and strait forwards. Just want Mura needed.

    Functionality is still the same overall, but if you have customized the admin to work with anything fusebox centric then you could easly have some issues. Looking forward and seeing this as a potential hazard we have built out instructions which will allow you to revert the admin to use fusebox once again. It's important to note though that from v5.2 on updates to the admin console will be FW/1 centric, not fusebox centric. So we encourage you to review any custom admin colsole changes you have made and migrate them to FW/1 accordingly.

    {should write about how we are using the attributes scope?}

    We are excited about this move to FW/1 and have plans to use it as our framework of choice when it comes to building out plugins.
  • Improved Plugin API: Mappings (Req's/Plugins)
  • New Content Iterator

    Mura 5.2 also has api enhancements for programatically working with content in Mura. With the new content iterators and new improved bean methods we were able to make managing content and users simpler. Here are some examples:

    The New Content Iterator

    ContentBean.getKidsIterator()
    <!--- Read out an existing node from the default site.---> 
    <cfset content=application.contentManager.getActiveContentByFilename('blog','default')>

    <!--- Pull out a content iterator of the nodes child content.--->
    <cfset it=content.getKidsIterator()>

    <!--- The number of Items to be listed is determined by the content.getNextN() value. It's default is 10. --->
    <cfset it.setPage(1)>

    <!--- You can also set the start row instead of setting a page number. --->
    <cfset it.setStartRow(1)>
    <cfloop from="1" to="#it.pageCount()#" index="p">
    <cfset it.setPage(p)>
    <cfoutput><h2>Page #p#</h2></cfoutput>
    <!--- Iterate throught the child content.
    The it.hasNext() will return true until the page length
    as determined by the content.getNextN() has been reached --->
    <cfloop condition="it.hasNext()"> <!--- The it.next() method returns a new contentNavBean. It acts as a facade to data into the wrapped query while digging into the full bean when needed. --->
    <cfset sub1=it.next()>
    <cfoutput>
    #it.currentIndex()#:#sub1.getMenuTitle()#</br>
    </cfoutput>
    </cfloop> </cfloop>

    FeedBean.getIterator()

    You can also get the same iterator from local content indexes:

    <!--- Pull a index by it's name with the newfeedManager.readByName() method. This example is pulling alocal index named "documents" from the default site.---><cfset feed=application.feedManager.readByName('documents','default')><cfset it=feed.getIterator()><h2><cfoutput>#feed.getName()#</cfoutput></h2><cfif it.recordCount()><!--- Iterate throught the child content ---><cfloop condition="it.hasNext()"><cfset subContent=it.next()><cfoutput>#it.currentIndex()#: #subContent.getMenutitle()#</br></cfoutput></cfloop></cfif>
    Wrap an Existing Query

    You can also wrap any existing query that contains contentID and siteID or contentHistID and siteID and start iterating.

    <cfquery name="rsExample">select content,siteID from tcontent where .....</cfquery><cfset it=application.serviceFactory.getBean("contentIterator")><cfset it.setQuery(rsExample)/><!--- Now Iterate and pull attributes that aren't in the query ---><cfloop condition="it.hasNext()"><cfset content=it.next()><cfoutput>#it.currentIndex()#: #content.getMenutitle()# - #content.getCustomVar()#</br></cfoutput>
    You Can Event Start with a List
    <cfset it=application.serviceFactory.getBean("contentIterator")><cfset it.BuildQueryFromList("423AC11B-3DB8-49EF-B411A2FB008CAB1E,423AC11B-3DB8-49EF-B411A2FB008CABAS","default")><!--- Now Iterate ---><cfloop condition="it.hasNext()"><cfset content=it.next()><cfoutput>#it.currentIndex()#: #content.getMenutitle()# - #content.getCustomVar()#</br></cfoutput>

    Simpler Way to Manage Beans

    Many beans in Mura now have direct methods for saving and deleting content instead of having to always submitting to it's appropriate service manager.

    contentBean.save()contentBean.delete()contentBean.deleteVersion()contentBean.deleteVersionHistory()contentBean.getKidsQuery()contentBean.getKidsIterator()contentBean.getRelatedContentQuery()contentBean.getRelatedContentIterator()contentBean.getVersionHistoryQuery()contentBean.getVersionHistoryIterator()contentBean.getCategoriesQuery()
    userBean.save()userBean.delete()<!--- Get members[returnType] returns usersthat belong to this use.For example if this user.getType() equas 1then it is a group and it would return it's members--->userBean.getMembersQuery()userBean.getMembersIterator()<!--- getMemberships[returnType] returns groups towhich this user belongs --->userBean.getMembershipsQuery()userBean.getMembershipsIterator()userBean.getAddressesQuery()userBean.getAddressesIterator()addressBean.save()addressBean.delete()
    feedBean.save()feedBean.delete()feedBean.getQuery()feedBean.getIterator()
  • New Event Hooks

    With Mura 5.2 you now have an expanded number of events available. They easily allow developers to target specific aspects of the Mura application flow.  In each event your are provided with an event object which contains relevant data to the specific event occurrence. 

    USER
    ------------------
    onBeforeUserUpdate
    onBeforeUserCreate
    onBeforeUserSave
    onBeforeUser{subType}Update
    onBeforeUser{subType}Create
    onBeforeUser{subType}Save

    onUserUpdate
    onUserCreate
    onUserSave
    onUser{subType}Update
    onUser{subType}Create
    onUser{subType}Save
    onAfterUserUpdate
    onAfterUserCreate
    onAfterUserSave
    onAfterUser{subType}Update
    onAfterUser{subType}Create
    onAfterUser{subType}Save

    onBeforeGroupUpdate
    onBeforeGroupCreate
    onBeforeGroupSave
    onBeforeGroup{subType}Update
    onBeforeGroup{subType}Create
    onBeforeGroup{subType}Save

    onGroupUpdate
    onGroupCreate
    onGroupSave
    onGroup{subType}Update
    onGroup{subType}Create
    onGroup{subType}Save
    onAfterGroupUpdate
    onAfterGroupCreate
    onAfterGroupSave
    onAfterGroup{subType}Update
    onAfterGroup{subType}Create
    onAfterGroup{subType}Save

    onGroupEdit (renders as a tab when editing a group)
    onUserEdit (renders as a tab when editing a User)


    LOGIN
    -----------
    onSiteLogin
    onGlobalLogin
    onSiteLoginSuccess
    onGlobalLoginSuccess
    onSiteLoginBlocked
    onGlobalLoginBlocked


    CONTENT
    ----------------
    Note: Node Level events only fire for node level content nodes (ie. Page, Portal, Gallery, File, Calendar, Gallery)
    onBeforeContentSave (Node Level Only)
    onBefore{type}Save
    onBefore{type}{subType}Save
    on{type}Save
    on{type}{subType}Save
    onAfter{type}Save
    onAfter{type}{subType}Save
    onAfterContentSave (Node Level Only)
    onContentSave (Node Level Only)

    onContentDelete (Node Level Only)
    onBeforeContentDelete (Node Level Only)
    on{type}delete
    onBefore{type}delete
    on{type}{subType}delete
    onBefore{type}{subType}delete
    onAfterContentDelete (Node Level Only)
    onAfter{type}delete
    onAfter{type}{subType}delete

    onContentDeleteVersionHistory (Node Level Only)
    onBeforeContentDeleteVersionHistory (Node Level Only)
    on{type}DeleteVersionHistory
    onBefore{type}DeleteVersionHistory
    on{type}{subType}DeleteVersionHistory
    onBefore{type}{subType}DeleteVersionHistory
    onAfterDeleteVersionHistory (Node Level Only)
    onAfter{type}DeleteVersionHistory
    onAfter{type}{subType}DeleteVersionHistory

    onContentDeleteVersion (Node Level Only)
    onBeforeContentDeleteVersion (Node Level Only)
    onBefore{type}ContentDeleteVersion
    onBefore{type}{subType}ContentDeleteVersion
    onAfterContentDeleteVersion (Node Level Only)
    onAfter{type}ContentDeleteVersion (Node Level Only)
    onAfter{type}{subType}ContentDeleteVersion

    onContentEdit (Node Level Only) (renders as a tab when editing a User)

    CATEGORY
    -----------
    onBeforeCategoryUpdate
    onBeforeCategoryCreate
    onBeforeCategorySave
    onBeforeCategoryDelete

    onCategoryUpdate
    onCategoryCreate
    onCategoryDelete
    onCategorySave
    onAfterCategoryUpdate
    onAfterCategoryCreate
    onAfterCategorySave
    onAfterCategoryDelete


    FEED
    -----------
    onBeforeFeedUpdate
    onBeforeFeedCreate
    onBeforeFeedSave
    onBeforeFeedDelete

    onFeedUpdate
    onFeedCreate
    onFeedDelete
    onFeedSave
    onAfterFeedUpdate
    onAfterFeedCreate
    onAfterFeedSave
    onAfterFeedDelete


    RENDERING
    ---------------
    onSiteEditProfileRender
    onSiteSearchRender
    onSiteLoginPromptRender
    onContentOffLineRender
    onContentDenialRender
    on{type}{subType}BodyRender
    on{type}BodyRender
    onDashboardPrimaryTop
    onDashboardPrimaryBottom
    onDashboardSidebarTop
    onDashboardSidebarBottom
    onFEToolbarAdd (renders in front end toolbar add list)

    SYSTEM:
    ---------------
    onApplicationLoad
    onSiteDeploy
    onBeforeSiteDeploy
    onAfterSiteDeploy
    onSiteRequestInit
    onSiteRequestStart
    onSiteRequestEnd
    onGlobalRequestStart
    onGlobalRequestEnd
    onGlobalSessionStart

    FRONT END APPLICATION FLOW EVENTS

    GENERAL EVENTS
    --------------------
    onRenderStart
    onRenderEnd


    Handlers, Validators and Translators are special events that control front end business logic implementations.

    TRANSLATORS
    --------------
    standardFileTranslator
    standardHTMLTraslator
    standardLinkTranslator

    HANDLERS
    ---------------
    standard404Handler
    standardDoActionsHandler
    standardDoResponseHandler
    standardFileTranslationHandler
    standardForceSSLHandler
    standardLinkTranslationHandler
    standardPostLogoutHandler
    standardRequireLoginHandler
    standardSetAdTrackingHandler
    standardSetContentHandler
    standardSetContentRendererHandler
    standardSetIsOnDisplayHandler
    standardSetLocaleHandler
    standardSetPermissionsHandler
    standardSetPreviewHandler
    standardTrackSessionHandler
    standardTranslationHandler
    standardWrongDomainHandler

    VALIDATORS
    ----------------
    standard404Validator
    standardForceSSLValidator
    standardRequireLoginValidator
    standardTrackSessionValidator
    standardWrongDomainValidator
  • Bean Hooks: Save, Delete, Extended Attributes
    There are some cool new features within our beans now. Each core bean has CRUD related methods which allow you to easily create, update and delete records within the database. So instead of relying on managers to do such work, you now only need to rely on the bean. Simple, easy and powerful.

    loadBy({properties}): Give you the ability to load persistant data from the database based on properties passed.
    Example:
    // create a new bean
    bean = event.getBean( "user" );
    // load the bean with data
    bean.loadBy( userid=11223344 );

    getValue({property}): This method has been expanded to automatically pull extended attribute values if they exist against the bean. Not more needing to use getExtendedAttribute (it's still in there though on case you rely on it)
    Example:
    // create a new bean
    bean = event.getBean( "user" );
    // load the bean with data
    bean.loadBy( userid=11223344 );
    // let's get some data
    attributeValue = bean.getValue( "extendedAttributeA" );

    setValue({property}, {value}): This method has been expanded to allow setting of extended attributes. No more needing to figure out extend set id's, etc
    Example:
    // create a new bean
    bean = event.getBean( "user" );
    // load the bean with data
    bean.loadBy( userid=11223344 );
    // set extended information
    bean.setValue( "extendedAttributeA", "value" );
    // save the record
    bean.save();

    save(): The save method is quite simple. If you want to save the data in the bean to the database (add or update) just call this method.
    Example:
    // create a new bean
    bean = event.getBean( "user" );
    // load the bean with data
    bean.loadBy( userid=11223344 );
    // set extended information
    bean.setValue( "extendedAttributeA", "value" );
    // save the record
    bean.save();

    delete(): As long as the data is persitent, when you call this method it will delete the record from the database.
    Example: bean.delete()
    // create a new bean
    bean = event.getBean( "user" );
    // load the bean with data
    bean.loadBy( userid=11223344 );
    // let's delete the record
    bean.delete();

    In the future we plan on make beans more extendable, allowing developers to create custom types similar to how extended attributes currently work within Mura.
  • Remote Proxy
    Just a few months back we entertained the idea of building a remote proxy that would give outside applications the ability to hook into Mura for content manipulation. The first version of this has come into fruition in Mura v5.2. With it you can add, edit and delete content quickly and securely.

    Here is how you can use the proxy:

    One of our goals with this feature is to encourage community collaboration on current and future Mura features. So take a peek and give us your thoughts. 

Each of these was discussed in the first episode of the Mura Show so if you'd like more info on any of these, it's covered in the 15 or 20 minutes, as well as in a couple of recent blog posts. We'll be blogging about each of the new features over the next few weeks - check back for more details. We've also updated the documentation to reflect some of these revisions and will be adding more. 

Also, we are opening our documentation to the Mura CMS Community if you'd like to contribute. Please Contact Us if you're interested and we'll set you up.

Mura CMS 5.2 will be released in early 2010.

Comments

Post a Comment

Required Field