We're going to create a simple plugin which adds a menu item to the admin menu, opens a new tab when clicked and displays a table of data which is fetched from a webservice.
Before we start, you need to understand a bit about how plugins are routed (if you have a solid knowledge of how Zend framework works, this will probably not be necessary). If you strictly follow this example, you probably won't have any problems but if you a mistake as little as a wrong-cased letter you will have a hard time debugging it. Pimcore has special routes for plugins so you need to understand how these work.
For plugins, requesting a controller and action in the browser works a little bit different from the standard pimcore way. For the example below, we will have a URL like this:
http://www.elements.at/plugin/MyPlugin/admin/get-address-book
There are some aspects regarding the above URL that you should keep in mind:
- /plugin - is always the prefix for accesing plugins (notice there is no "s" in plugin)
- /MyPlugin/ - the plugin name is always case sensitive
- /get-address-book - if the action is in camelcase you should write it with hyphens and make it lowercase
Plugin Skeleton
First create a directory named:
plugins/MyPlugin
And add the following file:
plugins/MyPlugin/plugin.xml
With the following content:
<?xml version="1.0"?><zend-config xmlns:zf="http://framework.zend.com/xml/zend-config-xml/1.0/"> <plugin> <pluginName>MyPlugin</pluginName> <pluginDescription>An example plugin</pluginDescription> <pluginNiceName>My Plugin</pluginNiceName> <pluginIcon>/plugins/MyPlugin/static/img/icon.png</pluginIcon> <pluginVersion>1.0.0</pluginVersion> <pluginRevision>1</pluginRevision> <pluginBuildTimestamp></pluginBuildTimestamp> <pluginClassName>MyPlugin_Plugin</pluginClassName> <pluginIncludePaths> <path>/MyPlugin/lib</path> <path>/MyPlugin/controllers</path> </pluginIncludePaths> <pluginNamespaces> <namespace>MyPlugin</namespace> </pluginNamespaces> <pluginJsPaths> <path>/MyPlugin/static/js/admin.js</path> </pluginJsPaths> </plugin> </zend-config>
Next, we need to write the plugin PHP class, so create the following file:
plugins/MyPlugin/lib/MyPlugin/Plugin.php
With the following content:
<?php class MyPlugin_Plugin extends Pimcore_API_Plugin_Abstract implements Pimcore_API_Plugin_Interface { public static function needsReloadAfterInstall() { return true; } public static function install() { // we need a simple way to indicate that the plugin is installed, so we'll create a directory ////////////////////////////////////////////////////////////////////////////////////////////////////// // NOTE - make sure that your plugin/MyPlugin directory is writable by whatever user Apache runs as // ////////////////////////////////////////////////////////////////////////////////////////////////////// $path = self::getInstallPath(); if(!is_dir($path)) { mkdir($path); } if (self::isInstalled()) { return "MyPlugin Plugin successfully installed."; } else { return "MyPlugin Plugin could not be installed"; } } public static function uninstall() { rmdir(self::getInstallPath()); if (!self::isInstalled()) { return "MyPlugin Plugin successfully uninstalled."; } else { return "MyPlugin Plugin could not be uninstalled"; } } public static function isInstalled() { return is_dir(self::getInstallPath()); } public static function getTranslationFile($language) { } public static function getInstallPath() { return PIMCORE_PLUGINS_PATH."/MyPlugin/install"; } }
At this point, if you log into the Pimcore admin then navigate to Extras -> Extensions -> Manage Extensions you should be able to see, install and uninstall your new plugin.
Modifying The Admin Interface
Next, we're going to modify the admin interface. All of the UI changes are driven by javascript, so create the following file:
plugins/MyPlugin/static/js/admin.js
And put the following code in it:
pimcore.registerNS("pimcore.plugin.myPlugin"); pimcore.plugin.myPlugin = Class.create(pimcore.plugin.admin, { getClassName: function() { return "pimcore.plugin.myPlugin"; }, initialize: function() { pimcore.plugin.broker.registerPlugin(this); }, pimcoreReady: function (params,broker){ // add a sub-menu item under "Extras" in the main menu var toolbar = Ext.getCmp("pimcore_panel_toolbar"); var action = new Ext.Action({ id: "my_plugin_menu_item", text: "My Plugin", iconCls:"fraud_check_menu_icon", handler: this.showTab }); toolbar.items.items[1].menu.add(action); }, showTab: function() { myPlugin.panel = new Ext.Panel({ id: "spark_fraud_check_panel", title: "My Plugin", iconCls: "spark_fraud_check_panel_icon", border: false, layout: "fit", closable: true, items: [] }); var tabPanel = Ext.getCmp("pimcore_panel_tabs"); tabPanel.add(myPlugin.panel); tabPanel.activate("my_plugin_check_panel"); pimcore.layout.refresh(); } }); var myPlugin = new pimcore.plugin.myPlugin();
Now, if you reload the admin, you should see a new menu item under Extras -> My Plugin, where clicking on it will bring up a blank tab.
Making It Do Something Useful
Let's add some functionality to pull data from a web service and display it in a table.
In the showTab function, in admin.js, change the following line:
items: []
To:
items: [myPlugin.getGrid()]
And add a new method after showTab:
showTab: function() {
...
},
getGrid: function() {
// fetch data from a webservice (which we haven't written yet!)
myPlugin.store = new Ext.data.JsonStore({
id: 'my_plugin_store',
url: '/plugin/MyPlugin/admin/getAddressBook',
restful: false,
root: "addresses",
fields: [
"name",
"phoneNumber",
"address"
]
});
myPlugin.store.load();
var typeColumns = [
{header: "Name", width: 100, sortable: true, dataIndex: 'name'},
{header: "Phone Number", width: 100, sortable: true, dataIndex: 'phoneNumber'},
{header: "Address", width: 100, sortable: true, dataIndex: 'address'}
];
myPlugin.grid = new Ext.grid.GridPanel({
frame: false,
autoScroll: true,
store: myPlugin.store,
columns: typeColumns,
trackMouseOver: true,
columnLines: true,
stripeRows: true,
viewConfig: { forceFit: true }
});
return myPlugin.grid;
}
Now we write a simple webservice so that we can pull some data - create the following file:
plugins/MyPlugin/controllers/AdminController.php
With the following content:
<?php class MyPlugin_AdminController extends Pimcore_Controller_Action_Admin { public function getaddressbookAction() { $addresses = array(); $addresses[] = array( 'name' => 'Bob Dole', 'phoneNumber' => '1234567890', 'address' => '123 Fake Street' ); $addresses[] = array( 'name' => 'Joe Smith', 'phoneNumber' => '0987654321', 'address' => '45 Newington Heights' ); return $this->_helper->json(array('addresses' => $addresses)); } }
Reload the admin interface, navigate to Extras -> My Plugin and you should see a table with two rows, which can be sorted by column.
Comments (5)
Aug 15, 2011
KOWALSKI says:
hello, i tried your example but it does not work when i try to use your WS. I ...hello,
i tried your example but it does not work when i try to use your WS.
I think pimcore does not provide the library for json, how can i get it, even on google i do not find it ?
and where shall i put it if the problem comes with this library ?
thanks
Oct 22, 2011
Bojan Kovačec says:
Example works just great. except maybe return myPlugin.grid; }); cou...Example works just great.
except maybe return myPlugin.grid;
});
could be if you copied all code ..
return myPlugin.grid;
}
});
Nice and simple plugin arhitecture. Thank you Pimcore team.
For Json, Pimcores core is Zend Framework. Look for Zend Json.
May 13
laurent says:
It doesn't work in pimcore from Version: 1.4.5 any update ?It doesn't work in pimcore from Version: 1.4.5
any update ?
May 16
Christian Fasching says:
I just tested it, it works... There was just a small syntax error in the last c...I just tested it, it works...
There was just a small syntax error in the last change of admin.js ... but this had nothing to do with pimcore 1.4.5, this is pure java script.
May 16
laurent says:
yeah thanks for testing it too, I got working, it was a malformed admin.js ...yeah thanks for testing it too, I got working, it was a malformed admin.js issue. I think for users its better to put the zipped files online.