Concrete5 Mandatory Custom Attributes

Posted on: 17 December 2014

I've built a few sites now using the Concrete5 CMS, and on the whole I really love working with it. It provides a whole heap of really nice user-facing functionality out of the box, and makes it really easy to add your own. However, today I had to build something which seems routine and trivial, and found no way to do it.

Concrete5 makes it really easy to define new page types, and to attach custom attributes to those pages (such as text inputs, files, checkboxes, etc). It then exposes these in a really nice UI called Composer which we can hand over to customers. Unfortunately there's no way to make any of these custom attributes mandatory. Oddly, there's a very similar mechanism to add custom attributes to user profiles, and this process does allow you to specify if these attributes are mandatory. But you can't for custom attributes on pages. Go figure.

So, my first option is to work out how to modify the core system to support required custom attributes on pages, then contribute that back to the main project. Sadly, I don't have time (or more importantly, the skills and knowledge) for that option.

Instead, I looked at somehow injecting some Javascript validation into Composer. The cleanest way to add content into Composer is by adding more attributes, so I explored creating a custom attribute which would have no user interface, but would add some Javascript to check that all those custom attributes had been populated.

The hardest part was working out what the custom attributes on the page are. If you know the page type, it's pretty easy:

$ct = Concrete5_Model_CollectionType::getByHandle($pageType);
$customAttributes = $ct->getComposerContentItems();

However, the clean encapsulation of Concrete5 means that within my new validator attribute, I don't know which type of page I'm on. This is technically a good thing, but kind of awkward for this particular use case. I've worked around it by using the attribute handle to tell me which page type needs to be validated. It's a bit untidy, but works well.

The validator consists of two parts:

  • controller.php - gets the page type from the attribute handle, and builds a list of the custom attributes to be validated
  • form.php - injects the javascript to validate each of the custom attributes

You can grab the code from github if this sounds like something you could use.