Requirements
- Contao CMS
- PHP 5.3
- JavaScript
Preparation
To create a GroupDocs Viewer plugin for Contao CMS:- Install Contao CMS. The installation of this CMS is a simple.
- Allow GroupDocs <iframe> to appear go to Admin > Setting > Security settings > Allowed HTML tags and just add <iframe> at the end.
- 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 Plugin
This 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:<?php if (!defined('TL_ROOT')) die('You can not access this file directly!'); /** * GroupDocs * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, please visit the Free * Software Foundation website at http://www.gnu.org/licenses/. * * PHP version 5 * @copyright 2012 * @author sales@groupdocs.com * @license GPL */ /** * @package Controller */ class ModuleGroupdocsViewer extends Module { /** * Template * @var string */ protected $strTemplate = 'mod_groupdocsviewer'; /** * Display a wildcard in the back end * @return string */ public function generate() { 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() { /* $this->Template->gdv = $arrGdv; $this->Template->width = $objCategory->width; $this->Template->height = $objCategory->height; $this->Template->categories = $arrCategories; */ } } ?>
The Code Line by Line
Let’s take a look at the code we inserted. The first lineif (!defined('TL_ROOT')) die('You can not access this file directly!');
class ModuleGroupdocsViewer extends Module
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; */ }
Completing the Plugin Declaration
Before adding functionality to the plugin, we need to set up some files and file structures.- 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.
- Create a languages folder in the plugin’s root folder and, in this folder, create one an en folder. In the enfolder, create two files which will contain a string declaration of all titles and messages for our plugin.
modules.php
The first file is named modules.php and contain basic data such as the plugin name:<?php if (!defined('TL_ROOT')) die('You can not access this file directly!'); /** * GroupDocs * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, please visit the Free * Software Foundation website at http://www.gnu.org/licenses/. * * PHP version 5 * @copyright 2012 * @author sales@groupdocs.com * @license GPL */ /** * Back end modules */ $GLOBALS['TL_LANG']['MOD']['groupdocs_viewer'] = array('GroupDocs Viewer', 'Module name'); /** * Front end modules */ //$GLOBALS['TL_LANG']['FMD']['groupdocs_viewer'] = array('GDV List', 'Module list'); ?>
tl_gdv.php
The second language file is named tl_gdv.php and contains all local names, titles and messages for our plugin:<?php if (!defined('TL_ROOT')) die('You can not access this file directly!'); /** * GroupDocs * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, please visit the Free * Software Foundation website at http://www.gnu.org/licenses/. * * PHP version 5 * @copyright 2012 * @author sales@groupdocs.com * @license GPL */ /** * Table tl_gdv */ $GLOBALS['TL_DCA']['tl_gdv'] = array ( // Config 'config' => array ( 'dataContainer' => 'Table', //'ptable' => 'tl_gdv', ), // List 'list' => array ( 'global_operations' => array ( 'all' => array ( 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], 'href' => 'act=select', 'class' => 'header_edit_all', 'attributes' => 'onclick="Backend.getScrollOffset();"', 'button_callback' => array('GrouDocs_Details', 'groupdocs_owner'), ) ), 'operations' => array ( 'edit' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['edit'], 'href' => 'act=edit', 'icon' => 'edit.gif' ), 'copy' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['copy'], 'href' => 'act=copy', 'icon' => 'copy.gif' ), 'delete' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['delete'], 'href' => 'act=delete', 'icon' => 'delete.gif', 'attributes' => 'onclick="if (!confirm(\'' . $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] . '\')) return false; Backend.getScrollOffset();"' ), 'show' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['show'], 'href' => 'act=show', 'icon' => 'show.gif' ) ) ), // Palettes 'palettes' => array ( 'default' => '{title_legend},apiKey,clientId,width,height;' ), // Fields 'fields' => array ( 'id' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['id'], 'inputType' => 'text', 'search' => false, 'eval' => array('mandatory'=>true) ), 'apiKey' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['apiKey'], 'inputType' => 'text', 'search' => false, 'eval' => array('mandatory'=>true, 'maxlength'=>128, 'tl_class'=>'w50') ), 'clientId' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['clientId'], 'inputType' => 'text', 'search' => false, 'eval' => array('mandatory'=>true, 'maxlength'=>128, 'tl_class'=>'w50') ), 'width' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['width'], 'inputType' => 'text', 'search' => false, 'eval' => array('mandatory'=>true, 'maxlength'=>4, 'tl_class'=>'w50') ), 'height' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['height'], 'inputType' => 'text', 'search' => false, 'eval' => array('mandatory'=>true, 'maxlength'=>4, 'tl_class'=>'w50') ), /* 'image' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['image'], 'inputType' => 'fileTree', 'eval' => array('files'=>true, 'filesOnly'=>true, 'fieldType'=>'radio') ),*/ ) ); /** @calss GrouDocs_Details groupdocs_owner() - method manipulate */ class GrouDocs_Details{ function groupdocs_owner(){ print "<script>"; // admin interface echo " setTimeout(function(){ var GroupDocsAcc = document.getElementsByClassName('tl_file_list'); GroupDocsAcc[0].innerHTML = 'GroupDocs Details'; },500); "; print "</script>"; }} ?>
class GrouDocs_Details{ function groupdocs_owner(){ print "<script>"; // admin interface echo " setTimeout(function(){ var GroupDocsAcc = document.getElementsByClassName('tl_file_list'); GroupDocsAcc[0].innerHTML = 'GroupDocs Details'; },500); "; print "</script>"; }}
Adding Functionality
- Create three folders: html, config and dca.
- Place an icon .gif file, 16×16 pixels, in the html folder. That’s all we need to do with the html folder.
- In the dcafolder, create two files:
- .htaccess
- tl_gdv.php
htaccess
order deny,allow deny from all
tl_gdv.php
The code for the second file:<?php if (!defined('TL_ROOT')) die('You can not access this file directly!'); /** * GroupDocs * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, please visit the Free * Software Foundation website at http://www.gnu.org/licenses/. * * PHP version 5 * @copyright 2012 * @author sales@groupdocs.com * @license GPL */ /** * Table tl_gdv */ $GLOBALS['TL_DCA']['tl_gdv'] = array ( // Config 'config' => array ( 'dataContainer' => 'Table', //'ptable' => 'tl_gdv', ), // List 'list' => array ( 'global_operations' => array ( 'all' => array ( 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], 'href' => 'act=select', 'class' => 'header_edit_all', 'attributes' => 'onclick="Backend.getScrollOffset();"', 'button_callback' => array('GrouDocs_Details', 'groupdocs_owner'), ) ), 'operations' => array ( 'edit' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['edit'], 'href' => 'act=edit', 'icon' => 'edit.gif' ), 'copy' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['copy'], 'href' => 'act=copy', 'icon' => 'copy.gif' ), 'delete' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['delete'], 'href' => 'act=delete', 'icon' => 'delete.gif', 'attributes' => 'onclick="if (!confirm(\'' . $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] . '\')) return false; Backend.getScrollOffset();"' ), 'show' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['show'], 'href' => 'act=show', 'icon' => 'show.gif' ) ) ), // Palettes 'palettes' => array ( 'default' => '{title_legend},apiKey,clientId,width,height;' ), // Fields 'fields' => array ( 'id' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['id'], 'inputType' => 'text', 'search' => false, 'eval' => array('mandatory'=>true) ), 'apiKey' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['apiKey'], 'inputType' => 'text', 'search' => false, 'eval' => array('mandatory'=>true, 'maxlength'=>128, 'tl_class'=>'w50') ), 'clientId' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['clientId'], 'inputType' => 'text', 'search' => false, 'eval' => array('mandatory'=>true, 'maxlength'=>128, 'tl_class'=>'w50') ), 'width' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['width'], 'inputType' => 'text', 'search' => false, 'eval' => array('mandatory'=>true, 'maxlength'=>4, 'tl_class'=>'w50') ), 'height' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['height'], 'inputType' => 'text', 'search' => false, 'eval' => array('mandatory'=>true, 'maxlength'=>4, 'tl_class'=>'w50') ), /* 'image' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_gdv']['image'], 'inputType' => 'fileTree', 'eval' => array('files'=>true, 'filesOnly'=>true, 'fieldType'=>'radio') ),*/ ) ); /** @calss GrouDocs_Details groupdocs_owner() - method manipulate */ class GrouDocs_Details{ function groupdocs_owner(){ print "<script>"; // admin interface echo " setTimeout(function(){ var GroupDocsAcc = document.getElementsByClassName('tl_file_list'); GroupDocsAcc[0].innerHTML = 'GroupDocs Details'; },500); "; print "</script>"; }} ?>This second file is a copy of the language file with the same name – tl_gdv.php. We do this in order that Contao CMS will have access to this file from any Admin side page where user edit the content of this page.
The Config Folder
The most important and interesting files are placed in the Config folder:- .htaccess
- config.php
- database.sql
- Create these three files in the config folder.
- The .htaccess file is a copy of .htaccess file created in the dca folder. We need this file here for the same purposes.
- The config.php file contains all the plugin’s usefull logic. You’ll find the code below.
<?php if (!defined('TL_ROOT')) die('You can not access this file directly!'); /** * GroupDocs * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, please visit the Free * Software Foundation website at http://www.gnu.org/licenses/. * * PHP version 5 * @copyright 2012 * @author sales@groupdocs.com * @license GPL */ array_insert($GLOBALS['BE_MOD']['content'], 3, array ( 'groupdocs_viewer' => array ( 'tables' => array('tl_gdv'), 'icon' => 'system/modules/groupdocs_viewer/html/groupdocs.gif' ) )); // 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 "<script> //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'; btn.id = '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=\"https://apps.groupdocs.com/document-viewer/embed/'+ans+'?&referer='+CMSNAME+'/'+CMSVERSION+'\" frameborder=\"0\" width=\"600\" height=\"400\"></iframe>'; var tinyMceContent = tinyMCE.activeEditor.getContent(); // set content tinyMCE.activeEditor.setContent(tinyMceContent+iframe); } // as in jquery .after() function insertAfter(referenceNode, newNode) { referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); } </script>"; } } } ?>
array_insert($GLOBALS['BE_MOD']['content'], 3, array ( 'groupdocs_viewer' => array ( 'tables' => array('tl_gdv'), 'icon' => 'system/modules/groupdocs_viewer/html/groupdocs.gif' ) ));
// 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 "<script> //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'; btn.id = '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=\"https://apps.groupdocs.com/document-viewer/embed/'+ans+'?&referer='+CMSNAME+'/'+CMSVERSION+'\" frameborder=\"0\" width=\"600\" height=\"400\"></iframe>'; var tinyMceContent = tinyMCE.activeEditor.getContent(); // set content tinyMCE.activeEditor.setContent(tinyMceContent+iframe); } // as in jquery .after() function insertAfter(referenceNode, newNode) { referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); } </script>"; } }
//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' btn.id = '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);We’ve created a button and added its function. Then we have a function that generates a dialog window and places an iframe in the editor.
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=\"https://apps.groupdocs.com/document-viewer/embed/'+ans+'?&referer='+CMSNAME+'/'+CMSVERSION+'\" frameborder=\"0\" width=\"600\" height=\"400\"></iframe>'; 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); }That’s it. We created a GroupDocs Viewer plugin for Contao CMS.
The Final Plugin
This is the plugin in action:
Plugin structure

Button

Dialog

Iframe