Friday, December 21, 2012

TYPO3 Extbase - mapping existing fields from fe_users

Extbase comes with an own domain model and repository to access the frontend users (fe_users) and frontend groups (fe_groups) tables. If you install sr_feuser_register, several extra fields are added to the fe_users table. Those extra fields are not included in extbase default domain model for fe_users, so you have to extend the domain model with the fields you want to access. This article show howto extend the existing domain model and some things to keep in mind.

Preperation

The first thing to do is to create a new domain model, which extends the existing one. Create a new class for this in your extensions Domain\Model folder.

class Tx_Testext1_Domain_Model_FrontendUser extends Tx_Extbase_Domain_Model_FrontendUser {

}

Next you need to create a repository for the new domain model. Create this in the Domain\Repository folder of your extension.

class Tx_Testext1_Domain_Repository_FrontendUserRepository extends Tx_Extbase_Domain_Repository_FrontendUserRepository {

}

The next thing to do is to setup the mapping for the new table, so Extbase knows from which table it has to get the fields. Add the following to your sites typoscript setup.

config.tx_extbase.persistence.classes {
    Tx_Testext1_Domain_Model_FrontendUser {
        mapping {
            tableName = fe_users
        }
    }
}

You also need to configure, in which storage pid the frontend users are stored. You can set this in the typoscript constants of your extension.

plugin.tx_testext1 { 
  persistence.storagePid = 100
}

Extending the existing domain model
Now you're ready to extend the domain model Tx_Extbase_Domain_Model_FrontendUser to access the fields, which are not included in the default domain model. Actually you can also extend the domain model with new fields, but this is not part of this article.

Lets assume, you want to access the field "comments", which was created by sr_feuser_register. The only thing to do is to add a getter and a setter for this field in the newly created domain model.

class Tx_Testext1_Domain_Model_FrontendUser extends Tx_Extbase_Domain_Model_FrontendUser {

 /**
  * Comment
  *
  * @var string
  */
 protected $comment;

 /**
  * Setter for comment
  *
  * @param string $comment
  * @return void
  */
 public function setComment ($comment) {
  $this->comment = $comment;
 }

 /**
  * Getter for comment
  *
  * @return string
  */
 public function getComment () {
  return $this->comment;
 }
}

Now you can inject the newly created repository to get a record from the database.

/**
 * @var Tx_Testext1_Domain_Repository_FrontendUserRepository
 */
protected $userRepository;

/**
 * Inject the user repository
 *
 * @param Tx_Testext1_Domain_Repository_FrontendUserRepository $userRepository
 * @return void
 */
public function injectFrontendUserRepository (Tx_Testext1_Domain_Repository_FrontendUserRepository $userRepository) {
 $this->userRepository = $userRepository;
}

/**
 * Test action
 *
 * @return void
 */
public function testAction () {
 $user = $this->userRepository->findByUid(1);
 t3lib_utility_Debug::debug($user);
}

When you call the action showed above, you should see the debug output of the user object from the user with the uid 1. In the debug output, you should see the additional field "comment", which is included in the newly created domain model.

Fields with underscore and mixed case
The extension sr_feuser_register adds some additional field to fe_users, which include underscores. The same does "felogin", which actually adds fields with underscores and mixed case (e.g. "felogin_forgotHash").

If you want to include fields with underscore in your domain model (e.g. "date_of_birth"), make sure to remove the underscore and to set a Uppercase of the next letter instead.

/**
 * Date of birth
 *
 * @var int
 */
protected $dateOfBirth;

/**
 * Setter for date_of_birth
 *
 * @param int $dateOfBirth
 * @return void
 */
public function setDateOfBirth ($dateOfBirth) {
 $this->dateOfBirth = $dateOfBirth;
}

/**
 * Getter for date_of_birth
 *
 * @return int
 */
public function getDateOfBirth () {
 return $this->dateOfBirth;
}

If you have fields with underscore and mixed case, just remove the underscore. Extbase seems to ignore the case.

Here is an example of the field "felogin_forgotHash"

/**
 * Password forgot hash
 *
 * @var string
 */
protected $feloginForgothash;



Saturday, December 15, 2012

TYPO3 Flow / Fluid - translating select fields

In a TYPO3 Flow project, I had to create a select box with countries, from which the user could select one. This task is really easy with TYPO3 Flow. Just create a domain and repository for the countries, add the necessary templates and create the country-records. Now you are ready to create a relation from a existing domain (e.g. a domain with some address-fields) to the country domain. No problems here. But what, if you want to translate the country-names in different languages?

The Fluid viewhelper "f:form.select" seems to have an argument called "translate" which can handle translation of select fields labels. I could'nt find a tutorial how to use this argument and finally found out, that everything was described directly in the viewhelpers class.

Here is a short summary on how to use the f:form.select viewhelper together with the "translate" argument.

Assume you have an domain called "country". It only has one property called "alpha2", which is a string representing the country's ISO-3166 alpha2-code. You create some records in the new domain like "DE" for Germany, "DK" for Denmark and so on. You also have an domain called "address", where you have a relation to the country domain.

The first thing to do is to create the translation files. In this example I create one for english and one for german.

<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file original="" source-language="en"  datatype="plaintext">
        <body>
            <trans-unit id="DE">
                <source>Germany</source>
            </trans-unit>
            <trans-unit id="DK">
                <source>Denmark</source>
            </trans-unit>
        </body>
    </file>
</xliff>


<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file original="" source-language="en" target-language="de"  datatype="plaintext">
        <body>
            <trans-unit id="DE">
                <source>Germany</source>
                <target>Deutschland</target>
            </trans-unit>
            <trans-unit id="DK">
                <source>Denmark</source>
                <target>Dänemark</target>
            </trans-unit>
        </body>
    </file>
</xliff>

Next you should configure your f:form.select viewhelper, so it uses the translations.

<f:form.select property="country" id="country" options="{countries}" optionLabelField="alpha2" translate="{using: 'label'}"/>

The viewhelper is configured to use "alpha2" as a label field and to use the label field for translation. There are several other options for the translate argument (e.g. the "source" attribute which enables you to select a different localization file), which are described directly in the class.

Now you just have to assign the object "countries" (containing all countries from the country-repository) through the controller to the corresponding view and you're done.

Thursday, December 6, 2012

TYPO3 CMS - Run Extbase unit tests in PHPStorm

Update 27.06.2014

With TYPO3 6.2 unit- and functional test execution is possible directly through phpunit on command line. So keep in mind, that the steps described below are obsolete, if you use TYPO3 6.2.

Original Article

TYPO3 CMS is great and since Extbase it is easy to create unit tests for your code. Just create your extension with the extension_builder (or manually), install the extension phpunit from TER, add some tests to your extension and now you´re fine to run your unit tests in the phpunit TYPO3 backend module.

If you want to run your tests directly in an IDE (in this article it´s PhpStorm), there are some things to keep care of, before the IDE is ready to run the tests. This article describes how to configure PhpStorm to run Extbase unit tests directly in the IDE and also shows some common error messages including a possible solution.

Prerequisites:
  • A working TYPO3 installation with at least one page and a TS template
  • An Extbase extension with at least one test
  • TYPO3 extension "phpunit" installed 
  • The Extbase unit tests must run in TYPO3´s backend module "phpunit"
Setup:

  1. Configure the PHP interpreter and set the PHP home path to:

    /path-to-typo3-site/typo3conf/ext/phpunit/Ressources/Private/Scripts


  2. Edit your PhpStorm project to use the new PHP interpreter

  3. Adjust the PHP interpreter script.

    The script which comes with the TYPO3 extension "phpunit" seems to contain an error in the CLI path. Adjust this path, so it uses php_ide_testrunner instead of php_ide as the cliKey

    CLI_PATH="${TYPO3_SITE_PATH}/typo3/cli_dispatch.phpsh phpunit_ide_testrunner"
    
  4. Configure an environment variable in your PhpStorm project

    Edit the test configuration for the folder "Tests" of your Extbase extension and set the environment variable ENV_TYPO3_SITE_PATH to the path of your website root

  5. Create a new TYPO3 Backend user named _cli_phpunit
  6. Configure include paths

    Add the TYPO3 source and the TYPO3 extension phpunit to your PhpStorm projects include paths



    This step is optional, but I think it is always nice to have code completion working when coding TYPO3 extensions.
  7. Now you should be ready to run your Extbase unit tests directly in PhpStorm




TYPO3 6.0 issues

TYPO3 6.0 comes with a new base test class, which actually is´nt recognised by the TYPO3 Extension "phpunit" in TER (version 3.6.11). The problem has already been fixed, but it is not published yet, so you have to get the changes manually and pull a new version of the extension from the GIT repository at git://git.typo3.org/TYPO3v4/Extensions/phpunit.git


Error messages and possible solutions

While working with TYPO3, Extbase, phpunit and PhpStorm, I stumbled across some situations, where the tests were not running because of some misconfigured settings. Below are 2 possible situations with an error message an a description how I fixed them.

Situation 1

If you face the error message "Unable to attach test reporter to test framework or test framework quit unexpectedly", this may indicate, that something is wrong with your local permissions.

Solution 1 - Wrong permissions

I am developing on an Ubuntu 12.04 desktop and apache2 and TYPO3 is installed locally. I have my own user to start the desktop, so my user does not have necessary permissions to access the files owned by the webserver.

First, you should add your local user to the group "www-data" (or the group running your local webserver). Next, you should check the TYPO3 install tool for the following:

[fileCreateMask] = 664
[FolderCreateMask] = 775

This is needed, so you local user can read/write to typo3temp. Finally delete the typo3temp/ folder, so the folder is recreated with the new file- and folder permissions.

Solution 2 - Trailing slash in ENV_TYPO3_SITE_PATH

This error message can also orrur, if the ENV_TYPO3_SITE_PATH contains a trailing slash. So check if the path is correct.

Situation 2

Once I also came across this error message "PHP Fatal error:  Cannot redeclare phpunit_autoload() (previously declared in /some/path/script.php)".

The solution for this problem was, that the cliKey in the php interpreter script was set to "phpunit" instead of "phpunit_ide_testrunner"