This extension provides a library of functions useful for front-end
plug-ins as well as for back-end modules. It currently is mostly used
in extensions by Oliver Klee, but it is free to be used by every
extension author.
Key features
functions for easy handling of marker-based HTML templates
feature to easily remove subparts from a HTML template while hiding
the subpart markers for non-removed subparts
get data from flexforms and from TS setup with one function call
automatic configuration checks
provides a proxy to access the EM configuration values and also to
fake them for unit tests
provides a price view helper
the code follows the TYPO3 coding guidelines
the extension is actively developed
Examples
These are some of the extensions that make use of these libraries:
BZD Staff Directory
Contacts List
One-time FE Account
Realty Manager
Seminar Manager
Credits
Thanks go to the following persons for contributing bug fixes or for
doing code reviews:
This extension already provides ready-to-use domain model and data
mapper classes for the following:
back-end users
back-end user groups
front-end users
front-end user groups
countries (readonly)
languages (readonly)
currencies (readonly)
Models
All models need to inherit from AbstractModel and be located in the
Model/ directory of your extension. Have a look at the front-end user
model in oelib as an example:
class FrontEndUser extends AbstractModel implements MailRole, Address
{
/**
* Gets this user's user name.
*
* @return string this user's user name, will not be empty for valid users
*/
public function getUserName() {
return $this->getAsString('username');
}
/**
* Gets this user's user groups.
*
* @return Collection this user's FE user groups, will not be empty if
* the user data is valid
*/
public function getUserGroups() {
return $this->getAsList('usergroup');
}
}
Copied!
For accessing the model data, you need to use the getAs*/setAs*
functions so the type checking/conversion and lazy loading works.
Using member variables directly will circumvent this and is not
recommended.
That’s pretty much all you need to know how to build your own models.
Please read the other provided model classes for examples.
Writing data mappers
Data mappers allow reading models from the database and writing them
again. Relations are also automatically handled (the relation details
are read from TCA). Please have a look at the provided data mappers
for examples:
class FrontEndUserMapper extends AbstractDataMapper {
/**
* @var string the name of the database table for this mapper
*/
protected $tableName = 'fe_users';
/**
* @var class-string<M> the model class name for this mapper, must not be empty
*/
protected $modelClassName = FrontEndUser::class;
/**
* @var array the (possible) relations of the created models in the format
* DB column name => mapper name
*/
protected $relations = array(
'usergroup' => FrontEndUserGroupMapper::class,
);
}
Copied!
Please note that you explicitly need to list all relations that should
be supported (because you might want to omit some unneeded relations
for performance reasons). For all relations, you also need to write
the corresponding getters in the model class.
Using data mappers
To ensure object identity, you need to access all data mappers through
the mapper registry:
A model that is retrieved through a data mapper can have several
states:
virgin: has neither any data nor a UID yet
ghost: already has a UID (which is not checked yet to actually
exist in the DB), but the data has not been (lazily) loaded from the
DB yet; will be loaded the first time a data item is accessed
loading: the data currently is being loaded from the DB; this is a
transient state between ghost and loaded/dead
loaded: the model’s data has been successfully loaded from the DB
dead: the data mapper has tried to load this model from the DB,
but has failed (because there is not record with that UID in the DB)
When working with mappers and model in unit tests, you can often skip
accessing the DB by using ghosts (when only a UID is needed and the
model’s data is never expected to be loaded or saved):
Using the automatic configuration check for extensions
You can use oelib to let your extension warn users about configuration
annoyances in your extensions. This already is used in the following
extensions:
One-time FE account
Realty Manager
Seminar Manager
Using the testing framework for unit tests
While testing new features in the Seminar Manager extension, we were
in need of tools that allow us to easily create and delete dummy
records in the database. We designed a small “testing framework” as we
call it.
Overview
The testing framework enables you to easily
Add and change dummy records with defined record data that uses real
UIDs
Remove single records from a database table
Add dummy relations to an m:n table
Remove single relations from a database table
Add dummy FE pages, FE user groups, FE users, system folders, content
elements, TS templates and page cache entries
Create a fake front end for testing front-end plugins
Count records
Before you start
You need the following stuff before you start:
This extension (tx_oelib) must be installed
You'll have to write your own test suite for your extension
Write a test suite
Now write your test suite. Keep in mind that the file must be located
under /tests/ in your extension's directory, the filename must end
with “testcase.php” and the names of all test methods must start with
“test”.
The testing framework must be instantiated once per extension that
you're about to write tests. This is mainly for security reasons! If
you instantiate it for “tx_seminars”, it will not allow you to
add/remove any record on any table outside of the tx_seminars scope
(this means all table names must start with “tx_seminars” in that
case).
Here's a very short example that might help you to integrate our
testing framework into your tests. It's taken 1:1 from the tests for
the Seminar Manager extension.We're not able to provide a full
introduction about unit testing and PHPUnit at all. So please read one
of the many good documentations regarding this topic.
<?php
class tx_seminars_categoryTest extends tx_phpunit_testcase {
private $fixture;
private $testingFramework;
/** UID of the fixture's data in the DB */
private $fixtureUid = 0;
public function setUp() {
$this->testingFramework = new tx_oelib_testingFramework('tx_seminars');
$this->fixtureUid = $this->testingFramework->createRecord(
SEMINARS_TABLE_CATEGORIES,
array('title' => 'Test category')
);
}
public function tearDown() {
$this->testingFramework->cleanUp();
unset($this->fixture, $this->testingFramework);
}
public function testGetTitle() {
$this->fixture = new tx_seminars_category($this->fixtureUid);
$this->assertEquals(
'Test category',
$this->fixture->getTitle()
);
}
}
?>
Copied!
You can have a deeper look into our example in the subdirectory
“tests/” of oelib: All methods of this testing framework are covered
with at least one unit test. So it will be easy to see how these tools
can be used for your own unit tests.
Using the configuration proxy
The configuration proxy provides access to the EM configuration, which
is done when installing/updating an extension and defined in an
extension's “ext_conf_template.txt”.Apart from getting configuration
values easily, the proxy can fake configuration values. This feature
is supposed to testing purposes.The configuration proxy is a singleton
and is implemented lazily.
Use the proxy in a class
Get the instance of your extension's proxy. Pass the
extension key without the prefix “tx” for this. There is no need for
any further initialization as this is done automatically if necessary:
In addition to the getters described above, the proxy provides setters
to fake the configuration for testing purposes. The setters overwrite
existing configuration values and can also set totally new values
which are not defined in the “ext_conf_template.txt” if this is
needed:
$proxyInstance->setConfigurationValueString('configurationValue', 'any string needed for tests');$proxyInstance->setConfigurationValueBoolean('newValue', true);
Copied!
To ensure an unchanged configuration, you can retrieve the original
configuration. Usually this should not be necessary:
$proxyInstance->retrieveConfiguration();
Copied!
For debugging, it might be useful to get the complete configuration:
See the tutorial how to change your extension to use the Salutation
Switcher. In your TS Setup, set the following option for your
extension ( not the Salutation Switcher extension!):