Simple Groupware Customization
This is a short tutorial about customizing Simple Groupware to your needs. If you have any further questions, please use the Forum.
Folder structure
| bin/ | translated source files, will be filled automatically by the setup, for contents see "src/". |
| custom/ | folder for individual customizations (see persistent changes) |
| docs/ | changelog, information about the included libraries and the package contents |
| -- map/ | contains a map showing the call structure of the functions in the code (can be viewed with http://<your-server>/<sgs-dir>/docs/map/graph.php) |
| import/ | folder to import files into the tree using mountpoints |
| lang/ | translation files used to localize Simple Groupware to different languages |
| simple_cache/ | cache directories used to store temporary information |
| simple_store/ | uploaded files, attachments (esp. emails module), user directories, backups, lock files, and the system configuration file (config.php) |
| src/ | system tools (console, file browser), scripts to download files, get data for search boxes and chat, preview content (wiki, charts) |
| -- core/ | code directory for core functions (assets, import, export, triggers, folders, xml, input validation), setup, setup settings |
| -- ext/ | background images, icons, layout components (calendar, HTML editor, spreadsheet editor, etc.), Javascript files (user interface) |
| -- lib/ | external libraries for handling mails, templates, archives and images (e.g. Smarty, PmWiki, Pear, vCard parse, Text_Wiki) |
| -- modules/ | folder templates, libraries for the data handlers, user modules, system modules |
| -- templates/ | Smarty templates, stylesheets (user interface) |
| -- tools/ | binary tools to get plain text summaries for documents, resize images (win32) and other programs like the PHP/Java bridge |
Language files are not parsed by Simple Groupware for every page request. Therefore there are two folders containing the sources and the translated sources: "src/" and "bin/". After the installation, only the "bin/" folder will be used by the system, so all changes should be made here.
In essence, Simple Groupware is a PHP application which stores the user's data, including the folder tree structure, in a database (SQL server). All kinds of attachments are stored in "<sgs-dir>/simple_store/".
Database structure
Apart from a few special modules, each module has an associated table in the database that holds that module's data. For example, each "contact" is a record in the "simple_contacts" table, each HTML document is a record in the simple_htmldocs table and so on.
Each module has a corresponding sgsML file which defines the fields within that module's table (see <sgs-dir>/modules/schema/*.xml). The sgsML file also specifies the user interface to be used to display and edit each field, e.g. text, date, drop-down list, etc. For example, the Contacts module is defined in "<sgs-dir>/bin/modules/schema/contacts.xml".
Every dataset automatically contains common fields like created (creation time), created by (originator), lastmodified (modification time), lastmodifiedby (editor), id (unique identifier), dsize (size of the dataset including files).
The folder tree is represented by its own table in the database (named simple_sys_tree). This table contains one record for each folder with an ID field giving the unique folder number. The tables for the other modules have a "folder" field which references the ID of the "folder" in which each record resides. For example, "simple_sys_tree" has a 1:n relationship to "simple_contacts".
Some system tables in detail:
simple_sys_tree: contains the folders in the tree
| Field(s) | Description |
| id | unique ID of the folder |
| ftitle | name of the folder |
| ftype | module assigned to the folder, e.g. "sys_users" for "schema_sys/users.xml", "blank" if none |
| fmountpoint | describes mountpoint information if available (see data handlers) |
| lft, rgt, flevel, parent | describe the position of the folder in the tree |
| rread_users, rread_groups, rwrite_users, ... | describe the permissions assigned to users and groups |
| rexception_users, rexception_groups | describes exceptional permissions assigned to users and groups |
| fcount, fchcount | numbers of datasets in the folder, in its subfolders |
| fsizecount, fchsizecount | size of datasets in the folders, in its subfolders |
| fquota | maximum folder size in MB |
| anchor | if the folder has a function, e.g. a user's home directory, project directory, etc. |
| default_values | Default values for new assets, e.g. field1=value1 field2=value2 |
simple_seq_*: contains the highest ID for a special table, required for creating new (unique) IDs
simple_blank: empty table used by the default module ("schema/blank.xml")
Change the "<simple> Groupware" logo and link in the upper right corner
The logos can be changed by placing new files at "custom/ext/images/<new_file>.gif". Then copy "bin/templates/core_css.conf" to "custom/templates/core_css.conf", and edit the new file, replace:
logo = ext/images/logo.gif
logo_link = http://www.simple-groupware.de
logo_login = ext/images/sgs_logo.gif
with:
logo = ext/images/<new_file>.gif
logo_link = http://<your-homepage>
logo_login = ext/images/<new_file>.gif
When finished, make sure to clear the output cache.
Change the background in the login screen
The image can be changed by placing a new file at "custom/ext/images/bg_bridge.jpg".
Remove the copyright in the lower right corner and the login screen
This is not allowed. (see this article from PHP-Nuke)
Change the webpage icon next to the URL in the browser
The icon can be changed by placing a new file at "custom/ext/images/favicon.ico". If you need a free icon editor, I reommend IcoFX.
Change the top menu
The top menu is defined at the end of "bin/ext/js/functions.js". To make changes, copy "bin/ext/js/functions.js" to "custom/ext/js/functions.js" and edit the new file. There are some functions to control the menu structure:
| menu_begin() | initializes the top menu |
| menuitem() | creates a new menu item in the first level and is followed by the smenu_begin() function |
| smenu_begin() | initializes the second menu level which gets finished by the smenu_end() function |
| smenuitem() | creates a new menu item in the second level, parameters are the description and the Javascript action that should take place |
| sWin() | opens a URL in the same window |
| nWin() | opens a URL in a new window |
| smenu_hr() | creates a new line in the second level |
| smenu_end() | finishes the second menu level |
| menubutton() | creates a new menu button in the first level, does not open a menu in the second level |
| menu_end() | finishes the top menu |
Example for a new menu entry:
menu_begin();
...
menuitem("My Company");
smenu_begin();
smenuitem("Intranet","sWin('http://my_company/intranet')");
smenuitem("Other page","nWin('http://other_page')");
smenu_end();
...
menu_end();
Changing templates
All templates are written with the Smarty Template Engine and are stored at "bin/templates/*.tpl". The templates will be compiled to PHP and stored at "simple_cache/smarty/". The Smarty manual can be found here.
To make changes to a template file, copy "bin/templates/<template_file>" to "custom/templates/<template_file>" and edit the new file.
When finished, make sure to clear the output cache. To let this happen automatically, see the DEBUG parameter below.
Changing themes, styles and formats
Themes are stored at "bin/templates/core_css.conf". Every theme is initiated with "[theme_name]" and contains some variables in "field = value" pairs. The values contain typical CSS colors and font definitions. The first section is not initiated by a "[theme_name]" and contains common variables that belong to all themes. That means that all variables in a theme section override the common variables. By default, every user gets the "core" theme. This can be changed in setup settings.
To make changes, copy "bin/templates/core_css.conf" to "custom/templates/core_css.conf" and edit the new file.
To create your own theme, it is recommended to expand the "[core]" section. Smaller changes like the "logo" or the "logo_link" can be also made to the common variables in the first section.
Simple Groupware can automatically change the colors of the folder icons in the tree. This is configured by the field "folder" which can be filled with "adapt" to activate this function.
A background image can be also added to the user interface by filling the variable "bg_full" with a filename that is located at "custom/ext/images/".
Other styles can be set in the cascading style sheet located at "bin/templates/core.css". To make changes, copy "bin/templates/core.css" to "custom/templates/core.css" and edit the new file.
Translation / localization
If You want to translate or localize Simple Groupware for Your language, please click here.
Create a new sgsML module
Creating a new module is basically creating a new sgsML file in "<sgs-dir>/custom/modules/schema". The simplest way is to copy the xml file of an existing module that is similar to what you want, open it in a text editor then add and delete field definitions as required. E.g. copy "<sgs-dir>/bin/modules/schema/contacts.xml" to "<sgs-dir>/custom/modules/schema/contacts2.xml". The sgsML tutorial gives an example and there is also a reference guide available.
Note: To be able to assign new modules to folders, remember to register the module in "custom/modules/schema/modules.txt" (can be copied from "bin/modules/schema/modules.txt").
Customize modules
All modules in Simple Groupware are defined in their own language called sgsML (Simple Groupware Solutions Markup Language). A tutorial is available here.
Use PHP functions to display content in a view
It is possible to load the content of a folder from a PHP function. All content is defined and interpreted in Smarty templates. So it normally looks like this in a module:
<view name="display" displayname="Display" template="display">
</view>
This uses the template "<sgs-dir>/bin/templates/asset_display.tpl" in the view "Display". To load the data from a PHP function, just use:
<view name="display" displayname="Display" function="get_my_data">
</view>
When creating a new module it should look like this:
<table modulename="Custom PHP include" default_view="display" default_sql="no_select" schema_mode="static" load_library="../custom/core/classes/custom.php">
<view name="display" displayname="Display" function="get_my_data">
</view> <field name="id" simple_type="id" displayname="{t}Id{/t}"> </field>
</table>
This loads the data from a function named "custom::get_my_data" which can be placed in "<sgs-dir>/custom/classes/core/custom.php" (load_library attribute). So you need to create the PHP file "custom.php" and write the function into it, e.g.:
class custom {
public static function get_my_data($folder, $view, $params) {
$output = "<b>Hello World</b><br/>";
$output .= "...<br/>";
/* Smarty can be also used here (templates are in templates/*):
*
* $output .= sys::$smarty->fetch("custom.tpl");
*/
// use echo $output to avoid output filtering for bad HTML and Javascript
return $output;
}
}
Note: All modifiers, formatters, triggers and selectors can be also added to the "custom" class.
Note: For security reasons, Simple Groupware automatically filters the output for Javascript and dynamic HTML elements. To avoid this, use "echo $output;" instead of "return $output;".
Note: To be able to assign new modules to folders, remember to register the module in "custom/modules/schema/modules.txt" (can be copied from "bin/modules/schema/modules.txt").
Make changes persistent over new releases and updates
All kinds of changes to the code, new files, images etc. can be made persistent over new releases.
During the update process, all files of the old release are moved to "<sgs-dir>/old", except those contents from the custom folder (<sgs-dir>/custom). Then the new files get extracted. Next, the setup process takes the language file (<sgs-dir>/lang) and the sources (<sgs-dir>/src), and merges both into the bin folder ("<sgs-dir>/bin").
Individual changes to the source code can be made in "<sgs-dir>/custom/customize.php". The following commands can be used to change the Simple Groupware code base:
- Append code:
setup::customize_replace($file,$code_before,$code_before.$append_code); - Replace code:
setup::customize_replace($file,$code_old,$code_new); - Remove code:
setup::customize_replace($file,$code_remove,"");
This is a very low-level technique, but it enables you to change PHP files as well as Javascript files, Smarty templates or other files.
Examples:
Create two modules under "<sgs-dir>/custom/modules/schema/new_module.xml" and "<sgs-dir>/custom/modules/schema/news2.xml".
Copy "<sgs-dir>/bin/modules/schema/modules.txt" to "<sgs-dir>/custom/modules/schema/modules.txt" and add these lines:
new_module|My new module
news2|News2
As an alternative to the "custom/" directory structure, you can use the customization functions which are called in the update or installation process, add the modification commands to "<sgs-dir>/custom/customize.php" (\n = line break):
// add a new module to module list
setup::customize_replace("modules/schema/modules.txt", "wiki|Wiki",
"wiki|Wiki\nnew_module|My new module");
// replace a module in the module list
setup::customize_replace("modules/schema/modules.txt", "\nnews|News","\nnews2|News2");
// remove a module from the module list
setup::customize_replace("modules/schema/modules.txt", "\nwiki|Wiki","");
// use text areas instead of wiki areas in the news module
setup::customize_replace("modules/schema/news.xml", "simple_type=\"wikiarea\"",
"simple_type=\"textarea\"");
Tip: Never forget to document your changes!
"custom/" directory structure
Beginning with Simple Groupware 0.620, there is an additional way to make changes persistent over new releases. Custom modules and functions can be easily persisted with the "custom/" directory structure. This directory structure is included in many operations automatically, so nothing needs to be copied in the update or setup process. E.g. having "<sgs-dir>/custom/modules/schema/tasks.xml" will be automatically used instead of "<sgs-dir>/bin/modules/schema/tasks.xml".
Here are some structures that can be overridden with the "<sgs-dir>/custom/" folder:
- sgsML modules: modules/schema/*.xml, modules/schema_sys/*.xml
- Folder templates (runxml trigger): modules/core/*.xml
- Modules list: modules/schema/modules.txt, modules/schema_sys/modules.txt
- Copy/paste schema mappings: modules/schema/mappings.txt
- Writable popups: modules/core/popup_write.txt
- Images / icons: ext/icons/*, ext/images/*, ext/modules/*, ext/cms/*
- Custom class: core/classes/custom.php
- Folder specific schema: modules/schema/*.xml.<folder_id>
- Differential schema: modules/schema/<module>/<diff-name>.xml
Examples:
You can copy "<sgs-dir>/bin/modules/schema/tasks.xml" to "<sgs-dir>/custom/modules/schema/tasks.xml", then remove or add fields. The changed module will be automatically used in favor of the original module.
To use the changes only in a specific folder, you can copy "<sgs-dir>/bin/modules/schema/tasks.xml" to "<sgs-dir>/custom/modules/schema/tasks.xml.<folder_id>" , then remove or add fields. The changed module will be automatically used in favor of the original module in folder <folder_id>.
Instead of copying the whole tasks module to the custom directory structure, you can define a differential schema for the tasks module. E.g. create a new file "<sgs-dir>/custom/modules/schema/tasks/my_diff.xml". There can be several differential schema files which are merged in alphabetic order of the filename. Please note that "<field>" or "<view>" tags get overwritten when the "name" attribute is identical. To insert a new "<field>" before another existing "<field>", just add a "before" attribute to the new "<field>" representing the name attribute of the following "<field>". Instead of creating a new file, you can also store the differential schema in the database, see the Customization FAQs for an example.
Custom functions like validators, formatters, modifiers and selectors can be (re-)placed in "<sgs-dir>/custom/core/classes/custom.php":
custom/modules/schema/some_module.xml:
<table name="some_module" ... load_library="../custom/core/classes/custom.php">
<view name="display" displayname="{t}Display{/t}" function="my_view" />
<field ...>
<filter views="all" function="my_filter"/>
</field>
</table>
custom/core/classes/custom.php:
class custom {
static function my_view($folder, $view, $params) {
return "Hello world!";
}
static function my_filter($val) {
...
}
}
Using this customization method helps you to:
- keep your changes separated to the standard Simple Groupware code
- persist your changes when doing an update
Debugging
For debugging the code, you can use these functions:
debug_html($var) gives out the contents of a variable and stops the script
debug_html(array($var1,$var2)) gives out the contents of 2 variables and stops the script
debug_queries() gives out all queries that were executed by the request and stops the script
print_r($var) gives out the contents of a variable
print_r(func_get_args()) gives the input parameters for the current function
print_r(array($var1,$var2)) gives out the contents of 2 variables
debug_file($var) writes the contents of a variable to "<sgs-dir>/simple_cache/debug/debug.txt"
In Smarty templates, you can use:
{$var|@print_r} gives out the contents of a variable
{$var|@debug_file} writes the contents of a variable to "<sgs-dir>/simple_cache/debug/debug.txt"
Search the code for a function: grep -rn "function somefunc" /<sgs-dir>/
Customization FAQ
See this page for the Customization FAQs.
General
If you change any images or icons, you may need to empty the browser cache to see the new image.
When changing templates or CSS files, make sure to clear the output cache and the browser cache.
Note: In order to get images in the "custom/" directory working, your Apache server needs to have the module "mod_rewrite" installed and running. Also ".htaccess" files need to be enabled with the "AllowOverride FileInfo" statement in "httpd.conf".
Note: If the DEBUG mode is enabled in setup settings, the templates will be automatically refreshed and the browser caching for CSS files will be disabled.