One of the best things about CiviCRM 3.4 and 4 for Joomla! users is that hooks are now implemented using the Joomla! plugin system. This actually has always worked, but it was not documented and now it's implemented a lot more cleanly.
As Joomla! developers know, Joomla plugins are an implementation of the observer design pattern. They are part of the framework layer sitting next to the Joomla! Platform and external libraries and underneath the CMS application. Plugins are incredibly powerful and can override almost anything that happens in Joomla. At the same time, basic plugins are simple to code, at base just requiring one php file and one xml file. They also should have two language files (I'm going to skip those) because I'm not giving a plugin tutorial here but you can read more in the Joomla documentation.
Plugins respond to events and context. So in the case of hooks we need to have extension specific plugins that will be listening when we are inside com_civicrm. Therefore the plugins implementing hooks will go into a plugin subfolder called civicrm (plugins/civicrm). Each plugin will have its own folder.
Plugins can implement as many hooks as you want in whatever combination you want, but for this post I'm going to show how to make a plugin implementing the example for hook_civicrm_tabs in the CiviCRM wiki. This hook is used when composing the tabs in a contact display.
The example shows how to remove the contributions tab and then display a copy of it with a new name as the last tab.
I'm going to call the plugin tabs. It's important to understand that Joomla! is strongly conventions driven so you should always follow the naming patterns to ensure that you are taking maximum advantage of the Joomla! framework.
To make the plugin first, we make the xml file, tabs.xml. (I'm having trouble getting indenting to render properly so just imagine that part.)
<?xml version="1.0" encoding="UTF-8"?>
<extension version="1.6" type="plugin" group="civicrm"> <name>plg_civcrm_tabs</name> <author>Joomla! Project</author> <creationDate>November 2005</creationDate> <copyright>Copyright (C) 2005 - 2011 Open Source Matters. All rights reserved.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>1.6.0</version> <description>PLG_CIVICRM_TABS_XML_DESCRIPTION</description> <files> <filename plugin="tabs">tabs.php</filename> <filename>index.html</filename> <folder>language</folder> </files> <config> </config> </extension>
Notice a few things. First,<extension version="1.6" type="plugin" group="civicrm"> identifies this as a plugin and says what group it will belong to. The installer will use this to put it in the right location.
Second, notice the name of the plugin is plg_civicrm_tabs which reflects the file system location of the plugin. From Joomla 1.6 forward the php native ini parser is used and strings should have no spaces and should be named spaced. The same applies for the description. These strings will be one of the language files (language/en-GB/en-GB.plg_civicrm_tabs.sys.ini). In Joomla we always include a blank index.html to keep nosey people from seeing what files you have. These strings will also work in Joomla! 1.5.
Third, note <filename plugin="tabs">tabs.php</filename> this gives the plugin name and the name of the file with the code. Notice that they match. All files in the language folder are also included. Again following the naming and location conventions is important.
Next we create tabs.php.
<?php /** * @version * @package Civicrm * @subpackage Joomla Plugin * @copyright Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ // No direct access defined('_JEXEC') or die; jimport('joomla.plugin.plugin'); class plgCivicrmTabs extends JPlugin { /**
* Example Civicrm Plugin
* @package Civicrm
* Joomla plugins * @since 1.5 */ public function civicrm_tabs(&$tabs, $contactID) { // unset the contribition tab, i.e. remove it from the page unset( $tabs[1] ); // let's add a new "contribution" tab with a different name and put it last // this is just a demo, in the real world, you would create a url which would // return an html snippet etc. $url = CRM_Utils_System::url( 'civicrm/contact/view/contribution', "reset=1&snippet=1&force=1&cid=$contactID" ); $tabs[] = array( 'id' => 'mySupercoolTab', 'url' => $url, 'title' => 'Contribution Tab Renamed', 'weight' => 300 ); } }
First we use jimport to bring in the plugin class. Then we extend it using the appropriate naming convention:
it contains:
; Joomla! Project ; Copyright (C) 2005 - 2011 Open Source Matters. All rights reserved. ; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php ; Note : All ini files need to be saved as UTF-8 PLG_CIVICRM_TABS_XML_DESCRIPTION="Deletes the existing contribution tab and adds a new one with a different name." PLG_CIVICRM_TABS="CiviCRM - Tabs"
The second should be
language/en-GB/en-GB.plg_civicrm_tabs.ini
; Joomla! Project ; Copyright (C) 2005 - 2011 Open Source Matters. All rights reserved. ; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php ; Note : All ini files need to be saved as UTF-8
PLG_CIVICRM_TABS="CiviCRM - Tabs"
Comments
Thanks for providing the documentation for this.
I've created a base plugin to help get people started. It implements the hook above and one other, and is a bit more refined than the example code that ships with core -- including implementing the language files. You can access it here (on the wiki).
I know that I am likely missing something REALLY fundamentally simple, but, when I take the sample code as shown above, it works. I simply change the file names to ones that I like, also changing the XML... plugin="test" test.php. It no longer works. What stupid thing am I over looking?
Thanks,
Will
its a lot easier to support folks on the forums. Also a lot more users read the forums than blog comments
thanx
lobo