User Tools

Site Tools


Sidebar

js#vista.png msort nsort

vtigercrm:module_creation

Creating a Module

This is meant as an overview of module creation for VTiger as well as associated notes.

As we all know, the documentation of the VTiger vtlib module and it's associated API is not quite what it should be. This is NOT unusual in OSS based Projects and unfortunately is also doomed to remain so. Therefore it is left to us to make due and help each other. So if you find any information that is either incorrect or missing just let me know. PLEASE!!!

Basic outline

To create a module the following steps need to be taken.

  1. create your vtlib.Test.Create.Module1.php file so that vtlib can create/install your module in the first place.
  2. test install your module & modify your vtlib.Test.Create.Module1.php script until all is correct.
  3. create your Manifest.xml from the working vtlib.Test.Create.Module1.php so that the module can be installed.
  4. in the module/<ModuleName> directory is where you can do live testing and modifications until all is working.
  5. create your module package

vtlib.Test.html

Why they didn't go into details here I have no idea. Anyway, vtlib.Test.html is a simple html file which calls your vtlib.Test.Create.Module1.php script which contains your actual vtlib install script for your module. Both files can be named anything you want and, in fact, you don't even really need vtlib.Test.html. A simple call to vtlib.Test.Create.Module1.php is more than sufficient to get your module installed. As an example the first vtlib.Test.html that I used (just found it on a rep somewhere on the net):

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>vtlib Test Suite</title>
<style type="text/css">@import url("themes/softed/style.css");br { display: block; margin: 2px; }</style>
</head>

<body class=small style="font-size: 12px; margin: 2px; padding: 2px;">
<a href='index.php'><img src="themes/softed/images/vtiger-crm.gif" alt="vtiger CRM" title="vtiger CRM" border=0></a><hr style="height: 1px">
<h2>vtlib - vtiger development Library</h2>
<ul>
<li><a target=_blank href='vtlib.Test.Create.Module1.php'>Create Repository Module</a></li>
<li><a target=_blank href='vtlib.download.php'>Download Repository Module</a></li>
<li><a target=_blank href='vtlib.delete.php'>Delete module</a></li>
</ul>

</body>
</html>

vtlib.Test.Create.Module1.php

As an example I created the file vtlib.Install.Repository.php (same as vtlib.Test.Create.Module1.php). This file installs the Module and does not actually create anything. You upload your module in the modules directory (in my case modules/Repository) and you call up http://localhost/vtigercrm/vtlib.Install.Repository.php. if an error occurred during the install you will be informed. If all went well you can take the information in the PHP script to form your Manifest.xml file for your install package. As an example the beta version of my install script for the Repository Module:

<?php
// Turn on debugging level
$Vtiger_Utils_Log = true;
include_once('vtlib/Vtiger/Menu.php');
include_once('vtlib/Vtiger/Module.php');

// Create module instance and save it first
$module = new Vtiger_Module();
$module->name = 'Repository';
$module->save();

// Initialize all the tables required
$module->initTables();

// Add the basic module block
$block1 = new Vtiger_Block();
$block1->label = 'LBL_REPOSITORY_INFORMATION';
$module->addBlock($block1);

// Add custom block (required to support Custom Fields)
$block2 = new Vtiger_Block();
$block2->label = 'LBL_CUSTOM_INFORMATION';
$module->addBlock($block2);

/** Create required fields and add to the block */
$field1 = new Vtiger_Field();
$field1->name = 'RepositoryID';
$field1->label = 'Repository ID';
$field1->table = $module->basetable;
$field1->column = 'repositoryid';
$field1->columntype = 'int(11)';
$field1->uitype = 1;
$field1->typeofdata = 'I~M';
$field1->presence = 0;
$field1->quickcreate = 1;
$field1->masseditable = 0;
$field1->displaytype= 2;
$block1->addField($field1); /** Creates the field and adds to block */
// Set at-least one field to identifier of module record
$module->setEntityIdentifier($field1);

$field2 = new Vtiger_Field();
$field2->name = 'RepositoryName';
$field2->label = 'Repository Name';
$field2->table = $module->basetable;
$field2->column = 'repositoryname';
$field2->columntype = 'VARCHAR(255)';
$field2->uitype = 2;
$field2->typeofdata = 'V~M';
$field2->presence = 0;
$field2->quickcreate = 1;
$field2->masseditable = 0;
$field2->displaytype= 1;
$block1->addField($field2);

$field3 = new Vtiger_Field();
$field3->name = 'RepositoryType';
$field3->label = 'Repository Type';
$field3->columntype = 'VARCHAR(10)';
$field3->uitype = 15;
$field3->typeofdata = 'V~M';
$field3->presence = 0;
$field3->quickcreate = 1;
$field3->masseditable = 0;
$field3->displaytype= 1;
$field3->setPicklistValues( Array ('cvs', 'git', 'ssh+svn', 'svn') );
$block1->addField($field3); /** table, column, label, set to default values */

$field4 = new Vtiger_Field();
$field4->name = 'RepositoryHost';
$field4->label= 'Repository Host';
$field4->columntype = 'VARCHAR(255)';
$field4->uitype = 2;
$field4->typeofdata = 'V~M';
$field4->presence = 0;
$field4->quickcreate = 1;
$field4->masseditable = 0;
$field4->displaytype= 1;
$block1->addField($field4);

$field5 = new Vtiger_Field();
$field5->name = 'RepositoryPort';
$field5->label = 'Repository Port';
$field5->columntype = 'VARCHAR(6)';
$field5->uitype = 53;
$field5->typeofdata = 'V~M';
$field5->presence = 0;
$field5->quickcreate = 1;
$field5->masseditable = 0;
$field5->displaytype= 1;
$block1->addField($field5);

$field6 = new Vtiger_Field();
$field6->name = 'RepositoryUser';
$field6->label= 'Repository User';
$field6->columntype = 'VARCHAR(32)';
$field6->uitype = 2;
$field6->typeofdata = 'V~M';
$field6->presence = 0;
$field6->quickcreate = 1;
$field6->masseditable = 0;
$field6->displaytype= 1;
$block1->addField($field6);

$field7 = new Vtiger_Field();
$field7->name = 'RepositoryPass';
$field7->label= 'Repository Password';
$field7->columntype = 'VARCHAR(32)';
$field7->uitype = 2;
$field7->typeofdata = 'V~M';
$field7->presence = 0;
$field7->quickcreate = 1;
$field7->masseditable = 0;
$field7->displaytype= 1;
$block1->addField($field7);

$field8 = new Vtiger_Field();
$field8->name = 'RepositoryPath';
$field8->label= 'Repository Path';
$field8->columntype = 'VARCHAR(255)';
$field8->uitype = 2;
$field8->typeofdata = 'V~M';
$field8->presence = 0;
$field8->quickcreate = 1;
$field8->masseditable = 0;
$field8->displaytype= 1;
$block1->addField($field8);
/** END */

// Create default custom filter (mandatory)
$filter1 = new Vtiger_Filter();
$filter1->name = 'All';
$filter1->isdefault = true;
$module->addFilter($filter1);

// Add fields to the filter created
$filter1->addField($field1)->addField($field2, 1)->addField($field5, 2);

/** Associate other modules to this module */
$module->setRelatedList(Vtiger_Module::getInstance('Project'), 'Project',
Array('ADD','SELECT'));

/** Set sharing access of this module */
$module->setDefaultSharing('Private');

/** Enable and Disable available tools */
$module->enableTools(Array('Import', 'Export'));
$module->disableTools('Merge');
?>

vtlib.delete.php

This file deinstalls (hopefully cleanly) your installed module. below you see as an example the code to deinstall the Repository module (as you can see it must also be in the base directory of your VTiger install):

<?php
$Vtiger_Utils_Log = true;
include_once('vtlib/Vtiger/Module.php');

$module = Vtiger_Module::getInstance('Repository');
if($module) {
    $module->delete();
}
?>

vtlib.download.php

My vtlib.installer.php

Seeing as how I will be doing a few different modules I thought it would be easier for me to adopt a naming convention for the installer files and an installer to control it all. I now name all my vtlib.Test.Create.Module1.php files vtlib.Control.<ModuleName>.php. This way the following script (vtlib.installer.php) can find them and offer them for installation, deinstallation and downloading (this is a beta release and I will be prettying it up a bit later when I get time):

<?php
/**#@+
 * Extra GLOB constant for safe_glob()
 */
define('GLOB_NODIR',256);
define('GLOB_PATH',512);
define('GLOB_NODOTS',1024);
define('GLOB_RECURSE',2048);
/**#@-*/

/**
 * A safe empowered glob().
 *
 * Function glob() is prohibited on some server (probably in safe mode)
 * (Message "Warning: glob() has been disabled for security reasons in
 * (script) on line (line)") for security reasons as stated on:
 * http://seclists.org/fulldisclosure/2005/Sep/0001.html
 *
 * safe_glob() intends to replace glob() using readdir() & fnmatch() instead.
 * Supported flags: GLOB_MARK, GLOB_NOSORT, GLOB_ONLYDIR
 * Additional flags: GLOB_NODIR, GLOB_PATH, GLOB_NODOTS, GLOB_RECURSE
 * (not original glob() flags)
 * @author BigueNique AT yahoo DOT ca
 * @updates
 * - 080324 Added support for additional flags: GLOB_NODIR, GLOB_PATH,
 *   GLOB_NODOTS, GLOB_RECURSE
 */
function safe_glob($pattern, $flags=0) {
    $split=explode('/',str_replace('\\','/',$pattern));
    $mask=array_pop($split);
    $path=implode('/',$split);
    if ($path == "") $path=".";
    if (($dir=opendir($path))!==false) {
        $glob=array();
        while(($file=readdir($dir))!==false) {
            // Recurse subdirectories (GLOB_RECURSE)
            if( ($flags&GLOB_RECURSE) && is_dir($file) && (!in_array($file,array('.','..'))) )
                $glob = array_merge($glob, array_prepend(safe_glob($path.'/'.$file.'/'.$mask, $flags),
                    ($flags&GLOB_PATH?'':$file.'/')));
            // Match file mask
            if (fnmatch($mask,$file)) {
                if ( ( (!($flags&GLOB_ONLYDIR)) || is_dir("$path/$file") )
                  && ( (!($flags&GLOB_NODIR)) || (!is_dir($path.'/'.$file)) )
                  && ( (!($flags&GLOB_NODOTS)) || (!in_array($file,array('.','..'))) ) )
                    $glob[] = ($flags&GLOB_PATH?$path.'/':'') . $file . ($flags&GLOB_MARK?'/':'');
            }
        }
        closedir($dir);
        if (!($flags&GLOB_NOSORT)) sort($glob);
        return $glob;
    } else {
        return false;
    }
}

$action = $_REQUEST["action"];
$newmodule = $_REQUEST["module"];

if($action == "install" && $newmodule !== ""){
    require_once 'vtlib.Control.'.$newmodule.'.php';
    exit;
}elseif($action == "uninstall" && $newmodule !== ""){
    $Vtiger_Utils_Log = true;
    include_once('vtlib/Vtiger/Module.php');

    $module = Vtiger_Module::getInstance($newmodule);
    if($module) {
        $module->delete();
    }
    exit;
}elseif($action == "download" && $newmodule !== ""){
    require_once('vtlib/Vtiger/Package.php');
    require_once('vtlib/Vtiger/Module.php');
    $package = new Vtiger_Package();
    $package->export(Vtiger_Module::getInstance($newmodule), 'test/vtlib', $newmodule.'.zip', true);
    exit;
}else{
    if (!$module_files = safe_glob("vtlib.Control.*.php")) $module_files=false;

    //print_r($module_files);
    
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>vtlib Module Install Suite</title>
<style type="text/css">@import url("themes/softed/style.css");br { display: block; margin: 2px; }</style>
</head>

<body class=small style="font-size: 12px; margin: 2px; padding: 2px;">
<a href='index.php'><img src="themes/softed/images/vtiger-crm.gif" alt="vtiger CRM" title="vtiger CRM" border=0></a><hr style="height: 1px">
<h2>vtlib - vtiger development Library</h2>
<ul>
<?php
if(is_array($module_files)){
    foreach($module_files as $mfile){
        $mfile = explode("vtlib.Control.", $mfile);
        $mfile = explode(".php", $mfile[1]);
        echo "<li><table width=100% cell_padding=0><tr><td>Found ".$mfile[0]." Module:</td><td><a target=_blank href='vtlib.installer.php?action=install&module=".$mfile[0]."'>Install ".$mfile[0]." Module</a></td>
        <td><a target=_blank href='vtlib.installer.php?action=download&module=".$mfile[0]."'>Download ".$mfile[0]." Module</a></td>
        <td><a target=_blank href='vtlib.installer.php?action=uninstall&module=".$mfile[0]."'>Uninstall ".$mfile[0]." Module</a></li></td></tr></table>";
    }
}else echo "No Modules found to install";
?>
</ul>

</body>
</html>
<?php
}
?>
vtigercrm/module_creation.txt · Last modified: 2020/02/24 11:16 (external edit)