Login / Status
developer.Resource
Home . Documentation . Document Library . Core Documentation
Sponsors
hosted by punkt.deTYPO3 and Open Source Magazine

3.10. Various examples

Introduction

The follow pages will present some examples of how you can use the APIs of core libraries. Remember, ultimately the source is the documentation and the only point here is to show examples. Whenever you would like to use core features that are not shown here you should search in the core and system extensions for implementations that can work as an example for you.

Debugging with debug()

A very common tool used by TYPO3 developers is the debug() function. It basically prints out the content of a variable in a nicely formatted table. There are extensions available which extends the view from the debug() function to something more fancy. Here I will just present the basic version.

Use the debug() function whenever you want to look "inside" an array or parameters passed to a user processing function. Usually it makes it very easy to understand the parameters. For instance, lets say you call a script with the GET parameter string "?id=123&test[key]=A&test[key2]=B". How will the GET vars look to your application inside? Well, using the debug function makes that easy:

debug(t3lib_div::_GET(),'GET variables:');

The output in the browser will look like:

Notice that the debug() function is a wrapper for t3lib_div::debug() and the difference is that debug() (defined in "t3lib/config_default.php") will only output information if your IP addresse is within a certain range typical for internal networks.

Rendering page trees

In your backend modules you might like to show information or perform processing for a part of the page tree. There is a whole family of libraries in the core for making trees from records, static page trees or page trees that can be browsed (open/close nodes).

In this simple example I will show how to get the HTML for a static page tree, using the class "t3lib_pageTree" (child of "t3lib_treeView"). The output will look like this (missing the normal TYPO3 styles though):

The PHP code that generates this looks like:

   1: require_once(PATH_t3lib.'class.t3lib_pagetree.php');

   2:

   3:     // Initialize starting point of page tree:

   4: $treeStartingPoint = 1135;

   5: $treeStartingRecord = t3lib_BEfunc::getRecord('pages', $treeStartingPoint);

   6: $depth = 2;

   7:

   8:     // Initialize tree object:

   9: $tree = t3lib_div::makeInstance('t3lib_pageTree');

  10: $tree->init('AND '.$GLOBALS['BE_USER']->getPagePermsClause(1));

  11:

  12:     // Creating top icon; the current page

  13: $HTML = t3lib_iconWorks::getIconImage('pages', $treeStartingRecord, $GLOBALS['BACK_PATH'],'align="top"');

  14: $tree->tree[] = array(

  15:     'row' => $treeStartingRecord,

  16:     'HTML'=>$HTML

  17: );

  18:

  19:     // Create the tree from starting point:

  20: $tree->getTree($treeStartingPoint, $depth, '');

  21: #debug($tree->tree);

  22:

  23:     // Put together the tree HTML:

  24: $output = '

  25:     <tr  bgcolor="#999999">

  26:         <td><b>Icon / Title:</b></td>

  27:         <td><b>Page UID:</b></td>

  28:     </tr>';

  29: foreach($tree->tree as $data)    {

  30:     $output.='

  31:         <tr bgcolor="#cccccc">

  32:             <td nowrap="nowrap">'.$data['HTML'].htmlspecialchars($data['row']['title']).'</td>

  33:             <td>'.htmlspecialchars($data['row']['uid']).'</td>

  34:         </tr>';

  35: }

  36:

  37: $output = '<table border="0" cellspacing="1" cellpadding="0">'.$output.'</table>';

  1. In line 1 the class is included. Notice how the constant "PATH_t3lib" is used to set the path for "t3lib/".

  2. Line 4-5 sets up the starting point. You need a page id for that and additionally you must select that page record. Notice how another important API function, t3lib_BEfunc::getRecord(), is used to get the record array for the page!

  3. Line 6 defines that the page tree will go 2 levels down from the starting point.

  4. Line 9-10 initializes the class. Notice how the BE_USER object is called to get an SQL where clause that will ensure that only pages that are accessible for the user will be shown in the tree! Notice how t3lib_div::makeInstance() is used to create the object. This is required by the TYPO3 CGL.

  5. Line 13-17 sets up the starting point page in the tree. This must be done externally if you would like your tree to include the root page (which is not always the case).Notice how line 13 calls the function t3lib_iconWorks::getIconImage() to get the correct icon image for the pages table record! Also, $GLOBALS['BACK_PATH'] is used to make sure the icon has a correct "back-path" to the location where the icon is on the server.

  6. Line 20 renders the page tree from the starting point and $depth levels down (at least 1 level)

  7. The rendered page tree is stored in a data array inside of the tree object. We need to traverse the tree data to create the tree in HTML. This gives us the chance to organize the tree in a table for instance. That is very useful if you need to show additional information for each page.

    1. Lines 24-28 renders a table row with headings for the tree.

    2. Lines 29-35 traverses the tree data and for each element a table row will be rendered with the icon/title and an additional cell containing the uid.

    3. Line 37 wraps the table rows in a table tag.

Local extensions of the page tree classes

If you search in the source for other places where this class is used you will often find that the class is extended locally in those scripts. This is because it is possible to override certain functions that generate for instance the icon or wraps the title in some way.

Accessing the clipboard

You can easily access the internal clipboard in TYPO3 from your backend modules.

   1: require_once(PATH_t3lib.'class.t3lib_clipboard.php');

   2:

   3:     // Clipboard is initialized:

   4: $clipObj = t3lib_div::makeInstance('t3lib_clipboard');        // Start clipboard

   5: $clipObj->initializeClipboard();    // Initialize - reads the clipboard content from the user session

   6: debug($clipObj->clipData);

  1. Line 1 includes the clipboard library

  2. Line 4-5 initializes it.

  3. Line 6 outputs the content of the internal variables, ->clipData. That will look like what you see below:

This tells us what objects are registered on the "normal" tab (page record with id 1146 in "copy" mode) and the numeric tabs (can contain more than one element). The current clipboard (Pad 2 active) looks like this:

The correct way of accessing clipboard content is to the method, elFromTable(), in the clipboard object.

    debug($clipObj->elFromTable('_FILE'),'Files available:');

    debug($clipObj->elFromTable('pages'),'Page records:');

    $clipObj->setCurrentPad('normal');

    echo 'Changed to "normal" pad...';

    debug($clipObj->elFromTable('_FILE'),'Files available:');

    debug($clipObj->elFromTable('pages'),'Page records:');

Here we first try to get all files and then all page records on the current pad (which is pad 2). Then we change to the "Normal" pad, call the elFromTable() method again and output the results. The output shows that in the first attempt we get the list of files but no page records while in the second attempt after having changed to the normal pad we will get no files but the page record on the normal pad in return:

Setting elements on the clipboard

This is too complicated to describe in detail. The following codelisting is from the Web > List module where selections for the clipboard is posted from a form and registered.

    // Clipboard actions are handled:

$CB = t3lib_div::_GET('CB');    // CB is the clipboard command array

if ($this->cmd=='setCB') {

        // CBH is all the fields selected for the clipboard, CBC is the checkbox fields which were checked. By merging we get a full array of checked/unchecked elements

        // This is set to the 'el' array of the CB after being parsed so only the table in question is registered.

    $CB['el'] = $dblist->clipObj->cleanUpCBC(array_merge(t3lib_div::_POST('CBH'),t3lib_div::_POST('CBC')),$this->cmd_table);

}

if (!$this->MOD_SETTINGS['clipBoard'])    $CB['setP']='normal';    // If the clipboard is NOT shown, set the pad to 'normal'.

$dblist->clipObj->setCmd($CB);        // Execute commands.

$dblist->clipObj->cleanCurrent();    // Clean up pad

$dblist->clipObj->endClipboard();    // Save the clipboard content

Adding Context Sensitive Menu items

When the CSM is being generated in the "alt_clickmenu.php" script an array with the elements is created. Before the array is passed over to the final rendering function that will create the menu HTML, the array will be passed in turns to external processing scripts. These scripts are configured in this global array:

$GLOBALS['TBE_MODULES_EXT']['xMOD_alt_clickmenu']['extendCMclasses'];

Each script will then have a chance to manipulate the content of the array and add/remove items as the script wants. This is what makes it possible to add custom options to CSM.

The extensions "extra_page_cm_options" adds a lot of CSM options. The extension has an "ext_tables.php" file and it contains code that adds an entry in the array mentioned above:

<?php

if (!defined ('TYPO3_MODE'))     die ('Access denied.');

if (TYPO3_MODE=='BE')    {

    $GLOBALS['TBE_MODULES_EXT']['xMOD_alt_clickmenu']['extendCMclasses'][]=array(

        'name' => 'tx_extrapagecmoptions',

        'path' => t3lib_extMgm::extPath($_EXTKEY).'class.tx_extrapagecmoptions.php'

    );

}

?>

The value of the "path" key is pointed to the absolute path of the class file that contains code for manipulation of the CSM array. This file must contain a class by the name of "name" and inside that class a "main()" method that will be called for manipulation. The basic skeleton looks like this:

/**

 * Class, adding extra context menu options

 *

 * @author    Kasper Skaarhoj <kasper@typo3.com>

 * @package TYPO3

 * @subpackage tx_extrapagecmoptions

 */

class tx_extrapagecmoptions {

    /**

     * Adding various standard options to the context menu.

     * This includes both first and second level.

     *

     * @param    object        The calling object. Value by reference.

     * @param    array        Array with the currently collected menu items to show.

     * @param    string        Table name of clicked item.

     * @param    integer        UID of clicked item.

     * @return    array        Modified $menuItems array

     */

    function main(&$backRef,$menuItems,$table,$uid)    {

        global $BE_USER,$TCA,$LANG;

        $localItems = array();    // Accumulation of local items.

        ...

            $menuItems = array_merge($menuItems,$localItems);

            return $menuItems;

        }

    }

}

The "extra_page_cm_options" is a slightly special since it produces additional CSM elements by calls back to the parent object where rendering functions exists. This is due to historical reasons. Better examples of handcrafted menu items can be found in extensions such as "templavoila" (1st level additions for specific table) and "impexp" (2nd level addition). Finally, the best way to initiate adding elements is using the Kickstarter Wizard which contains an options for creating CSMs:

Implementing Context Sensitive Menus

If you want to implement a CSM for an element in your own backend modules you have to do two things:

  1. Include standard JavaScript and HTML code in the HTML document for all CSM instances.

  2. Wrap the icon / element title with a link that opens the CSM.

The standard JavaScript and HTML can be fetched from the backend document template object. In a typical backend module environment this object is available as $this->doc and these four lines will do the trick:

   1:             // Setting up the context sensitive menu:

   2:         $CMparts = $this->doc->getContextMenuCode();

   3:         $this->doc->bodyTagAdditions = $CMparts[1];

   4:         $this->doc->JScode.=$CMparts[0];

   5:         $this->doc->postCode.= $CMparts[2];

These lines must be executed before calling "$this->doc->startPage()".

  1. Line 2 asks the template object to generate the standard content. It is returned in an array.

  2. Line 3 adds event handlers for the <body> tag:

    onmousemove="GL_getMouse(event);" onload="initLayer();"

  3. Line 4 adds JavaScript functions in the <head> of the HTML output

  4. Line 5 adds the <div> layers in the bottom of the page:

    <div id="contentMenu0" style="z-index:1; position:absolute;visibility:hidden"></div>

    <div id="contentMenu1" style="z-index:2; position:absolute;visibility:hidden"></div>

CSM for database elements

Linking icons to open the CSM is easy:

    // Get icon with CSM:

$icon = t3lib_iconworks::getIconImage('tx_templavoila_datastructure',$row,$GLOBALS['BACK_PATH'],' align="top"');

$content.= $this->doc->wrapClickMenuOnIcon($icon,'tx_templavoila_datastructure',$row['uid'],1);

In this example the first line creates an <img> tag with the icon of a record from the table "tx_templavoila_datastructure". The variable $row must be the record array of an element from this database table.

The second line wraps the icon ($icon) in a link that will open the CSM over it. This is done by calling "template::wrapClickMenuOnIcon()" with $icon HTML, table name and element uid. The fourth argument is a boolean you should set if your script is shown in the list frame of the backend. This will tell "alt_clickmenu.php" which generates the HTML content that it should be written back to the list frame and not the navigation frame for instance.

Result:

CSM for files

Activating a CSM for a file is also easy. As for database elements it requires that the standard content is added to the HTML document. From that point you just call the same function, "template::wrapClickMenuOnIcon()" but set the second argument to the absolute path of the file (and keep the third argument, the uid, blank).

$GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($theIcon,$path);

Notice, that in this case the document template object used is the global variable $SOBE which is normally available in backend modules as well. You might also use the default instance found in $TBE_TEMPLATE.

For more information see the inline documentation of the function wrapClickMenuOnIcon(). It is found in the file "template.php" in the typo3/ folder.

Parsing HTML: t3lib_parsehtml

This class is very handy for various processing needs of HTML. In the future it might be obsolete if the "tidy" extension becomes standard in PHP but for now there are no native features in PHP which lets us parse HTML.

Extracting blocks from an HTML document

In the first example it is shown how we can extract parts of an HTML document.

   1: require_once(PATH_t3lib.'class.t3lib_parsehtml.php');

   2:

   3: $testHTML = '

   4:     <DIV>

   5:         <IMG src="welcome.gif">

   6:         <p>Line 1</p>

   7:         <p>Line <B class="test">2</B></p>

   8:         <p>Line <b><i>3</i></p>

   9:         <img src="test.gif" />

  10:         <BR><br/>

  11:         <TABLE>

  12:             <tr>

  13:                 <td>Another line here</td>

  14:             </tr>

  15:         </TABLE>

  16:     </div>

  17:     <B>Text outside div tag</B>

  18:     <table>

  19:         <tr>

  20:             <td>Another line here</td>

  21:         </tr>

  22:     </table>

  23: ';

  24:

  25:     // Splitting HTML into blocks defined by <div> and <table> tags

  26: $parseObj = t3lib_div::makeInstance('t3lib_parsehtml');

  27: $result = $parseObj->splitIntoBlock('div,table',$testHTML);

  28: debug($result,'Splitting by <div> and <table> tags');

  29: 

  1. Line 1 includes the library.

  2. Line 3-23 loads the HTML sample code into a variable.

  3. Line 36 creates an instance of the parser-class. Notice how t3lib_div::makeInstance() is used (required).

  4. Line 27 splits the HTML content into an array dividing it by <div> or <table> tags.

  5. Line 28 outputs the result array with the debug() function:

As you can see the HTML source has been divided so the <div> section and the <table> is found in key 1 and 3. The keys of the extracted content is always the odd keys while the even keys are the "outside" content.

Notice that the table inside of the <div> section was not "found". So when you split content like this you get only elements on the same block-level in the source. You have to traverse the content recursively to find all tables - or just split on <table> only (which will not give you tables nested inside of tables though).

Extracting single tags

You can split the content by tag as well. This is done in the next example. Here all <img> and <br> tags are found:

  30:     // Splitting HTML into blocks defined by <img> and <br> tags

  31: $result = $parseObj->splitTags('img,br',$testHTML);

  32: debug($result,'Extracting <img> and <br> tags');

  33:

Line 31 performs the splitting operation. This is the output:

Again, all the odd keys in the array contains the tags that were found. If you wanted to do processing on this content you just traverse the array, process all odd keys and implode the array again. A code listing for that might look like this:

foreach($result as $intKey => $HTMLvalue)    {

        // Find all ODD keys:

    if ($intKey%2)    {

        $result[$intKey] = '--'.$result[$intKey].'--';

    }

}

$newContent = implode('',$result);

Cleaning HTML content

You can also do processing on the HTML content by the HTMLcleaner() method. This code listings shows a basic example of how you can configure it. There are a lot of features hidden in the $tagCfg array and you should refer to the inline documentation of the method in the class.

  34:     // Cleaning HTML:

  35: $tagCfg = array_flip(explode(',','b,img,div,br,p'));

  36: $tagCfg['b'] = array(

  37:     'nesting' => 1,

  38:     'remap' => 'strong',

  39:     'allowedAttribs' => 0

  40: );

  41: $tagCfg['p'] = array(

  42:     'fixAttrib' => array(

  43:         'class' => array(

  44:             'set' => 'bodytext'

  45:         )

  46:     )

  47: );

  48: $result = $parseObj->HTMLcleaner($testHTML, $tagCfg, FALSE, FALSE, array('xhtml' => 1));

  49: debug(array($result),'Cleaning to XHTML, removing non-allowed tags and attributes');

  1. Line 35 initializes the $tagCfg array by setting the five allowed tags as keys. Only these tag names are allowed! All others are removed (HTMLcleaner() can be configured to keep all unknown tags though).

  2. Line 36-40 configures additional options for the "b" tag. First of all correct nesting is required. This means that the single <b> tag in one of the paragraphs will be removed. Then the "remap" key is set which means that all occurencies of <b> tags will be substituted with <strong> tags instead. Finally the allowed attributes are set to false which means that any attributes set for <b> tags are removed.

  3. Line 41-47 configures additional options for the "p" tag. In this case it just hardcodes that the attribute "class" must exist and it must have the value "bodytext".

  4. Line 48 calls the HTMLcleaner() method - and notice the extra options being set where "xhtml" cleaning is enabled. This will convert all tag an attribute names to lowercase and "close" tags like <img> and <br> to <img.../> and <br />

This is the output:

Advanced call back processing

This code listing shows how you can register call back functions for recursive processing of an HTML source:

   1: class user_processing {

   2:     function process($str)    {

   3:         $this->parseObj = t3lib_div::makeInstance('t3lib_parsehtml_proc');

   4:         

   5:         $outStr = $this->parseObj->splitIntoBlockRecursiveProc(

   6:             'div|table|blockquote|caption|tr|td|th|h1|h2|h3|h4|h5|h6|ol|ul',

   7:             $str,

   8:             $this,

   9:             'callBackContent',

  10:             'callBackTags'

  11:         );

  12:         

  13:         return $outStr;

  14:     }

  15:     

  16:     function callBackContent($str,$level)    {

  17:         if (trim($str))    {

  18:

  19:                 // Fixing <P>

  20:             $pSections = $this->parseObj->splitTags('p', $str);

  21:             foreach($pSections as $k => $v)    {

  22:                 $pSections[$k] = trim(ereg_replace('[[:space:]]+',' ',$pSections[$k]));

  23:                 if (!($k%2))    {

  24:

  25:                     if ($k && !strstr(strtolower($pSections[$k]), '</p>'))    {

  26:                         $pSections[$k] = trim($pSections[$k]).'</p>';

  27:                     }

  28:

  29:                     $pSections[$k].=chr(10);

  30:                 }

  31:             }

  32:             $str = implode('',$pSections);

  33:         }

  34:

  35:         if (trim($str))    {

  36:             $str = $this->parseObj->indentLines(trim($str),$level).chr(10);

  37:         } else {

  38:             $str = trim($str);

  39:         }

  40:

  41:         return $str;

  42:     }

  43:

  44:     function callBackTags($tags,$level)    {

  45:

  46:         if (substr($tags['tag_name'],0,1)=='h')    {

  47:             $tags['tag_end'].=chr(10);

  48:             $tags['content'] = trim($tags['content']);

  49:                 // Removing the <hx> tags if they content nothing when tags are stripped:

  50:             if (!strlen(trim(strip_tags($tags['content']))))    {

  51:                 $tags['tag_start'] = $tags['tag_end'] = '';

  52:                 $tags['add_level'] = 0;

  53:                 $tags['content'] = '';

  54:                 return $tags;

  55:             }

  56:         } elseif ($tags['tag_name']=='div' || $tags['tag_name']=='blockquote')    {

  57:             $tags['tag_start'] = $tags['tag_end'] = '';

  58:             $tags['add_level'] = 0;

  59:         } else {

  60:             $tags['tag_start'] = $this->parseObj->indentLines(trim($tags['tag_start']),$level).chr(10);

  61:             $tags['tag_end'] = $this->parseObj->indentLines(trim($tags['tag_end']),$level).chr(10);

  62:         }

  63:         return $tags;

  64:     }

  65: }

In the method "process()" processing is started. Like when splitting HTML content you define a list of tags to split by. Each of these will be processed by the call back functions "callBackContent" and "callBackTags" for processing of both the content between the splitted tags and the tags themselves.

Notice how it is all within the same class which is a requirement for the call back functions.

I'll not explain this listing in further detail. Explore it yourself if you are interested in call back processing of HTML sources.

Links to edit records

Quite often in your backend modules you might like to create a link to edit a record. This is easily done with an API function call to t3lib_BEfunc::editOnClick(). This script will create an onclick-JavaScript event linking you to the "alt_doc.php" script in the "PATH_typo3" directory.

All you need to do is prepare GET parameters for the "alt_doc.php" script. Please look inside of "alt_doc.php" for more details of possible GET vars you can use and what they mean. In this example I have shown the most typical options.

The result of the code listing will be three links like these:

The code listing looks like this:

   1: $editUid = 1135;

   2: $editTable = 'pages';

   3:

   4:     // Edit whole record:

   5: $params = '&edit['.$editTable.']['.$editUid.']=edit';

   6: $output.= '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$GLOBALS['BACK_PATH'])).'">'.

   7:         '<img'.t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],'gfx/edit2.gif','width="11" height="12"').' title="Edit me" border="0" alt="" />'.

   8:         'Edit record '.$editUid.' from the "'.$editTable.'" table'.

   9:         '</a><br/><br/>';

  10:

  11:     // Edit only "title" and "hidden" fields from record:

  12: $params = '&edit['.$editTable.']['.$editUid.']=edit&columnsOnly=title,hidden';

  13: $output.= '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$GLOBALS['BACK_PATH'])).'">'.

  14:         'Edit "title" and "hidden" fields from record '.$editUid.' from the "'.$editTable.'" table'.

  15:         '</a><br/><br/>';

  16:

  17:     // Create new "Content Element" record in PID 1135

  18: $params = '&edit[tt_content]['.$editUid.']=new&defVals[tt_content][header]=New%20Element';

  19: $output.= '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$GLOBALS['BACK_PATH'])).'">'.

  20:         'Create new Content Element inside page '.$editUid.

  21:         '</a><br/>';

Editing a record

In line 5 you see the basic GET parameter you need to set up to edit a record. You need to know the database table name, record uid in advance. The syntax is "&edit[ tablename ][ uid ]=edit". You can specify as many tables and uids you like and you will get them all in one single form! The "uid" variable can even be a comma list of uids (short way of editing more records from the same table at once).

The lines 5-9 produces a link which shows this form:

Editing only a few fields from a record

Lines 11-15 creates the same link but with additional information that only the field names "title" and "hidden" should be edited! That is done by adding the GET parameters "&columnsOnly=title,hidden". This means the form will look like this:

Creating a form for new elements

Lines 17-21 creates a link which will make a new content element inside the page with "pid" 1135. The syntax for creating new records is "&edit[ table_name_of_new_record ][ pid_reference ]=new". The pid reference is special: If it is a negative value it points to another record from the same table after which the new record should be created. If it is positive or zero it just points to the page id where the record should be created (as the top element).

Another feature is that a custom default value for the header field is automatically passed along. This is done by the additional GET parameter "&defVals[tt_content][header]=New%20Element" and you can see how the Header field is pre-filled with this value below.

The result of the "create new" will be this form.

Support for custom tables in the Page module

In the Web > Page module you can have listings of other records than Content Elements and guest book items. If you want your custom table to be listed there you can configure it using the $TYPO3_CONF_VARS["EXTCONF"]['cms'] array. This is a configuration option offered from within the Page module.

In this example the Mininews extension is configured for listing in the Page module. It would look like this (here a single item only is shown):

The configuration required is as simple as this, put into (ext_)localconf.php:

$TYPO3_CONF_VARS['EXTCONF']['cms']['db_layout']['addTables']['tx_mininews_news'][0] = array(

    'fList' => 'name;title;email;company,image,title',

    'icon' => TRUE

);

The "fList" key value is a list of field names separated first by ";" (semi colon) and then by comma. The semicolon separates table columns while the comma allows you to list more than one field to be displayed inside a single column.

Adding elements to the Content Element Wizard

The content element wizard helps people to select the most common kinds of content elements in a one-click operation, thus saving them to know about setting the content element type etc.

The script is a part of the “cms” extension.

Adding elements under the “Plugins” header

If you want to add elements in the wizard under the plugins header there is native support in the script for this.

Basically, what you do is to set content in the global variable $TBE_MODULES_EXT['xMOD_db_new_content_el']['addElClasses']. The keys in this array must be class names and the values is the absolute path of the class. When the script is run the class files will be included during initialization. Then, during the building of the array of wizard elements the default wizard array is passed to the class you have configured through the method proc() in your class.

For details the most easy thing will be to look into the script in the function wizardArray() - this will make it clear to you how it works.

Example

As an example of how this works from an extension you can take a look at the extension tt_guest. This extension adds itself in the plugin category by inserting these lines in its ext_tables.php file:

if (TYPO3_MODE=="BE")    {

    $TBE_MODULES_EXT["xMOD_db_new_content_el"]["addElClasses"]["tx_ttguest_wizicon"] = 

        t3lib_extMgm::extPath($_EXTKEY)."class.tx_ttguest_wizicon.php";

}

In the file class.tx_ttguest_wizicon.php you will find a class looking like this:

/**

 * Class, containing function for adding an element to the content element wizard.

 *

 * @author    Kasper Skaarhoj <kasper@typo3.com>

 * @package TYPO3

 * @subpackage tx_ttguest

 */

class tx_ttguest_wizicon {

    /**

     * Processing the wizard-item array from db_new_content_el.php

     *

     * @param    array        Wizard item array

     * @return    array        Wizard item array, processed (adding a plugin for tt_guest extension)

     */

    function proc($wizardItems)    {

        global $LANG;

            // Include the locallang information.

        $LL = $this->includeLocalLang();

            // Adding the item:

        $wizardItems['plugins_ttguest'] = array(

            'icon'=>t3lib_extMgm::extRelPath('tt_guest').'guestbook.gif',

            'title'=>$LANG->getLLL('plugins_title',$LL),

            'description'=>$LANG->getLLL('plugins_description',$LL),

            'params'=>'&defVals[tt_content][CType]=list&defVals[tt_content][list_type]=3&defVals[tt_content][select_key]='.rawurlencode('GUESTBOOK, POSTFORM')

        );

        

        return $wizardItems;

    }

    /**

     * Include locallang file for the tt_guest book extension (containing the description and title for the element)

     *

     * @return    array        LOCAL_LANG array

     */

    function includeLocalLang()    {

        include(t3lib_extMgm::extPath('tt_guest').'locallang.php');

        return $LOCAL_LANG;

    }

}

As you can see this class modifies the wizard array with an additional item. This is how you can also add / modify elements in the array using this API.

Using custom permission options

TYPO3 (3.7.0+) offers extension developers to register their own permission options to be automatically managed by TYPO3s user group access lists. The options can be grouped in categories. A custom permission option is always a checkbox (on/off). The scope of such options is for use in the backend of TYPO3 only.

Registering a header and options

You configure options in the global variable $TYPO3_CONF_VARS['BE']['customPermOptions']. You can read the comment inside “config_default.php” regarding the syntax of the array.

This example shows how three options are registered under a new category:

$TYPO3_CONF_VARS['BE']['customPermOptions'] = array(

            'tx_coreunittest_cat1' => array(

                'header' => '[Core Unittest] Category 1',

                'items' => array(

                    'key1' => array('Key 1 header'),

                    'key2' => array('Key 2 header'),

                    'key3' => array('Key 3 header'),

                )

            ),

The result is that these options appear in the group access lists like this:

You can also add icons, a description and use references to locallang values. Such a detailed configuration could look like this (also just an example):

...

'tx_coreunittest_cat2' => array(

    'header' => 'LLL:EXT:coreunittest/locallang_test.php:test_header',

    'items' => array(

        'keyA' => array('Key a header','icon_ok.gif','This is a description....'),

        'keyB' => array('LLL:EXT:coreunittest/locallang_test.php:test_item','../typo3/gfx/icon_ok2.gif','LLL:EXT:coreunittest/locallang_test.php:test_description'),

        'key3' => array('Key 3 header','EXT:coreunittest/ext_icon.gif'),

    )

)

...

Evaluating the options

Checking if a custom permission option is set you simply call this API function in the user object:

$BE_USER->check('custom_options',$catKey.':'.$itemKey)

$catKey is the category in which the option resides. From the example above this would be “tx_coreunittest_cat1”

$itemKey is the key of the item in the category you are evaluating. From the example above this could be “key1”, “key2” or “key3” depending on which one of them you want to evaluated.

The function returns true if the option is set, otherwise false.

Keys in the array

It is good practice to use the extension keys prefixed with “tx_” on the first level of the array. This will help to make sure you do not pick a key which someone else picked as well!

Also you should never pick a key containing any of the characters “,:|” since they are reserved delimiter characters.