TYPO3-konforme SQL-Anweisungen in ext_tables.sql

Geändert: Donnerstag, 17. September 2015 | Erstellt: Freitag, 9. Mai 2014

Auch in TYPO3 6.2 muss man noch darauf achten, wie man die SQL-Anweisungen in der Datei ext_tables.sql der eigenen Erweiterungen aufbaut, damit diese von TYPO3 „verstanden“ werden. Zwar werden die SQL-Anweisungen korrekt ausgeführt und die Tabelle wird angelegt, aber im „Database Analyser“ des Install Tools werden beim „Database Compare“ Unterschiede aufgezeigt.

So hängt z.B. die Syntax des Default-Wertes vom Spaltentyp ab:

  1. Der Spaltentyp „integer“ muss als Default-Wert DEFAULT '0' NOT NULL haben.
  2. Der Spaltentyp „varchar“ muss als Default-Wert DEFAULT '' NOT NULL haben.
  3. Der Spaltentyp „tinytext“, „text“, „mediumtext“ und „longtext“ darf keinen Default-Wert haben.
  4. Der Spaltentyp „double“ muss als Default-Wert DEFAULT '0' NOT NULL haben.

Außerdem muss man beachten:

  1. Die Anweisung „auto_increment“ muss klein geschrieben werden.
  2. Bei der Definition eines Schlüssels darf es bei den Feldern kein Leerzeichen geben.

Beispiel:

ext_tables.sql

CREATE TABLE tx_mytable (
    uid int(11) NOT NULL auto_increment,
    pid int(11) DEFAULT '0' NOT NULL,
    title varchar(255) DEFAULT '' NOT NULL,
    description text,
    image blob,
    flag tinyint(1) unsigned DEFAULT '0' NOT NULL,
    number1 int(11) DEFAULT '0' NOT NULL,
    number2 double DEFAULT '0' NOT NULL,
    latitude double(13,10) DEFAULT '0.0000000000' NOT NULL,
    date timestamp DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (uid),
    KEY parent (pid),
    KEY whatever (uid,number1)
);

Den Fehler bei Verwendung von „CURRENT_TIMESTAMP“ bekommt man nicht weg. Zwar verschwindet er, wenn man „DEFAULT ‚CURRENT_TIMESTAMP'“ schreibt, die Tabelle lässt sich mit dieser Abweisung aber nicht initial anlegen.

Sind euch noch weitere Fälle bekannt, die man beachten muss?

Thema: TYPO3 Extension-Programmierung | Kommentare (3)

TYPO3: FlashMessages

Geändert: Dienstag, 11. Oktober 2016 | Erstellt: Freitag, 28. Februar 2014

FlashMessages in Extbase

FlashMessages erstellen

Anlegen einer FlashMessage im Controller:

$this->addFlashMessage(
  'The message text.',
  'The title',
  \TYPO3\CMS\Core\Messaging\AbstractMessage::OK
);

oder

$this->controllerContext->getFlashMessageQueue()->enqueue(
  $this->objectManager->get(
    \TYPO3\CMS\Core\Messaging\FlashMessage::class,
    'The message text.',
    'The title',
    \TYPO3\CMS\Core\Messaging\AbstractMessage::OK
  )
);

Die zweite Funktion macht das gleiche wie die erste, die erste Funktion ist lediglich eine vereinfachte Variante der zweiten Funktion.

FlashMessages anzeigen

Auslesen von Meldungen im Controller:

$this->controllerContext->getFlashMessageQueue()->getAllMessages()

oder

$this->controllerContext->getFlashMessageQueue()->getAllMessagesAndFlush()

Ausgeben von Meldungen im Fluid Template:

<f:flashMessages renderMode="div" />

Anpassen der CSS Klassen

Kann sinnvoll, wenn man beispielsweise Bootstrap als Framework nutzt.

Geht vermutlich nur per XCLASS von \TYPO3\CMS\Core\Messaging\FlashMessage, damit wirklich ALLE Meldungen die eigenen CSS Klassen enthalten. Für die Änderung der CSS Klassen von Meldungen, die von einer eigenen Erweiterung erzeugt werden, gibt es folgende Möglichkeit:

EXT:my_ext/Classes/Messaging/FlashMessage.php

namespace TYPO3\MyExt\Messaging;
class FlashMessage extends \TYPO3\CMS\Core\Messaging\FlashMessage {
  protected $classes = array(
    self::NOTICE => 'notice alert alert-info',
    self::INFO => 'info alert alert-info',
    self::OK => 'ok alert alert-success',
    self::WARNING => 'warning alert alert-warning',
    self::ERROR => 'error alert alert-danger'
  );
}

Entsprechend ändert sich dann natürlich der Aufruf:

View

$this->controllerContext->getFlashMessageQueue()->enqueue(
  $this->objectManager->get(
    \Vendor\MyExt\Messaging\FlashMessage::class,
    'The message text.',
    'The title',
    \TYPO3\MyExt\Messaging\FlashMessage::OK
  )
);

FlashMessages in initializeAction()

Ist nicht möglich, da $this->contextController noch nicht bereitsteht.

Alternative: Funktion emitBeforeCallActionMethodSignal() nutzen, diese Funktion wird ebenfalls vor der Action aufgerufen:

/**
 * Called before all actions
 *
 * @param array $preparedArguments
 */
protected function emitBeforeCallActionMethodSignal(array $preparedArguments) {
    parent::emitBeforeCallActionMethodSignal($preparedArguments);
 
    $action = $this->request->getControllerActionName();
    if(in_array($action, array('list', 'new'))) {
        $this->addFlashMessage('Text', 'Title', \TYPO3\CMS\Core\Messaging\AbstractMessage::OK);
    }
}

FlashMessages im Backend (TYPO3 ab Version 6.1)

Nutzbar z.B. in einem Hook, der beim Speichern eines Datensatzes greift.

/** @var $flashMessage FlashMessage */
$flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
  'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
  htmlspecialchars($message),
  htmlspecialchars($title),
  \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR,
  true // store in session
);
/** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
$flashMessageService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessageService');
$defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
$defaultFlashMessageQueue->enqueue($flashMessage);

 

Thema: TYPO3 Extension-Programmierung | Kommentare (3)

Seitenbaum Reload via BE Modul

Erstellt: Donnerstag, 27. Februar 2014

Um über ein Backend Modul den Seitenbaum neu zu laden, kann man nachfolgende JavaScript-Anweisung nutzen:

if(top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) {
  top.content.nav_frame.refresh_nav();
}

Das kann beispielsweise sinnvoll sein, wenn das BE Modul Änderungen an Seiten vorgenommen hat und man diese Änderungen nun anzeigen möchte. Oft macht es Sinn, den Reload des Seitenbaums nur durchzuführen, nachdem der Benutzer eine bestimmte Aktion durchgeführt hat, z.B. ein Formular im BE Modul abgeschickt hat, hier ein Beispiel mit Extbase/Fluid:

View

<f:if condition="{submitted}">
  <script type="text/javascript">
  if(top.content && top.content.nav_frame && top.content.nav_frame.refresh_nav) {
    top.content.nav_frame.refresh_nav();
  }
  </script>
</f:if>
<f:form.submit name="submit" value="Submit" />

Controller

$this->view->assign('submitted', $this->request->hasArgument('submit'));

 

Thema: TYPO3 Extension-Programmierung | Keine Kommentare

TYPO3: Extbase/Fluid im BE Modul

Geändert: Mittwoch, 17. Mai 2017 | Erstellt: Dienstag, 18. Februar 2014

Backend Modul, erstellt mit Extbase und Fluid Templates – ohne viel Bla-Bla:

ext_tables.php

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
    'TYPO3.' . $_EXTKEY,
    'tools',
    'tx_myext_m1',
    '',
    array(
        'Backend' => 'migrate',
    ),
    array(
        'access' => 'user, group',
        'icon' => 'EXT:my_ext/ext_icon.gif',
        'labels' => 'LLL:EXT:my_ext/Resources/Private/Language/locallang_mod.xml',
    )
);

locallang_mod.xml

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3locallang>
    <meta type="array">
        <type>module</type>
        <description>Language labels for BE Module</description>
    </meta>
    <data type="array">
        <languageKey index="default" type="array">
            <label index="mlang_tabs_tab">My module</label>
            <label index="mlang_labels_tabdescr"></label>
        </languageKey>
    </data>
</T3locallang>

ext_typoscript_setup.txt

module.tx_myext {
    view {
        templateRootPaths {
            0 = EXT:my_ext/Resources/Private/Templates/
        }
        partialRootPaths {
            0 = EXT:my_ext/Resources/Private/Partials/
        }
        layoutRootPaths {
            0 = EXT:my_ext/Resources/Private/Layouts/
        }
    }
    settings {
        // your TypoScript setup for backend module
    }
}

Resources/Private/Templates/Backend/Migrate.html

<f:layout name="Backend"/>
 
<f:section name="main">
    <h2>Migrate Service Centers</h2>
    <f:flashMessages renderMode="div" />
 
    <f:form action="migrate" name="migrate">
        <f:form.submit name="submit" value="Migrate!" />
    </f:form>
</f:section>

Resources/Private/Layouts/Backend.html

<f:be.container>
    <div class="typo3-fullDoc">
        <div id="typo3-docheader">
            <div id="typo3-docheader-row1">
                <div class="buttonsleft">
                </div>
                <div class="buttonsright">
                    <f:be.buttons.shortcut />
                </div>
            </div>
            <div id="typo3-docheader-row2">
                <div class="docheader-row2-left">
                    <f:be.buttons.csh />
                    <f:be.menus.actionMenu>
                        <f:be.menus.actionMenuItem label="Action 1" controller="Backend" action="action1" />
                        <f:be.menus.actionMenuItem label="Action 2" controller="Backend" action="action2" />
                    </f:be.menus.actionMenu>
                </div>
                <div class="docheader-row2-right">
                    <f:be.pagePath />
                    <f:be.pageInfo />
                </div>
            </div>
        </div>
        <div id="typo3-docbody">
            <div id="typo3-inner-docbody">
                <f:render section="main" />
            </div>
        </div>
    </div>
</f:be.container>

 Classes/Controller/BackendController.php

namespace TYPO3\MyExt\Controller;
class BackendController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
    // TypoScript settings
    protected $settings = array();
    // id of selected page
    protected $id;
    // info of selected page
    protected $pageinfo;
 
    protected function initializeAction() {
        $this->id = (int)\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('id');
        $this->pageinfo = \TYPO3\CMS\Backend\Utility\BackendUtility::readPageAccess($this->id, $GLOBALS['BE_USER']->getPagePermsClause(1));
 
        $configurationManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager::class);
 
        $this->settings = $configurationManager->getConfiguration(
            $this->request->getControllerExtensionName(),
            $this->request->getPluginName()
        );
    }
 
    /**
     * action
     *
     * @return void
     */
    public function migrateAction() {
        $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
        $migrateRepository = $objectManager->get(\Vendor\MyExt\Domain\Repository\MigrateRepository::class);
 
        // form submitted
        if($this->request->hasArgument('submit')) {...}
 
        // add value to view
        $this->view->assign('var', 'value');
 
        // display message
        $this->addFlashMessage(
            'Some text',
            'The title',
            \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING
        );
    }
}

CSS/JS Datei einlesen

<f:be.container addCssFile="{f:uri.resource(path:'path/to/file.css')}" addJsFile="{f:uri.resource(path:'path/to/file.js')}">...</f:be.container>

Fragen?

Thema: TYPO3 Extension-Programmierung | Kommentare (1)

TYPO3: Datumsfeld für BE Modul

Geändert: Donnerstag, 21. Mai 2015 | Erstellt: Freitag, 14. Februar 2014

Datepicker für ein Input-Feld in einem BE-Modul (hier in einem BE Modul umgesetzt mit Extbase/Fluid, getestet unter TYPO3 6.2):

$doc = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Template\\DocumentTemplate');
$pageRenderer = $doc->getPageRenderer();
// Load ExtJS
$pageRenderer->loadExtJS();
$pageRenderer->addJsFile($this->backPath . 'sysext/backend/Resources/Public/JavaScript/tceforms.js');
$pageRenderer->addJsFile($this->backPath . 'js/extjs/ux/Ext.ux.DateTimePicker.js');
// Define settings for date picker
$typo3Settings = array(
    'datePickerUSmode' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? 1 : 0,
    'dateFormat' => array('j-n-Y', 'G:i j-n-Y'),
    'dateFormatUS' => array('n-j-Y', 'G:i n-j-Y')
);
$pageRenderer->addInlineSettingArray('', $typo3Settings);
 
$icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-edit-pick-date', array(
    'style' => 'cursor:pointer;',
    'id' => 'picker-tceforms-datefield-start'
));
$this->view->assign('icon', $icon);

Und das Template:

<f:form.textfield name="start" id="tceforms-datefield-start" value="" /> <f:format.raw>{icon}</f:format.raw>

Die Benennung der ID ist wichtig, diese muss in der Form tceforms-datefield-[fieldname] sein. Statt „datefield“ kann man auch „datetimefield“ verwenden, dann enthält der Datepicker noch die Uhrzeit.

datepickerDie System-Extension scheduler setzt einen solchen Datepicker in dem Backend-Modul für die Task-Planung ein (siehe Abbildung), ebenso die Extension formhandler und weitere.

Thema: TYPO3 Extension-Programmierung | Kommentare (2)

Übermittlung von tt_news über das Frontend

Erstellt: Dienstag, 28. Januar 2014

Die News-Erweiterung tt_news kann man oft flexibel für viele Anwendungsfälle einsetzen, z.B. als Glossar, als Veranstaltungskalender oder als Shop und es gibt etliche Erweiterungen für tt_news. Daher war ich mir sicher, für das Einreichen von neuen News-Datensätzen über das Frontend gibt es im TER eine Erweiterung, die zumindest ein paar der üblichen Anforderungen abdeckt:

  1. Upload von Bildern ist möglich
  2. Einteilung in Kategorien ist möglich
  3. Spam-Schutz
  4. Der Benutzer kann die eingereichten News nachträglich bearbeiten
  5. Der Administrator kann die eingereichten News direkt über Links in der E-Mail freischalten oder abweisen

Gefunden habe ich im TER diese Erweiterungen, von der leider keine einzige brauchbar ist:

  1. elemente_fenews Frontend Editing für News-Datensätze, mit RTE, Kategorie-Auswahl und Bild-Upload.
    Schlecht: Funktioniert ab TYPO3 Version 4.7 und tt_news Version 3.0.0 nicht mehr
  2. newsfrontendfeeder Übermittlung von News über das Frontend, mit Spam-Schutz (Captcha) und Benachrichtigung für Admin mit Freischaltung der neuen News über Link in E-Mail.
    Schlecht: Captcha funktioniert nicht; Plugin wird gecached eingebunden, dadurch werden Benutzereingaben nicht verarbeitet; keine Nur-Text-Version der E-Mails; bei Links in E-Mail fehlt die Domain; keine serverseitige Validierung, nur per JavaScript; deutscher Text in JavaScript-Validierung; kein Bild-Upload; Feld „Untertitel“ ist input statt textarea
  3. mt_fenews Übermittlung und Bearbeitung von News über das Frontend
    Schlecht: Kein Manual; schlampige Programmierung; unnötiges Plugin („FE future stuff„); erfordert Ext. mt_prize, die im TER nicht zu finden ist.

Die vorerst beste Möglichkeit scheint der Einsatz einer normalen Kontaktformular-Erweiterung (powermail oder formhandler) zu sein. Mit diesen Erweiterungen ist es möglich, die eingereichte News in der Datenbank zu speichern und per E-Mail an den Admin zu schicken. Damit ist der Upload von Bildern und die Einteilung in Kategorien möglich, einen Spam-Schutz hat jede Kontaktformular-Erweiterung sowieso. Schwieriger wird es, dem Benutzer die nachträgliche Bearbeitung seiner eingereichten News zu erlauben und dass der Administrator die News über Links in der E-Mail komfortabel freischalten kann, dafür muss man die Kontaktformular-Erweiterung mit einer eigenen Erweiterung erweitern.

Thema: TYPO3 Extensions | Kommentare (3)

Exit Disclaimer mit jQuery

Geändert: Montag, 1. August 2016 | Erstellt: Dienstag, 7. Januar 2014

Anzeigen eines Hinweises, dass der Benutzer die Webseite verlässt, nach dem Klick auf eine externe URL. Erst nach Bestätigung des Benutzers wird die externe Seite geöffnet. Es können Domains angegeben werden, bei denen die Hinweisbox nicht erscheint (z.B. bei Domains, die zur Unternehmensgruppe oder dem gleichen Inhaber gehören), außerdem wird das „target“ des Links (öffnen in neuer bzw. gleicher Seite) beachtet.

HTML

<div id="hint_external">
    <h2>Externer Link</h2>
    <p>
        Sie haben einen externen Link gewählt. Wenn Sie auf "Ja" klicken, verlassen Sie unsere Homepage.<br />
        Bitte beachten Sie, dass wir für den Inhalt der verlinkten Seite nicht verantwortlich sind.
    </p>
    <p>
        Wollen Sie die externe Seite <b id="hint_external_url">URL</b> betreten?
    </p>
    <p>
        <a id="hint_external_yes" href="#">Ja</a> <a id="hint_external_close" href="#">Nein</a>
    </p>
</div>

CSS

#hint_external {
    display: none;
    position: fixed;
    top: 30%;
    left: 50%;
    width: 300px;
    margin-left: -150px;
    background: #fff;
    border: 2px solid #000;
    padding: 10px;
}

JavaScript

// Hint for opening external url
var whiteList = new Array('www.domain.de', 'www.domain.com', '.allow-all-subdomains.de');
$('a').not('#hint_external a').on('click', function(e){
    var href = $(this).attr('href');
    var target = $(this).attr('target');
    if(href.match(/((http:\/\/)|(https:\/\/))/i)) {
        var whitelisted = false;
        // Check for external url
        var a = document.createElement('a');
        a.href = href;
        var hostname = a.hostname;
        $.each(whiteList, function(index, name) {
            name = name.replace(/\./g, String.fromCharCode(92) + '.');
            var re = new RegExp(name, 'i');
            if(re.test(hostname)) {
                whitelisted = true;
            }
        });
        if(!whitelisted) {
            e.preventDefault();
            $('#hint_external_url').text(hostname);
            $('#hint_external').show();
            $('#hint_external_close').one('click', function(e2){
                e2.preventDefault();
                $('#hint_external').hide();
            });
            $('#hint_external_yes').one('click', function(){
                $(this).attr('href', href);
                if(target){
                    $(this).attr('target', target);
                } else{
                    $(this).removeAttr('target');
                }
                $('#hint_external').hide();
            });
        }
    }
});

 

Thema: jQuery | Keine Kommentare

TYPO3: Mehrsprachige 404 Fehlerseite bei realurl

Geändert: Dienstag, 31. Mai 2016 | Erstellt: Montag, 23. Dezember 2013

Dies ist out-of-the-box nicht möglich, da TYPO3 zu einer ungültigen URL nicht die Sprach-ID (den Sprachparameter L) geliefert bekommt und die URL auch nicht über realurl aufgelöst werden kann, da keine entsprechende Seite im System existiert.
Ein Beispiel: Es wird die URL domain.com/de/veraltete-url/ aufgerufen. Da realurl zu dieser URL keine Seite findet, steigt realurl aus und obwohl die URL den Sprachkey „de“ enthält, wird die 404 Fehlerseite anschließend in der Default-Sprache angezeigt.

Mit Ext. realurl_force404lang

Edit Nov. 2015: Leider gab es für diese Erweiterung schon lange kein Update mehr, daher funktioniert sie in neueren TYPO3- und realurl-Versionen nicht mehr.

Die Erweiterung realurl_force404lang korrigiert diesen Umstand: Sie erkennt die Sprach-ID anhand der realurl-Konfiguration aus der sprechenden URL und schreibt diesen in die GET-Superglobale. Damit wird aber noch nicht automatisch die definierte Fehlerseite (z.B. $TYPO3_CONF_VARS[‚FE‘][‚pageNotFound_handling‘] = ‚/index.php?id=71‘) in der richtigen Sprache aufgerufen, daher muss man für das 404-Handling eine User-Funktion schreiben:

LocalConfiguration.php

$TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = 'USER_FUNCTION:fileadmin/php/pageNotFoundHandling.php:user_pageNotFound->pageNotFound';
$TYPO3_CONF_VARS['FE']['pageNotFound_handling_redirectPageID'] = 71; // Attention: this parameter is not provided by TYPO3, but needed for page-not-found-userfunction

pageNotFoundHandling.php

class user_pageNotFound {
  /**
   * Redirect to 404 error page with language-ID provided by ext. "realurl_force404lang"
   *
   * @param array $params: "currentUrl", "reasonText" and "pageAccessFailureReasons"
   * @param object $tsfeObj: object type "tslib_fe"
   */
  function pageNotFound(&$params, &$tsfeObj) {
    // handle default language
    $tsfeObj->pageErrorHandler('/index.php?id=' . $GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFound_handling_redirectPageID'] . (array_key_exists('L', $_GET) ? '&L=' . $_GET['L'] : ''));
  }
}

Ohne Erweiterung

Ohne die Erweiterung realurl_force404lang geht es auch, so könnte die Funktion aussehen:

class user_pageNotFound {
  /**
   * Detect language and redirect to 404 error page
   *
   * @param array $params: "currentUrl", "reasonText" and "pageAccessFailureReasons"
   * @param object $tsfeObj: object type "tslib_fe"
   */
  function pageNotFound($params, $tsfeObj) {
    // get first realurl configuration array (important for multidomain)
    $realurlConf = array_shift($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']);
    // look for language configuration
    foreach($realurlConf['preVars'] as $conf) {
      if($conf['GETvar'] == 'L') {
        foreach($conf['valueMap'] as $k => $v) {
          // we expect a part like "/de/" in requested url
          if(strpos($params['currentUrl'], '/' . $k . '/') !== false) {
            $tsfeObj->pageErrorHandler('/index.php?id=' . $GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFound_handling_redirectPageID'] . '&L=' . $v);
          }
        }
      }
    }
    // handle default language
    $tsfeObj->pageErrorHandler('/index.php?id=' . $GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFound_handling_redirectPageID']);
  }
}

Edit Mai 2016: An der obigen Lösung gefällt mir nicht, dass TYPO3 auf die 404 Fehlerseite redirected, anstatt unter der aufgerufenen URL die Inhalte der 404 Fehlerseite mit Statuscode „404 Not Found“ anzuzeigen. Daher habe ich den PHP Code überarbeitet:

use TYPO3\CMS\Core\Utility\GeneralUtility;
 
class user_pageNotFound {
 
    /**
     * Redirect to 404 error page with language-ID
     *
     * @param array $params: "currentUrl", "reasonText" and "pageAccessFailureReasons"
     * @param object $tsfeObj: object type "tslib_fe"
     */
    function pageNotFound(&$params, &$tsfeObj) {
        // Get first realurl configuration array (important for multidomain)
        $realurlConf = array_shift($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']);
        // Look for language configuration
        $language = false;
        foreach($realurlConf['preVars'] as $conf) {
            if($conf['GETvar'] == 'L') {
                if(is_array($conf['valueMap'])) {
                    foreach($conf['valueMap'] as $k => $v) {
                        // We expect a part like "/de/" in requested url
                        if(strpos($params['currentUrl'], '/' . $k . '/') !== false) {
                            $language = $v;
                            break;
                        }
                    }
                }
            }
        }
        // Get contents of 404 page
        $contentUrl = GeneralUtility::locationHeaderUrl(sprintf(
            '/index.php?id=%u%s',
            $GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFound_handling_redirectPageID'],
            $language ? sprintf('&L=%u', $language) : ''
        ));
        $content = GeneralUtility::getUrl($contentUrl);
        // Output 404 page
        if($content) {
            echo $content;
        // No 404 page found: Display TYPO3 error page
        } else {
            $params['reasonText'] .= sprintf(
                ' Additionally, %s was not found while trying to retrieve the error document.',
                $contentUrl
            );
            if(strpos($contentUrl, 'https://') === 0) {
                $params['reasonText'] .= ' It seems, your SSL certificate seems not to be accepted.';
            }
            $tsfeObj->pageErrorHandler('', '', $params['reasonText']);
        }
    }
}

Thema: TYPO3 Extensions | Kommentare (5)

TYPO3: Accordion mit gridelements

Geändert: Sonntag, 2. März 2014 | Erstellt: Montag, 9. Dezember 2013

In Ergänzung zum Artikel Slider mit gridelements hier nun die Konfiguration zum Accordion mit der Ext. gridelements:

Die FlexForm-Konfiguration für die Accordion-Optionen. Ich setze das Accordion von jqueryui ein, daher stehen hier die Optionen für dieses jQuery Plugin:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3DataStructure>
    <meta>
        <langDisable>1</langDisable>
    </meta>
    <sheets>
        <sDEF>
            <ROOT>
                <TCEforms>
                    <sheetTitle>Allgemein</sheetTitle>
                </TCEforms>
                <type>array</type>
                <el type="array">
                    <active type="array">
                        <TCEforms type="array">
                            <label>Geöffnetes Element (0 = erstes, 1 = zweites, ..., -1 = letztes)</label>
                            <config type="array">
                                <type>input</type>
                                <size>1</size>
                                <max>3</max>
                            </config>
                        </TCEforms>
                    </active>
                </el>
            </ROOT>
        </sDEF>
        <advanced>
            <ROOT>
                <TCEforms>
                    <sheetTitle>Erweitert</sheetTitle>
                </TCEforms>
                <type>array</type>
                <el type="array">
                    <header type="array">
                        <TCEforms type="array">
                            <label>Überschrift Tag</label>
                            <config type="array">
                                <type>input</type>
                                <size>2</size>
                                <default>h3</default>
                            </config>
                        </TCEforms>
                    </header>
                    <collapsible type="array">
                        <TCEforms type="array">
                            <label>Alle Elemente sind einklappbar</label>
                            <config type="array">
                                <type>check</type>
                                <default>1</default>
                            </config>
                        </TCEforms>
                    </collapsible>
                    <animate type="array">
                        <TCEforms type="array">
                            <label>Animation (Name des Effektes oder Dauer in Millisekunden)</label>
                            <config type="array">
                                <type>input</type>
                                <size>40</size>
                            </config>
                        </TCEforms>
                    </animate>
                    <heightStyle type="array">
                        <TCEforms type="array">
                            <label>Verhalten Höhe</label>
                            <config type="array">
                                <type>select</type>
                                <items type="array">
                                <numIndex index="0" type="array">
                                    <numIndex index="0">Keine Anpassung</numIndex>
                                    <numIndex index="1">content</numIndex>
                                </numIndex>
                                <numIndex index="1" type="array">
                                    <numIndex index="0">Orientierung an höchsten Element</numIndex>
                                    <numIndex index="1">auto</numIndex>
                                </numIndex>
                                </items>
                            </config>
                        </TCEforms>
                    </heightStyle>
                    <event type="array">
                        <TCEforms type="array">
                            <label>Aufklappen bei</label>
                            <config type="array">
                                <type>select</type>
                                <items type="array">
                                <numIndex index="0" type="array">
                                    <numIndex index="0">Klick</numIndex>
                                    <numIndex index="1">click</numIndex>
                                </numIndex>
                                <numIndex index="1" type="array">
                                    <numIndex index="0">Mouseover</numIndex>
                                    <numIndex index="1">mouseover</numIndex>
                                </numIndex>
                                </items>
                            </config>
                        </TCEforms>
                    </event>
                </el>
            </ROOT>
        </advanced>
    </sheets>
</T3DataStructure>

HTML-Ausgabe dieses Raster-Elementes:

TS Setup

tt_content.gridelements_pi1 {
    20.10.setup {
        13 < lib.gridelements.defaultGridSetup
        13 {
            columns {
                default.renderObj.wrap = <li class="accordionItem">|</li>
            }
            wrap.stdWrap.cObject = COA
            wrap.stdWrap.cObject {
                wrap = <div class="accordion">|</div>
                10 = COA
                10 {
                    10 = COA
                    10 {
                        wrap = <div class="options">{|}</div>
                        110 = TEXT
                        110.value = "active":false,
                        110.override.wrap = "active":|,
                        110.override.field = flexform_active
                        110.override.if.value = -2
                        110.override.if.isGreaterThan.field = flexform_active
                        120 = TEXT
                        120.wrap = "header":"|",
                        120.field = flexform_header
                        130 = TEXT
                        130.value = "collapsible":true,
                        130.if.isTrue.field = flexform_collapsible
                        140 = TEXT
                        140.wrap = "animate":|,
                        140.field = flexform_animate
                        140.required = 1
                        140.override.wrap = "|"
                        140.override.field = flexform_animate
                        140.override.if.value = 1000000
                        140.override.if.isGreaterThan.field = flexform_animate
                        150 = TEXT
                        150.wrap = "heightStyle":"|",
                        150.field = flexform_heightStyle
                        160 = TEXT
                        160.wrap = "event":"|"
                        160.field = flexform_event
                    }
                    20 = TEXT
                    20.value = <ul class="accordionContents">|</ul>
                }
            }
        }
    }
}

Der JavaScript-Code, um die Optionen an den Slider weiterzugeben:

$('.accordion').each(function(){
    options = $(this).find('.options').text();
    if(options) {
        options = $.parseJSON(options);
    } else {
        options = [];
    }
    $(this).find('.accordionContents').accordion(options);
});

Thema: TYPO3 | Kommentare (9)

TYPO3: Zugriffsbeschränkte Seiten mit Login

Geändert: Donnerstag, 7. Januar 2016 | Erstellt: Mittwoch, 30. Oktober 2013

In den Seiteneigenschaften einer Seite kann man in Reiter „Zugriff“ über Einstellung „Zugriffsrechte für Benutzergruppen“ festlegen, ob der Benutzer eingeloggt oder ob er einer bestimmten Benutzergruppen zugehörig sein muss, um die Seite sehen zu dürfen. Standardmäßig zeigt TYPO3 Links auf solche Seiten nicht an, wenn der Benutzer nicht eingeloggt ist. Hier wird die Einrichtung einer alternativen Handhabung erklärt, bei der die Links auf diese Seiten angezeigt werden, beim Aufruf der Seite wird aber ein Login-Formular eingeblendet. Nach der richtigen Eingabe von Benutzername und Passwort wird der nun authentifizierte Benutzer auf die zuvor zugriffsbeschränkte Seite weitergeleitet.

Vorteile dieser Lösung:

  1. Verzicht auf Parameter „addParams“
  2. Parameter „redirect_url“ ist nicht in der URL sichtbar
  3. Leitet weiter zu sprechender URL
  4. Nutzt TYPO3 Funktion „pageErrorHandler“
  5. Konfigurierbar über localconf.php (ähnlich der Konfiguration für die 404 Fehlerseite)

TS Setup

config.typolinkLinkAccessRestrictedPages = NONE

TS Setup für Menü (TMENU)

Durch das „NONE“ erscheint der Link zur zugriffsbeschränkten Seite sowohl im Menü als auch bei Links im Seitencontent, der Link wird aber nicht auf die Login-Seite umgebogen. Die zugriffsbeschränkte Seite wird also ganz normal aufgerufen, der Inhalt wird aber nicht angezeigt, sondern ein Login-Formular.

Mit dem Menü-Status USR kann man den zugriffsbeschränkten Seiten eine eigene CSS-Klasse zuweisen und diesen damit eine andere Formatierung geben.

Um die Anzeige des Login-Formulars auf zugriffsbeschränkten Seiten kümmert sich eine PHP-Funktion, die auch für die Anzeige der 404-Fehlerseite zuständig ist. Über die localconf.php wird konfiguriert, welche ID und welchen HTTP-Status-Code die 404-Seite und die Login-Seite haben:

localconf.php

$TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = 'USER_FUNCTION:fileadmin/php/pageNotFoundHandling.php:user_pageNotFound->pageNotFound';
$TYPO3_CONF_VARS['FE']['pageNotFound_handling_statheader'] = 'HTTP/1.0 404 Not Found';
$TYPO3_CONF_VARS['FE']['pageNotFound_handling_redirectPageID'] = [page id for 404 page]; // attention: this parameter is not provided by TYPO3, but needed for page-not-found-userfunction
$TYPO3_CONF_VARS['FE']['accessRestrictedPages_handling_statheader'] = 'HTTP/1.0 403 Forbidden'; // attention: this parameter is not provided by TYPO3, but needed for page-not-found-userfunction
$TYPO3_CONF_VARS['FE']['accessRestrictedPages_handling_redirectPageID'] = [page id for login page]; // attention: this parameter is not provided by TYPO3, but needed for page-not-found-userfunction

pageNotFoundHandling.php

class user_pageNotFound {
 
    /**
     * Redirect to 404 error page with language-ID provided by ext. "realurl_force404lang" (if installed)
     * Redirect to login page
     *
     * @param array $params: "currentUrl", "reasonText" and "pageAccessFailureReasons"
     * @param object $tsfeObj: object type "tslib_fe"
     */
    function pageNotFound(&$params, &$pObj) {
        // access restricted page
        if(array_shift($params['pageAccessFailureReasons']['fe_group'])) {
            $pObj->pageErrorHandler(
                '/index.php?id=' . $GLOBALS['TYPO3_CONF_VARS']['FE']['accessRestrictedPages_handling_redirectPageID'] . '&redirect_url=' . urlencode($params['currentUrl']),
                $GLOBALS['TYPO3_CONF_VARS']['FE']['accessRestrictedPages_handling_statheader'],
                $params['pageAccessFailureReasons']['reasonText']
            );
        // 404 not found
        } else {
            // handle default language
            $pObj->pageErrorHandler('/index.php?id=' . $GLOBALS['TYPO3_CONF_VARS']['FE']['pageNotFound_handling_redirectPageID'] . (array_key_exists('L', $_GET) ? '&L=' . $_GET['L'] : ''));
        }
    }
}

Als Extension für den Login wird felogin verwendet. Diese Erweiterung muss noch so konfiguriert sein, dass sie auf den Parameter „redirect_url“ hört, der in der URL übermittelt wird. Dazu wählt man Option „Definiert durch GET- oder POST-Variablen“ für den Weiterleitungsmodus aus.

Getestet mit TYPO3 4.7

Thema: TYPO3 | Kommentare (3)