ExtBase Snippets :: TYPO3 CMS & SEO
ARM Technologies   ...  TYPO3 ExtBase Snippets 

Powering TYPO3 CMS, Neos and Flow

ExtBase, the modern development framework!

What ExtBase has to offer?

ExtBase provides the TYPO3 platform to develop extensions in MVC design pattern. It provides every feature any modern MVC framework provides. ExtBase also uses the Fluid template engine making extension development fun!

Registration of a extbase extension

ext_tables.php

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
    $_EXTKEY,
    'Map',
    'ARM Google map'
);

//Add Extension Typoscript
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile($_EXTKEY, 'Configuration/TypoScript', 'ARM Google Map');

ext_localconf.php

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
    'ARM.'.$_EXTKEY,
    'Map',
    array(
        'Map' => 'index'
    ),
    array(
        'Map' => 'index'
    )
);

Extension TypoScript - constant.txt (This file resides in Configuration/TypoScript folder, see the path above)

plugin.tx_armgmap {
    view {
        templateRootPath = EXT:arm_gmap/Resources/Private/Templates/
    }
    persistence {
        storagePid =
    }
    settings {
        zoomScale = 12
    }
}

Extension TypoScript - setup.txt (This file resides in Configuration/TypoScript folder)

plugin.tx_armgmap {
    view {
        templateRootPath = {$plugin.tx_armgmap.view.templateRootPath}
    }
    persistence {
        storagePid = {$plugin.tx_armgmap.persistence.storagePid}
    }
    settings {
        zoomScale = {$plugin.tx_armgmap.settings.storagePid}
    }
}

Checking and loading of different extension class

if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('armpdfkit')) {
    require_once(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('armpdfkit').'Classes/Pdf/Pdf.php');
}

Building and Redirecting to a link

 $link = $this->uriBuilder->setTargetPageUid($pageUid)->build();
 $this->redirectToUri($link);

Forwarding to another action of same controller

 $this->forward('new', NULL, NULL, array('newFile' => $newFile));

Redirecting to another action

$this->redirect('list');

Flashing message to template

$this->flashMessageContainer->add('Success message','',\TYPO3\CMS\Core\Messaging\FlashMessage::OK);

$this->flashMessageContainer->add('Error message!','',\TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);

$this->flashMessageContainer->add('Warning message!','',\TYPO3\CMS\Core\Messaging\FlashMessage::WARNING);

$this->flashMessageContainer->add('Information','',\TYPO3\CMS\Core\Messaging\FlashMessage::INFO);

Control flash message styling

We can include Css block in the extension setup.txt

plugin.tx_armgmap._CSS_DEFAULT_STYLE (
    .typo3-messages {
        padding: 2px;
        margin-left: 10px;
        margin-bottom: 20px;
        text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
        background-color: #fcf8e3;
        border: 1px solid #fbeed5;
        -webkit-border-radius: 4px;
        -moz-border-radius: 4px;
        border-radius: 4px;
    }
    .message-warning {
        color: #FFB73E;
        background: #FFFF99;
        padding: 8px;
    }
    .message-ok {
        color: #33aa33;
        background: #CCFFCC;
        padding: 8px;
    }
    .message-error {
        color: #FF1944;
        background: #FFCCCC;
        padding: 8px;
    }
)

ViewHelper class for TYPO3 version < 6.0

The following ViewHelper determines whether booking is full for an event and displays the child block accordingly.

class Tx_Armevent_ViewHelpers_SeatIfViewHelper extends Tx_Fluid_Core_ViewHelper_AbstractConditionViewHelper {

   /**   
     * bookingRepository
     *
     * @var Tx_Armevent_Domain_Repository_BookingRepository
     */
    protected $bookingRepository;

    /**
     * injectBookingRepository
     *
     * @param Tx_Armevent_Domain_Repository_BookingRepository $bookingRepository
     * @return void
     */
    public function injectBookingRepository(Tx_Armevent_Domain_Repository_BookingRepository $bookingRepository) {
        $this->bookingRepository = $bookingRepository;
    }

    /**
     *
     * @param Tx_Armevent_Domain_Model_Event $event
     * @return string
     */
    public function render(Tx_Armevent_Domain_Model_Event $event) {
        
        $cnt = $this->bookingRepository->countByEvent($event->getUid());
        
        if ($cnt < $event->getSeats()) {
            return $this->renderThenChild();
        } else {
            return $this->renderElseChild();
        }
    }
}

Uploading file in ExtBase 6.0 and above

$file = $this->request->getArgument('file_form_elment');
$destination = PATH_site.'uploads/tx_myextension/'.$file['name'];
\TYPO3\CMS\Core\Utility\GeneralUtility::upload_copy_move($file['tmp_name'], $destination);

Uploading a media file

Controller class

   /**
     * Set TypeConverter option for image upload
     */
    public function initializeUploadAction() {
        $this->setTypeConverterConfigurationForImageUpload('photo');
    }
    
    /**
     * upload action
     *
     * @param \ARM\Gallery\Domain\Model\Photo $photo
     */
    public function uploadAction(\ARM\Gallery\Domain\Model\Photo $photo) {
    
        if ($this->request->hasArgument('tags')) {
            $frmtags = $this->request->getArgument('tags');
            if ($frmtags != '') {
                foreach ($frmtags as $tag) {
                    $tagObj = $this->tagRepo->findByUid($tag);
                    $photo->addTag($tagObj);
                }
            }
        }
        $this->photoRepo->add($photo);
        $this->flashMessageContainer->add('File upload successful!','',\TYPO3\CMS\Core\Messaging\FlashMessage::OK);
        $this->redirect('uploadform');
    }

    /**
     * Type converter
     */
    protected function setTypeConverterConfigurationForImageUpload($argumentName) {
        $uploadConfiguration = array(
                \ARM\Gallery\Property\TypeConverter\UploadedFileReferenceConverter::CONFIGURATION_ALLOWED_FILE_EXTENSIONS => $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'],
                \ARM\Gallery\Property\TypeConverter\UploadedFileReferenceConverter::CONFIGURATION_UPLOAD_FOLDER => '1:/user_upload/',
        );
        /** @var PropertyMappingConfiguration $newConfiguration */
        $newConfiguration = $this->arguments[$argumentName]->getPropertyMappingConfiguration();
        $newConfiguration->forProperty('image')
        ->setTypeConverterOptions(
                'ARM\\Gallery\\Property\\TypeConverter\\UploadedFileReferenceConverter',
                $uploadConfiguration
        );
        $newExampleConfiguration->forProperty('imageCollection.0')
        ->setTypeConverterOptions(
                'ARM\\Gallery\\Property\\TypeConverter\\UploadedFileReferenceConverter',
                $uploadConfiguration
        );
    }

TypeConverter class [gallery/Classes/Property/TypeConverter/UploadedFileReferenceConverter.php]

<?php
namespace ARM\Gallery\Property\TypeConverter;

use TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException;
use TYPO3\CMS\Core\Resource\File as FalFile;
use TYPO3\CMS\Core\Resource\FileReference as FalFileReference;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3\CMS\Extbase\Error\Error;
use TYPO3\CMS\Extbase\Property\Exception\TypeConverterException;
use TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface;
use TYPO3\CMS\Extbase\Property\TypeConverter\AbstractTypeConverter;
use TYPO3\Flow\Utility\Files;

class UploadedFileReferenceConverter extends AbstractTypeConverter {
    /**
     * Folder where the file upload should go to (including storage).
     */
    const CONFIGURATION_UPLOAD_FOLDER = 1;
    /**
     * How to handle a upload when the name of the uploaded file conflicts.
     */
    const CONFIGURATION_UPLOAD_CONFLICT_MODE = 2;
    /**
     * Whether to replace an already present resource.
     * Useful for "maxitems = 1" fields and properties
     * with no ObjectStorage annotation.
     */
    const CONFIGURATION_ALLOWED_FILE_EXTENSIONS = 4;
    /**
     * @var string
     */
    protected $defaultUploadFolder = '1:/user_upload/';
    /**
     * One of 'cancel', 'replace', 'changeName'
     *
     * @var string
     */
    protected $defaultConflictMode = 'changeName';
    /**
     * @var array<string>
     */
    protected $sourceTypes = array('array');
    /**
     * @var string
    */
    protected $targetType = 'TYPO3\\CMS\\Extbase\\Domain\\Model\\FileReference';
    /**
     * Take precedence over the available FileReferenceConverter
     *
     * @var integer
     */
    protected $priority = 2;
    /**
     * @var \TYPO3\CMS\Core\Resource\ResourceFactory
     * @inject
     */
    protected $resourceFactory;
    /**
     * @var \TYPO3\CMS\Extbase\Security\Cryptography\HashService
     * @inject
     */
    protected $hashService;
    /**
     * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
     * @inject
     */
    protected $persistenceManager;
    /**
     * @var \TYPO3\CMS\Core\Resource\FileInterface[]
     */
    protected $convertedResources = array();
    /**
     * Actually convert from $source to $targetType, taking into account the fully
     * built $convertedChildProperties and $configuration.
     *
     * @param string|integer $source
     * @param string $targetType
     * @param array $convertedChildProperties
     * @param \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface $configuration
     * @throws \TYPO3\CMS\Extbase\Property\Exception
     * @return \TYPO3\CMS\Extbase\Domain\Model\AbstractFileFolder
     * @api
    */
    public function convertFrom($source, $targetType, array $convertedChildProperties = array(), PropertyMappingConfigurationInterface $configuration = NULL) {
        if (!isset($source['error']) || $source['error'] === \UPLOAD_ERR_NO_FILE) {
            if (isset($source['submittedFile']['resourcePointer'])) {
                try {
                    $resourcePointer = $this->hashService->validateAndStripHmac($source['submittedFile']['resourcePointer']);
                    if (strpos($resourcePointer, 'file:') === 0) {
                        $fileUid = substr($resourcePointer, 5);
                        return $this->createFileReferenceFromFalFileObject($this->resourceFactory->getFileObject($fileUid));
                    } else {
                        return $this->createFileReferenceFromFalFileReferenceObject($this->resourceFactory->getFileReferenceObject($resourcePointer), $resourcePointer);
                    }
                } catch(\InvalidArgumentException $e) {
                    // Nothing to do. No file is uploaded and resource pointer is invalid. Discard!
                }
            }
            return NULL;
        }
        if ($source['error'] !== \UPLOAD_ERR_OK) {
            switch ($source['error']) {
                case \UPLOAD_ERR_INI_SIZE:
                case \UPLOAD_ERR_FORM_SIZE:
                case \UPLOAD_ERR_PARTIAL:
                    return new Error(Files::getUploadErrorMessage($source['error']), 1264440823);
                default:
                    return new Error('An error occurred while uploading. Please try again or contact the administrator if the problem remains', 1340193849);
            }
        }
        if (isset($this->convertedResources[$source['tmp_name']])) {
            return $this->convertedResources[$source['tmp_name']];
        }
        try {
            $resource = $this->importUploadedResource($source, $configuration);
        } catch (\Exception $e) {
            return new Error($e->getMessage(), $e->getCode());
        }
        $this->convertedResources[$source['tmp_name']] = $resource;
        return $resource;
    }
    /**
     * Import a resource and respect configuration given for properties
     *
     * @param array $uploadInfo
     * @param PropertyMappingConfigurationInterface $configuration
     * @return \TYPO3\CMS\Extbase\Domain\Model\FileReference
     * @throws TypeConverterException
     * @throws ExistingTargetFileNameException
     */
    protected function importUploadedResource(array $uploadInfo, PropertyMappingConfigurationInterface $configuration) {
        if (!GeneralUtility::verifyFilenameAgainstDenyPattern($uploadInfo['name'])) {
            throw new TypeConverterException('Uploading files with PHP file extensions is not allowed!', 1399312430);
        }
        $allowedFileExtensions = $configuration->getConfigurationValue('ARM\\Braasbautafel\\Property\\TypeConverter\\UploadedFileReferenceConverter', self::CONFIGURATION_ALLOWED_FILE_EXTENSIONS);
        if ($allowedFileExtensions !== NULL) {
            $filePathInfo = PathUtility::pathinfo($uploadInfo['name']);
            if (!GeneralUtility::inList($allowedFileExtensions, strtolower($filePathInfo['extension']))) {
                throw new TypeConverterException('File extension is not allowed!', 1399312430);
            }
        }
        $uploadFolderId = $configuration->getConfigurationValue('ARM\\Braasbautafel\\Property\\TypeConverter\\UploadedFileReferenceConverter', self::CONFIGURATION_UPLOAD_FOLDER) ?: $this->defaultUploadFolder;
        $conflictMode = $configuration->getConfigurationValue('ARM\\Braasbautafel\\Property\\TypeConverter\\UploadedFileReferenceConverter', self::CONFIGURATION_UPLOAD_CONFLICT_MODE) ?: $this->defaultConflictMode;
        $uploadFolder = $this->resourceFactory->retrieveFileOrFolderObject($uploadFolderId);
        $uploadedFile =  $uploadFolder->addUploadedFile($uploadInfo, $conflictMode);
        $resourcePointer = isset($uploadInfo['submittedFile']['resourcePointer']) && strpos($uploadInfo['submittedFile']['resourcePointer'], 'file:') === FALSE
        ? $this->hashService->validateAndStripHmac($uploadInfo['submittedFile']['resourcePointer'])
        : NULL;
        $fileReferenceModel = $this->createFileReferenceFromFalFileObject($uploadedFile, $resourcePointer);
        return $fileReferenceModel;
    }
    /**
     * @param FalFile $file
     * @param int $resourcePointer
     * @return \ARM\Braasbautafel\Domain\Model\FileReference
     */
    protected function createFileReferenceFromFalFileObject(FalFile $file, $resourcePointer = NULL) {
        $fileReference = $this->resourceFactory->createFileReferenceObject(
                array(
                        'uid_local' => $file->getUid(),
                        'uid_foreign' => uniqid('NEW_'),
                        'uid' => uniqid('NEW_'),
                )
        );
        return $this->createFileReferenceFromFalFileReferenceObject($fileReference, $resourcePointer);
    }
    /**
     * @param FalFileReference $falFileReference
     * @param int $resourcePointer
     * @return \ARM\Gallery\Domain\Model\FileReference
     */
    protected function createFileReferenceFromFalFileReferenceObject(FalFileReference $falFileReference, $resourcePointer = NULL) {
        if ($resourcePointer === NULL) {
            /** @var $fileReference \ARM\Gallery\Domain\Model\FileReference */
            $fileReference = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Domain\\Model\\FileReference');
        } else {
            $fileReference = $this->persistenceManager->getObjectByIdentifier($resourcePointer, 'TYPO3\\CMS\\Extbase\\Domain\\Model\\FileReference', FALSE);
        }
        $fileReference->setOriginalResource($falFileReference);
        return $fileReference;
    }
}


ObjectStorageConverter class [gallery/Classes/Property/TypeConverter/ObjectStorageConverter.php]

<?php
namespace ARM\Gallery\Property\TypeConverter;
class ObjectStorageConverter extends \TYPO3\CMS\Extbase\Property\TypeConverter\ObjectStorageConverter {
    /**
     * Take precedence over the available ObjectStorageConverter
     *
     * @var integer
     */
    protected $priority = 2;
    /**
     * Return the source, if it is an array, otherwise an empty array.
     * Filter out empty uploads
     *
     * @param mixed $source
     * @return array
     * @api
     */
    public function getSourceChildPropertiesToBeConverted($source) {
        $propertiesToConvert = array();
        // TODO: Find a nicer way to throw away empty uploads
        foreach ($source as $propertyName => $propertyValue) {
            if ($this->isUploadType($propertyValue)) {
                if ($propertyValue['error'] !== \UPLOAD_ERR_NO_FILE || isset($propertyValue['submittedFile']['resourcePointer'])) {
                    $propertiesToConvert[$propertyName] = $propertyValue;
                }
            } else {
                $propertiesToConvert[$propertyName] = $propertyValue;
            }
        }
        return $propertiesToConvert;
    }
    /**
     * Check if this is an upload type
     *
     * @param mixed $propertyValue
     * @return bool
     */
    protected function isUploadType($propertyValue) {
        return is_array($propertyValue) && isset($propertyValue['tmp_name']) && isset($propertyValue['error']);
    }
}

Model class Photo

    /**
     * image
     *
     * @var \TYPO3\CMS\Extbase\Domain\Model\FileReference
     */
    protected $image = NULL;

    /**
     * Returns the image
     *
     * @return \TYPO3\CMS\Extbase\Domain\Model\FileReference $image
     */
    public function getImage() {
        return $this->image;
    }

    /**
     * Sets the image
     *
     * @param \TYPO3\CMS\Extbase\Domain\Model\FileReference $image
     * @return void
     */
    public function setImage(\TYPO3\CMS\Extbase\Domain\Model\FileReference $image) {
        $this->image = $image;
    }


Model FileReference

class FileReference extends \TYPO3\CMS\Extbase\Domain\Model\FileReference {
    /**
     * Uid of a sys_file
     *
     * @var integer
     */
    protected $originalFileIdentifier;
    /**
     * @param \TYPO3\CMS\Core\Resource\FileReference $originalResource
     */
    public function setOriginalResource(\TYPO3\CMS\Core\Resource\FileReference $originalResource) {
        $this->originalResource = $originalResource;
        $this->originalFileIdentifier = (int)$originalResource->getOriginalFile()->getUid();
    }
}


TCA settings

'image' => array(
            'exclude' => 1,
            'label' => 'LLL:EXT:gallery/Resources/Private/Language/locallang_db.xlf:tx_gallery_domain_model_photo.image',
            'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig('image',
                array(
                        'maxitems' => 1,
                        'foreign_match_fields' => array(
                                'fieldname' => 'image',
                                'tablenames' => 'tx_gallery_domain_model_photo',
                                'table_local' => 'sys_file',
                        ),
                        'foreign_types' => array(
                                '0' => array(
                                        'showitem' => '
                            --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
                            --palette--;;filePalette'
                                ),
                                \TYPO3\CMS\Core\Resource\File::FILETYPE_TEXT => array(
                                        'showitem' => '
                            --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
                            --palette--;;filePalette'
                                ),
                                \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => array(
                                        'showitem' => '
                            --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
                            --palette--;;filePalette'
                                ),
                                \TYPO3\CMS\Core\Resource\File::FILETYPE_AUDIO => array(
                                        'showitem' => '
                            --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
                            --palette--;;filePalette'
                                ),
                                \TYPO3\CMS\Core\Resource\File::FILETYPE_VIDEO => array(
                                        'showitem' => '
                            --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
                            --palette--;;filePalette'
                                ),
                                \TYPO3\CMS\Core\Resource\File::FILETYPE_APPLICATION => array(
                                        'showitem' => '
                            --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
                            --palette--;;filePalette'
                                )
                        )
                ),
                $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']
            ),
        )

Sending email with attachment

        $mailtpl = $this->objectManager->create('Tx_Fluid_View_StandaloneView');
        $mailtpl->setFormat('html');
        
        $extbaseFrameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
        $templateRootPath = GeneralUtility::getFileAbsFileName($extbaseFrameworkConfiguration['view']['templateRootPath']);
        $templatePathAndFilename = $templateRootPath. "Email/Order.html";
        $mailtpl->setTemplatePathAndFilename($templatePathAndFilename);
        $mailtpl->assign('order', $order);
        $mailbody = $mailtpl->render();

        $objMail = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');        
        $senderMail = $this->settings['mail']['adminEmail'];
        $senderName = $this->settings['mail']['adminName'];
        $email = 'contact@armtechnologies.com';
        $name = 'ARM Technologies';
        $subject = $this->settings['mail']['prePaySubject'];
           
        if (\TYPO3\CMS\Core\Utility\GeneralUtility::validEmail($email)) {
                $invoicePdf = PATH_site . 'uploads/tx_armshop/invoice_'.$order->getUid().'.pdf';
                require_once PATH_typo3 . 'contrib/swiftmailer/classes/Swift/Attachment.php';
                require_once PATH_typo3 . 'contrib/swiftmailer/classes/Swift/Mime/Attachment.php';
                require_once PATH_typo3 . 'contrib/swiftmailer/classes/Swift/Mime/SimpleMimeEntity.php';
                $objMail->attach(\Swift_Attachment::fromPath($invoicePdf));
         }

        $objMail->setFrom(array($senderMail => $senderName))
        ->setTo(array($email => $name))
        ->setCc(array($senderMail => $senderName))
        ->setSubject($subject)
        ->setBody($mailbody, 'text/html')
        ->send();