jeffchannell.com

Moving the JomSocial Wall

Posted in Joomla!
2010-03-09 01:13:06 +0000 UTC

Recently, a client of mine had an issue - they wanted the "Wall" application of JomSocial moved above the "Latest Activity" section, but wanted the rest of the applications to remain where they were. Looking into it, I discovered a post on the JomSocial forums addressing this very item, and the response from Azrul was basically, "we'll see what we can do." Taking it upon myself, I managed to move the wall...

JomSocial's applications are echoed in the template using the following:

<?php echo $content; ?>

Since this is just echoing text, I figured with some creative coding, I could pull the Wall out before rendering. My plan of action was basically to feed this text into an XML parser, find the node for the Wall, and echo that separate from the rest. I managed to get it working, with an annoying side-effect: sometimes the XML parser would produce an error about entities. I decided that, rather than parse the string and replace entities, I'd just dump the errors if they exist. Also, empty tags were converted from open/close tags to a single tag, so <textarea></textarea> became <textarea />, so I also had to account for that.

What I did was edit the JomSocial template's profile.index.php, and right after the line:

defined('_JEXEC') or die();

I added the following, which parses the applications into XML nodes, removes any XML parsing errors, and sets up an array of tags to fix:

jimport('joomla.utilities.simplexml');

$parser = JFactory::getXMLParser('Simple');

$parser->loadString( '<xml>'.$content.'</xml>' );

// remove any XML parsing errors

$appl =& JFactory::getApplication();

$queue = $appl->getMessageQueue();

$errors = array();

if( count( $queue ) )

{

	foreach( $queue as $key => $q )

		if( preg_match( '`XML\\ Parsing\\ Error`', $q['message'] ) )

			$errors[] = $key;

}

if( count( $errors ) ) foreach( $errors as $err ) unset( $queue[$err] );

$appl->set( '_messageQueue', $queue );

// tags to "fix"

$tags = array(

	'`(<textarea[^>].*?)\\/(>)`' => '$1$2</textarea>',

	'`(<span[^>].*?)\\/(>)`' => '$1$2</span>',

	'`(<div[^>].*?)\\/(>)`' => '$1$2</div>',

	'`\\"\\;`' => '"'

);

Now that I had the applications split into their individual pieces, I turned to the rest of the template. Just above the block of code that rendered the Recent Activities, I added the following:

<?php

foreach( $parser->document->children() as $child ) {

	$html = $child->toString();

	if( preg_match( '`\\<a\\ name\\=\\"app\\-walls\\"\\s\\/\\>`', $html ) )

	{

		echo html_entity_decode( preg_replace( array_keys( $tags ), $tags, $html ) );

		break;

	}

}

?>

Basically, this loops through each application node, and checks it for the "app-walls" anchor. If it matches, that node is echoed to the page and the loop is broken.

Next, I found the part of the template that actually rendered the applications, which is done using the following tag:

<?php echo $content; ?>

I commented this tag out, like so:

<?php /* echo $content; */ ?>

then added the following to render the remaining applications:

<?php

foreach( $parser->document->children() as $child ) {

	$html = $child->toString();

	if( !preg_match( '`\\<a\\ name\\=\\"app\\-walls\\"\\s\\/\\>`', $html ) )

	{

		echo html_entity_decode( preg_replace( array_keys( $tags ), $tags, $html ) );

	}

}

?>

As far as I could tell, this seemed to work okay, and didn't involve changing any of JomSocial's core coding (preserving the ability to upgrade later). If anyone finds any issues with this, feel free to post a comment below!