Stand With Ukraine. Stop Putin. Stop War.

Hello! Welcome to my humble web presence. I'm Mark Hamstra, 32 years young, wearer of many hats at modmore, resident of Leeuwarden, the Netherlands. Most of my time is spent building and maintaining awesome extras and tools at modmore, but I also love gaming, cooking, and my dogs. More about me.

This site is where I share thoughts, cool projects and other oddities related to MODX, xPDO and ExtJS. I also write about MODX regularly over at Sometimes I post three blogs in a week, sometimes there's nothing new here in a year. Read a random article.

As of MODX Revolution 2.2, developers are handed class-based processors to speed up development of the back-end components. These are great, and I have blogged about Class Based Processors in general before with some quick examples, but in this article we'll dive into a particularly awesome one: modObjectGetListProcessor.

The modObjectGetList processor is mostly used for populating grids through the modExt Grid implementation, but you could also use it for any other widget that uses a JSON Data Store. And processors aren't limited to being used by connectors for back-end components.. they're also great to keep your code DRY (Don't Repeat Yourself) for use in Snippets!

For this article we'll assume a simple grid though. The techniques displayed can be used to point you in the right direction for other implementations.

The Basics

Here's basically the minimum processor file you can use:

.. and the reason they're so awesome. Brief, super awesome, working code!

The most important thing to note is the public variable $classKey, this is the class name of the object you are going to retrieve. Furthermore you'll see we define the $defaultSortField to the "initiatedon" date field from the schema, and with $defaultSortDirection we make sure we get the latest on top. The $objectType variable is not necessarily required, but allows you to use prefix (lexicon) error messages for some default sanity checks. For example in the update processor it will use the objectType to prefix _err_ns if the primary key is not specified.

We also make sure we return the name of our extended class in the end, as that is used to instantiate the processor when it's called. While you're free to name it whatever you want, I'd advise you to keep it the same as your classKey. That way, when adding a new processor, you can just copy/paste another one and find/replace the old classKey for the new one and you're good to go.

Exploring the Processor Process

Just like an earlier post, dealing with the modObjectUpdateProcessor class based processor, I have created a list of what happens in the processor that you will find below.

  1. Processor instantiated, properties being set.
  2. Using checkPermissions() the processor decides if the user is allowed to access it.
  3. The processor finds lexicon topics to load via getLanguageTopics, which gets its data from the languageTopics variable (as an array).
  4. initialize() is called on the processor, which sets a number of default properties including sort to the defaultSortField (default: name) class variable, and the direction to the defaultSortDirection variable (default: ASC).
  5. process() is called.
  6. beforeQuery() is triggered by process(), and if the result is not a boolean TRUE it will consider the processor to have failed and cancel further execution.
  7. getData() is triggered by process().
  8. The getData() method builds an xPDOQuery object for the classKey type.
  9. The getData() method calls prepareQueryBeforeCount(xPDOQuery $c) allowing you to add additional conditions to the queries. After calling that, it fetches the total amount of results using modX.getCount.
  10. prepareQueryAfterCount(xPDOQuery $c) is called by getData().
  11. The query is sorted with help of the getSortClassKey() method, and the sortAlias, sort and dir properties.
  12. If the limit property is larger than 0 it limits the query and sets an offset.
  13. modX.getCollection is called with your data, it's been retrieved.
  14. Every row is iterated over using the iterate(array $data) method. iterate calls beforeIteration(array $list), and starts looping over the rows.
  15. If the checkListPermission variable is true, the object extends modAccessibleObject and checkPolicy('list') is false, it skips the row.
  16. prepareRow(xPDOObject|modAccessibleObject $object) is called which needs to return an array with the objects' fields. Great method to customize the retrieved data. The array is added to the list.
  17. After iteration over the entire result set afterIteration(array $list) is called.
  18. The data is returned.

Example Usages

Defining Constraints (where field X has value Y)

When adding constraints, we will take our minimum processor and add (actually override) a new function called prepareQueryBeforeCount. This function takes in the xPDOQuery object as parameter, and expects it to be returned as well.

Easy enough we first get the "reservation" value using $this->getProperty(). By specifying a second value we are assigned a default instead of NULL. In this case I'm setting the default value to zero, which makes sure that if there is no reservation passed, it will not return any results - but no results instead (as all rows have a reservation set to > 0).

After getting the reservation variable, we just interact with the xPDOQuery $c as we would in a normal processor (or script) and pass our where condition.

In the end we return the xPDOQuery (this is important!) and we've limited our query to just that reservation.

Modifying the way row data is returned

In some cases, your database set up may not completely match how you want to display that data in the front end. For example, you may have an array (which is stored serialized), which you want returned as one line of text per array key=>value, for rending in a textarea for example.

You will also see that instead of calling simply $object->toArray(), I am passing some additional parameters.

Specifically selecting fields

You could also join tables in the prepareQueryBeforeCount processor, add additional constraints etc.

Are there any more examples you would like to see, or have some to share yourself? Let me know in the comments!

Some time ago @tlyczko suggested I write a how-to on using MIGX with image Galleries or Sliders. As I'm using MIGX all over the place, I guess it can't hurt to spread the love with this How-To! We'll go over the basics of MIGX and work towards the new slider I recently set up for use in my blog.

Try MoreGallery!

While you can still use MIGX for image galleries, I have recently released MoreGallery, a custom Gallery resource for MODX, as part of my new business modmore. The user experience is significantly better compared to using MIGX, so check it out.

The end-result of what we're doing will be the following slider which you may have seen in my MODX Meetup post recently:

    no stuff


  1. A MODX Revolution site. This one is on 2.1.5, but MODX Revolution 2.2 will work fine..
  2. The MIGX custom TV input type installed (available via package management or from here).
  3. A slider or gallery script we'll want to integrate. I went for FlexSlider by WooThemes as it adjusts itself to its containers' width (which is quite important with a responsive design!). It's also quite configurable, supports swiping on smart phones and it looks pretty good out of the box.
  4. The phpthumbof snippet installed via the Package Manager for autocropping images.
  5. Some images!

Getting Started

There's a few parts involved. There's the back-end MIGX TV we'll need to set up, and we need to take that data to our front-end to put our slider to work. As this tutorial assumes WooThemes' FlexSlider, we will make sure the markup is exactly what that needs - but it should be easy enough to adapt for other sliders as well.

Step 1: Setting up the MIGX TV to manage Images

Let's start with setting up the TV. The beauty of MIGX is that you can define the fields you want. You should basically see it as a table, and you get to define the headers. In this case, I will want three different fields:

  1. An image input field to select an image from the file system (or in 2.2, from your media source).
  2. A simple text input to give a caption / tag-line / description. FlexSlider handles captions quite nicely, so we'll be using that.
  3. I'm also adding a text input for "Set". As we'll see later, I'm using this to manage an infinite amount of individual sliders which could be added at any point in the resource.
You can use different fields if you want, though the rest of the tutorial will assume the fields above.

Now let's start creating the TV. Here's a quick slider with an overview of the things you should be seeing (in 2.1-UI style), in case the blurb of text catches you off-guard.

    no stuff

Create a new Template Variable via the left-hand Elements tab, and give it a proper name. I called it mh.images, so if you gave it a different name make sure to replace [[*mh.images]] with the right one further on in the tutorial. On the Input Options tab, choose the "migx" input type drop down. If you're not seeing it there, make sure you have installed the MIGX Package through Package Manager. You will notice that a couple of options have been added to the bottom of the screen, including Form Tabs and Grid Columns. If you're not seeing this and running MODX 2.0, sorry - it's slightly different there and you really should consider updating soon.

Note: Both the Form Tabs and Grid Columns field expect to be fed a valid JSON string. JSON is basically a way of showing objects, arrays or just key -> value combinations in a way that is supported in pretty much any programming language available. There's a technical specification and some examples available on the official JSON website.

Setting the Form Tabs

As the name implies, the form allows different tabs to be used. Every tab has a caption and a number of fields. There are some advanced things you can do with this, though most usages will only use a single tab so we'll keep it at that for now. Here's the Form Tabs JSON I am using:

Let's just briefly go through that per line:

  1. Line one shows us opening the array of tabs with a square bracket ( [ ), and opening the tab object with the curly bracket ( { ). After that we define our caption option with a value of Image. Note that it is important to use double quotes ( " " ) for both the properties and its values, as single quotes are not according to the spec and can have unexpected results. If you have any double quotes inside any properties or values, escape it with a slash ( \ ). After we defined our caption, we go ahead and start defining the "fields" array by opening it with the square bracket ( [ ).
  2. We define our first field, the set in this case. The "field" property defines we want to be able of accessing it in the code as "set" - this would be the name part of a regular text input as well. Next we give it a caption of "Set", which will be shown in the form as field label.
  3. Next we define the description field in the same way.
  4. Line 4 defines the image. What's special here is that it uses another TV (with the name "image") as input type. This is a very powerful feature of MIGX that allows you to use other TVs to build up your form. In this case, the "image" template variable is really simple. Input type is an image, and in 2.2 you would assign it to the right media source as well. You don't need to link it to a template to make this work. Another way you could use this (which I use in another MIGX powered TV) is to build radio boxes or select boxes.
  5. Line five closes the fields array. Also note that the last field definition line (image) does not end with a comma - this is important! If you leave a trailing comma in an array it will not be able to process your JSON, and your form would not work.
  6. Line six closes the tab object as well as the tabs array.
Having put that in place (and having created the "image" TV!) you should have a working form, though there's no grid to show its values yet..

Setting the Grid Columns

The Grid Columns are what builds up the actual table (grid) in the resource's TV panel. You get to define the headers for that grid with the Grid Columns input option.

Here's the (again, JSON) definition I'm use:

Per line:

  1. Open the array of headers with the square bracket ( [ ), and the first column header object with the curly bracket ( { ).
  2. We give the header a title of "Set", say it can be sorted (optional), and tell it the dataIndex is "set", which corresponds with the Set Form Tabs definition which had "field":"set".
  3. End Set / start Description
  4. Give the header a title of "Description", sortable, and match it with the Descriptions' field with dataIndex.
  5. End Description / start Image
  6. Give the header a title of "Image", not sortable, and match it with the Images' field with dataIndex. We also define a renderer which is an ExtJS thing that allows you to change how the value is displayed. In this case, the "this.renderImage" renderer will automatically take the selected image URL, and show a thumbnail for it instead of the url itself.
  7. End Image object, end headers array.
Now that's done, you can assign it to your template and check out the result. No grid or form showing up? Go back to your tab fields and make sure you have all properties and their values enclosed in double quotes, not single ones, and if there are any trailing or missing commas. Can't find anything wrong? It's probably something easy to miss. Use JSONLint to validate the JSON.

Step 1a: Fill in some data!

Find some kitty or dog pictures and put them in through the new magical MIGX TV.

Step 2: Take the data to the Front End

Now you could do something funny to your visitors, and just throw your [[*mh.images]] TV somewhere in the template and telling them to imagine it's all images.If I would have done that to you, the example slider would have looked something like this (without the nice indentation I threw in for readability) instead:

Correct, that's a JSON array with our fields and values!

Now, luckily, MIGX comes with a snippet called getImageList which can help you make sense of that JSON. As I'm a developer and it's easier for me to write an 8 line piece of PHP to parse it, I tend to write that 8 line php myself and not use getImageList at all. If you do want to use getImageList, you can find the documation for it here.

Here's the snippet (which I called mh.parseMIGXToGallery) I'm using to generate the markup (from a &tpl chunk) based on the TV data:

That looks easy enough don't you think? Let's just go through it line by line again.

  1. We take the $input variable (which is populated by the data passed in by &input on the snippet call, more on that later), and parse the JSON into a php array.
  2. We set up an empty array to hold our output.
  3. We make sure the $input variable isn't NULL or false, which would mean there was either no JSON passed or it was not valid, as well as we check the $tpl variable (passed from &tpl in the snippet call) isn't empty. If either condition is true we'll return an error "no stuff' which is a hint for you, as content manager, that something's not set up right.
  4. Next we loop over each item in the $input array as $row.
  5. We check if the $set variable (which is set by calling &set on the snippet) is set, and if it's not empty we match it against what the value of "set" in the current row is. If it's not the same as what we want, we continue to the next item in the array.
  6. We get the chunk by the name of $tpl, and inject the values of the current row into it as placeholders.
  7. We close the foreach loop.
  8. Finally we glue together the $output array, separating every entry with a simple line break, and return it to the page.
So to sum that up, we take our input, loop over the individual rows and if they belong to the set we defined it gets the chunk we defined and adds that to the output.

Putting the Snippet to work

Now all we need is a snippet call where we want our images to appear and a chunk that matches the markup required for FlexSlider. Here's how we'd call the snippet:

and the chunk to match what FlexSlider is looking for is as follows:

and we will also need to wrap the entire snippet output in a div with an unordered list, according to the FlexSlider documentation. To make that easier (and a helluva lot more client friendly), is to put all that in a chunk. My chunk is called mh.slider and has the following contents:

With this chunk in place, I can simply reference the following in the content which is much easier to remember or to put on a cheat sheet.

We could also use a TV to have it type in the name of the set (gallery or collection) in a TV which, when filled in, puts that chunk in a predefined place in the template.

Now we've got our raw markup as FlexSlider wants.. but it's not doing much yet. Off to hook up FlexSlider!

Step 3: Hooking up FlexSlider

FlexSlider is relatively easy to use (download its files here), and there's a number of examples on its site to look at if you need help. You will need to include jQuery on the page, as well as its CSS file (found in the zip) and the FlexSlider plugin (also found in the zip). After having done that you will need to initiate it on the right element, using a code like the following:

The website advises to put all of it in the head of the file, though I personally put it in the bottom. If your slider will appear near the top of the page (above the fold), it can be better to put it in the <head> so it loads before the page shows, though that's just a preference.

And that sums it up for this very long article! I hope this how-to can help people getting started with MIGX and galleries like FlexSlider!

It's now mid-April. Realizing that, it's almost a shock to think I will be back from my week-long trip to Chicago for the CMS Expo in a month! It's time to start packing... I've never been to the US of A before. I've never been to an actual web conference either. But all that is about to change!

As you may have heard (if you follow me on twitter and you didn't, you're not paying attention!) there is a great web conference in Chicago this year, called the CMS Expo. It's hosted by John Coonen and his wife Linda and will take place in a four star hotel, spread out over three days (and a bit).

The reason I've signed up should be obvious: MODX is one of the Spotlight CMS' this year, and there will be some great announcements and presentations there for MODX specifically as well as content management in general (and the other CMS there, of course).

Ryan Thrash, the MODX Leader of Awesomeness, will be taking the stage to tell the world MODX is ready for take off and to make the life of designers and developers easier all over the globe. He will also be joining the CTO of SoftLayer Duke Skarda, one of the great sponsors behind MODX, to talk about the next big thing: MODX Cloud.

The official MODX itinerary will be announced soon, however,  there is simply no way we're not throwing together a MODX Meetup while we're there. Ryan is in town, I will be in town and a number of clients and fellow freelancers are also attending the conference who I look forward to meeting in person.

You've still got until April 30th to get your tickets at $779 for three days, or $679 if you enter code MODX2012. See you there!

    no stuff

Images above are from the 2011 Expo, credits go to Monty Ksycki and Chris Hammond (last picture).

Last week we had a MODX Meetup here in Leeuwarden (The Netherlands), and I figured I'd write a lil' bit about it and why I think you need to host one too. I think they're a great way to socialize with people that use (or are simply looking into) the same system. Not just if you're top-notch developer, or an expert in the field - everyone who uses MODX one way or another should take part in events like this. There's something to gain in them for everyone, and it's a great excuse to have a couple of beers together!

Here's the history.

Let me just take you through my history with meetups and what I learned from each of them.

Meetup #1: July 2011, Noordwolde (Friesland)

You have to start somewhere, and this is where it did for me. Together with Gauke Pieter of Sterc Internet Marketing I organised a meetup in 't Vlechtwerk, Noordwolde. This one was quite formal with a firm schedule (that we didn't even exactly follow). There were two main presentations, one by Gauke on MODX in general and SEO, and one by myself about customizing the manager. On top of that we had a skype video call with the MODX HQ over in Dallas where some great questions were asked and answered, which was really very much appreciated - not everyone gets to talk to those great folks on a regular basis :) We finished the evening with informal chatting which was a great time to catch up with people and to exchange business cards and the likes.

    no stuff

Don't think it was too bad for a first time, though I do think it was too tightly organised, and that I needed to let go some more and let the attendees help build the evening more. It was great to finally meet so many people (25!) that I've known via Twitter or Skype for a longer period of time.

Meetup #2: March 23rd 2012, Tilburg (Noord-Brabant)

As I was headed for a show just across the border in Belgium, a few tweets were sent out looking for people who would like to attend (and host) a meetup in the area. The next day we had a location at Yoman's Studio in Tilburg and Jasper also offered to arrange drinks, some snacks etc. As there were literally four days between confirming the location and the planned date, there were not a lot of attendees (5), but nevertheless it was a great evening with some very creative individuals who each have their own way of working with MODX.

This meetup learned me that it can be as easy as reaching out to people in order to get a meetup going.

Meetup #3: April 11th 2012, Leeuwarden, (Friesland)

For the meetup in Leeuwarden, which was hosted at Grand Café de Walrus, I took a way different route compared to the first Dutch meetup. This time, I prepared nothing - no presentations, schedules etc. Just get people to come, have a drink and see where it ends up. Despite some internet issues I think it was quite fun, and with about 15 attendees there were a surprising amount of new faces. MODX is definitely growing in the Netherlands!

Now, the lack of any planning did make it quite chaotic (though there were plenty of drinks!). People sat together in small groups to discuss things together, and I think it would have been more beneficial to people to sit together and discuss things in a larger group. So next time; a general schedule to kick things off.

Now it's your turn!

MODX is growing, rapidly. Start networking, pick a date, and host a meetup in your office, a local bar or a conference centre if you fancy. It doesn't have to be complicated or hard to host one, but do start some time in advance. I'd at least give people a month or so to keep an eye out on their schedule, make babysitter arrangements or to convince their boss to pay for the traffic costs. Use Twitter (mention @modxcms and use the #MODX hashtag), Facebook (post it on the MODX CMS page, or your countrie's/state's page) and send personal emails to people you know who may be interested, asking them to spread the word with any of their contacts who may be interested too. The MODX'ers are there, you just need to put some time into finding them and having them find you.

You don't need big names, big budgets or dedicated teams to get a meetup going. Find a way to offer attendees value (provide quality content, sponsor the first drink, try to get some big names involved to speak or share experiences, give them a sponsored goodybag.. be creative) and get them interested. Often it's enough to just give people the opportunity to get to know eachother.

So. When's your next meetup?

One of the new features in MODX 2.2.1 is the ability to indicate if a user is a "sudo" user. This humble checkbox is one to be extremely careful with, as it allows a user to completely bypass ANY access control you may have set up. This bypass is in the core, and will therefore also affect any custom access policies you built up and access policies by 3PCs, such as Quip.

When to use sudo users

Its goal is to allow the concept of a super user or administrator which is not affected by the security setting... you can imagine that to be helpful when you are working on actually setting up the security (to prevent yourself from getting locked out), or when you want to make sure someone has access to it all. This was a much requested feature from the forums.

More importantly: when NOT to use them

Please do not set a front-end user to be a "sudo" user. All access permissions means all access permissions, and if they find out the link to your manager (cause, being security aware, you used the advanced distribution to move it, right?) they are free to do ANYTHING, from editing resources to deleting your account or other wrecking things.

Sudo users don't even need to be assigned to any user groups in order to get full access.

Sudo users are to be used for providing access to everything in the manager and all front-end contexts - if you don't feel at ease with someone having that access, do NOT set them as a sudo user. Simple as that.

How to set a user as Sudo user in MODX

If you are updating to MODX 2.2.1, you will find that any users which are assigned to the Administrator user group with Super User permissions will have been marked as a sudo user. The first account you create via the installer (for a new install) will also be set to be a sudo user by default.

To set other users as sudo users, open Security > Users in your MODX 2.2.1 manager, and edit a user you want to give full access. You'll see the below screen. Simply tick the Sudo user box, and save the user.

How to set a user as Sudo user in MODX

Programmatically setting a user as sudo user

As we're dealing with what is pretty much root permissions, it is not possible to simply use sudo in a modUser->set() or modUser->fromArray() method - this is filtered out and will return false. This is to prevent auto assignment exploits (like the ones that caused an uproar in the Rails & Github communities recently).

Instead, you will want to use the modUser->setSudo(true|false) method. Pass it a boolean true to mark a user as sudo user.

Conclusion thingy

Do not start handing out sudo permissions! It's an extremely easy way to lose control over your manager if the user is not to be trusted. Every user set as sudo user could get its password guessed and cause you some major problems. But it's a great feature for developers setting up the security who don't like getting locked out!

This is probably a surprise for most of you (I have been in touch with some clients and partners about this already), but I am joining the MODX team! Mid March I will join the team part-time for a few weeks and in April I will officially hop on board full time for hopefully years to come.

Whoah, what?!

Yep, it's a big change that will not only affect me but also the very loyal clients I have had the pleasure to work with over the past year and 3 months. It wasn't one I took lightly (it rivaled the school vs freelance business battle back in March-Sept '11 for those that sticked around since then!), however I would be crazy not to accept an offer from the MODX team!

I will be joining MODX Services (consultancy, development and support) team, which is led by James Bohan-Pitt (most Partners will know him), and includes Garry Nutting and Mike Schell as Developers, and Robert Walker as Customer & Partner Support Manager. The team deals with obviously the support requests coming in from MODX Complete subscribers as well as development work for Partners and potentially some of the amazing MODX clients. Besides that, I will also get the chance to work on some great projects I can't say anything about yet, as well as the core product: MODX Revolution.

This job offer didn't just hit my inbox out of nowhere of course, I've been talking with Ryan Thrash on and off over the past year about the prospect of joining the team. The ball really got rolling in the past weeks when talking with Ryan, James and John Corcoran (the MODX CEO) and we're all very excited to finally be able of moving forward with my addition to the team.

What about my Company & Clients?

As said before, this new job does not differ much from what I used to do. Because of that I will be able to still provide the services I have offered before, however the invoice will have "MODX" on it and there will be an entire team to handle the work instead of just me! The MODX guys have been amazing in trying to make the transition as smooth as possible and if you would prefer me as your main point of contact they'll gladly oblige!

I will be working with MODX fulltime starting in April and likely wont be able of taking on many other projects, though stay on the lookout for one of the many personal projects that I will be working on.

If you're a current client (or we have been discussing a project for some time) and I've not yet been in touch about how your project will be moving forward with this very quick transition, send me an email. I've tried to reach out to everyone directly influenced by this, but with everything going on around here it's possible I've missed you. Sorry!

What about the site?

Over the coming weeks my website's content will be updated to more accurately display the new situation. Most of the Services section will be deprecated and removed (yes, that's part of the reason I made a new centralised Testimonials page) and some information will be added here and there to indicate the new situation.

The blog will remain like it is, and I will still be aiming for 2 posts a week (Monday and Thursday), so there's plenty coming up to keep you informed!

In other news...

I'm finally moving out (again)! Around the same time we were finishing up the deal of me joining the team I was offered a three bedroom (read: a bedroom, office and washing/junk/sleep-over room) apartment and I'll be working on painting the walls, laying floors and getting some furniture in over the coming weeks as well. I hope to have officially moved by the time I join the MODX team full time... we'll see how that goes :)