MODX 360

the personal website of garry nutting

How to prevent MODX tags from parsing in MODX Revo

So, you have a shiny new blog rolling in MODX Revolution and you want to post up some code samples about MODX Revo - but, hold on, if MODX tags are posted in the sample code, they get parsed. Oh oh!


So, you have a shiny new blog rolling in MODX Revolution and you want to post up some code samples about MODX Revo - but, hold on, if MODX tags are posted in the sample code, they get parsed. Oh oh!

Just how do you work around that little annoyance? Well, with a plugin of course! Read on for the solution.

The solution is relatively simple and requires a plugin to fire on three events, these are:

  • OnLoadWebDocument: This event fires before any tags are parsed, we are going to use this to pre-format our sample tags into a format the MODx parser won't recognize.
  • OnWebPagePrerender: This fires after all tags have been parsed (actually, right before the page is delivered to the browser). We're going to use this event to remove all that pre-formatting to make our MODX sample code copy-friendly.
  • OnBeforeSaveWebPageCache: This event fires right before the cache is written to. We'll use this event to set the resource content back to the original content that before all the parsing was done.

The first step is to create a new plugin, select those three events above in the 'System Events' tab and then paste in the following code:

$eventName = $modx->event->name;
switch ($eventName) {
	case 'OnLoadWebDocument' :
		$output = $GLOBALS['code_content'] = $modx->resource->get('content');
		preg_match_all('/<code.*?>(.*?)<\/code>/ims', $output, $matches);

		$i = 0;
		foreach ($matches[1] as $key => $match) {
			$output = str_replace($match, '~*code_' . $i . '*~', $output);
			$GLOBALS['code_matches']['~*code_' . $i . '*~'] = $match;
			$i++;
		}
		$modx->resource->set('content', $output);
		break;
	case 'OnWebPagePrerender' :
		$html = & $modx->resource->_output;
		$output = $modx->resource->get('content');
		preg_match_all('/<code.*?>(.*?)<\/code>/ims', $html, $matches);
		$i = 0;

		$replacements = array (
			'<' => '<',
			'>' => '>'
		);

		foreach ($GLOBALS['code_matches'] as $key => $match) {
			$match = preg_replace('/&amp;([^\s]*;)/i', '&amp;amp;$1', $match);
			foreach ($replacements as $key => $value) {
				$match = str_replace($key, $value, $match);
			}

			$html = str_replace('~*code_' . $i . '*~', $match, $html);
			$output = str_replace('~*code_' . $i . '*~', $match, $output);
			$i++;
		}
		$modx->resource->set('content', $output);
		break;
	case 'OnBeforeSaveWebPageCache' :
		$modx->resource->set('content', $GLOBALS['code_content']);
		break;
	default :
		break;
}

Save the plugin, and then go give it a whirl! Just paste in some MODX tags between some <code> tags and the MODx tags should get rendered out to the page unparsed.

Maximizing the content caching

You may have noticed that the plugin makes a few uses of $modx->resource in both getting the content and setting it. This may seem a bit puzzling for a start, but the answer lies in bypassing the content caching.

By getting and setting the content dynamically, I can still call my page cached but still allow for direct manipulation of the content variable ([[*content]]). The only other alternative would be to call the page uncached which would have a serious disadvantage in terms of performance.

Caveats

This plugin isn't 100% perfect, there will still be some instances where you have to manually escape tags (and HTML entities) - one example being when I posted the plugin code above. But, on the whole, it will greatly reduce the time to post up MODX code samples on a MODX Revo driven site.


Comments (0)


Add a Comment





Allowed tags: <b><i><br>Add a new comment: