Typo3 Manual-Doc Core API
Typo3 Manual-Doc Core API
I hope these two documents, "Inside TYPO3" and "TYPO3 Core API", will finally form a complete picture of the TYPO3 Core
architecture, the backend and be the reference of choice in your work with TYPO3. It has taken me more than a year to
finally get these published!
Dedication
I want to dedicate this document to the people in TYPO3s community who has the discipline to do the boring job of writing
documentation for their extensions or contributes to TYPO3 documentation in general. It's great to have good coders, but
it's even more important to have coders with character to carry their work through till the end - even when it means spending
days writing good documents. Go for completeness!
- kasper
Reserved filenames
This list of filenames are all reserved filenames in the root directory of extensions. None of them are required but for
example you cannot have a TYPO3 extension recognized by TYPO3 without the “ext_emconf.php” file etc. You can read
more details like that in the table below.
In general, do not introduce your own files in root directory of extensions with the name prefix “ext_”.
Filename Description
ext_emconf.php Definition of extension properties
Name, category, status etc. Used by the EM. Also auto-written by EM when extensions are imported from
repository.
Notice: If this file is not present the EM will not find the extension.
ext_localconf.php Addition to “localconf.php” which is included if found. Should contain additional configuration of
$TYPO3_CONF_VARS and may include additional PHP class files.
All 'ext_localconf.php' files of included extensions are included right after the typo3conf/localconf.php file has
been included and database constants defined. Therefore you cannot setup database name, username,
password though, because database constants are defined already at this point.
Notice: Observe rules for content of these files. See section on caching below.
All 'ext_tables.php' files of loaded extensions are included right after the 'tables.php' file in the order they are
defined in the global array TYPO3_LOADED_EXT but right before a general “extTables” file (defined with the var
$typo_db_extTableDef_script in the typo3conf/localconf.php file, later set as the constant
TYPO3_extTableDef_script). Thus a general “extTables” file in typo3conf/ may overrule any settings made by
loaded extensions.
You should not use this file for setting up $TYPO3_CONF_VARS. See “ext_localconf.php”.
Notice: Observe rules for content of these files. See section below.
ext_tables.sql SQL definition of database tables.
This file should contain a table-structure dump of the tables used by the extension. It is used for evaluation of the
database structure and is therefore important to check and update the database when an extension is enabled.
If you add additional fields (or depend on certain fields) to existing tables you can also put them here. In that case
insert a CREATE TABLE structure for that table, but remove all lines except the ones defining the fields you
need.
The ext_tables.sql file may not necessarily be “dumpable” directly to MySQL (because of the semi-complete table
definitions allowed defining only required fields, see above). But the EM or Install Tool can handle this. The only
very important thing is that the syntax of the content is exactly like MySQL made it so that the parsing and
analysis of the file is done correctly by the EM.
ext_tables_static+adt.sql Static SQL tables and their data.
If the extension requires static data you can dump it into a sql-file by this name.
Example for dumping mysql data from bash (being in the extension directory):
--add-drop-table will make sure to include a DROP TABLE statement so any data is inserted in a fresh table.
You can also drop the table content using the EM in the backend.
Notice: The table structure of static tables needs to be in the ext_tables.sql file as well - otherwise an installed
static table will be reported as being in excess in the EM!
ext_typoscript_constants.txt Preset TypoScript constants
Deprecated (use static template files instead, see extMgm API description)
Such a file will be included in the constants section of all TypoScript templates.
ext_typoscript_setup.txt Preset TypoScript setup
Deprecated (use static template files instead, see extMgm API description)
Such a file will be included in the setup section of all TypoScript templates.
ext_typoscript_editorcfg.txt Preset TypoScript editor configuration
Deprecated (use static template files instead, see extMgm API description)
Such a file will be included in the “Backend Editor Configuration” section of all TypoScript templates.
ext_conf_template.txt Extension Configuration template.
Configuration code in TypoScript syntax setting up a series of values which can be configured for the extension
in the EM.
If this file is present the EM provides you with an interface for editing the configuration values defined in the file.
The result is written as a serialized array to localconf.php file in the variable
$TYPO3_CONF_VARS["EXT"]["extConf"][extension_key]
The content of the “res/” folder is used for filelists in configuration forms.
If you want to do user processing before the content from the configuration form is saved (or shown for that
sake) there is a hook in the EM which is configurable with
$TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm'][] = “function
reference”
ext_icon.gif Extension Icon
The filename “locallang.php” (or any file matching locallang*.php) is used for traditional definition of language
labels in the $LOCAL_LANG array. If you use this name consistently those files will be detected by the
translation tool!
Notice: PLEASE DO ONLY put the definition of the variable $LOCAL_LANG into this file and don't rely on
comments in the file. The file will be automatically updated by the extension repository when translations are
applied.
If this file is found it will install a new menu item, “UPDATE”, in the EM when looking at details for the extension.
When this menu item is selected the class inside of this file (named “ext_update”) will be instantiated and the
method “main()” will be called and expected to return HTML content.
Also you must add the function “access()” and make it return a boolean value whether or not the menu item
should be shown. This feature is meant to let you disable the update tool if you can somehow detect that it has
already been run and doesn't need to run again.
The point of this file is to give extension developers the possibility to provide an update tool if their extensions in
newer versions require some updates to be done. For an example, see “newloginbox” extension.
ext_api_php.dat PHP API data
A file containing a serialized PHP array with API information for the PHP classes in the extension. The file is
created - and viewed! - with tools found in the extension “extdeveval” (Extension Development Evaluator)
pi*/ Typical folder for a frontend plugin class.
mod*/ Typical folder for a backend module.
res/ Extensions normally consist of other files: Classes, images, html-files etc. Files not related to either a frontend
plugin (pi/) or backend module (mod/) might be put in a subfolder of the extension directory named “res/” (for
“resources”) but you can do it as you like (inside of the extension directory that is).
The “res/” folder content will be listed as files you can select in the configuration interface.
Files in this folder can also be selected in a selector box if you set up Extension configuration in a
“ext_conf_template.txt” file.
Notice about symlinking: Local extension can successfully be symlinked to other local extensions
on a server as long as they are running under the same TYPO3 source version (which would typically
also be symlinked). This method is useful for maintenance of the same local extension running under
several sites on a server.
Global typo3/ext/ This is a “per-server” way to install an extension; they are global for the TYPO3 source code on the
web server. These extensions will be available for any TYPO3 installation sharing the source code.
Notice on distribution:
As of version 4.0, TYPO3 is no longer distributed with a fixed set of global extensions. In previous
versions these were distributed for reasons like popularity and sometimes history.
System typo3/sysext/ This is system default extensions which cannot and should not be updated by the EM. They are
distributed with TYPO3 core source code and generally understood to be a part of the core system.
Loading precedence
Local extensions take precedence which means that if an extension exists both in typo3conf/ext/ and typo3/ext/ the one in
typo3conf/ext/ is loaded. Likewise global extension takes precedence over system extensions. This means that extensions
are loaded in the order of priority local-global-system.
In effect you can therefore have - say - a “stable” version of an extension installed in the global dir (typo3/ext/) which is used
by all your projects on a server sharing source code, but on a single experimental project you can import the same
extension in a newer “experimental” version and for that particular project the locally available extension will be used
instead.
Extension key
The “extension key” is a string uniquely identifying the extension. The folder where the extension resides is named by this
string. The string can contain characters a-z0-9 and underscore. No uppercase characters should be used (keeps folder-,
file- and table/field-names in lowercase). Furthermore the name must not start with an “tx” or “u” (this is prefixes used for
modules) and because backend modules related to the extension should be named by the extension name without
underscores, the extension name must still be unique even if underscores are removed (underscores are allowed to make
the extension key easily readable).
The naming conventions of extension keys are automatically validated by the registration at the repository, so you have
About GPL and extensions: Remember that TYPO3 is GPL software and at the same moment you extend TYPO3 your
extensions are legally covered by GPL. This does not force you to share your extension, but it should inspire you to do so
and legally you cannot prevent anyone who gets hold of your extension code from using it and further develop it.
The TYPO3 Extension API is designed to make sharing of your work easy as well as using others work easy. Remember
TYPO3 is Open Source Software and we rely on each other in the community to develop it further.
Responsibility: It's also your responsibility to make sure that all content of your extensions is legally covered by GPL. The
webmaster of TYPO3.org reserves the right to kick out any extension without notice that is reported to contain non-GPL
material.
Naming conventions
Based on the extension key of an extension these naming conventions should be followed:
The order of the registered extensions in this array corresponds to the order they were listed in
TYPO3_CONF_VARS["EXT"]["requiredExt"].TYPO3_CONF_VARS["EXT"]["extList"] with duplicates removed of course.
The inclusion of ext_tables.php or ext_localconf.php files are done by traversing (a copy of) the $TYPO3_LOADED_EXT
array.
ext_emconf.php
This script configures the extension manager. The only thing included is an array, $EM_CONF[extension_key] with these
associative keys (below in table).
When extensions are imported from the online repository this file is auto-written! So don't put any custom stuff in there -
only change values in the $EM_CONF array if needed.
• be
Backend (Generally backend oriented, but not a module)
• module
Backend modules (When something is a module or connects with one)
• fe
Frontend (Generally frontend oriented, but not a “true” plugin)
• plugin
Frontend plugins (Plugins inserted as a “Insert Plugin” content element)
• misc
Miscellaneous stuff (Where not easily placed elsewhere)
• services
Contains TYPO3 services
• templates
Contains website templates
• example
Example extension (Which serves as examples etc.)
• doc
Documentation (Eg. tutorials, FAQ's etc.)
shy boolean If set, the extension will normally be hidden in the EM because it might be a default extension or
otherwise something which is not so important. Use this flag if an extension is of “rare interest”
(which is not the same as un-important - just an extension not sought for very often...)
It does not affect whether or not it's enabled. Only display in EM.
Normally “shy” is set for all extensions loaded by default according to TYPO3_CONF_VARS.
dependencies list of extention-keys This is a list of other extension keys which this extension depends on being loaded before itself.
The EM will manage that dependency while writing the extension list to localconf.php
conflicts list of extention-keys List of extension keys of extensions with which this extension does not work (and so cannot be
enabled before those other extensions are un-installed)
priority “top”, “bottom” This tells the EM to try to put the extensions as the very first in the list. Default is last.
loadOrder
Syntax:
• [version]-
Extension is compliant with TYPO3 from this version (included) and forward
• -[version]
Extension is compliant with TYPO3 until this version (included)
• [version]-[version]
Extension is compliant within this span of TYPO3 versions
4.0.0
3.6.1
3.6.1rc1
3.6.0
3.6.0rc2
3.6.0rc1
3.6.0b2
3.6.0b1
3.6.0dev2
3.6.0dev1
3.6.0dev (=3.6.0dev0)
3.5.10
3.5.0
3.1.1
3.1 (=3.1.0)
3 (=3.0.0)
PHP_version [version-span] Defines the PHP version requirements of this extension.
Syntax is the same as for “TYPO3_version”, see above.
module list of strings If any subfolders to an extension contains backend modules, those foldernames should be listed
here. It allows the EM to know about the existence of the module, which is important because the
EM has to update the conf.php file of the module in order to set the correct TYPO3_MOD_PATH
constant.
state string Which state is the extension in?
• alpha
Alpha state is used for very initial work, basically the state is has during the very process of
creating its foundation.
• beta
Under current development. Beta extensions are functional but not complete in functionality.
Most likely beta-extensions will not be reviewed.
• stable
Stable extensions are complete, mature and ready for production environment. You will be
approached for a review. Authors of stable extensions carry a responsibility to be maintain
and improve them.
• experimental
Experimental state is useful for anything experimental - of course. Nobody knows if this is
going anywhere yet... Maybe still just an idea.
• test
Test extension, demonstrates concepts etc.
• obsolete
The extension is obsolete or depricated. This can be due to other extensions solving the
same problem but in a better way or if the extension is not being maintained anymore.
internal boolean This flag indicates that the core source code is specifically aware of the extension. In other words
this flag should convey the message that “this extension could not be written independently of
core source code modifications”.
An extension is not internal just because it uses TYPO3 general classes eg. those from t3lib/.
True non-internal extensions are characterized by the fact that they could be written without
making core source code changes, but relies only on existing classes in TYPO3 and/or other
extensions, plus its own scripts in the extension folder.
uploadfolder boolean If set, then the folder named “uploads/tx_[extKey-with-no-underscore]” should be present!
createDirs list of strings Comma list of directories to create upon extension installation.
modify_tables list of tables List of table names which are only modified - not fully created - by this extension. Tables from this
list found in the ext_tables.sql file of the extension
lockType char; L, G or S Locks the extension to be installed in a specific position of the three posible:
• L = local (typo3conf/ext/)
• G = global (typo3/ext/)
• S = system (typo3/sysext/)
clearCacheOnLoad boolean If set, the EM will request the cache to be cleared when this extension is loaded.
author string Author name (Use a-z)
Please see the Project Coding Guidelines for a description of each compliance keyword (and the
full allowed list).
CGLcompliance_note string Any remarks to the compliance status. Might describe some minor incompatibilities or other
reservations.
private boolean If set, this version of the extension is not included in the public list!
Extending “extensions-classes”
A rather exotic thing to do but nevertheless...
If you are programming extensions yourself you should as a standard procedure include the “class extension code” in the
bottom of the class file:
if (defined("TYPO3_MODE") &&
$TYPO3_CONF_VARS[TYPO3_MODE]["XCLASS"]["ext/class.cool_shop.php"]) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]["XCLASS"]["ext/class.cool_shop.php"]);
}
Normally the key used as example here (“ext/class.cool_shop.php”) would be the full path to the script relative to the
PATH_site constant. However because modules are required to work from both typo3/sysext/, typo3/ext/ and typo3conf/ext/
it is policy that any path before “ext/” is omitted.
After the installation of the extension you will find a new menu item named "Make new extension" in the selector box menu
of the Extension Manager.
After entering this information you can begin to create new tables and fields in the database, you can configure backend
modules and frontend plugins etc. Basically this is what tutorials will cover in detail.
When you are through with the configuration you click the button to the left called "View result". This will let you preview the
content of the files the Kickstarter will write to the server.
Clicking the "Start new" button will bring you back to the Kickstarter with all the original configuration used (configuration
loaded from "doc/wizard_form.dat" which must still exist).
The TYPO3 APIs are first and foremost documented inside of the source scripts. It would be impossible to maintain
documentation at more than one location given the fact that things change and sometimes fast.
Inline documentation
We have dedicated ourselves to document the classes and methods inside the source scripts (JavaDoc style). This means
that you can use any JavaDoc compliant documentor programme to extract API documentation from the source. You can
also install the extension "extdeveval" which will offer you a menu with links to the most important APIs in TYPO3 from
within TYPO3:
Clicking a link like "extMgm" will bring up a new window with the full API of that class:
General functions
There are a few core classes in TYPO3 which contain general functionality. These classes are (typically) just a collection of
individual functions you call non-instantiated, like [class name]::[method name].
These are the most important classes to know about in TYPO3:
These classes are always included and available in the TYPO3 backend and frontend (except "t3lib_BEfunc" and
"t3lib_iconWorks").
The following pages will list methods from these classes in priority of importance. You should at least acquaint yourself with
all High-priority functions since these are a part of the Coding Guidelines requirements. In addition you might like to know
about other functions which are very often used since they might be very helpful to you (they were to others!).
Function Comments
t3lib_div::_GP Getting values from GET or POST vars
t3lib_div::_GET
t3lib_div::_POST APIs for getting values in GET or POST variables with slashes stripped regardless of PHP environment.
Always use these functions instead of direct access to $_GET, $_POST or
$HTTP_GET_VARS/$HTTP_POST_VARS.
t3lib_div::_GP($varname) will give you the value of either the GET or POST variable with priority to POST if
present. This is useful if you don't know whether a parameter is passed as GET or POST. Many scripts will
use this function to read variables in the init function:
// Setting GPvars:
$this->file = t3lib_div::_GP('file');
$this->size = t3lib_div::_GP('size');
t3lib_div::_GET() will give you GET vars. For security reasons you should use this if you know your
parameters are passed as GET variables. This example gives you the whole $_GET array:
$params = t3lib_div::_GET();
t3lib_div::POST() will give you POST variables. Works like t3lib_div::_GET(). For security reasons you
should use this if you know your parameters are passed as POST variables.
This example gives you the content of the POST variable TSFE_ADMIN_PANEL, for instance it could
come from a form field like "<input name="TSFE_ADMIN_PANEL[command]" ..../>
$input = t3lib_div::_POST('TSFE_ADMIN_PANEL');
Examples:
API function for delivery of system and environment variables on any web-server brand and server OS.
Always use this API instead of $_ENV/$_SERVER or getenv() if possible.
Examples:
if (t3lib_div::getIndpEnv('HTTP_ACCEPT_LANGUAGE') == $test)...
if (t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $pcs[1]))...
$prefix = t3lib_div::getIndpEnv('TYPO3_REQUEST_URL');
$redirectTo = t3lib_div::getIndpEnv('TYPO3_SITE_URL').$redirectTo;
if (!t3lib_div::getIndpEnv('TYPO3_SSL')) ...
t3lib_div::loadTCA Loading full table description into $TCA
If you want to access or change any part of the $TCA array for a table except the ['ctrl'] part then you should
call this function first. The $TCA might not contain the full configuration for the table (depending on
configuration of the table) and to make sure it is loaded if it isn't already you call this function.
Examples of PHP code which traverses the ['columns'] part of an unknown table and loads the table
before.
t3lib_div::loadTCA($this->table);
reset($TCA[$this->table]["columns"]);
while(list($fN)=each($TCA[$this->table]["columns"])) {
$fieldListArr[]=$fN;
}
t3lib_BEfunc::deleteClause Get SQL WHERE-clause filtering "deleted" records
Tables from $TCA might be configured to set an integer flag when deleted instead of being physically
deleted from the database. In any case records with the deleted-flag set must never be selected in TYPO3.
To make sure you never make that mistake always call this function which will pass you a SQL WHERE-
clause like " AND deleted=0" if the table given as argument has been configured with a deleted-field.
(Notice: In the frontend this is build into the "enableFields()" function.)
Example:
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
'pid,uid,title,TSconfig,is_siteroot,storage_pid',
'pages',
'uid='.intval($uid).' '.
t3lib_BEfunc::deleteClause('pages').' '.
$clause
);
If you need to check if an extension is loaded in a TYPO3 installation simply use this function to ask for
that.
Example:
Examples:
// Include a PHP file from the extension "extrep_wizard".
// t3lib_extMgm::extPath() returns the absolute path to the
// extension directory.
require_once(
t3lib_extMgm::extPath('extrep_wizard').
'pi/class.tx_extrepwizard.php'
);
// Get relative path (relative to PATH_typo3) to an icon (backend)
$icon = t3lib_extMgm::extRelPath("tt_rating")."rating.gif";
// Get relative path (relative to PATH_site) to an icon (frontend)
return '<img src="'.
t3lib_extMgm::siteRelPath("indexed_search").'pi/res/locked.gif"
... />';
t3lib_div::validPathStr() - Checks for malicious file paths. Returns true if no '//', '..' or '\' is in the $theFile.
This should make sure that the path is not pointing 'backwards' and further doesn't contain double/back
slashes.
t3lib_div::isAbsPath() - Checks if the input path is absolute or relative (detecting either '/' or 'x:/' as first
part of string) and returns true if so.
t3lib_div::isAllowedAbsPath() - Returns true if the path is absolute, without backpath '..' and within the
PATH_site OR within the lockRootPath. Contrary to t3lib_div::getFileAbsFileName() this function can also
validate files in filemounts outside the web-root of the installation, but this is rarely used!
One would think that creating directories is one thing you can do directly with PHP. Well, it turns out to be
quite error-prone if it should be compatible with Windows servers and safe-mode at the same time. So
TYPO3 offers a substitution function you should always use.
Example:
$root.=$dirParts.'/';
if (!is_dir($extDirPath.$root)) {
t3lib_div::mkdir($extDirPath.$root);
if (!@is_dir($extDirPath.$root)) {
return 'Error: The directory "'.
$extDirPath.$root.
'" could not be created...';
}
}
This example shows how to handle an uploaded file you just want to read and then delete again:
t3lib_div::tempnam() - Create temporary filename (creates file with unique file name). This function
should be used for getting temporary filenames - will make your applications safe for "open_basedir = on".
Remember to delete the temporary files after use! This is done by t3lib_div::unlink_tempfile()
In the following example it is shown how two temporary filenames are created for being processed with an
external program (diff) after which they are deleted again:
This function allows you to truncate a string from eg. "Hello World" to "Hello Wo..." so for example very
long titles of records etc. will not break the visual appearance of your backend modules.
Since text strings cannot be cropped at any byte if the character set is utf-8 or another multibyte charset
this function will process the string assuming the character set to be the one used in the backend.
It is recommended to use $BE_USER->uc['titleLen'] for the length parameter.
Use this function to prepare content for <textarea> tags. Then you will avoid extra / stripped whitespace
when the form is submitted multiple times.
// Create item:
$item = '
<textarea>'.
t3lib_div::formatForTextarea($value).
'</textarea>';
Use this to prepare redirection URLs for location-headers. It will convert the URL to be absolute. This is
needed for some webservers (Windows) while unix servers will work fine without. So to honor compatibility,
use this function like this:
Header('Location: '.t3lib_div::locationHeaderUrl($this->retUrl));
exit;
The selector box is made by this function call. It sets the ID variable (zero if not available), the GET var
name, "SET[mode]", the current value from MOD_SETTINGS and finally the array of menu options,
MOD_MENU['mode']:
t3lib_BEfunc::getFuncMenu(
$this->id,
'SET[mode]',
$this->MOD_SETTINGS['mode'],
$this->MOD_MENU['mode']
)
Prior to making the menu it is required that the MOD_MENU array is set up with an array of options. This
could look like this (getting some labels from the "locallang" system). In addition the incoming "SET" GET-
variable must be registered in the session which is also done in this listing:
$this->MOD_MENU = array(
'mode' => array(
0 => $LANG->getLL('user_overview'),
'perms' => $LANG->getLL('permissions')
)
);
// Clean up settings:
$this->MOD_SETTINGS = t3lib_BEfunc::getModuleData(
$this->MOD_MENU,
t3lib_div::_GP('SET'),
$this->MCONF['name']
);
Then the function call looks like this. Notice the fourth argument is gone because a checkbox does not
have any information about options like a selector box would have.
t3lib_BEfunc::getFuncCheck(
0,
'SET[own_member_only]',
$this->MOD_SETTINGS['own_member_only']
);
For checkboxes you must set the key in the MOD_MENU array as well. Otherwise the values are not
registered in the user session:
Use this function to create a link to the "alt_doc.php" core script which can generate editing forms for any
$TCA configured record. The actual editing command is passed to "alt_doc.php" through the GET
parameter "&edit".
See the section with "Various examples" for detailed examples of this!
Example:
$params='&edit[pages]['.$row['uid'].']=edit';
$link = '<a href="#" onclick="'.
htmlspecialchars(t3lib_BEfunc::editOnClick($params,'',-1)).
'">Edit</a>';
t3lib_BEfunc::viewOnClick Create onclick-JavaScript code that opens a page in the frontend
It will detect the correct domain name if needed and provide the link with the right back path. Also it will re-
use any window already open.
Example:
// Delete
$params = '&cmd[tt_content]['.$row['uid'].'][delete]=1';
$out.= '<a href="'.
htmlspecialchars($GLOBALS['SOBE']->doc->issueCommand($params)).
'" onclick="'.
htmlspecialchars("return confirm('Want to delete?');").
'">Delete record</a>';
(Note: For the short description to be displayed and not only the icon the user must set up "Field help
mode" in the User>Setup module to "Display full text message".)
Examples:
Prior to calling helpTextIcon and helpText you might need to load the description table with:
if ($BE_USER->uc['edit_showFieldHelp']) {
$LANG->loadSingleTableDescription($tableIdent);
}
Alternatively you can use t3lib_BEfunc::cshItem(). It's a quicker way of integrating the descriptions since
description files are loaded automatically and the text/icon mode is integrated in a single function call. This
is recommended for sporadic usage:
$HTMLcode.=
t3lib_BEfunc::cshItem($tableIdent,'quickEdit',$BACK_PATH);
t3lib_iconWorks::getIconImage Getting correct icon for database table record
t3lib_iconWorks::getIcon
Always use these functions if you need to get the icon for a record. Works only for records from tables
which are defined in $TCA
Pass the filename and width/height attributes of all images you use in your backend applications through
this function. See Skin API description for more details.
$skin_enabled_icon = '<img'.
t3lib_iconWorks::skinImg(
$this->doc->backPath,
'gfx/recordlock_warning3.gif',
'width="17" height="12"'
).
' alt="" />';
Inserting a record:
Just fill an array with "fieldname => value" pairs and pass it to exec_INSERTquery() along with the table
name in which it should be inserted:
$insertFields = array(
'md5hash' => $md5,
'tstamp' => time(),
'type' => 2,
'params' => $inUrl
);
$GLOBALS['TYPO3_DB']->exec_INSERTquery(
'cache_md5params',
$insertFields
);
Updating a record:
Create an array of "fieldname => value" pairs before calling exec_UPDATEquery(). The function call is
almost like inserting, but you need to add a WHERE clause to target the update to the record you want to
update. It is the second argument you set to a value like "uid=???".
$fields_values = array(
'title' => $data['sys_todos'][$key]['title'],
'deadline' => $data['sys_todos'][$key]['deadline'],
'description' => $data['sys_todos'][$key]['description'],
'tstamp' => time()
);
$GLOBALS['TYPO3_DB']->exec_UPDATEquery(
'sys_todos',
'uid='.intval($key),
$fields_values
);
Deleting a record:
Call exec_DELETEquery() with the tablename and the WHERE clause selecting the record to delete:
$GLOBALS['TYPO3_DB']->exec_DELETEquery(
'sys_todos',
'uid='.intval($key)
);
Selecting a record:
Call exec_SELECTquery() with at least the first three arguments (field list to select, table name and
WHERE clause). The return value is a result pointer (or object) which should be passed to
->sql_fetch_assoc() in a loop in order to traverse the result rows.
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
'*',
$theTable,
$theField.'="'.
$GLOBALS['TYPO3_DB']->quoteStr($theValue, $theTable).'"'.
$this->deleteClause($theTable).' '.
$whereClause,
$groupBy,
$orderBy,
$limit
);
$rows = array();
Function Comments
t3lib_div::inList Check if an item exists in a comma-separated list of items.
if (t3lib_div::inList('gif,jpg,png',$ext)) {
t3lib_div::intInRange Forces the input variable (integer) into the boundaries of $min and $max.
t3lib_div::intInRange($row['priority'],1,5);
t3lib_div::isFirstPartOfStr Returns true if the first part of input string matches the second argument.
t3lib_div::isFirstPartOfStr($path,PATH_site);
t3lib_div::testInt Tests if the input is an integer.
t3lib_div::shortMD5 Creates partial/truncated MD5 hashes. Useful when a 32 byte hash is too long or you rather work with an
t3lib_div::md5int integer than a string.
$addQueryParams.= '&cHash='.t3lib_div::shortMD5(serialize($pA));
t3lib_div::md5int() - Creates an integer from the first 7 hex chars of the MD5 hash string
$value = t3lib_div::deHSCentities(htmlspecialchars($value));
t3lib_div::modifyHTMLColor('#cca823',+10,+10,+10)
t3lib_div::modifyHTMLColorAll($this->doc->bgColor,-20);
t3lib_div::formatSize Formats a number of bytes as Kb/Mb/Gb for visual output.
array_unique(t3lib_div::trimExplode(',',$rawExtList,1));
t3lib_div::trimExplode(chr(10),$content);
t3lib_div::intExplode() - Explodes a by a token and converts each item to an integer value. Very useful to
force integer values out of a value list, for instance for an SQL query.
t3lib_div::revExplode() - Reverse explode() which allows you to explode a string into X parts but from the
back of the string instead.
$p=t3lib_div::revExplode('/',$path,2);
t3lib_div::array_merge_recursive_ov Merging arrays with fixes for "PHP-bugs"
errule
t3lib_div::array_merge t3lib_div::array_merge_recursive_overrule() - Merges two arrays recursively and "binary safe" (integer
keys are overridden as well), overruling similar the values in the first array ($arr0) with the values of the
second array ($arr1). In case of identical keys, ie. keeping the values of the second.
t3lib_div::array_merge() - An array_merge function where the keys are NOT renumbered as they happen
to be with the real php-array_merge function. It is "binary safe" in the sense that integer keys are overridden
as well.
t3lib_div::array2xml Serialization of PHP variables into XML.
t3lib_div::xml2array
These functions are made to serialize and unserialize PHParrays to XML files. They are used for the
FlexForms content in TYPO3, Data Structure definitions etc. The XML output is optimized for readability
since associative keys are used as tagnames. This also means that only alphanumeric characters are
allowed in the tag names and only keys not starting with numbers (so watch your usage of keys!). However
there are options you can set to avoid this problem. Numeric keys are stored with the default tagname
"numIndex" but can be overridden to other formats). The function handles input values from the PHP array
in a binary-safe way; All characters below 32 (except 9,10,13) will trigger the content to be converted to a
base64-string. The PHP variable type of the data is preserved as long as the types are strings, arrays,
integers and booleans. Strings are the default type unless the "type" attribute is set.
t3lib_div::array2xml($this->FORMCFG['c'],'',0,'T3FormWizard');
t3lib_div::xml2array() - Converts an XML string to a PHP array. This is the reverse function of array2xml()
if ($this->xmlStorage) {
$cfgArr = t3lib_div::xml2array($row[$this->P['field']]);
}
t3lib_div::getURL Reading / Writing files
t3lib_div::writeFile
t3lib_div::getURL() - Reads the full content of a file or URL. Used throughout the TYPO3 sources.
$templateCode = t3lib_div::getURL($templateFile);
t3lib_div::writeFile($extDirPath.$theFile,$fileData['content']);
t3lib_div::split_fileref Splits a reference to a file in 5 parts. Alternative to "path_info" and fixes some "PHP-bugs" which makes
page_info() unattractive at times.
$sFiles = t3lib_div::getFilesInDir(PATH_typo3conf,'',1,1);
$files = t3lib_div::getFilesInDir($dir,'png,jpg,gif');
// Traverse files and remove abs path from each (becomes relative)
$fileList_rel =
t3lib_div::removePrefixPathFromList($fileList_abs,$absPath);
t3lib_div::implodeArrayForUrl Implodes a multidimentional array into GET-parameters (eg.
¶m[key][key2]=value2¶m[key][key3]=value3)
$pString = t3lib_div::implodeArrayForUrl('',$params);
t3lib_div::get_tag_attributes Works on HTML tag attributes
t3lib_div::implodeAttributes
t3lib_div::get_tag_attributes() - Returns an array with all attributes of the input HTML tag as key/value
pairs. Attributes are only lowercase a-z
$attribs = t3lib_div::get_tag_attributes('<'.$subparts[0].'>');
t3lib_div::implodeAttributes() - Implodes attributes in the array $arr for an attribute list in eg. and HTML
tag (with quotes)
function procItems($items,$iArray,$config,$table,$row,$field) {
global $TCA;
$params=array();
$params['items'] = &$items;
$params['config'] = $config;
$params['TSconfig'] = $iArray;
$params['table'] = $table;
$params['row'] = $row;
$params['field'] = $field;
t3lib_div::callUserFunction(
$config['itemsProcFunc'],
$params,
$this
);
return $items;
}
$_procObj = &t3lib_div::getUserObj($_classRef);
$_procObj->pObj = &$this;
$value = $_procObj->transform_rte($value,$this);
t3lib_div::linkThisScript Returns the URL to the current script. You can an array with associative keys corresponding to the GET-
vars you wish to add to the URL. If you set them empty, they will remove existing GET-vars from the current
URL.
t3lib_div::plainMailEncoded Mail sending functions
t3lib_div::quoted_printable
t3lib_div::plainMailEncoded() - Simple substitute for the PHP function mail() which allows you to specify
encoding and character set.
t3lib_div::quoted_printable() - Implementation of quoted-printable encode.
t3lib_BEfunc::getRecord Functions for selecting records by uid or field value.
t3lib_BEfunc::getRecordsByField
t3lib_BEfunc::getRecord() - Gets record with uid=$uid from $table
$label = t3lib_BEfunc::getRecordPath(
intval($row['shortcut']),
$perms_clause,
20
);
t3lib_BEfunc::readPageAccess Returns a page record (of page with $id) with an extra field "_thePath" set to the record path if the WHERE
clause, $perms_clause, selects the record. Thus is works as an access check that returns a page record if
access was granted, otherwise not.
$perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
$pageinfo = t3lib_BEfunc::readPageAccess($id,$perms_clause);
t3lib_BEfunc::date Date/Time formatting functions using date/time format from TYPO3_CONF_VARS.
t3lib_BEfunc::datetime
t3lib_BEfunc::calcAge t3lib_BEfunc::date() - Returns $tstamp formatted as "ddmmyy" (According to
$TYPO3_CONF_VARS['SYS']['ddmmyy'])
t3lib_BEfunc::datetime($row["crdate"])
t3lib_BEfunc::datetime($row["item_mtime"])
t3lib_BEfunc::calcAge() - Returns the "age" in minutes / hours / days / years of the number of $seconds
inputted.
$out = t3lib_BEfunc::titleAttribForPages($row,'',0);
$out = t3lib_BEfunc::titleAttribForPages($row,'1=1 '.$this->clause,0);
t3lib_BEfunc::thumbCode Returns image tags for thumbnails
t3lib_BEfunc::getThumbNail
t3lib_BEfunc::thumbCode() - Returns a linked image-tag for thumbnail(s)/fileicons/truetype-font-previews
from a database row with a list of image files in a field. Slightly advanced. It's more likely you will need
t3lib_BEfunc::getThumbNail() to do the job.
t3lib_BEfunc::getThumbNail() - Returns single image tag to thumbnail using a thumbnail script (like
thumbs.php)
t3lib_BEfunc::getThumbNail(
$this->doc->backPath.'thumbs.php',
$filepath,
'hspace="5" vspace="5" border="1"'
);
Example of how both functions are used together; first getHash() to fetch any possible content and if
nothing was found how the content is generated and stored in the cache:
$line.= t3lib_BEfunc::getRecordTitle('tt_content',$row,1);
$outputValue = nl2br(
htmlspecialchars(
trim(
t3lib_div::fixed_lgd_cs(
t3lib_BEfunc::getProcessedValue(
$table,
$fieldName,
$row[$fieldName]
),
250
)
)
)
);
t3lib_BEfunc::getFileIcon Returns file icon name (from $FILEICONS) for the fileextension $ext
$fI = pathinfo($filePath);
$fileIcon = t3lib_BEfunc::getFileIcon(strtolower($fI['extension']));
$fileIcon = '<img'.
t3lib_iconWorks::skinImg(
$this->backPath,
'gfx/fileicons/'.$fileIcon,
'width="18" height="16"'
).' alt="" />';
t3lib_BEfunc::getPagesTSconfig Returns the Page TSconfig for page with id, $id.
This example shows how an object path, "mod.web_list" is extracted from the Page TSconfig for page $id:
$modTSconfig = $GLOBALS["BE_USER"]->getTSConfig(
"mod.web_list",
t3lib_BEfunc::getPagesTSconfig($id)
);
// tt_address modified
t3lib_div::loadTCA('tt_address');
t3lib_extMgm::addTCAcolumns('tt_address',array(
'module_sys_dmail_category' =>
Array('config'=>array('type'=>'passthrough')),
'module_sys_dmail_html' =>
Array('config'=>array('type'=>'passthrough'))
));
t3lib_extMgm::addToAllTCAtypes Makes fields visible in the TCEforms, adding them to the end of (all) "types"-configurations
For usage in "ext_tables.php" files
t3lib_extMgm::addToAllTCAtypes(
"fe_users",
"tx_myext_newfield;;;;1-1-1, tx_myext_another_field"
);
t3lib_extMgm::allowTableOnStandar Add tablename to default list of allowed tables on pages (in $PAGES_TYPES)
dPages For usage in "ext_tables.php" files
t3lib_extMgm::allowTableOnStandardPages('tt_board');
t3lib_extMgm::addModule Adds a module (main or sub) to the backend interface
For usage in "ext_tables.php" files
t3lib_extMgm::addModule(
'user',
'setup',
'after:task',
t3lib_extMgm::extPath($_EXTKEY).'mod/'
);
t3lib_extMgm::addModule(
'tools',
'txcoreunittestM1',
'',
t3lib_extMgm::extPath($_EXTKEY).'mod1/'
);
t3lib_extMgm::insertModuleFunction Adds a "Function menu module" ('third level module') to an existing function menu for some other backend
module
For usage in "ext_tables.php" files
t3lib_extMgm::insertModuleFunction(
'web_func',
'tx_cmsplaintextimport_webfunc',
t3lib_extMgm::extPath($_EXTKEY).
'class.tx_cmsplaintextimport_webfunc.php',
'LLL:EXT:cms_plaintext_import/locallang.php:menu_1'
);
t3lib_extMgm::addPlugin Adds an entry to the list of plugins in content elements of type "Insert plugin"
For usage in "ext_tables.php" files
t3lib_extMgm::addPlugin(
Array(
'LLL:EXT:newloginbox/locallang_db.php:tt_content.list_type1',
$_EXTKEY.'_pi1'
),
'list_type'
);
t3lib_extMgm::addPItoST43($_EXTKEY);
Example:
This is how simple it is to use this record in your frontend plugins when you do
queries directly (not using API functions already using them):
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(...);
while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))
{
$GLOBALS['TSFE']->sys_page-
>versionOL($table,$row);
if (is_array($row)) {
...
When the live record is selected, call ->versionOL() and make sure to check if the
input row (passed by reference) is still an array.
$GLOBALS['TSFE']->sys_page->fixVersioningPid() Finding online PID for offline version record.
Will look if the "pid" value of the input record is -1 (it is an offline version) and if the
table supports versioning; if so, it will translate the -1 PID into the PID of the
original record
Used whenever you are tracking something back, like making the root line. In fact,
it is currently only used by the root line function and chances are that you will not
need this function often.
Backend challenges
The main challenge in the backend is to reflect how the system will look when the workspace gets published. To create a
transparent experience for backend users we have to overlay almost every selected record with any possible new version it
might have. Also when we are tracking records back to the page tree root point we will have to correct pid-values. All issues
related to selecting on fields other than pid and uid also relates to the backend as they did for the frontend.
Function Description
t3lib_BEfunc::workspaceOL() Overlaying record with workspace version if any. Works like ->sys_page->versionOL() does,
but for the backend. Input record must have fields only from the table (no pseudo fields) and
the record is passed by reference.
Example:
$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'pages',
'uid='.intval($id).$delClause);
$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
t3lib_BEfunc::workspaceOL('pages', $row);
t3lib_BEfunc::getRecordWSOL() Gets record from table and overlays the record with workspace version if any.
Example:
$row = t3lib_BEfunc::getRecordWSOL($table,$uid);
Example:
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
'count(*)',
$this->table,
$this->parentField.'='.$GLOBALS['TYPO3_DB']->fullQuoteStr($uid,
$this->table).
t3lib_BEfunc::deleteClause($this->table).
t3lib_BEfunc::versioningPlaceholderClause($this->table).
$this->clause
);
$BE_USER->workspaceCannotEditRecord() Checking if editing of an existing record is allowed in current workspace if that is offline.
$BE_USER- Like $BE_USER->workspaceCannotEditRecord() but also requires version to be offline (draft)
>workspaceCannotEditOfflineVersion()
$BE_USER->workspaceCreateNewRecord() Checks if new records can be created in a certain page (according to workspace restrictions).
$BE_USER->workspacePublishAccess($wsid) Returns true if user has access to publish in workspace.
$BE_USER->workspaceSwapAccess() Returns true if user has access to swap versions.
$BE_USER->checkWorkspace() Checks how the users access is for a specific workspace.
$BE_USER->checkWorkspaceCurrent() Like ->checkWorkspace() but returns status for the current workspace.
$BE_USER->setWorkspace() Setting another workspace for backend user.
$BE_USER->setWorkspacePreview() Setting frontend preview state.
Files
TCE also has a part for handling files. The file operations are normally performed in the File > List module where you can
manage a directory on the server by copying, moving, deleting and editing files and directories. The file operations are
managed by two core classes, t3lib_basicFileFunc and t3lib_extFileFunc.
Apart from this ordinary permissions apply as if the user wants to make a copy of the record on the
same page.
version array Versioning action.
Keys:
● [action] : Keyword determining the versioning action. Options are:
● “new” : Indicates that a new version of the record should be created.
Additional keys, specific for “new” action:
● [treeLevels] : (Only pages) Integer, -1 to 4, indicating the number of levels of the page
tree to version together with a page. This is also referred to as the versioning type:
-1 (“element”) means only the page record gets versioned (default)
0 (“page”) means the page + content tables (defined by ctrl-flag
“versioning_followPages”)
>0 (“branch”) means the the whole branch is versioned (full copy of all tables), down
to the level indicated by the value (1= 1 level down, 2= 2 levels down, etc.)
The treeLevel is recorded in the field “t3ver_swapmode” and will be observed when
the record is swapped during publishing.
● [label] : Indicates the version label to apply. If not given, a standard label including
version number and date is added.
● “swap” : Indicates that the current online version should be swapped with another.
Additional keys, specific for “swap” action:
● [swapWith] : Indicates the uid of the record to swap current version with!
● [swapIntoWS]: Boolean, indicates that when a version is published it should be
swapped into the workspace of the offline record.
● “clearWSID” : Indicates that the workspace of the record should be set to zero (0). This
removes versions out of workspaces without publishing them.
● “setStage” : Sets the stage of an element.
Special feature: The id-key in the array can be a comma list of ids in order to perform the
stageChange over a number of records. Also, the internal variable ->generalComment
(also available through tce_db.php as "&generalComment") can be used to set a default
comment for all stage changes of an instance of tcemain.
Additional keys for this action is:
● [stageId] : Values are: -1 (rejected), 0 (editing, default), 1 (review), 10 (publish)
● [comment] : Comment string that goes into the log.
Notice: For FlexForms the data array of the FlexForm field is deeper than three levels. The number of possible levels for
FleFforms is infinite and defined by the data structure of the FlexForm. But FlexForm fields always end with a "regular
value" of course.
This creates a new page titled "The page title" right after page id 45 in the tree:
$data['pages']['NEW9823be87'] = array(
"title" => "The page title",
"subtitle" => "Other title stuff",
"pid" => "-45"
);
This creates two new pages right after each other, located right after the page id 45:
$data['pages']['NEW9823be87'] = array(
"title" => "Page 1",
"pid" => "-45"
);
$data['pages']['NEWbe68s587'] = array(
"title" => "Page 2",
"pid" => "-NEW9823be87"
);
Notice how the second "pid" value points to the "NEW..." id placeholder of the first record. This works because the new id of
the first record can be accessed by the second record. However it works only when the order in the array is as above since
the processing happens in that order!
This updates the page with uid=9834 to a new title, "New title for this page", and no_cache checked:
$data['pages'][9834] = array(
"title" => "New title for this page",
"no_cache" => "1"
);
$TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc'][]='myext_cacheProc
->proc';
require_once(t3lib_extMgm::extPath('myext').'class.myext_cacheProc.php');
Flags in TCEmain
There are a few internal variables you can set prior to executing commands or data submission. These are the most
significant:
It is highly recommended to set this value to zero every time the class is used!
If you set this value to false you can pass values as-is to the class and it is most like that this is what
you want. Otherwise you would have to pass all values through addslashes() first.
require_once (PATH_t3lib."class.t3lib_tcemain.php");
This aims to create two new pages in the page with uid "456". In the follow code this is submitted to the database. Notice
how line 3 reverses the order of the array. This is done because otherwise "page 1" is created first, then "page 2" in the
same PID meaning that "page 2" will end up above "page 1" in the order. Reversing the array will create "page 2" first and
then "page 1" so the "expected order" is preserved.
Apart from this line 6 will send a "signal" that the page tree should be updated at the earliest occasion possible. Finally, the
cache for all pages is cleared in line 7.
1: $tce = t3lib_div::makeInstance('t3lib_TCEmain');
2: $tce->stripslashes_values = 0;
3: $tce->reverseOrder = 1;
4: $tce->start($data,array());
5: $tce->process_datamap();
6: t3lib_BEfunc::getSetUpdateSignal('updatePageTree');
7: $tce->clear_cacheCmd('pages');
Typically it comes from a POST form which submits a form field like <input
name="data[tt_content][123][header]" value="This is the headline" />
cmd array Command array on the form [tablename][uid][command] = value. This array may get additional
data set internally based on clipboard commands send in CB var!
Typically this comes from GET vars passed to the script like "&cmd[tt_content][123][delete]=1"
which will delete Content Element with UID 123
cacheCmd string Cache command sent to ->clear_cacheCmd
redirect string Redirect URL. Script will redirect to this location after performing operations (unless errors has
occured)
flags array Accepts options to be set in TCE object. Currently it supports "reverseOrder" (boolean).
mirror array Example: [mirror][table][11] = '22,33' will look for content in [data][table][11] and copy it to
[data][table][22] and [data][table][33]
prErr boolean If set, errors will be printed on screen instead of redirection. Should always be used, otherwise you
will see no errors if they happen.
CB array Clipboard command array. May trigger changes in "cmd"
vC string Verification code
uPT string Update Page Tree Trigger. If set and the manipulated records are pages then the update page tree
signal will be set.
See t3lib_t3lib_extFileFunctions::func_upload()
unzip "data" "data" = Absolute path to the zip-file. (fileextension must be "zip")
"target" "target" = The absolute path to the target folder (destination) (if not set, default is the same as the
zip-file)
It is unlikely that you will need to use this internally in your scripts like you will need t3lib_TCEmain. It is fairly uncommon to
need the file manipulations in own scripts unless you make a special application. Therefore the most typical usage of this
API is from tce_file.php and the core scripts that are activated by the "File > List" module.
However, if you need it this is an example (taken from tce_file.php) of how to initialize the usage.
1: // Initializing:
2: $this->fileProcessor = t3lib_div::makeInstance('t3lib_extFileFunctions');
3: $this->fileProcessor->init($FILEMOUNTS, $TYPO3_CONF_VARS['BE']['fileExtensions']);
4: $this->fileProcessor->init_actionPerms($BE_USER->user['fileoper_perms']);
5:
6: $this->fileProcessor->start($this->file);
7: $this->fileProcessor->processData();
Line 2 makes an instance of the class and line 3 initializes the object with the filemounts of the current user and the array of
allow/deny file extensions in web-space and ftp-space (see below). Then the file operation permissions are loaded from the
user object in line 4. Finally, the file command array is loaded in line 6 (and internally additional configuration takes place
from $TYPO3_CONF_VARS!). In line 7 the command map is executed.
This could typically be a GET var like "&file[delete][0][data]=[absolute file path]" or a POST form
field like "<input type="text" name="file[newfolder][0][data]" value=""/><input type="hidden"
name="file[newfolder][0][target]" value="[absolute path to folder to create in]"/>"
redirect string Redirect URL. Script will redirect to this location after performing operations.
CB array Clipboard command array. May trigger changes in "file"
vC string Verification code
overwriteExistingFiles boolean If existing files should be overridden.
Hooks
The concept of "hooks"
Hooks are basically places in the source code where a user function will be called for processing if a such has been
configured. Hooks provide a way to extend functionality of TYPO3 and extensions easily and without blocking for others to
do the same.
Proposing hooks
If you need to extend something which have no hook yet, then you should suggest implementing a hook. Normally that is
rather easily done by the author of the source you want to extend.
Line 1 includes a class which contains the user defined PHP code to be called by the hook.
Line 2 registers the class/method name from the included file with a hook inside of "t3lib_TCEmain". The hook will call the
user function after the clear-cache command has been executed. The user function will receive parameters which allows it
to see what clear-cache action was performed and typically also an object reference to the parent object. Then the user
function can take additional actions as needed.
If we take a look inside of t3lib_TCEmain we find the hook to be activated like this:
This is how hooks are typically constructed. The main action happens in line 5 where the function
"t3lib_div::callUserFunction()" is called. The user function is called with two arguments, an array with variable parameters
and the parent object.
In line 3 the contents of the parameter array is prepared. This is of high interest to you because this is where you see what
data is passed to you and what data might possibly be passed by reference and thereby possible to manipulate from your
hook function.
Finally, notice how the array $TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc']
is traversed and for each entry the value is expected to be a function reference which will be called. This allows many hooks
to be called at the same place. The hooks can even rearrange the calling order if they dare.
The syntax of a function reference (or object reference if t3lib_div::getUserObj is used in the hook instead) can be seen in
the API documentation of t3lib_div.
Hook configuration
There is no complete index of hooks in the core. But they are easy to search for and find. And typically it comes quite
naturally since you will find the hooks in the code you want to extend - if they exists.
This index will list the main variable spaces for configuration of hooks. By the names of these you can easily scan the
source code to find which hooks are available or might be interesting for you.
The index below also includes some variable spaces which does not only carry hook configuration but might be used for
other purposes as well.
$TYPO3_CONF_VARS['EXTCONF']
Configuration space for extensions.
This will contain all kinds of configuration options for specific extensions including possible hooks in them! What options are
available to you will depend on a search in the documentation for that particular extension.
$TYPO3_CONF_VARS['EXTCONF'][ extension_key ][ sub_key ] = value
Notice: $TYPO3_CONF_VARS["EXTCONF"] is the recommended place to put hook configuration that are available inside
your extensions!
Here is an example of how the EXTCONF array is used inside an extension. Notice, this example is not a hook (sorry,
couldn't find a better example) but it is based on the same principles. It is just an example of configuration of additional "root
line fields" that can be used during indexing (line 8-12). It shows the versatility of the EXTCONF array:
1: function getRootLineFields(&$fieldArr) {
2: $rl = $this->rootLevel;
3:
4: $fieldArr['rl0'] = intval($rl[0]['uid']);
5: $fieldArr['rl1'] = intval($rl[1]['uid']);
6: $fieldArr['rl2'] = intval($rl[2]['uid']);
7:
8: if
(is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['addRootLineFields'])) {
9: foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['addRootLineFields'] as
$TYPO3_CONF_VARS['SC_OPTIONS']
Configuration space for core scripts.
This array is created as an adhoc space for creating hooks from any script. This will typically be used from the core scripts
of TYPO3 which do not have a natural identifier like extensions have their extension keys.
$TYPO3_CONF_VARS['SC_OPTIONS'][ main_key ][ sub_key ][ index ] = function_reference
● main_key : The relative path of a script (for output scripts it should be the "script ID" as found in a comment in the
HTML header )
● sub_key : Whatever the script defines. Typically it identifies the context of the hook.
● index : Integer index typically. Can be unique string if you have a reason to use that. Normally it has no greater
significance since the value of the key is not used. The hooks normally traverse over the array and uses only the value
(function reference)
● function_reference : A function reference using the syntax of t3lib_div::callUserFunction() or t3lib_div::getUserObj()
depending on implementation of the hook.
The above syntax is how a hook is typically defined but it might differ and it might not be a hook at all, but just configuration.
Depends on implementation in any case.
The following example shows a hook from tslib_fe. In this case the function t3lib_div::getUserObj() is used for the hook. The
function_reference is referring to the class name only since the function returns an object instance of that class. The method
name to call is predefined by the hook, in this case "sendFormmail_preProcessVariables()". This method allows to pass any
number of variables along instead of the limited $params and $pObj variables from t3lib_div::callUserFunction().
In this example we are looking at a special hook, namely the one for RTE transformations. Well, maybe this is not a "hook"
in the normal sense, but the same principles are used. In this case the "index" key is defined to be the transformation key
name, not a random integer since we do not iterate over the array as usual. In this case t3lib_div::getUserObj() is also used.
1: if ($_classRef =
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['transformation'][$cmd
]) {
2: $_procObj = &t3lib_div::getUserObj($_classRef);
3: $_procObj->pObj = &$this;
4: $_procObj->transformationKey = $cmd;
5: $value = $_procObj->transform_db($value,$this);
6: }
A classic hook also from tslib_fe. This is also based on t3lib_div::callUserFunction() and it passes a reference to $this along
to the function via $_params. In the user defined function $_params['pObj']->content is meant to be manipulated in some
way. The return value is insignificant - everything works by the reference to the parent object.
1: // Hook for post-processing of page content cached/non-cached:
2: if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-
$TYPO3_CONF_VARS['TBE_MODULES_EXT']
Configuration space for backend modules.
Among these configuration options you might find entry points for hooks in the backend. This somehow overlaps the
intention of "SC_OPTIONS" above but this array is an older invention and slightly outdated.
$TBE_MODULES_EXT[ backend_module_key ][ sub_key ] = value
● backend_module_key : The backend module key for which the configuration is used.
● sub_key : Whatever the backend module defines.
● value : Whatever the backend module defines.
The following example shows TBE_MODULES_EXT being used for adding items to the Context Sensitive Menus
(Clickmenu) in the backend. The hook value is an array with a key pointing to a file reference to class file to include. Later
each class is instantiated and a fixed method inside is called to do processing on the array of menu items. This kind of hook
is non-standard in the way it is made.
The following code listings works in the same way. First, a list of class files to include is registered. Then in the second code
listing the same array is traversed and each class is instantiated and a fixed function name is called for processing.
1: // Setting class files to include:
2: if (is_array($TBE_MODULES_EXT['xMOD_db_new_content_el']['addElClasses'])) {
3: $this->include_once = array_merge($this-
>include_once,$TBE_MODULES_EXT['xMOD_db_new_content_el']['addElClasses']);
4: }
1: // PLUG-INS:
2: if (is_array($TBE_MODULES_EXT['xMOD_db_new_content_el']['addElClasses'])) {
3: reset($TBE_MODULES_EXT['xMOD_db_new_content_el']['addElClasses']);
4:
while(list($class,$path)=each($TBE_MODULES_EXT['xMOD_db_new_content_el']['addElClasses'])) {
5: $modObj = t3lib_div::makeInstance($class);
6: $wizardItems = $modObj->proc($wizardItems);
7: }
8: }
Creating hooks
You are encouraged to create hooks in your sources of extensions if they seem meaningful. Typically someone would
request a hook somewhere. Before you implement it, consider if it is the right place to put it etc. On the one hand we want to
Constants
Constants normally define paths and database information. These values are global and cannot be changed when they are
first defined. This is why constants are used for such vital information.
These constants are defined by either init.php or scripts included from that script.
Notice: Constants in italics may be set in a script prior to inclusion of init.php so they are optional.
Example:
define('TYPO3_enterInstallScript', '1');
This constant is set by for instance the "index.php" script so it can include
"init.php" and still show the login form:
define("TYPO3_PROCEED_IF_NO_USER", 1);
require ("init.php");
Please be very careful with this feature - use it only when you have total
control of what you are doing!
TYPO3_cliMode [prior to init.php] Initiates CLI (Command Line Interface) mode. This is used when you want
a shell executable PHP script to initialize a TYPO3 backend.
For more details see section about “Initialize TYPO3 backend in a PHP
shell script” in “Inside TYPO3”
TYPO3_version config_default.php The TYPO3 version: YES
x.x.x for released versions,
x.x.x-dev for development versions leading up to releases
x.x.x-bx for beta-versions
Global variables
Notice: Variables in italics may be set in a script prior to inclusion of "init.php" so they are optional.
Notice: The variables from "t3lib/stddb/tables.php" are only available in the frontend occasionally or partly. Please read
more in the documentation of the "cms" extension on this issue.
Is "admin"?
If you want to know if a user is an "admin" user (has complete access), just call this method:
$BE_USER->isAdmin();
Changing the "1" for other values will check other permissions. Fx. "2" will check id the user may edit the page and "4" will
check if the page can be deleted.
Again the number "1" represents the "read" permission; "2" would represent "edit" permission and "4" would be delete
permission and so on. The result from the above query could be this string:
((pages.perms_everybody & 1 = 1)OR(pages.perms_userid = 2 AND pages.perms_user & 1 =
1)OR(pages.perms_groupid in (1) AND pages.perms_group & 1 = 1))
-1 is a temporary detail number you can use while developing and error messages are not fixed yet.
0 is a value that means the message is not supposed to be translated
>=1 means the message is fixed and ready for translation.
details tinytext $details The log message text (in english). By identification through type/action/details_nr this can be
translated through the localization system.
If you insert “%s” markers in the details message and set $data to an array the first 5 entries (keys
0-4) from $data will substitute the markers sequentially (using sprintf)
log_data tinyblob $data Data that follows the log entry. Can be an array. See “details” for more info.
tablename varchar(40) $table Table name. Special field used by tce_main.php.
recuid int $recuid Record UID. Special field used by tce_main.php.
recpid int $recpid Record PID. Special field used by tce_main.php. [OBSOLETE; not used anymore.]
event_pid int $event_pid The page ID (pid) where the event occurred. Used to select log-content for specific pages.
NEWid varchar(20) $NEWid Special field used by tce_main.php. NEWid string of newly created records.
tstamp int - EXEC_TIME of event, UNIX time in seconds.
uid int - Unique ID for log entry, automatically inserted
userid int - User ID of backend user, automatically set for you
IP varchar(39) - REMOTE_ADDR of client
workspace int - Workspace ID
Example
Say you wish to make an addition to the stdWrap method found in the class “tslib_cObj” (found in the class file
tslib/class.tslib_content.php).
The first thing to do is to create the extension class. So you create a file in the typo3conf/ directory named
“class.ux_tslib_content.php”. “ux” is a prefix meaning “user-extension”. This file may look like this:
<?php
/**
* User-Extension of tslib_cObj class.
*
* @author Kasper Skårhøj <[email protected]>
*/
?>
The next thing is to configure TYPO3 to include this class file as well after the original file tslib/class.tslib_content.php:
$TYPO3_CONF_VARS["FE"]["XCLASS"]["tslib/class.tslib_content.php"]=
PATH_typo3conf."class.ux_tslib_content.php";
So when the file “tslib/class.tslib_content.php” is included inside of class.tslib_pagegen.php, the extension class is included
immediately from inside the “tslib/class.tslib_content.php” file (this is from the bottom of the file):
if (defined("TYPO3_MODE") &&
The last thing which remains is to instantiate the class ux_tslib_cObj instead of tslib_cObj. This is done automatically,
because everywhere tslib_cObj is instantiated, it is first examined if ux_tslib_cObj exists and if so, that class is instantiated
instead!
This is done by instantiating the object with "t3lib_div::makeInstance()":
$cObj = t3lib_div::makeInstance("tslib_cObj");
IMPORTANT
When setting up the file to include, in particular from t3lib/, notice the difference between
$TYPO3_CONF_VARS["BE"]["XCLASS"][...] and $TYPO3_CONF_VARS["FE"]["XCLASS"][...]. The key “FE” is used when
the class is included by a front-end script (those initialized by tslib/index_ts.php and tslib/showpic.php - both also known as
index.php and showpic.php in the root of the website), “BE” is used by backend scripts (those initialized by typo3/init.php or
typo3/thumbs.php). This feature allows you to include a different extension when the (t3lib/-) class is used in the frontend
and in the backend.
Which classes?
Most code in TYPO3 resides in classes and therefore anything in the system can be extended. So you should rather say to
yourself: In which script (and thereby which class) is it that I'm going to extend/change something. When you know which
script, you simply open it, look inside and somewhere you'll find the lines of code which are responsible for the inclusion of
the extension, typically in the bottom of the script.
The exceptions to this rule is classes like "t3lib_div", "t3lib_extMgm" or "t3lib_BEfunc". These classes contain methods
which are designed to be call non-instantiated, like "t3lib_div::fixed_lgd_cs()". Whether a class works on this basis is
normally noted in the header of the class file. When methods in a class is called non-instantiated there is no way you can
extend that method/class.
3. When you examine the SC_db_new class you find that the main() method is the one you would like to extend.
4. Finally you find that immediately after the definition of the two classes there is three lines of code which will provide you
with the final piece of knowledge you need:
// Include extension?
if (defined("TYPO3_MODE") && $TYPO3_CONF_VARS[TYPO3_MODE]["XCLASS"]["typo3/db_new.php"]) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]["XCLASS"]["typo3/db_new.php"]);
}
So now you know that the key to use is “typo3/db_new.php” when you wish to define a script which should be included
as the extension.
<?php
?>
2. Configure your extension class in typo3conf/localconf.php
$TYPO3_CONF_VARS["BE"]["XCLASS"]["typo3/db_new.php"] = PATH_typo3conf."class.test.php";
There is no “table of extendable classes” in this document because 1) all classes are extendable and 2) the number of
classes will grow as TYPO3 is further developed and extensions are made and 3) finally you cannot extend a class unless
you know it exists and have analysed some of its internal structure (methods / variables) - so you'll have to dig into the
source anyway!
Therefore; If you wish to extend something, follow this suggestion for an analysis of the situation and you'll end up with the
knowledge needed in order to extend that class and thereby extend TYPO3 without loosing backwards compatibility with
future updates. Great.
class SC_example {
function main() {
This class prints the text “The number is 100”. If you wish to do some calculations to the $number-variable before it is
printed, you are forced to simply include the whole original main-method in your extension script. Here it would be no
problem because the method is 2 codelines long. But it could be 200 codelines! So what you do is that you suggest to
the TYPO3 development to call a “harmless” dummy method in the main() method...
class SC_example {
function main() {
$number = 100;
$number = $this->processNumber($number);
echo "The number is ".$number;
}
function processNumber($theNumber) {
return $theNumber;
}
}
... and now the main() method would print “The number is greater than 100” instead.
Notice that you'll have to make such suggestions for dummy method calls because we will include them only as people
need them.
Extending methods
When extending a method like in the case above with stdWrap() please observe that such a method might gain new
parameters in the future without further notice. For instance stdWrap is currently defined like this:
function stdWrap($content,$conf) {
... but maybe some day this method will have another parameter added, eg:
function stdWrap($content,$conf,$yet_a_parameter=0) {
This means if you want to override stdWrap(), but still call the parent class' method, you must extend your own method call
from...:
function stdWrap($content,$conf) {
// Call the real stdWrap method in the parent class:
$content = parent::stdWrap($content,$conf);
...
... to:
function stdWrap($content,$conf,$yet_a_parameter=0) {
// Call the real stdWrap method in the parent class:
$content = parent::stdWrap($content,$conf,$yet_a_parameter);
...
Also be aware of constuctors. If you have a constructor in your extension class you must observe if there is a constructor in
the parent class which you should call first / after. In case, you can do it by “parent::[original class name]”
So as you see, you probably want to call this method. But lets also say you wish to make sure the $no_cache parameter is
always set to 1 (for some strange reason...). So you make an extension class like this with a new constructor, ux_tslib_fe(),
overriding the $no_cache variable and then calling the parent class constructor:
?>
Of course you need to know why it's the variable auth_timeout_field which must be set, but you are a bright person,
so of course you go directly to the file t3lib/class.t3lib_beuserauth.php, open it and find that
var $auth_timeout_field = 6000; there!
You could also easily insert an IP-filter (which is already present though...). Here you have to take a little adventure a bit
further. As you see in “class.t3lib_beuserauth.php” extends “t3lib_userAuthGroup” which extends “t3lib_userAuth” the
method start() is the place where the users are authenticated. This could quickly be exploited to make this IP filter for the
backend:
<?php
function start() {
if (!t3lib_div::cmpIP(getenv("REMOTE_ADDR"), "192.168.*.*")) {
die("Wrong IP, you cannot be authenticated!");
} else {
return parent::start();
}
}
}
?>
So now only users with client IP numbers in the 192.168.*.* series will gain access to the backend. If that is the case, notice
how the parent start() method is called and any result is returned. Thus your overriding method is a wrapped for the original.
Brilliant, right!
Here's another one:
<?php
The result is this; Normally the “General options” palette of the forms in the backend looks like this:
But the extensions does two things: 1) All formfields have their width multiplied with 1.5 so they are wider, 2) the titles of the
palette-fields are converted for uppercase. Looks like this:
So as you see you can do really stupid details - in fact almost any extension.
Warnings
There are a few warnings about using XCLASS extensions:
● Avoid using XCLASS extensions in your (public) extensions!
A PHP class can only be extended by one extension class at a time. Thus, having two extension classes set up, only the
latter one will be enabled. There is no way to work around this technologically in PHP. However
"t3lib_div::makeInstance()" supports "cascaded" extension classes, meaning that you can do "ux_ux_someclass" which
will extend "ux_someclass" but this requires an internal awareness of the extension class "ux_someclass" in the first
place.
The conclusion is that XCLASS extensions are best suited for project development where you need a quick hack of
something in the core which should still stay backwards compatible with TYPO3 core upgrades.
● Check if child classes are instantiated
Quite often people have been confused about extending for instance the "tslib_menu" class when they want to add a
feature for "TMENU". But actually the class to extend is "tslib_tmenu" which is an extension of "tslib_menu". So make
sure you are extending the right class name (and always make sure your extension class is included also).
● Strange opcode caching behaviours when you upgrade TYPO3 core
When you upgrade the TYPO3 core and you have an extension which extends a core class, the upgraded core
underneath might not be detected by opcode caches. In particular PHP-Accelerator is known for this behaviour
producing "undefined function...." errors. The solution is: Always clear "/tmp/php_a_*" files and restart your webserver
after upgrading source.
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.
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.
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:
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 <[email protected]>
* @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) {
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:
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];
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:
$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.
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:
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:
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);
● 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).
● 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.
● 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".
● 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:
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;
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.
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:
$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.
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 <[email protected]>
* @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;
return $wizardItems;
}
/**
* Include locallang file for the tt_guest book extension (containing the description and title for
the element)
*
* @return array LOCAL_LANG array
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.
$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:coreunitt
est/locallang_test.php:test_description'),
'key3' => array('Key 3 header','EXT:coreunittest/ext_icon.gif'),
)
)
...
$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.
What is $TCA?
This global array in TYPO3 defines the editable database tables and the relationship between them and how the fields in
tables are rendered in backend forms and processed in the TCE and so on.
The array is highly extendable through extensions and in fact only four tables are configured by default in TYPO3. These
four tables - those which are required for any TYPO3 installation - is configured in the file "t3lib/stddb/tables.php". The
tables are:
• the "pages" table containing the page tree of TYPO3
• the "be_users" table containing backend users
• the "be_groups" table containing backend user groups
• the "sys_filemounts" table containing file mounts for backend users.
All other tables are configured in extensions.
The file "t3lib/stddb/tables.php" contains not only the $TCA definition. You can also find other global core variables defined
there. For instance $PAGES_TYPES, $ICON_TYPES and $LANG_GENERAL_LABELS which are also used in relation to
$TCA but much less important and probably not relavant for you to use. There are more details on these arrays further
ahead in this document.
Here line 1-25 is about adding a column to the table "tt_content" which was in fact added by the extension "cms"
Then line 27-55 shows how a totally new table is added for the extension "mininews".
$TCA['tablename'] = Array (
'ctrl' => Array(
....
),
'interface' => Array(
....
),
'feInterface' => Array(
....
),
'columns' => Array(
'fieldname_1' => Array(
....
),
'fieldname_2' => Array(
....
),
....
),
'types' => Array(
....
),
'palettes' => Array(
....
),
);
(The bold/italic strings in blacks indicate that here actual table/fieldnames are used as keys)
This table describes each of the sections. Over the next pages you will see each section described in detail with all features.
Section Description
ctrl The table
The "ctrl" section contains properties for the table in general.
These are basically devided in two main categories;
• properties which affect how the table is displayed and handled in the backend interface .
This includes which icon, what name, which columns contains the title value, which column defines the type value etc.
• properties which determines how it is processed by the system (TCE).
This includes publishing control, "deleted" flag, if the table can only be edited by admin-users, may only exist in the tree
root etc.
interface The backend interface handling
The "interface" section contains properties related to the tables display in the backend, mostly the Web>List module.
feInterface Frontend Editing
The "feInterface" section contains properties related to Front End editing of the table, mostly related to the feAdmin_lib.
Is depricated in the sense that it will still exist, but will not be (and should not be) extended further.
columns The individual fields
The "columns" section contains configuration for each table field (also called "column") which can be edited by the backend.
The configuration includes both properties for the display in the backend as well as the processing of the submitted data.
Each field can be configured as a certain "type" (eg. checkbox, selector, input field, text area, file or db-relation field, user
defined etc.) and for each type a separate set of additional properties applies. These properties are clearly explained for each
type.
types The form layout for editing
The "types" section defines how the fields in the table (configured in the "columns" section) should be arranged inside the
editing form; in which order, with which "palettes" (see below) and with which possible additional features applied.
palettes The palette fields order
A palette is just a list of fields which will be arranged horizontally side-by-side. But the main idea is that these fields can be
displayed in the top-frame of the backend interface on request so they don't display inside the main form. In this way they are
kind of hidden fields which are brought forth either by clicking an icon in the main form or (more usually) when you place the
cursor in a form field of the main form).
You can insert plain text values, you can also add values for many languages by the obsolete
concept of "language-splitting" (where you separate each language label by a vertical bar, "|") but
please don't! In modern times it is always recommended to put the label values into an external
file/array (local_lang files) and let the "title" field contain a reference to that value. See the example
below. You should also have a look at the localization section in "Inside TYPO3"
Example:
$TCA['static_template'] = Array (
'ctrl' => Array (
'label' => 'title',
'tstamp' => 'tstamp',
'title' => 'LLL:EXT:cms/locallang_tca.php:static_template',
In the above example the "LLL:" prefix tells the system to look up a label from the localization
engine. The next prefix "EXT:cms" will look for the data source in the extension with the key "cms".
In that extension the file "locallang_tca.php" will contain a $LOCAL_LANG array inside of which
the label key "static_template" should contain the value, one for each language TYPO3 offers.
label string Required! Display
(fieldname) Points to the fieldname of the table which should be used as the "title" when the record is
displayed in the system.
label_alt string Commalist of fieldnames, which are holding alternative values to the value from the field pointed to Display
by "label" (see above) if that value is empty. May not be used consistently in the system, but
should apply in most cases.
Example:
$TCA['tt_content'] = Array (
'ctrl' => Array (
'label' => 'header',
'label_alt' => 'subheader,bodytext',
See t3lib_BEfunc::getRecordTitle()
Also see "label_alt_force"
label_alt_force boolean If set, then the "label_alt" fields are always shown in the title separated by comma. Display
See t3lib_BEfunc::getRecordTitle()
The most widely known usage of this feature is the Content Elements where the "Type:" selector is
defined as the "type" field and when you change that selector you will also get another rendering of
the form:
Example:
Here we will create an imaginary example to explain what the "type" property does. Imagine a table
with four user editable fields:
• One field, "displaytype", is a selectorbox with two values: "1" with the label "Regular display"
and "2" with the label "Regular display + link"
• Then three other fields, "title", "description" and "title_link"
We want the form in the backend to display only the fields "title" and "description" when the
"displaytype" selector has the value "1" ("Regular display"). When the selector is set to value "2"
("Regular display + link") we want the form to show all three fields.
This is done by first setting the "displaytype" field as the type field in [ctrl] section:
Then in the "types" section of the $TCA configuration (see later) we set up the fields for display:
The backend will select the "showitem" list for ...["types"][2] when the field "displaytype" contains
the value two. And likewise when "displaytype" is 1, then the first list is used to display fields in the
backend.
hideTable boolean Hide this table in record listings.
requestUpdate string This is a list of fields additional to the type field which will request the user to update the form due Proc.
(list of to some content having change and which til affect the layout. For example you could add any of
fieldnames) the subtype fields you might have configured.
$TCA["tx_mininews_news"] = Array (
"ctrl" => Array (
"iconfile" => t3lib_extMgm::extRelPath($_EXTKEY)."icon_tx_min
inews_news.gif",
typeicon_column string Fieldname, whose value decides alternative icons for the table (The default icon is the one defined Display
(fieldname) with the 'iconfile' value.)
An icon in the 'typeicons' array may override the default icon if an entry is found for the key having
the value of the field pointed to by "typeicon_column" (this feature).
Notice: These options ("typoicon_column" and "typeicons") does not work for the pages-table,
which is configured by the PAGES_TYPES array.
Related "typeicons"
This feature is used by for instance the "tt_content" table (Content Elements) where each type of
content element has its own icon.
Example:
See "typeicons"
typeicons array (See "typeicon_column") Display
Example:
For the "tt_content" table this option points to the field "image" which contains the list of images
that can be attached to the content element:
'thumbnail' => 'image',
The effect of the field can be see in listings in eg. the "List" module:
(You might have to enable "Show Thumbnails by default" in the Setup module first to see this
display).
selicon_field string Fieldname, which contains the thumbnail image used to represent the record visually whereever it Display
(fieldname) is shown in TCEforms as a foreign reference selectable from a selectorbox.
Only images of the ordinary webformat, like gif,png,jpeg,jpg, is allowed. No scaling is done.
You should consider this a feature where you can attach an "icon" to a record which is typically
selected as a reference in other records. For example a "category". In such a case this field points
out the icon image which will then be shown. This feature can thus enrich the visual experience of
selecting the relation in other forms.
The feature is seldomly used.
Related: "selicon_field_path"
selicon_field_path string The path prefix of the value from 'selicon_field'. This must be similar to the upload_path of that Display
field (and thereby redundant).
sortby string Fieldname, which is used to manage the order the records. Display/
(fieldname) The field will contain an integer value which positions it at the correct position between other Proc.
records from the same table on the current page.
NOTICE: The field should not be editable by the user since the TCE will manage the content
automatically in order to manage the order of records.
This feature is used by eg. the "pages" table and "tt_content" table (Content Elements) in order to
control the manually determined listing order of those records.
Typically the fieldname "sorting" is dedicated to this feature.
Related: "default_sortby"
default_sortby string If a fieldname for "sortby" is defined, then this is ignored. Display
Otherwise this is used as the 'ORDER BY' statement to sort the records in the table when listed in
TBE.
A few examples:
This box displays the fields from the "main palette". In the case above (table: "tt_content") the
main palette is "1" configured like this in $TCA for "tt_content":
canNotCollapse boolean If set, then the "Show secondary options" check box will not affect this table - no matter what, all Display
fields and palettes are displayed in the main form at all times. Just like if the check box was always
set.
tstamp string Fieldname, which is automatically updated to the current timestamp (UNIX-time in seconds) each Proc.
(fieldname) time the record is updated/saved in the system.
Typically the field name "tstamp" is used for the time stamp value.
Example:
This example shows the configuration for the "fe_users" table and how the tstamp, crdate and
cruser_id fields have been configured:
$TCA['fe_users'] = Array (
'ctrl' => Array (
'label' => 'username',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
crdate string Fieldname, which is automatically set to the current timestamp when the record is created. Is Proc.
(fieldname) never modified again.
Typically the field name "crdate" is used for the time stamp value.
cruser_id string Fieldname, which is automatically set to the uid of the backend user (be_users) who originally Proc.
(fieldname) created the record. Is never modified again.
Typically the field name "cruser_id" is used for the time stamp value.
rootLevel [0, 1, -1] Determines where a record may exist in the page tree. There are three options depending on the Proc. /
value: Display
Notice: The setting for "rootLevel" is ignored for records in the "pages" table (they are hardcoded
to be allowed anywhere, equal to a "-1" setting of rootLevel)
If this feature is used on the pages table it will also prevent editing of records on that page (except
other pages)! Also, no new records (including pages) can be created on the page.
This flag is cleared when a new copy or version of the record is created.
origUid string Fieldname, which will contain the UID of the original record in case a record is created as a copy Proc
(fieldname) or new version of another record.
Is used when new versions are created from elements and enables the backend to display a visual
comparison between a new version and its original.
delete string Fieldname, which indicates if a record is considered deleted or not. Proc. /
(fieldname) If this feature is used, then records are not really deleted, but just marked 'deleted' by setting the Display
value of the fieldname to "1". And in turn the whole system must strictly respect the record as
deleted. This means that any SQL query must exclude records where this field is true.
In the frontend libraries the enableFields() function automatically detects which of these fields are
configured for a table and returns the proper WHERE clause SQL code for creating select
queries.
There are the keys in the array you can use. Each of the values must be a field name in the table
which should be used for the feature:
Notice: In general these fields does not affect the access or display in the backend! They are
primarily related to the frontend. However the icon of records having these features enabled will
normally change as these examples show:
[INSERT IMAGE]
See also the "delete" feature which is related, but is active for both frontend and backend.
Example:
Typically the "enablecolumns" could be configured like this (here for the "tt_content" table):
hideAtCopy boolean If set, and the "disabled" field from "enablecolumns" (see below) is specified, then records will be Proc.
disabled/hidden when they are copied.
prependAtCopy string This string will be prepended the records title field when the record is inserted on the same PID as Proc.
(LS) the original record (thus you can distinguish them).
Usually the value is something like " (copy %s)" which tells that it was a copy that was just inserted
(The token "%s" will take the copy number).
setToDefaultOnCo string These fields are restored to the default value of the record when they are copied. Proc.
py (list of
fieldnames) Example:
$TCA["sys_action"] = Array (
"ctrl" => Array (
"setToDefaultOnCopy" => "assign_to_groups",
useColumnsForDe string When a new record is created, this defines the fields from the 'previous' record that should be Proc.
faultValues (list of used as default values.
fieldnames)
Example:
$TCA['sys_filemounts'] = Array (
'ctrl' => Array (
'useColumnsForDefaultValues' => 'path,base',
shadowColumnsFo string When a new element is created in a draft workspace a placeholder element is created in the Live
rNewPlaceholders (list of workspace. Certain values of the draft element can be necessary to transfer to the live element,
fieldnames) such as sys_language_uid typically. This list of fields will define which values are "shadowed" to
the Live record.
All fields listed for this option must be defined in $TCA[<table>]"[columns"] as well.
Further, fields which are listed in transOrigPointerField, languageField, label and type are
automatically added to this list of fields and do not have to re-appear in the list.
Example:
$TCA['tt_content'] = Array (
'ctrl' => Array (
'shadowColumnsForNewPlaceholders' => 'sys_language_uid,l18n_p
arent,colPos',
is_static boolean This marks a table to be "static". Used
A "static table" means that it should not be updated for individual databases because it is meant to by
be centrally updated and distributed. For instance static tables could contain country-codes used import/e
in many systems. xport
The foremost property of a static table is that the uid's used are the SAME across systems.
Import/Export of records expect static records to be common for two systems.
Example (also including the features "rootLevel", "readOnly" and "adminOnly" above):
$TCA['static_template'] = Array (
'ctrl' => Array (
'label' => 'title',
'tstamp' => 'tstamp',
'title' => 'LLL:EXT:cms/locallang_tca.php:static_template',
'readOnly' => 1, // Prevents the table from being altered
'adminOnly' => 1, // Only admin, if any
'rootLevel' => 1,
'is_static' => 1,
fe_cruser_id string Fieldname, which is used to store the uid of a front-end user if he is created the record through FE
(fieldname) fe_adminLib
fe_crgroup_id string Fieldname, which is used for storing the uid of a fe_group record, where the members of that FE
(fieldname) record are allowed to edit through fe_adminLib .
fe_admin_lock string Fieldname, which points to the fieldname which - as a boolean - will prevent any editing by the FE
(fieldname) fe_adminLib, if set. Say if the "fe_cruser_id" field matches the current fe_user normally the field is
editable. But with this option, you could make a check-box in the backend that would lock this
option.
The fieldname pointed to should be a single value selector box (maxitems <=1) saving its value
into an integer field in the database.
transOrigPointerFi string Fieldname, which contains the uid of the record which this record is a translation of. If this value is Proc /
eld (fieldname) found being set together with “languageField” then TCEforms will show the default translation Display
value under the fields in the main form. This is very neat if translators are to see what they are
translating of course...
Must be configured in “columns”, at least as a passthrough type.
transOrigPointerTa string Optional table name for the table where record uids in “transOrigPointerField” comes from. This is Proc /
ble (tablename) needed in very rare applications where the original language is found in another table of the Display
database. In such cases the field names must match between the tables.
An example of this is the pages table and “pages_language_overlay”.
WARNING: This is unsupported almost everywhere except for the “pages” table for which it was
originally invented.
transOrigDiffSourc string Fieldname which will be updated with the value of the original language record whenever the Proc /
eField (fieldname) translation record is updated. This information is later used to compare the current values of the Display
default record with those stored in this field and if they differ there will be a display in the form of
the difference visually. This is a big help for translators so they can quickly grasp the changes that
happened to the default language text.
The field type in the database should be a large text field (clob/blob).
You don't have to configure this field in the “columns” section of TCA, but if you do, select the
“passthrough” type. That will enable that the undo function also works on this field.
transForeignTable string Points to the table which holds translations of the records in this table. This feature must be used
(tablename) in pair with transOrigPointerTable but on separate tables of course: transForeignTable must point
to the tablename for which transOrigPointerTable is set to point to the table which has
transForeignTable set. Example: The table “pages” has “transForeignTable“ set to
“pages_language_overlay” because it holds the translations for pages. The table
“pages_language_overlay” has “transOrigPointerTable” set to “pages”.
WARNING: This is still highly unsupported for all other tables than the “pages” table. If this is to
work well for any table you wish to configure, some more work needs to get done!
Offline versions are identified by having a pid value = -1 and they refer to their online version by the
field “t3ver_oid”.
In order for versioning to work on a table there are certain requirements; Tables supporting
versioning must have these fields:
● “t3ver_oid” - Pointing back to online version
● “t3ver_id” - Incremental integer (version number)
● “t3ver_label” - Version label, eg. "1.1.1" or "Christmas edition"
● “t3ver_wsid” - Workspace ID. For all workspace Ids apart from 0 (zero) there can be only
one version of an element per ID.
● “t3ver_state” - Contains special states of a version used when new and deleted content
requires versioning.
● For an online version with this value set to “1” it means that it is a temporary placeholder
for a new element.
● For an offline (unpublished) version with this value set to “2” it means that when swapped,
the page must be deleted also.
● For an offline (unpublished) version with this value set to "-1" it is just an indication that
the online version has the flag set to "1" (is a placeholder for new records.). This only
affects display, not processing anywhere.
● “t3ver_stage” - For custom workspaces elements go through a cycle where 0 (zero)
represents the editing cycle, 1 represents review cycle and 10 represents ready for publishing.
● “t3ver_count” - 0/offline=draft/never published, 0/online=current, 1/offline=archive,
1+=multiple online/offline occurences (incrementation happens when versions are swapped
offline.)
● “t3ver_tstamp” - Timestamp of last swap/publish action.
● The fields pid and uid should have "signed" attributes in MySQL (so their content can be
negative!)
SQL definitions:
t3ver_oid int(11) DEFAULT '0' NOT NULL,
t3ver_id int(11) DEFAULT '0' NOT NULL,
t3ver_wsid int(11) DEFAULT '0' NOT NULL,
t3ver_label varchar(30) DEFAULT '' NOT NULL,
t3ver_state tinyint(4) DEFAULT '0' NOT NULL,
t3ver_stage tinyint(4) DEFAULT '0' NOT NULL,
t3ver_count int(11) DEFAULT '0' NOT NULL,
t3ver_tstamp int(11) DEFAULT '0' NOT NULL,
Tracking Originals
It is highly recommended to use the “origUid” feature for tables whose records are copied with
pages that are versioned with content or subtree since this will enable the possibility of content
comparison between current and future versions.
versioning [OBSOLETE] In version 3.7 and 3.8 this was used to activate versioning for a table. However large changes in
the API made it easier to simply disable this feature and introduce “versioningWS”.
Migration:
The migration is very easy: Simply set “versioningWS” instead of “versioning” for your table AND
upgrade the SQL fields as defined for “versioningWS”!
If you place a “--div--” field as the very first element in the types configuration it will just be used to
set the title of the first tab (which is by default “General”).
If you like to place the main palette on its own tab in the end, simply add “--div--” as the very last
field.
Example:
A types configuration for a table looks like this:
This will render a tab menu for the record where the fields are distributed on the various pads:
Here another tab is activated and another part of the form is shown:
Filename of the PHP file which contains the full configuration of the table in $TCA. The [ctrl] part
(and [feInterface] if used) are always mandatory, but the rest may be placed in such a file in order
to limit the amount of memory consumed by the $TCA array (when eg. the columns definitions are
not needed).
Example:
This is the typical configuration in an extension where the file named "tbl.php" contains all
configuration for the "columns", "types" and "palettes":
$TCA["tx_mininews_news"] = Array (
"ctrl" => Array (
"dynamicConfigFile" => t3lib_extMgm::extPath($_EXTKEY)."tca.p
hp",
),
"feInterface" => Array (
"fe_admin_fieldList" => "hidden, starttime, front_page",
)
);
In the file "tca.php" in the extension you will find this PHP code which completes the $TCA entry
for the table:
<?php
if (!defined ("TYPO3_MODE")) die ("Access denied.");
$TCA["tx_mininews_news"] = Array (
"ctrl" => $TCA["tx_mininews_news"]["ctrl"],
"interface" => Array (
"showRecordFieldList" => "hidden,starttime,front_page"
),
"feInterface" => $TCA["tx_mininews_news"]["feInterface"],
"columns" => Array (
"hidden" => Array (
"exclude" => 1,
"label" => $LANG_GENERAL_LABELS["hidden"],
"config" => Array (
"type" => "check",
"default" => "0"
)
),
... etc
EXT[extension_ke array User defined content for extensions. You can use this as you like. Ext.
y] Lets say you have an extension with the key "myext", then you have the right to define properties
for:
Examples
Here are a few examples of configurations of the control section.
1: $TCA['pages'] = Array (
2: 'ctrl' => Array (
3: 'label' => 'title',
4: 'tstamp' => 'tstamp',
The pages table has the configuration you see above (found in t3lib/stddb/tables.php). Here are a few notes:
• Line 3: When pages are displayed in the backend you will see the content from the field named "title" shown as the title
of the page record.
• Line 5: This configures the field "sorting" as the field which determines the order in which pages are displayed within
each branch of the page tree.
• Line 6: The title for the pages table as shown in the backend (eg. "Pages" in english, "Sider" in danish etc...) is defined
here to come from a "locallang" file.
• Line 7: Defines which field will be the "type" field. This determines the set of fields shown in the edit forms in the
backend.
• Line 10: Defines that pages should be hidden when copied.
The tt_content table (Content Elements) looks like this in the "ctrl" section (sysext/cms/ext_tables.php):
1: // ******************************************************************
2: // This is the standard TypoScript content table, tt_content
3: // ******************************************************************
4: $TCA['tt_content'] = Array (
5: 'ctrl' => Array (
6: 'label' => 'header',
7: 'label_alt' => 'subheader,bodytext',
8: 'sortby' => 'sorting',
9: 'tstamp' => 'tstamp',
10: 'title' => 'LLL:EXT:cms/locallang_tca.php:tt_content',
11: 'delete' => 'deleted',
12: 'type' => 'CType',
13: 'prependAtCopy' => 'LLL:EXT:lang/locallang_general.php:LGL.prependAtCopy',
14: 'copyAfterDuplFields' => 'colPos,sys_language_uid',
15: 'useColumnsForDefaultValues' => 'colPos,sys_language_uid',
16: 'enablecolumns' => Array (
17: 'disabled' => 'hidden',
18: 'starttime' => 'starttime',
19: 'endtime' => 'endtime',
20: 'fe_group' => 'fe_group',
21: ),
22: 'typeicon_column' => 'CType',
23: 'typeicons' => Array (
24: 'header' => 'tt_content_header.gif',
25: 'textpic' => 'tt_content_textpic.gif',
26: 'image' => 'tt_content_image.gif',
27: 'bullets' => 'tt_content_bullets.gif',
28: 'table' => 'tt_content_table.gif',
29: 'splash' => 'tt_content_news.gif',
30: 'uploads' => 'tt_content_uploads.gif',
31: 'multimedia' => 'tt_content_mm.gif',
32: 'menu' => 'tt_content_menu.gif',
33: 'list' => 'tt_content_list.gif',
34: 'mailform' => 'tt_content_form.gif',
35: 'search' => 'tt_content_search.gif',
• Line 7: Here additional fields are defined to be used if no content is found in the "header" field (defined in line 6)
• Line 16-21: The "enablecolumns" section is extensive for this table since it is a front end related table. Typically they use
the "enablecolumns" a lot.
• Line 22-41: For each content element type a new icon is defined. This helps the users to easily recognize which type of
content element they are looking at when they see the element in a list of records.
• Line 43: The column "image" is used to fetch any thumbnails there are to show for the record.
['interface'] section
Contains configuration for display and listing in various parts of the core backend:
Example
This is how the "pages" table is configured for these settings (in t3lib/stddb/tables.php):
'interface' => Array (
'showRecordFieldList' => 'doktype,title',
'maxDBListItems' => 30,
'maxSingleDBListItems' => 50
),
['feInterface'] section
The "feInterface" section contains properties related to Front End Editing of the table, mostly related to the feAdmin_lib.
Is depricated in the sense that it will still exist, but will not be (and should not be) extended further.
exclude boolean If set, all backend users are prevented from editing the field unless they are members of a Proc.
backend usergroup with this field added as an "Allowed Excludfield" (or "admin" user).
See "Inside TYPO3" document about permissions.
l10n_mode string Localization mode. Display /
(keyword) Only active if the ctrl-directive “languageField” is set. Proc.
The main relevance is when a record is localized by an API call in tcemain that makes a copy of
the default language record. You can think of this process as copying all fields from the source
record, except if a special mode applies as defined below:
Keywords are:
● exclude – Field will not be shown in TCEforms if this record is a localization of the default
language. (Works basically like a display condition.)
Excluded fields will not be copied when a language-copy is made.
May have frontend implications similar to “mergeIfNotBlank”.
● mergeIfNotBlank – Field will be editable but if the field value is blank the value from the
default translation is used (this can be very useful for images shared from the default record).
Requires frontend support.
In the backend the effect is that the field content is not copied when a new “localization copy”
is made.
● noCopy – Like mergeIfNotBlank but without the implications for the frontend; The field is just
not copied.
● prefixLangTitle – The field will get copied, but the content is prefixed with the title of the
language. Works only for field types like “text” and “input”
This option can be used to define the language related field rendering. This has nothing to do
with the processing of language overlays and data storage but the display of form fields.
Keywords are:
● hideDiff – The differences to the default language field will not be displayed.
● defaultAsReadonly – This renders the field as read only field with the content of the default
language record. The field will be rendered even if 'l10n_mode' is set to 'exclude'. While
'exclude' define the field not to be translated this option activate display of the default data.
l10n_cat string Localization category. Display
(keyword)
Keywords: text,media
When localization mode is set for a TCEforms, it must be either of these values. Only the fields
that have l10n_cat set to the localization mode is show. Used to limit display so only most relevant
fields are shown to translators. It doesn't prevent editing of other fields if records are edited
outside localization mode, it merely works as a display condition.
For FlexForm elements the fields are tags on same level. If <langChildren> is enabled, then the
value of other fields on same level is taken from the same language.
Example:
This example will require the field named "tx_templavoila_ds" to be true, otherwise the field for
which this rule is set will not be displayed:
Example value:
richtext[cut|copy|paste|formatblock|textcolor|bold|italic|underline|left|center|right|orderedlist|
unorderedlist|outdent|indent|link|table|image|line|chMode]:rte_transform[mode=ts_css|
imgpath=uploads/tx_mininews/rte/]
Keywords:
• required : A non-empty value is required in the field (otherwise the form cannot be saved).
• trim : The value in the field will have whitespaces around it trimmed away.
• date : The field will evaluate the input as a date, automatically converting the input to a UNIX-
time in seconds. The display will be like "12-8-2003" while the database value stored will be
"1060639200".
• datetime : The field will evaluate the input as a date with time (detailed to hours and minutes),
automatically converting the input to a UNIX-time in seconds. The display will be like "16:32
12-8-2003" while the database value will be "1060698720".
• time : The field will evaluate the input as a timestamp in seconds for the current day (with a
precision of minutes). The display will be like "23:45" while the database will be "85500".
• timesec : The field will evaluate the input as a timestamp in seconds for the current day (with
a precision of seconds). The display will be like "23:45:13" while the database will be "85513".
• year : Evaluates the input to a year between 1970 and 2038. If you need any year, then use
"int" evaluation instead.
• int : Evaluates the input to an integer.
• upper : Converts to uppercase (only A-Z plus a selected set of Western European special
chars).
• lower : Converts the string to lowercase (only A-Z plus a selected set of Western European
special chars).
• alpha : Allows only a-zA-Z characters.
• num : Allows only 0-9 characters in the field.
• alphanum : Same as "alpha" but allows also "0-9"
• alphanum_x : Same as "alphanum" but allows also "_" and "-" chars.
• nospace : Removes all occurencies of space characters (chr(32))
• md5 : Will convert the inputted value to the md5-hash of it (The JavaScript MD5() function is
found in typo3/md5.js)
• is_in : Will filter out any character in the input string which is not found in the string entered in
the key "is_in" (see below).
• password : Will show "*******" in the field after entering the value and moving to another field.
Thus passwords can be protected from display in the field. Notice that the value during
entering it is visible!
• double2 : Converts the input to a floating point with 2 decimal positions, using the "." (period)
as the decimal delimited (accepts also "," for the same).
• unique : Requires the field to be unique for the whole table. (Evaluated on the server only).
NOTICE: When selecting on unique-fields, make sure to select using “AND pid>=0” since the
field CAN contain duplicate values in other versions of records (always having PID = -1). This
also means that if you are using versioning on a table where the unique-feature is used you
cannot set the field to be truely unique in the database either!
• uniqueInPid : Requires the field to be unique for the current PID (among other records on the
same page). (Evaluated on the server only)
• tx_* : User defined form evaluations. See below.
All the above evaluations (unless noted) are done by JavaScript with the functions found in the
script t3lib/jsfunc.evalfield.js
"(TCE)" means the evaluation is done in the TCE on the server. The class used for this is
t3lib_TCEmain.
Example:
Setting the field to evaluate the input to a date returned to the database in UNIX-time (seconds)
Trimming the value for white space before storing in the database (important for
varchar fields!)
'eval' => 'trim',
By this configuration the field will be stripped for any space characters, converted
to lowercase, only accepted if filled in and on the server the value is required to be
unique for all records from this table:
'eval' => 'nospace,lower,unique,required'
User defined form evaluations:
You can supply your own form evaluations in an extension by creating a class with
two functions, one which returns the JavaScript code for client side validation
called returnFieldJS() and one which does the server side validation called
evaluateFieldValue().
The function evaluateFieldValue() has 3 arguments:
• $value :The field value to be evaluated.
• $is_in : The is_in value of the field configuration from TCA.
If you set this value then entering "12345" in the field will render this:
But if you either uncheck the checkbox or just enter the value "123" you will an empty input field
and no checkbox set - however the value of the field will be "123":
This feature is useful for date-fields for instance. In such cases the checkbox will allow people to
quickly remove the date setting (equal to setting the date to zero which actually means 1-1 1970 or
something like that).
Example listing:
'config' => Array (
'type' => 'input',
'size' => '8',
'max' => '20',
'eval' => 'date',
'checkbox' => '0',
'default' => '0'
)
Will create a field like this below. Checking the checkbox will insert the date of the
current day. Unchecking the checkbox will just remove the value and silently sent a
zero to the server (since the value of the key "checkbox" is set to "0").
range array An array which defines an integer range within which the value must be. Proc.
Keys:
"lower": Defines the lower integer value.
"upper": Defines the upper integer value.
Notice: This feature is evaluated on the server only so any regulation of the value will have
happend after saving the form.
Example:
Limits an integer to be within the range 10 to 1000:
In this example the upper limit is set to the last day in year 2020 while the lowest
possible value is set to the date of yesterday.
'range' => Array (
'upper' => mktime(0,0,0,12,31,2020),
'lower' => mktime(0,0,0,date('m')-
1,date('d'),date('Y'))
)
wizards array [See section later for options] Display
"virtual": (Default) The textarea will automatically wrap the lines like it would be expected for
editing a text.
"off": The textarea will not wrap the lines as you would expect when editing some kind of code.
Notice: If the string "nowrap" is found among options in the fields extra configuration from the
"types" listing this will override the setting here to "off".
Example:
This configuration will create a textarea useful for entry of code lines since it will not wrap the
lines:
You can have between 1 and 10 checkboxes and the field type in the database must be an integer. No matter how many
checkboxes you have each check box will correspond to a single bit in the integer value. Even if there is only one checkbox
(which in turn means that you should theoretically check the bit-0 of values from single-checkbox fields and not just whether
it is true or false!).
Notice: You can have a maximum of 10 checkboxes in such an array and each element is
represented by a single bit in the integer value which ultimately goes into the database.
In this array each entry is itself an array where the first entry is the label (LS) and the second
entry is a blank value. The value sent to the database will be an integer where each bit represents
the state of a checkbox in this array.
Example:
cols integer How many columns the checkbox array are shown in. Display
Range is 1-10, 1 being default.
Example:
An example of radio buttons configuration from "sys_filemounts" (see above):
'base' => Array (
'label' => 'BASE',
'config' => Array (
'type' => 'radio',
'items' => Array (
Array('absolute (root) / ', 0),
Array('relative ../fileadmin/', 1)
),
'default' => 0
)
)
It is also possible to configure more complex types where the values from from a look up in another database table and you
can even have a type where more than one value can be selected in any given order you like.
Example:
A configuration could look like this:
Markers:
You can use markers in the WHERE clause:
• ###REC_FIELD_[fieldname]###
• ###THIS_UID### - is current element uid (zero if new).
• ###CURRENT_PID### - is the current page id (pid of the record).
• ###STORAGE_PID###
• ###SITEROOT###
• ###PAGE_TSCONFIG_ID### - a value you can set from Page TSconfig
dynamically.
• ###PAGE_TSCONFIG_IDLIST### - a value you can set from Page TSconfig
dynamically.
• ###PAGE_TSCONFIG_STR### - a value you can set from Page TSconfig
dynamically.
fileFolder string Specifying a folder from where files are added to the item array. Display /
Specify the folder relative to the PATH_site, possibly using the prefix "EXT:" to point to Proc
an extension folder.
Files from the folder is selected recursively to the level specified by
"fileFolder_recursions" (see below) and only files of the extension defined by
"fileFolder_extList" is selected (see below).
Only the file reference relative to the "fileFolder" is stored.
If the files are images (gif,png,jpg) they will be configured as icons (third parameter in
items array).
Example:
'config' => Array (
'type' => 'select',
'items' => Array (
Array('',0),
),
'fileFolder' => 'EXT:cms/tslib/media/flags/',
'fileFolder_extList' => 'png,jpg,jpeg,gif',
'fileFolder_recursions' => 0,
'selicon_cols' => 8,
'size' => 1,
'minitems' => 0,
'maxitems' => 1,
)
fileFolder_extList string List of extensions to select. If blank, all files are selected. Specify list in lowercase. Display /
See "t3lib_div::getAllFilesAndFoldersInPath()" Proc
fileFolder_recursions integer Depth of directory recursions. Default is 99. Specify in range from 0-99. Display /
0 (zero) means no recursion into subdirectories. Proc
See "t3lib_div::getAllFilesAndFoldersInPath()"
The fieldname of the config is not used for data-storage anymore but rather it's set to
the number of records in the relation on each update, so the field should be an integer.
Notice: Using MM relations you can ONLY store real relations for foreign tables in the
list - no additional string values or non-record values.
MM_opposite_field string If you want to make an mm relation editable from the foreign side of the relation as Proc.
(field name) well, you need to set MM_opposite_field on the foreign side to the fieldname on the
local side.
E.g. if the field "companies.employees" is your local side and you want to make the
same relation editable from the foreign side of the relation in a field called
persons.employers, you would need to set the MM_opposite_field value of the TCA
configuration of the persons.employers field to the string "employees".
MM_match_fields array Array of field=>value pairs to both insert and match against when writing/reading MM
relations
MM_insert_fields array Array of field=>value pairs to insert when writing new MM relations
MM_table_where string (SQL Additional where clause used when reading MM relations.
WHERE)
special string This configures the selector box to fetch content from some predefined internal Display /
(any of source. These are the possibilities: Proc.
keywords) • tables - the list of TCA tables is added to the selector (excluding "adminOnly"
tables).
• pagetypes - all "doktype"-values for the "pages" table are added.
• exclude - the list of "excludeFields" as found in $TCA is added.
• modListGroup - module-lists added for groups.
• modListUser - module-lists added for users.
• explicitValues – List values that require explicit permissions to be allowed or
denied. (See “authMode” directive for the “select” type).
• languages – List system languages (sys_language records from page tree root +
Default language)
• custom – Custom values set by backend modules (see
TYPO3_CONF_VARS[BE][customPermOptions])
As you might have guessed these options are used for backend user management
and pretty worthless for most other purposes.
size integer Height of the selectorbox in TCEforms. Display
autoSizeMax integer If set, then the height of multiple-item selector boxes (maxitem > 1) will automatically Display
be adjusted to the number of selected elements, however never less than "size" and
never larger than the integer value of "autoSizeMax" itself (takes precedence over
"size"). So "autoSizeMax" is the maximum height the selector can ever reach.
selectedListStyle string If set, this will override the default style of the selector box with selected items (which Display
is “width:200px”).
Applies for when maxitems is > 1
itemListStyle string If set, this will override the default style of the selector box with available items to Display
select (which is “width:200px”).
Applies for when maxitems is > 1
Keywords are:
● checkbox - Renders a list of checkboxes
● singlebox - Renders a single multiple selector box
Notice: “maxitems” and “minitems” are not enforced in the browser for any of the
render modes here! However they will be on the server. It is recommended to set
“minitems” to zero and “maxitems” to a very large number exceeding the possible
number of values you can select (for instance set it to 1000 or so).
multiple boolean Allows the same item more than once in a list. Display /
Proc.
maxitems integer > 0 Maximum number of items in the selector box. (Default = 1) Display /
Proc
minitems integer > 0 Minimum number of items in the selector box. (Default = 0) Display
wizards array [See section later for options] Display
disableNoMatchingValueElem boolean If set, then no element is inserted if the current value does not match any of the Display
ent existing elements. A corresponding options is also found in Page TSconfig.
authMode string Authorization mode for the selector box. Keywords are: Display /
keyword Proc
● explicitAllow – All static values from the “items” array of the selector box will be
added to a matrix in the backend user configuration where a value must be
explicitly selected if a user (other than admin) is allowed to use it!)
● explicitDeny – All static values from the “items” array of the selector box will be
added to a matrix in the backend user configuration where a value must be
explicitly selected if a user should be denied access.
● individual – State is individually set for each item in the selector box. This is done
by the keywords “EXPL_ALLOW” and “EXPL_DENY” entered at the 5. position in
the item array (see “items” configuration above). Items without any of these
keywords kan be selected as usual without any access restrictions applied.
Notice: The authentication modes will work only with values that are statically present
in the “items” configuration. Any values added from foreign tables, file folder or by user
processing will not be configurable and the evaluation of such values is not
guaranteed for!
maxitems > 1
“authMode” works also for selector boxes with maxitems > 1. In this case the list of
values is traversed and each value is evaluated. Any disallowed values will be
removed.
If all submitted values turns out to be removed the result will be that the field is not
written – basically leaving the old value. For maxitems <=1 (single value) this means
that a non-allowed value is just not written. For multiple values (maxitems >1) it
depends on whether any elements are left in the list after evaluation of each value.
authMode_enforce string Various additional enforcing options for authMode. Display /
keyword Proc
Keywords are:
● strict - If set, then permission to edit the record will be granted only if the
“authMode” evaluates OK. The default is that a record having an authMode
configured field with a “non-allowed” value can be edited – just the value of the
authMode field cannot be set to an unallowed value.
Notice: This works only when maxitems <=1 (and no MM relations) since the
“raw” value in the record is all that is evaluated!
exclusiveKeys string (list of) List of keys that exclude any other keys in a select box where multiple items could be
selected.
In the configuration the elements are configured by the "items" array. Each entry in the array contains pairs of label/value.
Notice line 9; this entry is a divider. This value is not possible to select - it only helps to divide the list of options with a label
indicating a new section.
This shows a simple configuration where the values are fetched from a foreign database table ordered by the title (line 5-6).
Notice line 7 setting the size to 10 (the height of the selector boxes) and line 8 setting the maximum number of values you
can select to 20.
The value stored in the database will be a comma list of uid numbers of the records selected.
Notice how line 4 will set a condition that this box should only be displayed if the extension it belongs to exists! That is very
important since otherwise the table will not be in the database and we will get SQL errors.
In line 11 we see how a condition to the look up apply. Finally in line 12 and 14 it is explicitly configured that the selector box
can contain only one value (line 14) and therefore should be only one row high (line 12)
Notice how each label/value pair contains an icon reference on the third position and how line 18 configures that the icons
should be arranged in 6 columns.
Also, notice the default value (line 19) set to 8 meaning that the option with value "8" (line 9) will be selected by default.
The configuration is rather long and looks like this (notice, that wizards are not exclusively available for selector boxes!)
1: 'file_mountpoints' => Array (
2: 'label' => 'File Mounts:',
3: 'config' => Array (
4: 'type' => 'select',
5: 'foreign_table' => 'sys_filemounts',
6: 'foreign_table_where' => ' AND sys_filemounts.pid=0 ORDER BY sys_filemounts.title',
7: 'size' => '3',
8: 'maxitems' => '10',
9: 'autoSizeMax' => 10,
10: 'show_thumbs' => '1',
11: 'wizards' => Array(
12: '_PADDING' => 1,
13: '_VERTICAL' => 1,
14: 'edit' => Array(
15: 'type' => 'popup',
16: 'title' => 'Edit filemount',
17: 'script' => 'wizard_edit.php',
18: 'icon' => 'edit2.gif',
19: 'popup_onlyOpenIfSelected' => 1,
20: 'JSopenParams' => 'height=350,width=580,status=0,menubar=0,scrollbars=1',
21: ),
22: 'add' => Array(
23: 'type' => 'script',
24: 'title' => 'Create new filemount',
25: 'icon' => 'add.gif',
26: 'params' => Array(
27: 'table'=>'sys_filemounts',
28: 'pid' => '0',
29: 'setValue' => 'prepend'
30: ),
31: 'script' => 'wizard_add.php',
32: ),
33: 'list' => Array(
34: 'type' => 'script',
35: 'title' => 'List filemounts',
36: 'icon' => 'list.gif',
37: 'params' => Array(
38: 'table'=>'sys_filemounts',
39: 'pid' => '0',
40: ),
41: 'script' => 'wizard_list.php',
42: )
43: )
44: )
45: ),
From line 11 the configuration of the wizards takes place. See the wizard section in this document for more information.
Notice the configuration of "autoSizeMax" in line 9. This value will make the height of the selector boxes adjust themselves
automatically depending on the content in them.
In line 10 you see how the marker "###CURRENT_PID###" is used to limit the look up to the current page id.
In line 14 it is also defined that the array of options should be processed by a user defined function, namely the method
"main()" in the class "tx_templavoila_handleStaticdatastructures". For this to work, the class must be included during
configuration (typically in ext_localconf.php files)
Line 15 configures that non-integer values are allowed. Normally values are restricted to integers if we are dealing with
database look ups.
Line 16 means that even if icons can be displayed for each of the records in the look up, an icon will be displayed only for
the selected record (if any).
One thing to notice about attaching files is that the files are actually moved into an internal file folder for TYPO3! It doesn't
merely create a reference to the files original position!
The default value is none of them - you must specify one of the values correctly!
allowed string For the "file" internal type (Optional): Proc. /
(list of) A lowercase comma list of file extensions that are permitted. Eg. 'jpg,gif,txt'. Also see Display
'disallowed'.
If you set this value (to for example "php,php3") AND the "allowed" key is an empty
string all extensions are permitted except ".php" and ".php3" files (works like the
[BE][fileExtensions] config option).
In other words:
• If you want to permit only certain file-extentions, use 'allowed' and not disallowed.
• If you want to permit all file-extensions except a few, set 'allowed' to blank ("") and
enter the list of denied extensions in 'disallowed'.
• If you wish to allow all extensions with no exceptions, set 'allowed' to '*' and
disallowed to ''
The fieldname of the config is not used for data-storage any more but rather it's set to
the number of records in the relation on each update, so the field should be an integer.
#
# Example MM table for database relations
#
#
# Example MM table for file attachments
#
Notice: TYPO3 does NOT create a reference to the file in its original position! It
makes a copy of the file into this folder and from that moment that file is not supposed
to be manipulated from outside. Being in the upload folder means that files are
understood as a part of the database content and should be managed by TYPO3 only.
prepend_tname boolean [internal_type = db ONLY] Proc.
Will prepend the table name to the stored relations (so instead of storing "23" you will
store eg. "tt_content_23").
In line 5 it is configured that the internal type of the group field is "db" and then it follows that the allowed tables you can
select from is "tt_content" (Content Elements table). This could be a list of tables which means you can mix references as
you like!
Line 8 defines that there can be only 200 references and line 10 shows that they should be listed with their icons to the right
of the selector box list.
In this case it wouldn't have made sense to use a "select" type field since the situation implies that records might be found
all over the system in a table which could potentially carry thousands of entries. In such a case the right thing to do is to use
the "group" field so you have the Element Browser available for selector of the records.
Notice how "maxitems" in line 9 is used to enforce that only one relation is created despite the ability of the "group" type field
to create multiple references.
Notice how the same image has apparently been added twice - or at least the filename was the same
("DSC_7102_background.jpg"). In the second case the name has been made unique by appending "_01" before the
extension. This happens because all files attached to records through the group type are copied to a location defined by the
"uploadfolder" setting in the configuration (see line 8 below). Therefore, having two files with identical names means one of
them must be renamed automatically.
1: 'image' => Array (
2: 'label' => 'LLL:EXT:lang/locallang_general.php:LGL.images',
3: 'config' => Array (
4: 'type' => 'group',
5: 'internal_type' => 'file',
6: 'allowed' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'],
7: 'max_size' => '1000',
8: 'uploadfolder' => 'uploads/pics',
9: 'show_thumbs' => '1',
10: 'size' => '3',
11: 'maxitems' => '200',
12: 'minitems' => '0',
13: 'autoSizeMax' => 40,
14: )
15: ),
Storage methods
There are two main methods for this:
● Stored in a comma list
● Stored with a join table (MM relation)
The default and most wide spread method is the comma list.
Reserved tokens
In the comma list the token "," is used to separate the values. In addition the pipe sign "|" is used to separate value from
label value when delivered to the interface. Therefore these tokens are not allowed in reference values, not even if the MM
method is used.
Or for "tt_content_26,pages_123":
Or for "DSC_7102_background.jpg,DSC_7181.jpg,DSC_7102_background_01.jpg":
Values are transferred back to the database as a comma separated list of values without the labels but if labels are in the
value they are automatically removed.
Alternatively you can also submit each value as an item in an array; TCEmain will detect an array of values and implode it
internally to a comma list. (This is used for the "select" type, in renderMode "singlebox" and "checkbox").
Example:
This field is found in a number of table, eg. the "pages" table. It is apparently used by the extension "impexp" to store some
information.
'tx_impexp_origuid' => Array('config'=>array('type'=>'passthrough')),
Example:
In this example the extension "direct_mail" is adding some fields to the "tt_address" table but the fields are not editable
through TCEforms, just able to manipulate through TCE directly.
// tt_address modified
t3lib_div::loadTCA('tt_address');
t3lib_extMgm::addTCAcolumns('tt_address',array(
'module_sys_dmail_category' => Array('config'=>array('type'=>'passthrough')),
'module_sys_dmail_html' => Array('config'=>array('type'=>'passthrough'))
));
Two arguments will be passed to the function/method: The first argument is an array (passed by reference)
which contains the current information about the current field being rendered. The second argument is a
reference to the parent object (an instance of the t3lib_TCEforms class).
Example:
This field is rended by custom PHP code:
In addition you have to make sure the class "user_class" is included and has the method "user_TCAform_test". This the
example above it looked like this:
1: class user_class {
2: function user_TCAform_test($PA, $fobj) {
3: return '
4: <div style="
5: border: 2px dashed #666666;
6: width : 90%;
7: margin: 5px 5px 5px 5px;
8: padding: 5px 5px 5px 5px;"
9: >
10: <h2>My Own Form Field:</h2>
11: <input
12: name="'.$PA['itemFormElName'].'"
13: value="'.htmlspecialchars($PA['itemFormElValue']).'"
14: onchange="'.htmlspecialchars(implode('',$PA['fieldChangeFunc'])).'"
15: '.$PA['onFocus'].'
16: />
17: </div>';
18: }
19: }
This is not the place to dig into more details about user defined forms. By this example you can start yourself up but you will
have to figure out by yourself what options are available in the $PA array and how to use them.
Each key is a value that can be pointed to by “ds_pointerField”. Default key is “default” which is
what you should use if you do not have a “ds_pointerField” value of course.
“ds_pointerField” is in this case the pointer which should contain the uid of a record from that
table.
This is used by TemplaVoila extension for instance where a field in the tt_content table points to a
TemplaVoila Data Structure record:
FlexForm facts
FlexForms create a form-in-a-form. The content coming from this form is still stored in the associated database field - but
as an XML structure (stored by t3lib_div::array2xml())!
The “TCA” information needed to generate the FlexForm fields are found inside a <T3DataStructure> XML document. When
you configure a FlexForm field in a Data Structure (DS) you can use basically all column types documented here for TCA.
The limitations are:
• “unique” and “uniqueInPid” evaluation is not available
• You cannot nest FlexForm configurations inside of FlexForms.
• Charset follows that of the current backend (that is “forceCharset” or the backend users language selection)
“Array” Elements:
“Value” Elements:
“Value” Elements:
The DS used to render this field is found in the file “flexform_ds.xml” inside of the “mininews” extension. Notice the
<TCEforms> tags:
<T3DataStructure>
<meta>
<langDisable>1</langDisable>
</meta>
<ROOT>
<type>array</type>
<el>
<field_templateObject>
<TCEforms>
<label>LLL:EXT:mininews/locallang_db.php:tt_content.pi_flexform.select_template<
/label>
<config>
<type>select</type>
<items>
<numIndex index=”0”>
<numIndex index=”0”></numIndex>
<numIndex index=”1”>0</numIndex>
</numIndex>
</items>
<foreign_table>tx_templavoila_tmplobj</foreign_table>
<foreign_table_where>
AND tx_templavoila_tmplobj.pid=###STORAGE_PID###
AND
tx_templavoila_tmplobj.datastructure="EXT:mininews/template_datastructure.xml"
AND tx_templavoila_tmplobj.parent=0
ORDER BY tx_templavoila_tmplobj.title
</foreign_table_where>
<size>1</size>
<minitems>0</minitems>
<maxitems>1</maxitems>
</config>
</TCEforms>
</field_templateObject>
</el>
</ROOT>
</T3DataStructure>
It's clear that the contents of <TCEforms> is a direct reflection of the field configurations we normally set up in the $TCA
array.
To configure the FlexForm field to use this Data Structure, the “mininews” extension simply includes this in the
ext_tables.php file:
In line 1 the tt_content field “pi_flexform” is added to the display of fields when the Plugin type is selected and set on
“mininews_pi1”
In line 2 the DS xml file is configured to be the source of the FlexForm DS used.
If we browse the definition for the “pi_flexform” field in “tt_content” we will see this configuration:
As you can see two extension plugins, “newloginbox_pi1” and “mininews_pi1” has added pointers to their Data Structures.
....['config'] = array(
'type' => 'flex',
'ds' => array(
'default' => '
<T3DataStructure>
<sheets>
<sDEF>
<ROOT>
<TCEforms>
<sheetTitle>Default sheet</sheetTitle>
</TCEforms>
<type>array</type>
<el>
<header>
<TCEforms>
<label>Header</label>
<config>
<type>input</type>
<size>30</size>
</config>
</TCEforms>
</header>
<message>
<TCEforms>
<label>Message:</label>
<config>
<type>text</type>
<cols>30</cols>
<rows>5</rows>
</config>
</TCEforms>
'
)
);
Clicking “Second sheet” will now show the other Data Structure:
If you look at the XML stored in the database field this is how it looks:
And finally, you have to make sure that each of these languages points to the right ISO code:
Notice: If the “<meta><langDisable>” value is true then you will not see any languages of course.
The data XML in the data base will look like this:
<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
<T3FlexForms>
<meta>
<currentSheetId>sDEF</currentSheetId>
<currentLangId>
<numIndex index=”0”>DEF</numIndex>
<numIndex index=”1”>DA</numIndex>
</currentLangId>
</meta>
<data>
<sDEF>
<lDEF>
<header>
<vDEF>This is a header</vDEF>
</header>
<message>
<vDEF>Here goes the message
You can see that the Danish translation for the header is grouped with the default header and likewise for the “Message”
field.
The difference is also seen in the <T3FlexForms> content:
You can see the Danish counterparts to the default values are stored in tags named “<vDA>” on the same level as “<vDEF>”
is located.
NOTICE: The two localization methods are NOT compatible! You cannot suddenly change from the one method to the other
without having to do some conversion of the data format. That is obvious when you look at how the two methods also
require different data structures underneath!
The field which is configured as “inline” is not used for data-storage any more but
rather it's set to the number of records in the relation on each update, so the field
should be an integer.
Notice: Using MM relations you can ONLY store real relations for foreign tables in the
list - no additional string values or non-record values (so no attributes).
size integer Height of the selector box in TCEforms. Display
autoSizeMax integer If set, then the height of multiple-item selector boxes (maxitem > 1) will automatically Display
be adjusted to the number of selected elements, however never less than "size" and
never larger than the integer value of "autoSizeMax" itself (takes precedence over
"size"). So "autoSizeMax" is the maximum height the selector can ever reach.
maxitems integer > 0 Maximum number of items in the selector box. (Default = 1) Display /
Proc
minitems integer > 0 Minimum number of items in the selector box. (Default = 0) Display
symmetric_field string This works like foreign_field, but in case of using bidirectional symmetric relations. Display /
symmetric_field defines in which field on the foreign_table the uid of the “other” parent Proc.
is stored.
symmetric_label string If set, it overrides the label set in $TCA[<foreign_table>]['ctrl']['label'] for the inline-view Display /
and only if looking to a symmetric relation from the “other” side. Proc.
symmetric_sortby string This works like foreign_sortby, but in case of using bidirectional symmetric relations. Display /
Each side of a symmetric relation could have its own sorting, so symmetric_sortby Proc.
defines a field on the foreign_table where the sorting of the “other” side is stored.
$TCA['company'] = Array(
'columns' => Array(
'employees' => Array(
'label' => 'LLL:EXT:myextension/locallang_db.xml:company.employees',
'config' => Array(
'type' => 'inline',
'foreign_table' => 'person_company',
'foreign_field' => 'company',
'foreign_label' => 'person',
),
),
),
);
$TCA['person_company'] = Array(
'columns' => Array(
'person' => Array(
'label' => 'LLL:EXT:myextension/locallang_db.xml:person_company.person',
'config' => Array(
'type' => 'select',
'foreign_table' => 'person',
'size' => 1,
'minitems' => 0,
'maxitems' => 1,
),
),
Sorting could be individually defined for each of the both sides (perhaps this should not be applied to a wife-husband-
relationship in real life).
$TCA['person'] = Array(
'columns' => Array(
'employers' => Array(
'label' => 'LLL:EXT:myextension/locallang_db.xml:person.employers',
'config' => Array(
$TCA['person_symmetric'] = Array(
'columns' => Array(
'person' => Array(
'label' => 'LLL:EXT:myextension/locallang_db.xml:person_symmetric.person',
'config' => Array(
'type' => 'select',
'foreign_table' => 'person',
'size' => 1,
'minitems' => 0,
'maxitems' => 1,
),
),
'spouse' => Array(
'label' => 'LLL:EXT:myextension/locallang_db.xml:person_symmetric.spouse',
'config' => Array(
'type' => 'select',
'foreign_table' => 'person',
'size' => 1,
'minitems' => 0,
'maxitems' => 1,
),
),
'someattribute' => Array(
'label' => 'LLL:EXT:myextension/locallang_db.xml:person_symmetric.someattribute',
'config' => Array(
'type' => 'input',
),
),
'sorting_person' => Array(
'config' => Array(
'type' => 'passthrough',
),
),
'sorting_spouse' => Array(
'config' => Array(
'type' => 'passthrough',
),
),
),
);
['types'][key] section
You have to add at least one entry in the "types"-configuration before any of the configured fields from the ['columns']
section will show up in TCEforms.
Required configuration
For instance, if you would like a form to look like below...:
The key "showitem" lists the order in which to define the fields: "hidden, type, title, test_template"
Optional possibilities
The power of "types"-configuration is clear in the moment when you want the form composition of a record to depend on a
value from the record. From the example above, lets say we want the selector box "type" to define the composition of fields
in the form. This is configured like this:
Line 5 defines that the field name "type" is to be used as pointer to a key in the types-configuration.
Line 87-101 shows the configuration of this selector box which turns out to be rather normal, having four static values.
In the end of the TCA configuration the "types" section contain four listings, one for each value of the selector box:
If the "type" selector box has the value "0" (zero, "Mode 1") you will see the same as in the example above. If it is changed to
The order of fields in this case is clearly the one defined in line 142.
Changing the "type" value to "Mode 3" means we will see this form:
Default values
If no "type" field is defined the type value will default to "0" (zero). If the type value (coming from a field or being zero by
default) does not point to a defined index in the "types"-configuration, the configuration for key "1" will be used by default.
Notice: You must not show the same field more than once in the editing form. If you do, the field will not detect the value
properly.
Notice: Instead of a real fieldname you can theoretically insert "--div--" and you will have a divider line
shown. However this is not rendered by default so it has no significance.
Another special fieldname, '--palette--', will insert a link to a palette (of course you need to specify a
palette and title then...)
subtype_value_field string Fieldname, which holds a value being a key in the 'subtypes_excludelist' array. This is used to specify
(fieldname) a secondary level of 'types' - basically hiding certain fields of those found in the types-configuration,
based on the value of another field in the row.
Syntax:
“[field value]” => “[commalist of fields (from the main types-config) which are excluded]”
subtypes_addlist array A list of fields to add when the "subtype_value_field" matches a key in this array.
See "subtype_value_field".
Syntax:
“[value]” => “[commalist of fields which are added]
Notice: that any transformation configuration used by TCE will NOT work because that configuration
is visible for the TCEforms class only during the drawing of fields. In other words any configuration in
this list of fields will work for display only.”
bitmask_value_field string Fieldname, which holds a value being the integer (bit-mask) for the 'bitmask_excludelist_bits' array.
(fieldname) It works much like 'subtype_value_field' but excludes fields based on whether a bit from the value
field is set or not. See 'bitmask_excludelist_bits';
[+/-] indicates whether the bit [bit-number] is set or not.
Example:
['palettes'][key] section
"Palettes" represents a way to move less frequently used form fields out of sight. Palettes are groups of field which are
associated with a field in the main form. When this field is activated the palette fields are displayed. They are also known as
"secondary options" which is a more telling name I believe.
This configuration shows us that two palettes are defined (line 8 and 9) with key 1 and 2.
1: 'types' => Array (
Palette 1 is referred to from "types"-configuration "0" by the field name "hidden" and "type" and "types" configuration "1" by
the field "test_template".
Palette 2 is referred to from "types"-configuration "3" by the field name "type".
The configuration means that next to the checkbox for the field "hidden" there is an icon which will activate the palette when
clicked:
The palette fields appear in the top frame until another field in the main form is activated.
The other option is to enable "Show secondary options" (found in bottom of the form) which in some cases is more
convenient way to access palette fields:
This results in the palette fields being included into the form, but arranged horizontally instead of vertically:
Notice: You should not show the same field on more than one palette! If you do, the images (required and changed) will not
work in MSIE.
The result becomes a small textarea field where lines are not broken automatically. This is very useful for entering codes:
The point of setting "nowrap" in the types configuration is that under other "types"-configurations the field will wrap lines.
Likewise you can configure an RTE to appear for a field only if a certain type of the record is set and in other cases not.
This example is from the "mininews" extension which offers a RTE for editing the content of website news. This includes a
limited list of toolbar buttons and a transformation of content ("ts_css") as well as a definition of an alternative storage path
for uploaded images in the RTE ("uploads/tx_mininews/rte/")
richtext[cut|copy|paste|formatblock|textcolor|bold|italic|underline|left|center|right|orderedlist|
unorderedlist|outdent|indent|link|table|image|line|chMode]:rte_transform[mode=ts_css|
imgpath=uploads/tx_mininews/rte/]
The configuration for the RTE in the Content Elements is very similar regarding the enabled buttons. But the "rte_transform"
values are slightly different. Here the field "rte_enabled" will disable the RTE if true (this field is a checkbox) and the
transformation is "ts".
rte_transform[flag=rte_enabled|mode=ts]
static_write[] parameters
Keyword Description
f1 The field name which contains the name of the file being edited. This filename should be relative to the path configured in
$TYPO3_CONF_VARS[“BE”][“staticFileEditPath”] (which is "fileadmin/static/" by default).
f2 The field name which will also receive a copy of the content (in the database).
This should probably be the field name that carries this configuration.
The field "TEST02" must contain a filepath relative to "fileadmin/static/". In this case the filename is "static_write_file.txt".
###TYPO3_STATICFILE_EDIT###
Hello World!
###TYPO3_STATICFILE_EDIT###
outside below
When the content of the "TEST01" field is edited the content between the markers "###TYPO3_STATICFILE_EDIT###" is
updated as well.
You can study a fullblown configuration of these features in the extension called "static_file_edit".
Soft References
"Soft References" are references to database elements, files, email addresses, URls etc. which are found in-text in content.
The <link [page_id]> tag from typical bodytext fields are an example of this.
The Soft Reference parsers are used by the system to find these references and process them accordingly in import/export
actions and copy operations. Also, the soft references are utilized by integrity checking functions.
Wizards Configuration
Wizards are configurable for some field types, namely “input”, “text”, "select" and "group" types. They provide a way to insert
helper-elements, links to wizard scripts etc.
A well known example of a wizard application is the form wizard:
The wizard is configured for the text area field and appears as an icon to the right. Clicking the icon will guide the user to a
view where the "cryptic" form code is presented in a more user friendly interface:
Configuration of wizards
The value of the “wizards” key in the field config-array is an array. Each key is yet an array which configures the individual
wizards for a field. The order of the keys determines the order the wizards are displayed. The key-values themselves play no
important role (except from a few reserved words listetd in a table below).
The configuration for the new / edit / list links above looks like this:
1: 'usergroup' => Array (
2: 'label' => 'Group:',
3: 'config' => Array (
4: 'type' => 'select',
5: 'foreign_table' => 'be_groups',
6: 'foreign_table_where' => 'ORDER BY be_groups.title',
7: 'size' => '5',
8: 'maxitems' => '20',
9: 'wizards' => Array(
10: '_PADDING' => 1,
11: '_VERTICAL' => 1,
12: 'edit' => Array(
13: 'type' => 'popup',
14: 'title' => 'Edit usergroup',
15: 'script' => 'wizard_edit.php',
16: 'popup_onlyOpenIfSelected' => 1,
17: 'icon' => 'edit2.gif',
The wizard configuration takes place in line 9 and throughout. Two reserved keywords are used in line 10 and 11 to set
arrangement settings for the display of icons.
Then a new wizard is configured in lines 12 (edit), 20 (add) and 31 (list).
Reserved keys
Each wizard is identified by a key string. However some strings are reserved for general configuration. These are listed in
this table and as a rule of thumb they are prefixed with an underscore ("_"):
If the icon is not set, the title will be used for the link.
enableByTypeConfig boolean If set, then the wizard is enabled only the in Special Configuration in the types are set to “wizards[list
of wizard-keys]”. See wizard section.
RTEonly boolean If set, then this wizard will appear only if the wizard is presented for a RTE field.
hideParent array If set, then the real field will not be shown (but rendered as a hidden field). In “hideParent” you can
configure the non-editable display of the content as if it was a field of the “none” type. The options are
the same as for the “config” key for “none” types.
Example:
"JSopenParams" =>
"height=300,width=250,status=0,menubar=0,scrollbars=1",
Type: userFunc
Calls a user function/method to produce the wizard or whatever they are up to.
notNewRecords boolean See above, type “script”
userFunc string Calls a function or a method in a class.
Methods: [classname]->[methodname]
Functions: [functionname]
The function/class must be included on beforehand. This is adviced to be done within the
localconf.php file.
Two parameters are passed to the function/method: 1) An array with parameters, much like the ones
passed to scripts. One key is special though: the “item” key, which is passed by reference. So if you
alter that value it is reflected back! 2) $this (reference to the TCEform-object).
The content returned from the function call is inserted at the position where the the icon/title would
normally go.
Type: colorbox
Renders a square box (table) with the background color set to the value of the field. The id-attribute is set to a md5-hash so you might change the
color dynamically from pop-up- wizard.
The icon is not used, but the title is given as alt-text inside the color-square.
dim W x H, pixels Determines the dimensions of the box. Default is 20 pixels.
Example:
'exampleImg' => 'gfx/wizard_colorpickerex.jpg'
Type: select
This renders a selector box. When a value is selected in the box, the value is transferred to the field and the field (default) element is thereafter
selected (this is a blank value and the label is the wizard title).
“select” wizards make no use of the icon.
The “select” wizard's select-properties can be manipulated with the same number of TSconfig options which are available for “real” select-types in
TCEFORM.[table].[field]. The position of these properties is “TCEFORM.[table].[field].wizards.[wizard-key]”.
mode append, prepend, Defines how the value is processed: Either added to the front or back or (default) substitutes the
[blank] existing.
items, Options related to the Example:
foreign_table_ selection of elements
etc... known from “select” "items" => Array(
form-element type in
$TCA. Array("8 px","8"),
Array("10 px","10"),
Array("11 px","11"),
Array("12 px","12"),
Array("14 px","14"),
Array("16 px","16"),
Array("18 px","18"),
Array("20 px","20")
)
In the next section all the default core wizard scripts are demonstrated with examples. Before that, here is a few examples of
wizards that does not require an external script.
When an option from the selector box is selected it will be transferred to the input field of the element. The mode of transfer
can be either substitution (default) or prepending or appending the value to the existing value.
The example above is achieved by this configuration:
1: 'TEST01' => Array (
2: 'label' => 'TEST01: Preset values',
3: 'config' => Array (
4: 'type' => 'input',
5: 'size' => '10',
6: 'wizards' => array(
7: 'select' => array(
8: 'type' => 'select',
9: 'mode' => '',
10: 'items' => array(
11: array('Label 1', 'Value 1'),
12: array('Label 2', 'Value 2'),
13: array('Label 3', 'Value 3'),
14: )
15: ),
And obviously, you need the code listing of the class, "user_class", as well:
1: class user_class {
2: function user_TCAform_procWizard($PA, $fobj) {
3: // Wrapping the field item in a <div> with border.
4: // Notice that $PA['item'] is passed by reference, so any manipulation
5: // is automatically affecting the field without explicitly returning a value!
6: $PA['item'] = '<div style="border: maroon 4px dashed;">'.$PA['item'].'</div>';
7:
8: // Adding wizard HTML code: Showing value in JavaScript ALERT box:
9: $onclick = "alert('This is the field value: ' + ".
10: "document.".$PA['formName']."['".$PA['itemName']."'].value);".
11: "return false;";
12: $output = '<a href="#" onclick="'.htmlspecialchars($onclick).'">[Show field
value]</a><br/>';
13:
14: // Adding wizard HTML code: Showing value in JavaScript ALERT box:
15: $wTagBegin = '<'.$PA['params']['wrapTag'].'>';
16: $wTagEnd = '</'.$PA['params']['wrapTag'].'>';
17: $onclick = "document.".$PA['formName']."['".$PA['itemName']."'].value=".
18: "'".$wTagBegin."' + document.".$PA['formName']."['".$PA['itemName']."'].value
+ '".$wTagEnd."';".
19: implode('',$PA['fieldChangeFunc']). // Necessary to tell TCEforms that the
value is updated.
20: "return false;";
21: $output.= '<a href="#" onclick="'.htmlspecialchars($onclick).'">'.
22: htmlspecialchars('[Wrap in '.$wTagBegin.'...'.$wTagEnd.']').
23: '</a>';
24:
25: // Return Wizard HTML:
26: return $output;
27: }
28: }
In line 6 you see how the form field is wrapped in a <div> tag. Notice how all you need to do is to change the value of
$PA['item'] since that value is passed by reference to the function and therefore doesn't need a return value - only to be
changed.
In line 9-12 you see the first link created. It just reads the current value of the <input> field and shows in an alert box.
In line 15-23 you see how the value of the key "wrapTag" from the "params" array (reserved space for user defined
parameters) is used to create a link which will wrap whatever content of the input field in an HTML tag, in this case a <u>
wizard_add.php
This script links to a form which allows you to create a new record in a given table which may optionally be set as the value
on return to the real form.
###CURRENT_PID###
###THIS_UID###
###STORAGE_PID###
###SITEROOT###
In this example I have added the wizard script "wizard_add.php" to the well known Frontend User Group selector:
When the wizard icon is clicked the user is directed to a form where a new frontend user group can be created:
When the new group is saved and the user clicks the close button of the form the new group is automatically inserted as the
current value.
The configuration looks like this:
1: 'fe_group' => Array (
2: 'exclude' => 1,
3: 'label' => 'LLL:EXT:lang/locallang_general.php:LGL.fe_group',
4: 'config' => Array (
5: 'type' => 'select',
6: 'items' => Array (
7: Array('', 0),
8: Array('LLL:EXT:lang/locallang_general.php:LGL.hide_at_login', -1),
9: Array('LLL:EXT:lang/locallang_general.php:LGL.any_login', -2),
10: Array('LLL:EXT:lang/locallang_general.php:LGL.usergroups', '--div--')
11: ),
Line 15 defines the type to be "script" which is set to "wizard_add.php" in line 23. The parameters that instructs the Add-
wizard how to handle the creation is done in line 19-21; The table is of course fe_groups and the pid where the user is
created is the Storage Folder set for the website. Of course this requires a storage folder to exist. Finally, "setValue" tells the
wizard script that the uid of the new record should substitute any current value.
wizard_edit.php
The Edit wizard gives you a shortcut to edit references in "select" or "group" type form elements.
This time the type fitting the wizard script best is the "popup" type. It could have been the "script" type as well, but it just
works slightly better in this case if it is a pop-up so we don't leave the original form.
There are no parameters to pass along like there were for the Add wizard.
wizard_list.php
This links to the Web>List module for only one table and allows the user to manipulate stuff there.
###CURRENT_PID###
###THIS_UID###
###STORAGE_PID###
###SITEROOT###
The type is also the "script" type. In the "params" array the table and pid passed to the script is set.
wizard_colorpicker.php
The colorpicker wizard allows you to select a HTML color value from a user friendly pop-up box. The wizard type is
"colorbox" which will first of all add a colored box next to an input field:
The color of the box is set to the value of the text field. Clicking the box will open a popup window with the color picker
wizard script showing itself:
wizard_forms.php
The forms wizard is used typically with the Content Elements, type "Mailform". It allows to edit the code-like configuration of
the mail form with a nice editor. This is shown in the introduction to Wizards above.
This is the available parameters:
The configuration used for the editor in Content Elements looks like this:
'forms' => Array(
'notNewRecords' => 1,
'enableByTypeConfig' => 1,
wizard_table.php
The tables wizard is used typically with the Content Elements, type "Table". It allows to edit the code-like configuration of the
tables with a nice editor.
This is the configuration code used for the table wizard in the Content Elements:
'table' => Array(
'notNewRecords' => 1,
'enableByTypeConfig' => 1,
'type' => 'script',
'title' => 'Table wizard',
'icon' => 'wizard_table.gif',
'script' => 'wizard_table.php',
'params' => array('xmlOutput' => 0)
),
wizard_rte.php
This wizard is used to show a "full-screen" Rich Text Editor field. The configuration below shows an example taken from the
Text field in Content Elements:
'RTE' => Array(
'notNewRecords' => 1,
'RTEonly' => 1,
'type' => 'script',
'title' => 'LLL:EXT:cms/locallang_ttc.php:bodytext.W.RTE',
'icon' => 'wizard_rte2.gif',
'script' => 'wizard_rte.php',
),
browse_links.php
The "Links" wizard is used many places where you want to insert link references. Not only in the Rich Text Editor but also in
"typolink" fields:
$PAGES_TYPES
$PAGES_TYPES defines the various types of pages (field: doktype) the system can handle and what restrictions may apply
to them. Here you can set the icon and especially you can define which tables are allowed on a certain pagetype (doktype).
NOTE: The "default" entry in the $PAGES_TYPES-array is the "base" for all types, and for every type the entries simply
overrides the entries in the "default" type!!
This is the default array as set in t3lib/stddb/tables.php:
$PAGES_TYPES = Array(
'254' => Array( // Doktype 254 is a 'sysFolder' - a general purpose storage
'type' => 'sys',
'icon' => 'sysf.gif',
Key Description
type Can be "sys" or "web"
icon Alternative icon.
The file reference is on the same format "iconfile" in [ctrl] section of TCA
allowedTables The tables that may reside on pages with that "doktype".
Commalist with tables allowed on this page doktype. "*" = all
onlyAllowedTables Boolean. If set, the tce_main class will not allow a shift of doktype if unallowed records are on the page.
Notice: All four options must be set for the default type while the rest can choose as they like.
White $PAGES_TYPES is most significant, there are a few other global variables which deserves a mention in relation to
$TCA:
$ICON_TYPES
With $ICON_TYPES you can assign alternative icons to pages records based on the field 'module' in pages table. Each key
is a value from the "module" field of page records and the value is an array with a key/value pair, eg. "icon" =>
"modules_shop.gif". The file reference is on the same format "iconfile" in [ctrl] section of TCA
This is the configuration found in "cms" extension and setting icons for some legacy extensions:
// Setting ICON_TYPES
$ICON_TYPES = Array(
'shop' => Array('icon' => 'modules_shop.gif'),
'board' => Array('icon' => 'modules_board.gif'),
'news' => Array('icon' => 'modules_news.gif'),
'dmail' => Array('icon' => 'modules_dmail.gif'),
'fe_users' => Array('icon' => 'modules_fe_users.gif'),
'approve' => Array('icon' => 'modules_approvals.gif')
);
$LANG_GENERAL_LABELS
Commonly used language labels which can be used in the $TCA array and elsewhere. Has become obsolete - just use the
values of each entry directly.
For backwards compatibility $LANG_GENERAL_LABELS are still available but deprecated. This is the default values:
$LANG_GENERAL_LABELS = array(
'endtime' => 'LLL:EXT:lang/locallang_general.php:LGL.endtime',
'hidden' => 'LLL:EXT:lang/locallang_general.php:LGL.hidden',
'starttime' => 'LLL:EXT:lang/locallang_general.php:LGL.starttime',
'fe_group' => 'LLL:EXT:lang/locallang_general.php:LGL.fe_group',
'hide_at_login' => 'LLL:EXT:lang/locallang_general.php:LGL.hide_at_login',
where $config would obtain non-complete content. Instead it should look like:
while(list($table)=each($TCA)) {
t3lib_div::loadTCA($table);
$config=$TCA[$table]
...
}
\[“?(palettes|types|columns|interface)”?\] (regex) - to find places where the palettes, types, columns and interfaces
keys are used - which would require the whole array to be loaded!
It's recommended to always call the function t3lib_div::loadTCA() before using the non-[ctrl] sections of the $TCA array. The
function returns immediately if the table is already loaded, so the overhead should be small and the importance is great.
Benchmarks on a PIII/500 MHz Linux PHP4.1.2/Apache, 256 MB RAM. PHP-Cache is PHP-accelerator. All figures are
parsetimes in milliseconds.
Analysis:
What we see is, when showing a page in Web>List where all tables are loaded, the dynamic loading of tables includes a
little overhead (177-173=4 ms) regardless of script-caching. This seems fair, probably due to file operations. It's also evident
that the script-caching boosts the parsing considerably in both cases, saving approximately 150 ms in parsetime!
The Web>Info module does not load any tables (at least not in the mode, this was tested). This is the whole point of all this
- that the full table definitions are loaded only if needed (as they were by the Web>List module). Again the point of caching
is clear. But the main thing to look at is, that the Web>Info module is loaded in 66/136 seconds (cache/non-cache) with
dynamic loading (was later tested to 60/118 ms when tt_content was not loaded by default) which is LOWER than if the
whole tables.php was included (72/174 ms).
At this point the performance gain is not significant but welcomed. However the mechanism of dynamic loading of tables
provides the basis for much greater number of tables in TYPO3. Testing 31 duplicates of the tt_content table added to the
default number of configured tables (total of 62 tables configured) gave this benchmark:
This shows once again the work of the caching (1090-580 ms gained by PHPA) but clearly demonstrates the main objective
of dynamic loading; The Web>Info module is not at all affected by the fact that 31 big tables has been added.
The serialized size of the $TCA in this case was measured to approx 2MB. The total number of KB in table-definition PHP-
files was approx. 1.7 MB.
Number of tt_content Serialized size of $TCA Max size of httpd Parsetime of the
dupl. proces (from “top”) included documents
100 5,9 MB 23 MB 380 ms
250 14,5 MB 52 MB 12000 ms
500 28,8 MB 100 MB x
The configuration of tt_content is approx. 52 kb PHP code. The testing was done just loading the content into $TCA - no
further processing. However serializing the $TCA array (when that was tested) gave a double up on the amount of memory
the httpd process allocated. This was to expect of course.
From this table we learn, that PHP does not crash testing this. However it makes not much sense to use 500 tables of this
size. 250 tables might be alright and 100 tables is a more realistic roof over the number of tables in TYPO3 of the size of
tt_content!
Conducting the same experiment with a table configuration of only 8 kb with 9 fields configured (a reduced configuration for
the tt_content duplicate - which represents a more typical table) yielded these results:
Even if these pointers are used in the core of TYPO3 the default configuration as found in t3lib/stddb/tables.php includes
only a definition of the default "0" (zero) pointer:
$TBE_STYLES = array(
'colorschemes' => Array (
'0' => '#E4E0DB,#CBC7C3,#EDE9E5',
),
'borderschemes' => Array (
'0' => array('border:solid 1px black;',5)
)
);
Reference table:
Key Subkeys Description
colorschemes [0-x] This value is a comma separated list of five color/class definitions. The meaning of each
color/class is defined as:
[general cell] , [header cell] , [palette header cell] , [header label] , [palette header label]
Each composite color/class value is splitted with a "|" (vertical bar). The first part is a color
value, typically setting a background color or font color. The second part is a class
attribute value which will be set either for the table cell (td) or the span-tag around text
Class attributes are set only if there was a class value set. There are no default class
values.
Example:
$TBE_STYLES['colorschemes'][0]='red,yellow,blue,olive,green';
Example:
$TBE_STYLES['colorschemes'][0]='-|class-red,-|class-yellow,-|
class-blue,-|class-olive,-|class-green';
This sets class attribute values instead. If you add this to the stylesheet you will get the
same result as entering the real color values:
Example:
$TBE_STYLES['styleschemes'][0]['all'] = 'background-
color:#F7F7F3;';
$TBE_STYLES['styleschemes'][0]['check'] = '';
This (above) sets the background-color CSS attribute of all form elements except
checkboxes!
Example:
This will set the class attribute to 'formField' for all elements. The associated stylesheet
could look like:
Example:
$TBE_STYLES['borderschemes'][0][0] = 'border:solid 1px black;';
$TBE_STYLES['borderschemes'][0][1] = 5;
$TBE_STYLES['borderschemes'][0][2] =
'../typo3conf/freestyler_transp.gif';
(Black border, the distance to the next section is 5 pixels and there is a background
image)
Example:
$TBE_STYLES['borderschemes'][0]=
array('','','','wrapperTable');
With an associated stylesheet you can get the same result (image not included):
Examples
First, lets look at a plain types-configuration which merely renders a list of fields:
'types' => Array (
'0' => Array('showitem' => 'title;;1,photodate,description,images,fe_cruser_id')
),
Now I modify the types config to include the fifth parameters (in red):
'types' => Array (
'0' => Array('showitem' => 'title;;1;;1--0,photodate;;;;-4-,description;;;;2-0-,images;;;;1--
To understand how the style pointers works, lets organize them into a table. This is the "types"-configuration string:
title;;1;;1--0,photodate;;;;-4-,description;;;;2-0-,images;;;;1--0,fe_cruser_id
Explanation:
● "colorscheme" : The pointer is set to "1" for the first field ("title" field). This gives a green style (according to definitions in
$TBE_STYLES['colorscheme'][1]) which is active until the "description" field is rendered. Here the pointer is changed to
"2" which gives the yellow style. Immediately after the pointer is set back to "1" and that is active throughout the form.
● "stylescheme" : The pointer starts by being blank. Since no previous value is set, the pointer is implicitly "0" (zero) then.
At the field "photodate" the pointer is set to "4" which means the style attribute gets the value "background-color:
#B2B5C3;border:#7C8D84 solid 1px;" (according to the current configuration of $TBE_STYLES['stylescheme'][4]). This
gives the blueish background of the date field. Immidiately after the pointer is back at "0" again and that lasts for the rest
of the fields.
● "borderscheme" : The pointer is set to "0", then blank for three fields and then set to "0" again for the last two fields. In
effect we get the form divided into two sections. As you can see setting the borderscheme pointer explicitly - even if set
to the same value! - breaks up the form each time into a new section. Setting the first pointer to the default border
scheme was actually not necessary but served to illustrate that the same border was applied twice.
It should also be clear now, that setting an empty pointer (blank string) will just let the former value pass through.
It is not the scope of this section in the document to describe how you set up a text field to use an RTE. However I will give
you a short hint: The quickest way is to add the key “defaultExtras” to the configuration of the column and add the string
“richtext[*]” as value. This could look like this:
1: 'imagecaption' => Array (
2: 'label' => 'LLL:EXT:lang/locallang_general.php:LGL.caption',
3: 'config' => Array (
4: 'type' => 'text',
5: 'cols' => '30',
6: 'rows' => '3'
7: ),
8: 'defaultExtras' => 'richtext[*]'
9: ),
RTEs in Extensions
TYPO3 supports any Rich Text Editor for which someone might write a connector to the RTE API. This means that you can
freely choose whatever RTE you want to use among those available from the Extension Repository on typo3.org.
Here you see three possible Rich Text Editors listed in the Extension Manager. One of them is enabled while the other two
are not.
class.t3lib_rteapi.php
In the base class for the RTE API there are three main methods of interest:
● function isAvailable()
This method is asked for the availability of the RTE; This is where you should check for environmental requirements that
is needed for your RTE. Basically the method must return TRUE if the RTE is available. If it is not, the RTE can put text
entries in the internal array ->errorLog which is used to report back the reason why it was not available.
● function
drawRTE(&$pObj,$table,$field,$row,$PA,$specConf,$thisConfig,$RTEtypeVal,$RTErelPath,$thePidValue)
This method draws the content for the editing form of the RTE. It is called from the “t3lib_TCEforms” class which also
passes a reference to itself in $pObj. For details on the arguments in the method call, please see inside
“class.t3lib_rteapi.php”.
● function transformContent($dirRTE,$value,$table,$field,$row,$specConf,$thisConfig,$RTErelPath,$pid)
This method is used both from ->drawRTE() and from t3lib_tcemain to transform the content between the database and
RTE. When content is loaded from the database to the RTE (and vice versa) it may need some degree of
transformation. For instance references to links and images in the database might have to be relative while the RTE
requires absolute references. This is just a simple example of what “transformations” can do for you and why you need
them. There are plenty of details on this topic later.
As you can see it registers the API class to the system. In the class “tx_rte_base” the three methods from the list above is
available.
More Examples
More examples of Rich Text Editors exist. This is a list of some extensions offering RTEs:
● “rte” - this is the traditional TYPO3 RTE, working only in Windows, MSIE 5+
● “rteekit” - a proof-of-concept extension implementing the Ekit Java Editor which is also Open Source.
Transformations
Introduction
Transformation of content between the database and an RTE is needed if the format of the content in the database is
different than the format understood by an RTE. A simple example could be that bold-tags in the database <b> should be
converted to <strong> tags in the RTE or that references to images in <img> tags in the database should be relative while
absolute in the RTE. In such cases a transformation is needed to do the conversion both ways; From database (DB) to RTE
and from RTE to DB.
Generally transformations are needed for two reasons:
● Data Formats; If the agreed format of the stored content in TYPO3 is different from the HTML format the RTE produces.
This could be issues like XHTML, banning of certain tags or maybe a hybrid format in the database. (See section 3 in
the illustration some pages ahead)
● RTE specifics; If the RTE has special requirements to the content before it can be edited and if that format is different
from what we want to store in the database. For instance an RTE could require a full HTML document with <html>,
<head> and <body> - obviously we don't want that in the database and likewise we will have to wrap content in such a
dummy-body before it can be edited. (This is the case with “rteekit”, see section 4 in the illustration some pages ahead).
Hybrid modes
The traditional challenge of incorporating an RTE in TYPO3 has been that the RTE was available only to a limited set of
browsers, typically MSIE on Windows. Therefore if an RTE was supported it had to be backwards compatible with situations
where content was to be edited from regular <textarea>'s with no visual formatting.
Among the transformations in TYPO3 there are two modes, “ts_transform” and “css_transform”, which are trying to
maintain a data format that is as human readable as possible while still offering an RTE for editing if applicable.
To know the details of those transformations, please refer to the tables in the next section. More historical background can
also be obtained later in this document. But here is a short example of a hybrid mode:
In Database:
This is how the content in the database could look for a hybrid mode (such as “css_transform”). As you can see the TYPO3-
specific tag, “<link>” is used for the link to page 123. This tag is designed to be easy for editors to insert. It is of course
converted to a real <a> tag when the page is rendered in the frontend. Further line 2 shows bold text. In line 3 the situation
is that the paragraph should be centered - and there seems to be no other way than wrapping the line in a <p> tag with the
“align” attribute. Not so human readable but we can do no better without an RTE. Line 4 is just plain.
Generally this content will be processed before output on a page of course. Typically the rule will be this: “Wrap each line in
a <p> tag which is not already wrapped in a <p> tag and convert all TYPO3-specific <link>-tags to real <a> tags.” and thus
the final result will be valid HTML.
In RTE:
The content in the database can easily be edited as plain text thanks to the “hybrid-mode” used to store the content. But
when the content above from the database has to go into the RTE it will not work if every line is not wrapped in a <p> tag!
The same is true for the <link> tag; it has to be converted so the RTE understands it:
<p>This is line number 1 with a <a href=”index.php?id=123”>link</a> inside</p>
<p>This is line number 2 with a <strong>bold part</strong> in the text</p>
<p align=”center”>This line is centered.</p>
<p>This line is just plain</p>
This process of conversion from the one format to the other is what transformations do!
Configuration
Transformations are mainly defined in the “Special Configuration” of the $TCA "types"-configuration. There is detailed
description of this in the $TCA section of this document.
In addition transformations can be fine-tuned by Page TSconfig which means that RTE behaviour can be determined even
on page branch level! Details about this are found later in this chapter about the RTE API.
The concept of transformations is discussed in more detail a few pages ahead ("Historical perspective on RTE
transformations").
Process illustration
The following illustration shows the process of transformations graphically.
Content Examples
This table gives some examples of how content will look in the RTE, in the database and on the final website.
Notice: This is only examples! It might not happen exactly like that in real life since it depends on which exact
transformations you apply. But it illustrates the point that the content needs to be in different states whether in the RTE,
Database or Website frontend.
In addition, custom transformations can be created. This allows you to create your own tailor made transformations with a
PHP class where you can program how content is processed to and from the database. See section later.
Transformation details
The transformations offered by the TYPO3 core are performed by the class “t3lib_parsehtml_proc”. Here follows a technical
and detailed description of the transformation filters available:
Page TSconfig
The RTEs can be configured by Page TSconfig. There is a top level object name, "RTE", that is used for this. The main
object paths looks like this:
Configuration examples
This configuration in "Page TSconfig" will disable the RTE altogether:
RTE.default.disabled = 1
In the case below the RTE is still disabled generally, but this is overridden specifically for the table "tt_content" where the
RTE is used in the field "bodytext"; The "disabled" flag is set to false again which means that for Content Elements the RTE
will be available.
RTE.default.disabled = 1
RTE.config.tt_content.bodytext.disabled = 0
In this example the RTE is still enabled for content elements in generally but if the Content Element type is set to "Text"
(text) then the RTE will be disabled again!
RTE.default.disabled = 1
RTE.config.tt_content.bodytext.disabled = 0
RTE.config.tt_content.bodytext.types.text.disabled = 1
Configuration examples
0: RTE.default >
1: RTE.default {
2: mainStyle_font = Arial, sans-serif
3: mainStyle_size = 12
4: mainStyle_color = black
5: classesParagraph = redText
6: classesCharacter = redText
7: showButtons = cut,copy,fontstyle,fontsize, textcolor,table,bgcolor
8: proc.preserveTables = 1
9:
10: proc.entryHTMLparser_db = 1
11: proc.entryHTMLparser_db {
12: keepNonMatchedTags = 1
13: xhtml_cleaning = 1
14: }
15:
16: mainStyleOverride_add {
17: P = font-family:Arial, sans-serif; font-size:12;
18: H1 = font-family:Arial, sans-serif; font-size:16; font-weight:bold; margin-top:0;margin-
bottom:10;
19: H2 = font-family:Arial, sans-serif; font-size:12; font-weight:bold; color:navy; margin-
top:0;margin-bottom:10;
20: H3 = font-family:Arial, sans-serif; font-size:18; font-weight:bold;
21: H4 = font-family:Arial, sans-serif; font-size:24;
22: H5 = font-family:Arial, sans-serif; font-size:20; color:navy; font-weight:normal; margin-
top:0;margin-bottom:10;
23: H6 = font-family:Arial, sans-serif; font-size:16; font-weight:bold;
24: }
25: disablePCexamples = 0
26: }
In this example all the configuration except line 8-14 ("proc." configuration) is defining the RTE applications internal
features. These options will vary depending on the RTE used. In this case the configuration is for the classic MSIE Active-X
RTE in the extension "rte".
This enables/disables the conversion between <TYPOLIST> and <UL> sections. Default
(if unset) is that "typolist" is enabled.
Here you may specify a list of tags - possibly user-defined pseudo tags - which you wish to
preserve from being removed by the RTE. See the information about preservation in the
description of transformations.
Example:
In the default TypoScript configuration of content rendering the tags typotags <LINK>,
<TYPOLIST> and <TYPOHEAD> are the most widely used. However the <TYPOCODE>-
tag is also configured to let you define a section being formatted in monospace. Lets also
imaging, you have defined a custom tag, <MYTAG>. In order to preserve these tag from
removal by the RTE, you should configure like this.
RTE.default.proc {
preserveTags = TYPOCODE, MYTAG
}
By default <BR> tags in the content are converted to paragraphs. Setting this value will
prevent the convertion of <BR>-tags to new-lines (chr(10))
internalizeFontTags boolean (Applies for “ts_transform” and "css_transform" only (function divideIntoLines))
Enter tags which are allowed outside of <P> and <DIV> sections when converted back to
database.
Default is “img”
Example:
IMG,HR
allowTagsInTypolists commalist of strings (Applies for “ts_transform” only)
Enter tags which are allowed inside of <typolist> tags when content is sent to the
database.
Default is “br,font,b,i,u,a,img,span”
allowTags commalist of strings (Applies for “ts_transform” and "css_transform" only (function getKeepTags))
Tags to allow. Notice, this list is added to the default list, which you see here:
b,i,u,a,img,br,div,center,pre,font,hr,sub,sup,p,strong,em,li,ul,ol,blockquote,strike,span
If you wish to deny some tags, see below.
denyTags commalist of strings (Applies for “ts_transform” and "css_transform" only (function getKeepTags))
Direction: To database
Default is to re-convert literals to characters (that is < to <) outside of HTML-tags. This is
disabled by this boolean. (HSC means HtmlSpecialChars - which is a PHP function)
dontProtectUnknownTags_rte boolean (Applies for “ts_transform” and "css_transform" only (function setDivTags))
Direction: To RTE
Default is that tags unknown to HTMLparser_rte is “protected” when sent to the RTE. This
means they are converted from eg <MYTAG> to <MYTAG>. This is normally very fine,
because it can be edited plainly by the editor and when returned to the database the tag is
(by default, disabled by .dontUndoHSC_db) converted back.
Setting this option will prevent unknown tags from becoming protected.
dontHSC_rte boolean (Applies for “ts_transform” and "css_transform" only (function setDivTags))
Direction: To RTE
Default is that all content outside of HTML-tags is passed through htmlspecialchars(). This
will disable that. (opposite to .dontUndoHSC_db)
This option disables the default htmlspecialchars() conversion.
dontConvAmpInNBSP_rte boolean (Applies for “ts_transform” and "css_transform" only (function setDivTags))
Direction: To RTE
By default all codes are NOT converted to &nbsp; which they naturally word
(unless .dontHSC_rte is set). You can disable that by this flag.
allowedFontColors list of HTMLcolors (Applies for “ts_transform” and "css_transform" only (function getKeepTags))
Direction: To DB
If set, this is the only colors which will be allowed in font-tags! Case insensitive.
allowedClasses list of strings (Applies for “ts_transform” and "css_transform" only (function getKeepTags))
Direction: To DB
Allowed general classnames when content is stored in database. Could be a list matching
the number of defined classes you have. Case-insensitive.
This might be a really good idea to do, because when pasting in content from MS word for
instance there are a lot of <SPAN> and <P> tags which may have class-names in. So by
setting a list of allowed classes, such foreign classnames are removed.
If a classname is not found in this list, the default is to remove the class-attribute.
skipAlign boolean (Applies for “ts_transform” and "css_transform" only (function divideIntoLines))
skipClass
If set, then the align and class attributes of <P>/<DIV> sections (respectively) will be
ignored. Normally <P>/<DIV> tags are preserved if one or both of these attributes are
present in the tag. Otherwise it's removed.
keepPDIVattribs list of tag attributes (Applies for “ts_transform” and "css_transform" only (function divideIntoLines))
(strings)
“align” and “class” are the only attributes preserved for <P>/<DIV> tags. Here you can
specify a list of other attributes to preserve.
remapParagraphTag string / boolean (Applies for “ts_transform” and "css_transform" only (function divideIntoLines))
When <P>/<DIV> sections are converted to be put into the database, the tag - P or DIV -
is preserved. However setting this options to either P or DIV will force the section to be
converted to the one or the other.
If the value is set true (1), then it works as a general disable-flag for the whole section-
convertion stuff here and the result will be no tags preserved what so ever. Just removed.
useDIVasParagraphTagForRT string (Applies for “ts_transform” only and "css_transform" (function TS_transform_rte))
E
Use <DIV>-tags for sections when converting lines from database to RTE. Default is <P>.
Applies only to lines which has NO tag wrapped around already.
preserveTables boolean (Applies for “ts_transform”)
If set, images from external urls are not fetched for the page if content is pasted from
external sources. Normally this process of copying is done.
If set, all “plain” local images (those that are not magic images) will be cleaned up in some
way.
If the value is just set, then the style attribute will be removed after detecting any special
width/height CSS attributes (which is what the RTE will set if you scale the image
manually) and the border attribute is set to zero.
You can also configure with special keywords. So setting “plainImageMode” to any of the
value below will perform special processing:
“lockDimensions” : This will read the real dimensions of the image file and force these
values into the <img> tag. Thus this option will prevent any user applied scaling in the
image!
“lockRatio” : This will allow users to scale the image but will automatically correct the height
dimension so the aspect ratio from the original image file is preserved.
“lockRatioWhenSmaller” : Like “lockRatio”, but will not allow any scaling larger than the
original size of the image.
exitHTMLparser_rte boolean/- (Applies for all kinds of processing)
exitHTMLparser_db >HTMLparser
entryHTMLparser_rte Allows you to enable/disable the HTMLparser for the content before (entry) and after (exit)
entryHTMLparser_db the content is processed with the predefined processors (eg. ts_images or ts_transform).
There is no default values set.
disableUnifyLineBreaks boolean (Applies for all kinds of processing)
When entering the processor all \r\n linebreaks are converted to \n (13-10 to 10). When
leaving the processor all \n is reconverted to \r\n (10 to 13-10).
This options disables that processing...
usertrans.[user-defined - Custom option-space for userdefined transformations.
transformation key] See example from section about custom transformations.
[page:->PROC]
$TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['transformation']['tx_myext']
= 'EXT:myext/custom_transformation.php:user_transformation';
Here the transformation key is defined to be "tx_myext" (assuming the extension has the extension key "myext") and the
value points to a file inside the transformation which will contain the class "user_transformation" (instantiated by
t3lib_div::getUserObj())
This class must contain two methods, "transform_db" and "transform_rte" for each transformation direction.
0: /**
1: * Custom RTE transformation
2: */
3: class user_transformation {
4:
The order is important. The order in this list is the order of calling when the direction is "db". If the order is reversed the
<hr/> tag will come out as regular text in the RTE because "css_transform" protects all non-allowed tags with
htmlspecialchars().
Now the transformations should be called correctly. Before the <hr/> will be added/removed we also have to configure
through Page TSconfig (because we programmed our transformation to look for this configuration option):
RTE.default.proc.usertrans.tx_myext.addHrulerInRTE = 1
That's all!
Now lets see how this behaviour challenges the use of the RTE. This describes how the situation is handled regarding the
two Text-types as mentioned above. (Numbers refer to the previous bulletlist):
1. Line breaks: The RTE removes all line breaks and makes line breaks itself by either inserting a <P>...</P> section or
<DIV>...</DIV>. This means we'll have to convert existing lines to <P>...</P> before passing the content to the RTE and
further we need to revert the <DIV> and <P> sections in addition to the <BR>-tags to line breaks when the content is
returned to the database from the RTE.
The greatest challenge here is however what to do if a <DIV> or <P> tag has parameters like 'class' or 'align'. In that
case we can't just discard the tag. So the tag is preserved.
2. The substitution of http:// and mailto: does not represent any problems here.
3. "Typotags": The typotags are not real HTML tags so they would be removed by the RTE. Therefore those tags must be
converted into something else. This is actually an opportunity and the solution to the problem is that all <LINK>-tags are
converted into regular <A>-tags, all <TYPOLIST> tags are converted into <OL> or <UL> sections (ordered/unordered
lists, type depends on the type set for the <TYPOLIST> tag!), <TYPOHEAD>-tags are converted to <Hx> tags where the
number is determined by the type-parameter set for the <TYPOHEAD>-tag. The align/class-parameter - if set - is also
preserved. When the HTML-tags are returned to the database they need to be reverted to the specific typotags.
Other typotags (non-standard) can be preserved by being converted to a <SPAN>-section and back. This must be
configured through Page TSconfig.
(Update: With "css_styled_content" and the transformation "ts_css" only the <link> typotag is left. The <typolist> and
<typohead> tags are obsolete and regular HTML is used instead)
4. Allowed tags: As not all tags are allowed in the display on the webpage, the RTE should also reflect this situation. The
Finally images inserted are processed very intelligently because the 'magic' type images are automatically post-processed
to the correct size and proportions after being changed by the RTE in size.
Also if images are inserted by a copy/paste operation from another website, the image inserted will be automatically
transferred to the server when saved.
In addition all URLs for images and links are inserted as absolute URLs and must be converted to relative URLs if they are
within the current domain.
Conclusion:
These actions are done by so called transformations which are configured in the $TCA. Basically these transformations are
admittedly very customized to the default behaviour of the TYPO3 frontend. And they are by nature “fragile” constructions
because the content is transformed forth and back for each interaction between the RTE and the database and may so be
erroneously processed. However they serve to keep the content stored in the database 'clean' and human readable so it
may continuously be edited by non-RTE browsers and users. And furthermore it allows us to insert TYPO3-bulletlists and
headers (especially graphical headers) visually by the editor while still having TYPO3 controlling the output.
$TBE_STYLES API
The $TBE_STYLES array contains these keys
When the values are references to files (icons, logoes etc) the path must be relative to the TYPO3 backend dir.
Example:
$TBE_STYLES['mainColors'] = Array (
'bgColor' => '#EDF4EB',
'bgColor2' => '#7C8591',
'bgColor3' => '#E4E8F2',
'bgColor4' => '#92AA8B',
'bgColor5' => '#A5B7C1',
'bgColor6' => '#C7BF81',
'hoverColor' => '#800000'
);
Example:
scriptIDindex [script-id] All scripts in TYPO3s backend calculates an automatic “script-id”. This id can be found in
the HTML source:
<html>
<head>
<!-- TYPO3 Script ID: typo3/mod/web/perm/index.php -->
...
With the “scriptIDindex” feature you can override any $TBE_STYLES setting on a per-
script basis as long as you know the script ID.
An example is in the “skin360” extension where the rollover color of the Context Sensitive
Menus is defined by $TBE_STYLES['mainColors']['bgColor5']. However the color should
be different from the general “bgColor5”. This can be done by the PHP line below -
because the script ID 'typo3/alt_clickmenu.php' simply configures the bgColor5 value
differently when the alt_clickmenu.php script requests it!
$TBE_STYLES['scriptIDindex']['typo3/alt_clickmenu.php']['mainCo
lors']['bgColor5']='#E0E7C7';
Generally each subkey is a reference to the icon, relative to TYPO3 main dir (eg.
“gfx/ol/blank.gif”) or if from an extension, relative to “ext/[extension key]/” folder.
For modules the key is special. It is prefixed “MOD:” and then the module key. For
example “MOD:web/website.gif” or “MOD:web_uphotomarathon/tab_icon.gif”
Here is an example code listing for how most of these values can be set up in a “ext_tables.php” file for an extension:
0:
1:
2: if (TYPO3_MODE=='BE') {
3:
4: $presetSkinImgs = is_array($TBE_STYLES['skinImg']) ? $TBE_STYLES['skinImg'] : array(); //
Means, support for other extensions to add own icons...
5:
6: $TBE_STYLES['mainColors'] = Array (
7: 'bgColor' => '#EDF4EB',
8: 'bgColor2' => '#7C8591',
9: 'bgColor3' => '#E4E8F2',
10: 'bgColor4' => '#92AA8B',
11: 'bgColor5' => '#A5B7C1',
12: 'bgColor6' => '#C7BF81',
13: 'hoverColor' => '#800000'
14: );
15:
16: // Setting the relative path to the extension in temp. variable:
17: $temp_eP = t3lib_extMgm::extRelPath($_EXTKEY);
18:
19: // Setting login box image rotation folder:
Notice the last lines from 77-84; they configures alternative icons two extensions, “user_photomarathon” (see testsite
package) and “templavoila”. Thus the skin can include skinning information for other extensions.
When talking about skinning across extensions another way of making sure that a skin also includes other extensions is
shown in line 4 where any values set in $TBE_STYLES['skinImg'] prior to this extension is preserved. Thus other extensions
can also autonomously provide support for popular skins by themselves!
As long as you keep using the t3lib_iconWorks::getIconImage() function the icons will be skinned.
Any other icon you might use - either from inside the extension or eg. typo3/gfx/ - should now be created like this:
$iconImg = '<img'.t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],'gfx/edit2.gif','width="11"
height="12"').' title="My Icon" alt="" />';
This is contrary to the non-skinned state which would look like this:
So as you can see it is the src, width and height attributes which are affected!
The main thing to notice is that the relative path to the extension is prefixed the icon name:
t3lib_extMgm::extRelPath('templavoila').'mod1/greenled.gif'
In this screenshot you can see how I have pasted the HTML source of the script into the tool mentioned and in return I get a
nice overview of the CSS selectors inside:
Likewise I could easily find that the two selector boxes were encapsulated in a DIV section which I could address like this:
BODY#typo3-db-list-php DIV#typo3-listOptions {
border: dotted 1px #999999;
}
Again, notice how the variations over “icon_tx_mininews_news.gif” is prefixed with “flags” like “__h” and “__x”
If we enable more of the render options we might eventually hit a combination of options which is not found pre-rendered
As you can see the “endtime” flag has no icon associated with it.
$TYPO3_CONF_VARS['GFX']['noIconProc']=0;
Then you reload the “Table Icon Listing” and the icons are generated in typo3temp/:
If you want the new icons to be included in the extension you simply
• Move them from typo3temp/ into the extension folder (here “typo3conf/ext/mininews/”)
• Rename them to the expected names, eg. “icon_fb7ee72ecd_icon_tx_mininews_news__f.gif.gif” to
“icon_tx_mininews_news__f.gif” (remember to also remove the “double-gif” in the extension!)
And after another reload you will be assured that the icon is found correctly:
(Tip for code hackers: Inside “ext/extdeveval/mod1/class.tx_extdeveval_iconlister.php there is a line with a function call,
“$this->renameIconsInTypo3Temp();” which is commented out - if you uncomment this function call it will rename icons
made in typo3temp/ to filenames that can be copied directly into the extension you are making. Basically this removes
Elements
This is the elements and their nesting in the Data Structure. This could probably be expressed by a DTD or XML schema
(anyone?). In this case I will just express it by an explanation of words.
Notice: If the object was <ROOT> this tag must have the value “array”
<section> Boolean, 0/1 Defines for an object of the type <array> that it must contain other “array” type objects. The
meaning of this is application specific; For FlexForms it will allow the user to select
between possible arrays of objects to create in the form. For TemplaVoila it will select a
“container” element for another set of elements inside. This is quite fuzzy unless you
understand the contexts.
<T3DataStructure>
<meta>
<langDisable>1</langDisable>
</meta>
<ROOT>
<type>array</type>
<el>
<field_templateObject>
<TCEforms>
<label>LLL:EXT:mininews/locallang_db.php:tt_content.pi_flexform.select_template<
/label>
<config>
<type>select</type>
<items>
<numIndex index=”0”>
<numIndex index=”0”></numIndex>
<numIndex index=”1”>0</numIndex>
</numIndex>
</items>
<foreign_table>tx_templavoila_tmplobj</foreign_table>
<foreign_table_where>
AND tx_templavoila_tmplobj.pid=###STORAGE_PID###
AND
tx_templavoila_tmplobj.datastructure="EXT:mininews/template_datastructure.xml"
AND tx_templavoila_tmplobj.parent=0
ORDER BY tx_templavoila_tmplobj.title
</foreign_table_where>
<size>1</size>
<minitems>0</minitems>
<maxitems>1</maxitems>
</config>
</TCEforms>
</field_templateObject>
</el>
</ROOT>
</T3DataStructure>
Example #2
More complex example of a FlexForms structure, using two sheets, “sDEF” and “s_welcome” (snippet from “newloginbox”
<T3DataStructure>
<sheets>
<sDEF>
<ROOT>
<TCEforms>
<sheetTitle>LLL:EXT:newloginbox/locallang_db.php:tt_content.pi_flexform.sheet_ge
neral</sheetTitle>
</TCEforms>
<type>array</type>
<el>
<show_forgot_password>
<TCEforms>
<label>LLL:EXT:newloginbox/locallang_db.php:tt_content.pi_flexform.show_
forgot_password</label>
<config>
<type>check</type>
</config>
</TCEforms>
</show_forgot_password>
</el>
</ROOT>
</sDEF>
<s_welcome>
<ROOT>
<TCEforms>
<sheetTitle>LLL:EXT:newloginbox/locallang_db.php:tt_content.pi_flexform.sheet_we
lcome</sheetTitle>
</TCEforms>
<type>array</type>
<el>
<header>
<TCEforms>
<label>LLL:EXT:newloginbox/locallang_db.php:tt_content.pi_flexform.heade
r</label>
<config>
<type>input</type>
<size>30</size>
</config>
</TCEforms>
</header>
<message>
<TCEforms>
<label>LLL:EXT:newloginbox/locallang_db.php:tt_content.pi_flexform.messa
ge</label>
<config>
<type>text</type>
<cols>30</cols>
<rows>5</rows>
</config>
</TCEforms>
</message>
</el>
</ROOT>
</s_welcome>
</sheets>
</T3DataStructure>
Example
Taking the Data Structure from Example #2 above we can now rearrange it in three files:
Main Data Structure:
<T3DataStructure>
<sheets>
<sDEF>fileadmin/sheets/default_sheet.xml</sDEF>
<s_welcome>fileadmin/sheets/welcome_sheet.xml</s_welcome>
</sheets>
</T3DataStructure>
fileadmin/sheets/default_sheet.xml
<T3DataStructure>
<ROOT>
<TCEforms>
<sheetTitle>LLL:EXT:newloginbox/locallang_db.php:tt_content.pi_flexform.sheet_general</s
heetTitle>
</TCEforms>
<type>array</type>
<el>
<show_forgot_password>
<TCEforms>
<label>LLL:EXT:newloginbox/locallang_db.php:tt_content.pi_flexform.show_forgot_p
assword</label>
<config>
<type>check</type>
</config>
</TCEforms>
</show_forgot_password>
</el>
</ROOT>
</T3DataStructure>
fileadmin/sheets/welcome_sheet.xml
<T3DataStructure>
<ROOT>
<TCEforms>
<sheetTitle>LLL:EXT:newloginbox/locallang_db.php:tt_content.pi_flexform.sheet_welcome</s
heetTitle>
</TCEforms>
<type>array</type>
<el>
<header>
<TCEforms>
<label>LLL:EXT:newloginbox/locallang_db.php:tt_content.pi_flexform.header</label
>
<config>
<type>input</type>
<size>30</size>
</config>
</TCEforms>
</header>
<message>
<T3DataStructure>
<meta>
<langDisable>1</langDisable>
</meta>
<ROOT>
<config>
<type>select</type>
<items>
<numIndex index=”0”>
<numIndex index=”0”></numIndex>
<numIndex index=”1”>0</numIndex>
</numIndex>
</items>
<foreign_table>tx_templavoila_tmplobj</foreign_table>
<foreign_table_where>
AND tx_templavoila_tmplobj.pid=###STORAGE_PID###
AND
tx_templavoila_tmplobj.datastructure="EXT:mininews/template_datastructure.xml"
AND tx_templavoila_tmplobj.parent=0
ORDER BY tx_templavoila_tmplobj.title
</foreign_table_where>
<size>1</size>
<minitems>0</minitems>
<maxitems>1</maxitems>
</config>
</TCEforms>
</field_templateObject>
</el>
</ROOT>
</T3DataStructure>
Passing this to the xml2array function and you will get an array like this (screen shot from “extdeveval”):
As you can see the format of the XML generated by t3lib_div::array2xml() is designed to reflect the array structures PHP can
contain and thus the transformation to and from XML with the functions t3lib_div::array2xml() and t3lib_div::xml2array() is
very easy and quick.
<T3DataStructure>
<sheets>
<sDEF>fileadmin/sheets/default_sheet.xml</sDEF>
<s_welcome>fileadmin/sheets/welcome_sheet.xml</s_welcome>
This is done by t3lib_div::resolveSheetDefInDS() or t3lib_div::resolveAllSheetsInDS(). In fact, even if you don't have sheets
in your file but just want to stay compatible with DS XML with sheets you should use this function. For instance these
function calls will parse the DS into an array (screen shot above) and resolve the sheet definition, in this case creating a
default sheet “sDEF” (screen shot below):
$treeDat = t3lib_div::xml2array($inputCode);
$treeDat = t3lib_div::resolveAllSheetsInDS($treeDat);
Applications
For a more practical understanding of Data Structures you should study some of the applications of Data Structures:
• FlexForms - using Data Structures as a “DTD” for rendering a hierarchical editing form which saves the content back
into XML
• TemplaVoila - using Data Structures for mapping content to HTML template files.
<T3locallang>
Introduction
This XML format is used for "locallang-XML" (llXML) files, a format TYPO3 uses for storage of interface labels and
translations of them. The format is parsed by t3lib_div::xml2array() which means that tag-names and "index" attribute
values are inter-related in significance. The content is always in utf-8.
llXML files must be used from inside extension directories (system/global/local).
See "Inside TYPO3" for more details about locallang-files and the application of this format.
llXML files from installed extensions are translated by a backend tool (extension "llxmltranslate").
A "locallang-XML" file contains a set of labels in the default language (must always English!). The translated labels are
located in systematically named external files in typo3conf/l10n/[language key]/. Optionally the main files can contain the
translations directly but that should only be used in special cases since it constrains the translation process too much. It is
also possible with a specific file reference to use other external files than the automated ones.
Elements
This is the elements and their nesting in the locallang-XML format.
Notice: The contents in the <data> tag is all that is needed for labels inside TYPO3.
Everything else is meta information for the translation tool!
<orig_hash> Contains hash-integers for each translated label of the default label at the point of <languageKey>
translation. This is used to determine if the default label has changed since the
translation was made.
<orig_text> Contains the text of the default label that was the basis of the translated version! The <languageKey>
original text is used to show a diff between the original base of the translation and the
new default text so a translator can quickly see what has changed.
<languageKey> Array of labels for a language. The "index" attribute contains language key. <label>
For CSH it is important to know what "table" the labels belong to. A "table" in the context of
CSH is an identification of a group of labels. This can be an actual table name (containing
all CSH for a single table) or it can be module names etc. with a prefix to determine type.
See CSH section in "Inside TYPO3" for more details.
Examples:
<csh_table>xMOD_csh_corebe</csh_table> (General Core CSH)
<csh_table>_MOD_tools_em</csh_table> (For Extension Mgm. module)
<csh_table>pages</csh_table> (For "pages" table)
The main XML file looks like this. Notice the tag "csh_table" has a value which is important for CSH content so it can be
positioned in the right category.
In the <data> section you can see all default labels. But notice how the value for the "dk" translation is a reference to an
external file! The contents of that file is shown below this listing.
<T3locallang>
<meta type="array">
<description>CSH for Web>Info module(s) (General Framework)</description>
<type>CSH</type>
<csh_table>_MOD_web_info</csh_table>
<labelContext type="array"/>
</meta>
<T3locallangExt>
<data type="array">
<languageKey index="dk" type="array">
<label index="pagetree_overview.alttitle">Sidetræ overblik</label>
</languageKey>
</data>
<orig_hash type="array">
<languageKey index="dk" type="array">
<label index="pagetree_overview.alttitle" type="integer">92312309</label>
</languageKey>
</orig_hash>
<orig_text type="array">
<languageKey index="dk" type="array">
<label index="pagetree_overview.alttitle">Pagetree Overview</label>
</languageKey>
</orig_text>
</T3locallangExt>