TYPO3 fluid selectbox viewhelper.

In the below example, the selectbox options are coming from locallang.

‘hotelclass’ => array(
‘exclude’ => 1,
‘label’ => ‘LLL:EXT:myext/Resources/Private/Language/locallang_db.xlf:tx_myext_domain_model_hotels.hotelclass’,
‘config’ => array(
‘type’ => ‘select’,
‘items’ => array(
array(‘LLL:EXT:myext/Resources/Private/Language/locallang_db.xlf:tx_myext_domain_model_hotels.hotelclass.2star’, ‘2’),
array(‘LLL:EXT:myext/Resources/Private/Language/locallang_db.xlf:tx_myext_domain_model_hotels.hotelclass.3star’, ‘3’),
array(‘LLL:EXT:myext/Resources/Private/Language/locallang_db.xlf:tx_myext_domain_model_hotels.hotelclass.5star’, ‘5’),
array(‘LLL:EXT:myext/Resources/Private/Language/locallang_db.xlf:tx_myext_domain_model_hotels.hotelclass.7star’, ‘7’),
),
‘size’ => 1,
‘maxitems’ => 1,
‘eval’ => ”
),
)

To display this select box in FE from, we can use the custom view helper.

To use the viewhelpler follow the following steps.

1. Create the file

myext/Classes/viewHelpers/TcaOptionsViewHelper.php

2. Add the below code

<?php
namespace TYPO3\Myext\ViewHelpers;

class TcaOptionsViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {

/**
* local cache for dataMaps
* @var array
*/
protected $dataMaps = array();

/**
* @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper
* @inject
*/
protected $dataMapper;

/**
* objectManager
*
* @var \TYPO3\CMS\Extbase\Object\ObjectManager
* @inject
*/
protected $objectManager;

/**
* Is returning select values for a property or propertyPath of a given object or className
* @param mixed $subject The object or className the property belongs to
* @param string $property The property itself
* @return array The select options as array
*/
public function render($subject = NULL, $property = ”) {
if (!is_object($subject) && is_string($subject) && class_exists($subject)) {
$subject= $this->objectManager->get($subject);
}
return self::getSelectOptions($property, $subject);
}

/**
* Is resolving the select values for a property or propertyPath of a given object or className
* @param string $propertyPath The property itself
* @param object $subject The object or className the property belongs to
* @return array The select options as array
*/
private function getSelectOptions($propertyPath, $subject) {
$selectOptions = array();

if (is_object($subject)) {
$propertyPathSegments = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(‘.’, $propertyPath);
$object = clone($subject);
$propertyName = $propertyPath;

// resolve a property path
if (count($propertyPathSegments) > 1) {
foreach($propertyPathSegments as $key => $propertyName) {
$propertyType = $this->dataMapper->getType(get_class($tempObject), $propertyName);
if (strpos($propertyType,’_’)) {
$object = $this->objectManager->create($propertyType);
} else {
break;
}
}
}

$dataMap = self::getDataMap($object);

if ($dataMap == NULL || !$dataMap->isPersistableProperty($propertyName)) {
return $selectOptions;
}

$tableName = $this->dataMapper->convertClassNameToTableName(get_class($object));
$columnName = $dataMap->getColumnMap($propertyName)->getColumnName();

// only convert select items which do not have a DB relation
$columnConfig = $GLOBALS[‘TCA’][$tableName][‘columns’][$columnName][‘config’];
if ($columnConfig[‘type’] == ‘select’ && count($columnConfig[‘items’]) && !$columnConfig[‘foreign_table’]) {
foreach ($columnConfig[‘items’] as $option) {
$selectOptions[$option[1]] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($option[0], $this->controllerContext->getRequest()->getControllerExtensionName());
}
}
}
return $selectOptions;
}

/**
* Resolve the dataMap for the given object
* @param object $object The domain object to get the dataMap for
* @return Tx_Extbase_Persistence_Mapper_DataMap
*/
private function getDataMap($object) {
$class = is_object($object) ? get_class($object) : $object;
if (!isset($this->dataMaps[$class])) {
$this->dataMaps[$class] = $this->dataMapper->getDataMap($class);
}
return $this->dataMaps[$class];
}
}
?>

3. Add the below lines in fluid template, that is intended to show FE form

{namespace custom=TYPO3\Myext\ViewHelpers}

<f:form.select property=”hotelclass” options=”{custom:TcaOptions(property:’hotelclass’,subject:’TYPO3\\Myext\\Domain\\Model\\Hotels’)}” />

4. The output source will be like this.

<select name=”tx_myext_hotels[hotels][hotelclass]”>
<option value=”2″>2 Star</option>
<option value=”3″>3 Star</option>
<option value=”5″>5 Star</option>
<option value=”7″>7 Star</option>
</select>

Thanks to: https://gist.github.com/anonymous/888297

 

TYPO3 Extbase call action through ajax.

Below are the steps to call controller action from ajax.

1. Add the following typoscript on extension setup.

plugin.tx_extname {}
#After this
actionname = PAGE
actionname {
typeNum = 1234
config {
disableAllHeaderCode = 1
additionalHeaders = Content-type:application/html|Cache-Control:no-cache, must-revalidate, max-age=0|Pragma:no-cache
xhtml_cleaning = 0
admPanel = 0
}

10 < tt_content.list.20.extname_controllername
}

3. In controller

/**
* action actionname
*
* @return void
*/
public function actionnameAction() {
return ‘test ajax content’;
}

2. In fluid template

<f:link.action action=”actionname” additionalParams=”{type:’1234′,no_cache:’1′}” noCacheHash=”1″ class=”test”>
Ajax click
</f:link.action>
<div id=”ajax_content”></div>
<script type=”text/javascript”>
$(document).ready(function(){
$(‘.test’).click(function() {
var href = $(this).attr(‘href’);
$.ajax({
url: href,
cache: false,
success: function(htmldata){
$(“#ajax_content”).html(htmldata);
}
});
return false;
});
});
</script>

If everything is correct, it should work.

TYPO3 custom session handling.

To implement Shopping cart or shopping basket, we need to store the shopping data in session. Here is the way how we can use simple session handling “Service” to implement it in Extbase extensions.

Below is the php code to handle sessions.  The name of the php file will be “SessionHandler.php” and will be under folder EXT:myext/Classes/Domain/Service. We can identify this from namespace.

<?php

namespace TYPO3\Myext\Domain\Service;

class SessionHandler implements \TYPO3\CMS\Core\SingletonInterface {

public function restoreFromSession() {
$sessionData = unserialize($GLOBALS[‘TSFE’]->fe_user->getKey(‘ses’, ‘basket’));
if (mktime() >= $this->getSessionTimeout()) {
$this->cleanUpSession();
return null;
}
$this->setSessionTimeout();
return $sessionData;
}

public function writeToSession($object) {
$sessionData = serialize($object);
$GLOBALS[‘TSFE’]->fe_user->setKey(‘ses’, ‘basket’, $sessionData);
$GLOBALS[‘TSFE’]->fe_user->storeSessionData();
$this->setSessionTimeout();
return $this;
}

public function cleanUpSession() {
$GLOBALS[‘TSFE’]->fe_user->setKey(‘ses’, ‘basket’, NULL);
$GLOBALS[‘TSFE’]->fe_user->setKey(‘ses’, ‘basketLifetime’, NULL);
$GLOBALS[‘TSFE’]->fe_user->storeSessionData();
return $this;
}

public function setSessionTimeout() {
$GLOBALS[‘TSFE’]->fe_user->setKey(‘ses’, ‘basketLifetime’, mktime() + 600);
$GLOBALS[‘TSFE’]->fe_user->storeSessionData();
return $this;
}

public function getSessionTimeout() {
return $GLOBALS[‘TSFE’]->fe_user->getKey(‘ses’, ‘basketLifetime’);
}
}

So how to use these functions on our controllers ?

First we need to inject it in our controller like this

/**
* @var \TYPO3\Myext\Domain\Service\SessionHandler
* @inject
*/
protected $sessionHandler;

Then we can use below code in controller, for various actions on session.

Let us consider the variable “$basket” has the posted data from the forms. To store that data in session “basket”, below code will help.

$this->sessionHandler->writeToSession($basket);

To retrieve that data from session, we can use

$this->sessionHandler->restoreFromSession();

To cleanup the session,

$this->sessionHandler->cleanUpSession();

In the above php code, we can see that, I have set session timeout at 10 mins (600 secs).

If the user is loggedin, that user session timeout will be handled by

$TYPO3_CONF_VARS[“FE”][“lifetime”] = 600

 

TYPO3 FAL (file abstraction layer) in Extbase/Fluid extension

Recently I came across to implement extbase plugin having multiple file upload FE form.

My Typo3 version was 6.1
The extension was created using Extension Builder

File ext_tables.sql

CREATE TABLE tx_clientside_domain_model_orderitems (
:
files int(11) unsigned DEFAULT ‘0’ NOT NULL,
:

);

File Configuration/TCA/OrderItems.php

$TCA[‘tx_clientside_domain_model_orderitems’] = array(
//…… removed code

‘files’ => array(
‘exclude’ => 1,
‘label’ => ‘Files’,
‘config’ => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig(‘files’, array(
‘appearance’ => array(
‘createNewRelationLinkTitle’ => ‘LLL:EXT:cms/locallang_ttc.xlf:images.addFileReference’
),
), $GLOBALS[‘TYPO3_CONF_VARS’][‘GFX’][‘imagefile_ext’]),
),

//…..

);

File Classes/Domain/Model/OrderItems.php

class OrderItems extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {

/**
* Files
*
* @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference>
*/
protected $files;

/**
* __construct
*
* @return AbstractObject
*/
public function __construct() {
$this->files = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
/**
* Returns the files
*
* @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage
*/
public function getFiles() {
return $this->files;
}

}

I have not used function setFiles here.

File Classes/Controller/OrderItemsController.php

class OrderItemsController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {

/**
* orderItemsRepository
*
* @var \TYPO3\Clientside\Domain\Repository\OrderItemsRepository
* @inject
*/
protected $orderItemsRepository;

/**
* action create
*
* @param \TYPO3\Clientside\Domain\Model\OrderItems $newOrderItems
* @dontvalidate $newOrderItems
* @return void
*/
public function createAction(\TYPO3\Clientside\Domain\Model\OrderItems $newOrderItems) {

$this->orderItemsRepository->add($newOrderItems);

$persistenceManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(‘Tx_Extbase_Persistence_Manager’);
$persistenceManager->persistAll();
$uidNew = $newOrderItems->getUid();

if ($_FILES[‘tx_clientside_orderitems’]) {
for ($i = 0; $i < count($_FILES[‘tx_clientside_orderitems’][‘name’][‘myfiles’]); $i++) {
$file = array();
$file[‘name’] = $_FILES[‘tx_clientside_orderitems’][‘name’][‘myfiles’][$i];
$file[‘type’] = $_FILES[‘tx_clientside_orderitems’][‘type’][‘myfiles’][$i];
$file[‘tmp_name’] = $_FILES[‘tx_clientside_orderitems’][‘tmp_name’][‘myfiles’][$i];
$file[‘size’] = $_FILES[‘tx_clientside_orderitems’][‘size’][‘myfiles’][$i];
if ($file[‘name’]) {
$files = $this->uploadFile($file[‘name’], $file[‘type’], $file[‘tmp_name’], $file[‘size’]);
$sysFileCreate = $this->orderItemsRepository->myFileOperationsFal($files, $file[‘type’], $file[‘size’], $uidNew);
}
}
}

$this->flashMessageContainer->add(‘Your new OrderItems was created.’);
$this->redirect(‘list’);
}

protected function uploadFile($name, $type, $temp, $size) {
if($size > 0) {
$basicFileFunctions = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(‘t3lib_basicFileFunctions’);

$name = $basicFileFunctions->cleanFileName($name);
$uploadPath = $basicFileFunctions->cleanDirectoryName(‘fileadmin/user_upload/’);
$uniqueFileName = $basicFileFunctions->getUniqueName($name, $uploadPath);
$fileStored = move_uploaded_file($temp, $uniqueFileName);

$returnValue = basename($uniqueFileName);
}

return $returnValue;
}

}

 

File Classes/Romain/Repository/OrderItemsRepository.php

class OrderItemsRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {

public function myFileOperationsFal($filename, $filetype, $filesize, $uidNew){

$newSysFields = array(
‘pid’ => 0,
‘identifier’ =>’/user_upload/’.$filename,
‘mime_type’ => $filetype,
‘name’ => $filename,
‘size’ => $filesize,
‘storage’ => 1,
‘crdate’ => $GLOBALS[‘EXEC_TIME’],
‘tstamp’ => $GLOBALS[‘EXEC_TIME’]
);

$newSysRes = $GLOBALS[‘TYPO3_DB’]->exec_INSERTquery(‘sys_file’, $newSysFields);

$uid_local = $GLOBALS[‘TYPO3_DB’]->sql_insert_id($newSysRes);
$newRefFields = array(
‘pid’ => 88,
‘tablenames’ => ‘tx_clientside_domain_model_orderitems’,
‘uid_foreign’ => $uidNew,
‘uid_local’ => $uid_local,
‘table_local’ => ‘sys_file’,
‘fieldname’ => ‘files’,
‘crdate’ => $GLOBALS[‘EXEC_TIME’],
‘tstamp’ => $GLOBALS[‘EXEC_TIME’]
);

$GLOBALS[‘TYPO3_DB’]->exec_INSERTquery(‘sys_file_reference’, $newRefFields);
}

}

Here I am writing custom File operation function, that creates new entry in table sys_file and mm relation to table sys_file_reference.
I have searched google for any other good way, without success 🙁

Suggestions are welcome 🙂

File Resources/Private/Templates/Root/New.html

<f:form action=”create” enctype=”multipart/form-data” name=”newOrderItems” object=”{newOrderItems}” >
<input name=”tx_clientside_orderitems[myfiles][]” type=”file” /><br />
<input name=”tx_clientside_orderitems[myfiles][]” type=”file” /><br />
<f:form.submit value=”Create new” /></f:form>

 

Here is how to dispaly that images in frontend

File Resources/Private/Templates/Root/Show.html

<f:for each=”{orderItems.files}” as=”file”>
<f:image src=”{file.uid}” alt=”” width=’101′ height=”67″ treatIdAsReference=”1″/>
</f:for>