TYPO3
We're using this at the Centre for Sustainable Energy (CSE) for the Thermos website.
TYPO3 is a content management system (CMS) written in PHP.
It has its own sub-language called TypoScript embedded in it. This language configures a website by putting values into a PHP array.
In other words, it's a horrendous nightmare.
There is plenty of documentation, but it is not all up to date, and it is usually unclear which thing is the current blessed path.
Getting Help
There are two main ways to get help. You can go on StackOverflow and tag things with TYPO3. This is encouraged.
Alternatively, there is a forum: https://forum.typo3.org/.
Using TYPO3
Users
Users go in groups.
Admin users can access everything, regardless of group. They can effectively run arbitrary PHP.
Page permissions are a bit like Unix file system permissions.
Frontend and Backend
These terms don't mean what they would in normal web development. In TYPO3, the frontend is the actual website and the backend is the authoring interface for the CMS.
Useful backend terms:
- modules list
- select a module from the list on the left of the screen
- navigation frame
- usually displays the page hierarchy (depending on which module you have selected)
- content area
- make your changes to the currently selected page or database record
Editing
https://docs.typo3.org/typo3cms/EditorsTutorial/Introduction/Index.html
Go to the backend, use the Page module.
You can look at what you've done in the View module.
List Module
This is for mass editing. Things in this view correspond to records, which are rows in the database
Versioning
The workspaces feature lets you edit things without changing the live website.
You can create these using new record inside the List Module.
RealURL
By default, URLs look like www.my-website.com/typo3.php?id=93478
. The RealURL extension can turn these into more sensible URLs.
It's a bit flaky though.
Localization
Localization is probably the main selling point of TYPO3.
There is an interface in the backend, and a built-in language menu that you can put on a page.
When a person chooses a language from the language menu, it turns into ?L=<language-id>
query string parameters. You then have to add some TypoScript to actually set the language based on that variable.
You can use the RealURL extension to turn the query string parameters into clearer URLs that look like .e.g. /en/my-page.html
.
- Simple instructions
- https://docs.typo3.org/typo3cms/EditorsTutorial/Languages/Index.html
- About XLIFF
- http://xavier.perseguers.ch/tutoriels/typo3/articles/managing-localization-files.html
- Someone's guide
- https://typo3worx.eu/2017/04/language-handling-in-typo3-backend-configuration/ https://typo3worx.eu/2017/06/language-handling-in-typo3-frontend/
- Full docs
- https://docs.typo3.org/typo3cms/FrontendLocalizationGuide/
Templating
https://docs.typo3.org/typo3cms/TemplatingTutorial/ https://docs.typo3.org/typo3cms/TyposcriptIn45MinutesTutorial/
There's a specific templating tutorial package which you can install.
- HTML
Start by making a web page as normal.
Marks look like this, they have no spaces, and shouldn't go inside comments:
###TITLE###
Things get substituted into them.
Subparts are things inside a pair of marks. In this case, the marks can be inside comments.
- Using it
We create a template, and set it on our root page. It is then inherited.
Then we write some TypoScript to use it:
page = PAGE { // Create page object includeCSS.base = fileadmin/my_template/style.css 10 = TEMPLATE { // Set first content object as template workOnSubpart = DOCUMENT // What our content is templating over template = FILE { // Set template object's template to a file file = fileadmin/my_template/index.html // Set file object's file to a filename } subparts { SUBPART_NAME = thing } marks { MARK_NAME = TEXT { value = my text } } } }
- Menus
We need a HMENU object
nav = HMENU { wrap = <ul>|</ul> // Tell our menu what its outer object is special = list { // We'll provide a list of pages value = 2, 3 // List of pages by id } entryLevel = 0 // Start from the top // Inside our HMENU, we need some items like TMENU and GMENU // Nav depth 1: text menu 1 = TMENU { NO = 1 # Activate normal link styles NO { // If we had multiple levels, we'd need wrapItemAndSub instead allWrap = <li>|</li> } ACT = 1 # Activate active link styles ACT { allWrap = <li class="current">|</li> } } }
- Content
CONTENTRIGHT = CONTENT CONTENTRIGHT < styles.content.getRight
Administration
Backup
Zip up the following directories:
- fileadmin
- typo3conf
- uploads
Use mysqldump on the database.
Take the outputs of these two commands, zip them together, and you're done.
The downside of this approach is that typo3conf contains a lot of extensions, that it would be better to just re-download.
However, it seems to work fine.
Folders
- fileadmin
Files uploaded by the content authors. Can be accessed using the File Module.
- typo3
This is a symlink to the actual typo3 PHP code.
The .tar.gz package you download has all the composer stuff (which fetches libraries) already done.
- typo3/sysext
System extensions.
Each extension folder can contain:
- extemconf.php describes the extension programatically
- extlocalconf.php sets up hooks and configuration
- exttables.sql create table statements which should look like MySQL dump outputs
- exttables.php sets up backend display of database tables
- Classes
- Configuration
- Documentation (in restructured text format)
- Resources
- Tests
- hooks
- composer.json
- exticon.svg
- typo3/sysext
- typo3conf
Configuration. All configuration in typo3 is state: it's done after installation.
- typo3temp
Cache. You can delete this at any point and TYPO3 will make it again.
- uploads
Uploads directory. Not sure how this differs from fileadmin?
Developing Extensions for TYPO3
Architecture
Design to be extensible. Much of the core functionality is built as System extensions.
Extbase is an MVC framework based on Flow.
Fluid is a type of templating engine / view part of MVC.
So we use Extbase/Fluid to make our templates.
Command Controller
The Extbase command controller lets extensions register command line tasks.
Users can then schedule them with the interface.
File Abstraction
Files are grouped by storage. A storage can be a file system, some other server somewhere, or whatever. They are described in sysfilestorage.
There is a sysfile table in the database which records files we know about and some metadata about them.
There is also a filemetadata extension which adds more metadata like licensing.
The sysfilereference table connects a file to a content element. I don't know what this means. There is a matching \TYPO3\CMS\Core\Resource\FileReference class.
sysfileprocessedfile contains temporary generated files.
sysfilecollection lets you group files.
A Driver lets us do operations on a file.
Database
DatabaseConnection class.
You can get the singleton from $GLOBALS['TYPO3DB'].
- Schema
In
$GLOBALS['TCA']
there is a database table description.See TCA Reference.
Contains:
- validation
- join fields
- backend vs layout (hmm?)
An extension controls this using a file
<ext_name>/Configuration/TCA/<database-table-name>.php
. This file is automatically found, and its result cached.Each element of
$GLOBALS['TCA']
is a table name => associative array mapping.Each table has the following:
- ctrl (mandatory) is general stuff about the table
- interface backend display properties
- columns
- types maps columns to an editing form
- palettes a list of special fields which don't get in the main editing form.
- Schema Upgrades
There are tools in the backend for checking that the schema is up to date, and migrating it if not.
Fluid Templates
- Content templates
You need to create a backend layout which goes with your content template.
Then you write a typoscript template for your root page.
Then you assign that backend layout to your pages.
- Layout
This is the part you share between all your pages.
fileadmin/templates/layouts/mainlayout.html
You can reference a layout from within your content template.
- Partials
These are small pieces like headers.
I could just include them in my layout instead.
TypoScript Syntax
It has object-property dot notation (like a JS object).
Parsed line-by-line.
Looks like: path operator value
e.g. myObject.myProperty = value 2
.
Paths are defined with A-Za-z0-9-_.
Escape dots with \. (don't do this).
Values are trimmed for whitespace.
Operators
- = assigns
- := modifies using a function of the previous value
- { lets you assign lots of properties at once in a tree structure (like = { in Javascript).
- ( lets you assign a multiline value (e.g. some HTML).
- < copies one path to another. The whole value is copied, there are no references involved here.
- =< assigns a reference.
- > deletes.
Conditions
A line only applies when the condition above it is met.
A condition holds true until it is superceded.
[GLOBAL]
means no conditions.
[ELSE]
means, did the previous condition fail.
[END]
means, cancel the previous condition.
You can combine conditions with || or &&.
We can create our own custom conditions by extending the parser.
Includes
These are relative to the page.
They can have a condition property.
Comments
These are /* comment comment comment */
multiline comments. They must be the first non-whitespace thing in a line.
Page TypoScript
Customizes things based on where you are in the page hierarchy
User TypoScript
Customizes things based on who you are.