SMF, MODx and groups.

Posted on December 7th, 2009.

When building the new site of Mountain Rescue (England and Wales) I needed to link MODx and Simple Machines Forums (SMF).

Easy enough with the SMF connect plugin, but I needed to synchronise MODx webgroups with SMF groups and this package does not provide that.

The code below is a modified SMF connect plugin to cater for this. Note that it transfers MODx group membership to SMF and not vice versa. Also note that the groups that you wish transfered must be set up manually in SMF – but this does mean that groups that are intended to be kept purely within MODx will not end up cluttering up SMF.

The important part is the function modx_to_smf_groups() which reads in the modx webgroup memberships, and makes an array suitable for the SMF API. The latter requires an item for the ‘ID GROUP’ or main group, and an item called ‘additional groups’ which is a comma delimited list of other groups that the user is a member of. This is different from modx where all groups are created equal. The code below does not try and prioritise any particular group for ‘ID GROUP’.

Download the modified plugin here.

Too much style!

Posted on November 2nd, 2009.

After you deploy a CMS, the client types in their content, and as time goes on that is all there is too it. At least that is the proverbial theory.

Sometimes though, all your efforts to provide a consistent appearance to the content via CSS just don’t work. The trouble is your client is often copying and pasting content from all manner of sources including their favourite Word processing package.

The richtext editor bundled with MODx is TinyMCE, and a very good job it does. It even has a ‘Paste from Word’ button that if configured can filter out any styles that have been pasted in from Word, thus getting rid of the original font and font size related styling so that your CSS can do its job in providing a consistent look to the site.

Unfortunately you will need to configure it to strip out those styles, and pasting is not the only way some bright spark in your client’s organisation can insert styles. So maybe there is another, more bombproof, way.

The solution lies with MODx events, or rather the event OnDocFormSave. Basically, you run the content through a regular expression that removes any style attributes. Unfortunately you may want to keep some useful style attributes as TinyMCE itself does use some e.g. for image positioning and margins.

Personally I have (so far) found only the image tag’s style="float: left/right" worth keeping. Anything else just results in the consistent site look being, erm, inconsistent. Thus I have the following code:

/* * Clean styles from richtext content * *   Last modified: TS, 26/8/2009 * * for OnDocFormSave * * Note $unchanged_text_tv_fields in the config. This must include ALL unchanged text fields from modx_site_content. */ /* ----- CONFIG ----- */ $tv_fields = array('content'); $custom_tv_fields = array('subcontent'); $unchanged_text_tv_fields = array('pagetitle', 'longtitle', 'menutitle', 'introtext', 'type', 'contentType', 'description', 'alias', 'link_attributes'); // VERY IMPORTANT FOR SECURITY!!! // Regex to allow floats (no other styles must be included to preserve the float) $regex = '/(\<[^>]+)style\="(?!float\:\s*[a-z]+;?")[^"]+"([^>]*\>)/'; // Regex to strip all styles //$regex = '/(\<[^>]+)style\="[^"]+"([^>]*\>)/'; /* ----- ------ ----- */ require_once($modx->config['base_path'].'assets/libs/docmanager/document.class.inc.php'); $doc = new Document($id); $doc_tvs = $modx->getTemplateVarOutput(array_merge($tv_fields, $custom_tv_fields), $id); if ($doc_tvs)   {   foreach ($tv_fields as $field)     {     $doc->Set($field, $modx->db->escape(preg_replace($regex, '$1 $2', $doc_tvs[$field])));     }   foreach ($custom_tv_fields as $field)     {     if (isset($doc_tvs[$field]))       $doc->SetTV($field, $modx->db->escape(preg_replace($regex, '$1 $2', $doc_tvs[$field])));     }   foreach ($unchanged_text_tv_fields as $field)     {     $doc->Set($field, $modx->db->escape($doc->Get($field)));     }   $doc->Save();   }

A few points… I use the docmanager class on a regular basis and so I have used it here also. It does have a potential security flaw if you are not aware of how it works so I suggest you look up my posting on the issue in the MODx forums. If you use the above code as is, you will be fine; if you change it – read the comments.

The above config is by way of example set up to ‘clean’ styles from both the normal content field and a template variable named ‘subcontent’. If you have no richtext TVs other than the normal or standard one then you can change

$custom_tv_fields = array('subcontent');

to

$custom_tv_fields = array();

(actually you can just use the code above as is – it will ignore any TVs it cannot find rather than producing an error – which means it will work fine on different templates).

If you have other richtext TVs, then change it to (for example)

$custom_tv_fields = array('content2','content3');

There you have it – now enjoy consistent looking websites! Easy to install as per any plugin – just create a new plugin, paste in the code, and tick the OnDocFormSave event. Done!

Integrating WordPress and MODx

Posted on September 30th, 2009.

So at last I join the ever-growing world of blogging. Being a developer of modx sites I considered whether to use the various snippets available for building a blog in MODx, having done this before. However its always good to experiment so instead I opted to link a WordPress blog with my own existing MODx site.

I have recently linked SMF to MODx for the Mountain Rescue England and Wales website, and so adapted the code I used there.

I use the code (below) in an include file which is then included in each of the theme files that represents a WordPress page. Alternatively and to be on the safe side, use ‘require_once’ in every php file that needs data from MODx.

You will see from looking at the code that I have set things so that as far as the MODx API is concerned we are on the document/resource with id 31, which is the MODx weblink to this blog. As such, menu snippets such as Wayfinder will correctly identify docid 31 as being the page we are on. In addition I run the getDocumentObject method so that the template variables used by this document/resource are available.

Lastly I provide a function to parse a MODx chunk as this is what I mainly want it to do (for the header and the navigation in the top right corner).

<?php // MODx integration // ------------------------------------------------------------------------------- // ----- CONFIG ----- define('MODX_SITE_BASE_URL', '/'); define('MODX_MANAGER_PATH', '/home/timspe/public_html/TimSpencerWeb_modx/manager'); define('MODX_DOCUMENT_IDENTIFIER', 31); // The MODx document we are going to pretend to be // ------------------ // Some defines used by the modx API define('MODX_API_MODE', true); // Tells MODx index.php to not run $modx->executeParser define('MODX_SITE_URL', (!isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) == 'off' ? 'http://' : 'https://').$_SERVER['SERVER_NAME'].MODX_SITE_BASE_URL); // Run the MODx config and get site settings require(MODX_MANAGER_PATH.'/../index.php'); $modx->getSettings(); //  Set the docid (most sensibly to the MODx weblink to here) and get the MODx document object $modx->documentObject = $modx->getDocumentObject('id', MODX_DOCUMENT_IDENTIFIER); $modx->documentIdentifier = MODX_DOCUMENT_IDENTIFIER; // Set the base URL for any MODx snippets $modx->config['base_url'] = MODX_SITE_BASE_URL; // Get AND parse a modx chunk. Cannot cope with nested snippets within the chunk. function modx_chunk($chunk_name)   {   global $modx;   return $modx->rewriteURLs(str_replace('[~', MODX_SITE_URL.'[~', // Ensure that the link goes to the MODx site and not e.g. /blog/pagename       $modx->parseDocumentSource(str_replace('[!', '[[', str_replace('!]', ']]', $modx->getChunk($chunk_name))))));   } ?>