Howdy! Welcome to my humble web presence. I'm Mark Hamstra, the CEA at my latest venture modmore, where I spend most of my time developing and providing support for awesome tools and extras for MODX Revolution.

This website is where I share my thoughts, cool projects and other oddities related to MODX, xPDO and ExtJS. Sometimes I post three blogs in a day, sometimes there's no update in a year. Read a random article.

Exploring modObjectGetListProcessor, a powerful class based processor in MODX 2.2

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!


Read 7 comments and share your own thoughts!

How to: Managing Galleries with MIGX

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

Requirements

  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 mh.images.gallery.tpl 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!


Read 37 comments and share your own thoughts!

Chicago, here I come!

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).


Read 0 comments and share your own thoughts!