This article explains the basics of creating a plugin for the Contao CMS using the Contao Viewer plugin as an example. You can download the completed plugin from Contao.


  • Contao CMS
  • PHP 5.3
  • JavaScript

PreparationTo create a GroupDocs Viewer plugin for Contao CMS:

  1. Install Contao CMS. The installation of this CMS is a simple.
  2. Allow GroupDocs to appear go to Admin > Setting > Security settings > Allowed HTML tags and just add at the end.
  3. Create a folder to hold future plugin files in the root/system/modules directory of the Contao CMS installation and name it groupdocs_viewer.

Creating the PluginThis plugin adds a button to the Admin side of the CMS above the editing block of any article. When users click the button a dialog appears. Here, users enter the file GUID from their GroupDocs account to embed and iframe with this file. OK. Let’s start creating a Viewer plugin. All operations are in the groupdocs_viewer folder. First of all, create a ModuleGroupdocsViewer.php file. This file will contain the plugin’s installation and uninstallation logic. Enter this code into the file:```

### The Code Line by LineLet's take a look at the code we inserted. The first line

if (!defined(‘TL_ROOT’)) die(‘You can not access this file directly!’);

says that if TL\_ROOT has not been defined, the user can't access the file. This line must be in all plugin files as first line. The next, commented, block contains information about the plugin. Now create a basic class of our plugin which will extend the Contao CMS's **Module** class. This is necessary for Contao to understand that this is a module and give us access to the CMS's functions.

class ModuleGroupdocsViewer extends Module

That creates the class. Then we have the magic that installs and uninstalls the plugin. For this purpose we create some functions. All code explanations are on the same lines of the code in the section below.

protected $strTemplate = ‘mod_groupdocsviewer’; // Creation of the protected variable which declare a template with module name

 \* Display a wildcard in the back end
 \* @return string
public function generate() //This function is describe an insertion of plugin info to the CMS.
                              //For this purpose we use a variables of the basic Module class which we expanded by our class
	if (TL\_MODE == 'BE')
		$objTemplate = new BackendTemplate('be\_wildcard');

		$objTemplate->wildcard = '### GROUPDOCS VIEWER LIST ###';
		$objTemplate->title = $this->headline;
		$objTemplate->id = $this->id;
		$objTemplate->link = $this->name;
		$objTemplate->href = 'contao/main.php?do=themes&table=tl\_module&act=edit&id=' . $this->id;

		return $objTemplate->parse();

	return parent::generate();

 \* Generate module
protected function compile() //In this function we transfer our plugin data to the template such as button position and in which area to insert our button.

/* $this->Template->gdv = $arrGdv; $this->Template->width = $objCategory->width; $this->Template->height = $objCategory->height; $this->Template->categories = $arrCategories; */ }

So far, we've created the basic plugin file but the plugin doesn't do anything yet. So let's add some functionality.

### Completing the Plugin DeclarationBefore adding functionality to the plugin, we need to set up some files and file structures.

1.  First, create a **Template** folder and add an empty template file to it. The Contao CMS will write data that we declare for the template to this file. The file name for is **mod\_groupdocsviewer** - the same that we called our protected variable.
2.  Create a **languages** folder in the plugin's root folder and, in this folder, create one an **en** folder. In the **en**folder, create two files which will contain a string declaration of all titles and messages for our plugin.![]( "Image 1 - GD Viewer tree structure")

#### modules.phpThe first file is named **modules.php** and contain basic data such as the plugin name:

As you can see, even in language files there has to be a plugin info block and a line of code that limits access. So in this file we have only one line of code which declares an array with the plugin name and transfers it to the CMS's global data.

#### tl\_gdv.phpThe second language file is named **tl\_gdv.php** and contains all local names, titles and messages for our plugin:

Remember that all data is declared as arrays and transferred to the CMS's Global arrays. Also in this file we have JavaScript code which gets a list of sidebar elements and adds links to our plugin details:

class GrouDocs_Details{ function groupdocs_owner(){ print “”; // admin interface echo " setTimeout(function(){ var GroupDocsAcc = document.getElementsByClassName(’tl_file_list’); GroupDocsAcc[0].innerHTML = ‘GroupDocs Details’; },500); “; print “”; }}

You must write the JavaScript code as a simple text by using the 'echo' command. Also in this language file we declare all dependences and includes such as icons etc. That's the last step of the plugin declaration. Now we will add some useful functionality.

### Adding Functionality

1.  Create three folders: **html**, **config** and **dca**.
2.  Place an icon .gif file, 16x16 pixels, in the **html** folder. That's all we need to do with the **html** folder.
3.  In the **dca**folder, create two files:
    1.  .htaccess
    2.  tl\_gdv.php

#### htaccess

order deny,allow deny from all

That's all. This code gave access to this folder from ather web pages of Admin side where user can bee.

#### tl\_gdv.phpThe code for the second file:

#### The Config FolderThe most important and interesting files are placed in the **Config** folder:

*   **.htaccess**
*   **config.php**
*   **database.sql**

1.  Create these three files in the **config** folder.
2.  The **.htaccess** file is a copy of **.htaccess** file created in the **dca** folder. We need this file here for the same purposes.
3.  The **config.php** file contains all the plugin's usefull logic. You'll find the code below.

As you already know, we have the basic plugin info block. Then let's take a look at the code. This block inserts the icon file:

array_insert($GLOBALS[‘BE_MOD’][‘content’], 3, array ( ‘groupdocs_viewer’ => array ( ’tables’ => array(’tl_gdv’), ‘icon’ => ‘system/modules/groupdocs_viewer/html/groupdocs.gif’ ) ));

Contao uses the TinyMCE editor so we can use this as the starting point to get the position for where to place our button, and recognize if a user turns on page editing or not. Here is the code:

// Just add JS to Back End where using TinyMCE $GLOBALS[‘TL_HOOKS’][‘outputBackendTemplate’][] = array(‘ArticleAddGroupDocs’, ‘javaScriptFileID’); class ArticleAddGroupDocs{ public function javaScriptFileID($strContent, $strTemplate) { if ($strTemplate == ‘be_main’) { if($_GET[‘do’]==‘article’ && $_GET[‘act’]==‘edit’) print “ //build GroupDocs Button just above Text Editor setTimeout(function(){ var place_for_but = document.getElementById(‘pal_text_legend’); var leg = place_for_but.getElementsByTagName(’legend’)[0]; var btn=document.createElement(‘input’); btn.type = ‘button’; = ‘groupdocsv’ btn.value = ‘Embed GroupDocs Viewer’; btn.onclick = function() { insertGroupDocsIframe(); }; insertAfter(leg, btn); },500);

			function insertGroupDocsIframe(){
					// Enter GroupDocs File ID
					var ans=prompt('Enter GroupDocs File ID:','');
					if(ans.length<50) { alert('Sorry, but this File ID is too short'); return false; }
					if(ans.length>70) { alert('Sorry, but this File ID is too big'); return false; }
					// all good continue
                    var CMSNAME = 'Contao'
                    var CMSVERSION = '2.11.6'
					var iframe = '<iframe src=\\"'+ans+'?&referer='+CMSNAME+'/'+CMSVERSION+'\\" frameborder=\\"0\\" width=\\"600\\" height=\\"400\\"></iframe>';
					var tinyMceContent = tinyMCE.activeEditor.getContent();
					// set content
			// as in jquery .after()
			function insertAfter(referenceNode, newNode) {
				referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);


As I mentioned, we must use JavaScript as simple text and include it to the page by using **echo** or **print** commands. This JavaScript receives the button position and creates the button:

//build GroupDocs Button just above Text Editor setTimeout(function(){ //Set timeout that the page would be loaded completely var place_for_but = document.getElementById(‘pal_text_legend’); //Get element to place our button to him var leg = place_for_but.getElementsByTagName(’legend’)[0]; //Get legend element var btn=document.createElement(‘input’); //Creation of button btn.type = ‘button’; //Declare button type as ‘button’ = ‘groupdocsv’ //Declare button id as ‘groupdocsv’ btn.value = ‘Embed GroupDocs Viewer’; //Declare button value btn.onclick = function() { insertGroupDocsIframe(); }; //Declare function which will be executed on click insertAfter(leg, btn); //Inserting button above legend },500);

function insertGroupDocsIframe(){ // Enter GroupDocs File ID var ans=prompt(‘Enter GroupDocs File ID:’,’’); //Genaretion of dialog window if(ans.length<50) { alert(‘Sorry, but this File ID is too short’); return false; } //Check entered by user data lenght if(ans.length>70) { alert(‘Sorry, but this File ID is too big’); return false; } // all good continue var CMSNAME = ‘Contao’ var CMSVERSION = ‘2.11.6’ //Next long line of code it’s our iframe to which we transfer entered by user File GUID var iframe = ‘<iframe src=\“'+ans+'?&referer='+CMSNAME+'/'+CMSVERSION+'\” frameborder=\“0\” width=\“600\” height=\“400\">’; var tinyMceContent = tinyMCE.activeEditor.getContent(); //This line get editor content

					tinyMCE.activeEditor.setContent(tinyMceContent+iframe); //Here we add our iframe to editor
			// as in jquery .after()
			function insertAfter(referenceNode, newNode) {
				referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);

## The Final PluginThis is the plugin in action: \[caption id="attachment\_1841" align="alignnone" width="600" caption="Plugin structure"\]![Plugin structure]( "Plugin structure")\[/caption\] \[caption id="attachment\_1842" align="alignnone" width="600" caption="Button"\]![Button]( "Button")\[/caption\] \[caption id="attachment\_1843" align="alignnone" width="602" caption="Dialog"\]![Dialog]( "Dialog")\[/caption\] \[caption id="attachment\_1844" align="alignnone" width="598" caption="Iframe"\]![Iframe]( "Iframe")\[/caption\] That's all for today. See you in the next article.