Simple recursive PHP function to build a HTML <ul> list from array

   
    /**
     * @param $array
     * @return string
     */
    function buildHtmlList($array)
    {
        $out = '<ul>';
        foreach($array as $key => $v) {
            if( is_array($v) ) {
                $out .= '<li>' . $key ;
                $out  .= buildHtmlList($v);
                $out .= '</li>';
                continue;
            } else {
                $out .= '<li>' . $array[$key] . '</li>';
            }
        }
        $out .= '</ul>';
        return $out;
    }
 
     $array = array(
         'Item 1' => array(
             'Sub Item 1' => array(
               'Sub Sub Item 1'
             ),
         ),
         'Item 2' => array(
             'Sub Item 2' => array(
                 'Sub Sub Item 2'
           ),
         ),
         'Item 3',
     );

     $result = buildHtmlList($array);

Result

  • Item 1
    • Sub Item 1
      • Sub Sub Item 1
  • Item 2
    • Sub Item 2
      • Sub Sub Item 2
  • Item 3

Or with class names

    
/**
 * @param array $array
 * @param array $classes
 * @param int $level
 * @return string
 */
function buildHtmlList($array,$classes='',$level=0)
{
    $out = '<ul>';
    if(!empty($classes)) {
        $out = '<ul'.$classes[$level].'>';
    }
    foreach($array as $key => $value) {
        if( is_array($value) ) {
            $i = $level+1;
            $out .= "<li>" . $key ;
            $out .= $this->buildHtmlList($value,$classes,$i);
            $out .= '</li>';
            continue;
        } else {
            $out .= "<li>" . $array[$key] . "</li>";
        }
    }
    $out .= "</ul>";
    return $out;
}
$arr = array(
    'Item 1' => array(
        'Sub Item 1' => array(
            'Sub Sub Item 1'
        ),
    ),
    'Item 2' => array(
        'Sub Item 2' => array(
            'Sub Sub Item 2'
        ),
    ),
    'Item 3',
);
$classes = array(
    ' class="level-1"',
    ' class="level-2"',
    ' class="level-3"'
);
$result = buildHtmlList($arr,$classes);

Result

<ul class="level-1">
    <li>Item 1
        <ul class="level-2">
            <li>Sub Item 1
                <ul class="level-3">
                    <li>Sub Sub Item 1</li>
                </ul>
            </li>
        </ul>
    </li>
    <li>Item 2
        <ul class="level-2">
            <li>Sub Item 2
                <ul class="level-3">
                    <li>Sub Sub Item 2</li>
                </ul>
            </li>
        </ul>
    </li>
    <li>Item 3</li>
</ul>

Einfache TYPO3 Entwicklung mit Docker

Docker

Als ich vor ein paar Tagen meine erste Entwicklungsumgebung, mit Docker für TYPO3 anlegen wollte, bekam ich zunächst Probleme bei der Installation von Docker for Mac. Meine CPU ist zu alt und wird von der aktuellen Docker Version für Mac nicht unterstützt. Recht schnell fand ich Docker Desktop, welches scheinbar speziell für ältere Rechner zur Verfügung gestellt wird. Cool, Docker läuft.

Für TYPO3 fand ich das Image martinhelmich/typo3. Martin beschreibt sehr gut in seinem Blog wie man damit umgeht. Was er leider nicht verrät, ist wie man damit Dateien auf dem Host bearbeiten kann. In den Kommentaren findet sich zwar ein Ansatz:

$ docker run -d --name typo3-web --link typo3-db:db \
    --volume /pfad/zum/projekt/typo3conf:/var/www/typo3conf \
    --volume /pfad/zum/projekt/fileadmin:/var/www/fileadmin \
    --volume /pfad/zum/projekt/uploads:/var/www/uploads
 

Und damit werden die Host Verzeichnisse auch in den Container eingebunden, aber die Rechte der Verzeichnisse passen nicht, da die Rechte des Hosts übernommen werden. Sehr ärgerlich, denn mit einem readonly /typo3conf kann man nicht viel mit TYPO3 anfangen.

Aber man muss ja auch gar nicht das komplette /typo3conf mounten. Mir genügt es wenn ich meine Extension Verzeichnisse auf dem Host anlegen kann und sie einzeln in das Container /typo3conf Verzeichnis mounte.

$ docker run -d --name typo3-web --link typo3-db:db \
    --volume /pfad/zum/projekt/typo3conf/my_new_extension:/var/www/typo3conf my_new_extension
 

Container Daten auf den Host kopieren:

docker cp ###deine_container_id###:/var/www/html/fileadmin/introduction/ /pfad/zum/projekt/
 

Damit ich nun nicht immer meine Container einzeln starten muss, habe ich mir diese docker-compose.yml angelegt.

version: "2"
services:
  mysql:
    image: ${DB_IMAGE}
    container_name: ${APP_NAME}_database
    command:
      - --character-set-server=utf8
      - --collation-server=utf8_unicode_ci
    environment:
      - "MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}"
      - "MYSQL_DATABASE=${DB_NAME}"
      - "MYSQL_USER=${DB_USER}"
      - "MYSQL_PASSWORD=${DB_PASSWORD}"
    volumes: 
      - database:/var/lib/mysql   
  extensions:
    image: busybox
    container_name: ${APP_NAME}_extensions
    volumes:
      - ./Extensions/lgv_site_package:/var/www/html/typo3conf/ext/lgv_site_package
  typo3:
    image: martinhelmich/typo3:${TYPO3_VERSION}
    container_name: ${APP_NAME}_typo3_${TYPO3_VERSION}
    ports:
      - ${APP_PORT}:80
    volumes:
      - fileadmin:/var/www/html/fileadmin
      - typo3conf:/var/www/html/typo3conf
      - uploads:/var/www/html/uploads
    volumes_from:
      - extensions
    links: 
      - mysql:db
volumes:
  database:
  fileadmin:
  typo3conf:
  uploads:
 
APP_NAME=T3_Docker
APP_PORT=80
TYPO3_VERSION=latest
DB_IMAGE=mysql:5.7
DB_ROOT_PASSWORD=root
DB_NAME=typo3
DB_USER=typo3
DB_PASSWORD=typo3

Wie anfangs erwähnt ist mein MAC schon etwas älter. Bislang habe ich meine lokale Entwicklung mit MAMP umgesetzt. Aktuell stand ich aber vor einem Problem. TYPO V9 benötigt PHP 7.2. Aber PHP 7.2 ist mit meinem auch etwas älterem MAMP nicht verfügbar. Dank Docker ist das alles nun kein Problem mehr.

sys_file_reference mit Datahandler erzeugen

Wer mit Extbase zB. einen Datei-Upload im Frontend umsetzen will, merkt schnell wie tricky das sein kann. Meist landet man früher oder später bei Helmut Hummel’s Upload Example (https://github.com/helhum/upload_example). Ich habe aber trotzdem einige Zeit benötigt um es zum Laufen zu bringen.

Dmitry Dulepov hat mir vor 2 Tagen gezeigt, wie man das sehr viel einfacher umsetzen kann:
https://stackoverflow.com/questions/54695460/problems-with-…

protected function createFileReference($contentUid, $pid, $fieldName, File $file)
{
$data = [
'sys_file_reference' => [
StringUtility::getUniqueId('NEW') => [
'table_local' => 'sys_file',
'uid_local' => $file->getProperty('uid'),
'tablenames' => 'tt_content',
'uid_foreign' => $contentUid,
'fieldname' => $fieldName,
'pid' => $pid,
]
]
];
$dataHandler = GeneralUtility::makeInstance(DataHandler::class);
$dataHandler->start($data, []);
$dataHandler->admin = true;
$dataHandler->process_datamap();
}

Mit Extbase Pages Media Resources auslesen

Im Controller oder Repository:

public function findFileFromPageMedia( $pid ){
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
$fileRepository = $objectManager->get('TYPO3\CMS\Core\Resource\FileRepository');
$fileObjects = $fileRepository->findByRelation('pages', 'media', $pid);
// gibt Image Object Information
$files = array();
foreach ($fileObjects as $key => $value) {
$files[$key]['reference'] = $value->getReferenceProperties();
$files[$key]['original'] = $value->getOriginalFile()->getProperties();
}
return $files;
}

Fluid Template:

<f :image src="{result.image.0.reference.uid}" alt="" width="70c" height="70c" treatIdAsReference="1" />

Mit Extbase die Tabelle Pages erweitern

extTables.sql

#
# Modifying pages table
#
CREATE TABLE pages (
check_in_out varchar(255) DEFAULT '' NOT NULL,
price varchar(255) DEFAULT '' NOT NULL,
persons int(11) unsigned DEFAULT '0' NOT NULL,
disabled_access tinyint(4) unsigned DEFAULT '0' NOT NULL,
children tinyint(4) unsigned DEFAULT '0' NOT NULL,
use_as_room tinyint(4) unsigned DEFAULT '0' NOT NULL,
dinner tinyint(4) unsigned DEFAULT '0' NOT NULL,
breakfast tinyint(4) unsigned DEFAULT '0' NOT NULL,
);

Configuration/TCA/Overrides/pages.php

< ?php if (!defined('TYPO3_MODE')) { die ('Access denied.'); } // Configure new fields: $fields = array( 'check_in_out' => array(
'label' => 'Buchungen',
'exclude' => 1,
'config' => array(
'type' => 'inline',
'foreign_table' => 'tx_accomodation_domain_model_dates',
'maxitems' => 999,
'appearance' => array(
'collapseAll' => 1,
'expandSingle' => 1,
),
),
),
'price' => array(
'exclude' => 1,
'label' => 'Preis',
'config' => array(
'type' => 'input',
'default' => 0,
'eval' => 'double2'
)
),
'persons' => array(
'exclude' => 1,
'label' => 'Anzahl Personen',
'config' => array(
'type' => 'input',
'default' => 0
)
),
'children' => array(
'exclude' => 1,
'label' => 'Kinder',
'config' => array(
'type' => 'check',
'default' => 0
)
),
'disabled_access' => array(
'exclude' => 1,
'label' => 'Behindertengerecht',
'config' => array(
'type' => 'check',
'default' => 0
)
),
'use_as_room' => array(
'exclude' => 1,
'label' => 'Seite als Zimmer verwenden?',
'config' => array(
'type' => 'check',
'default' => 0
)
),
'breakfast' => array(
'exclude' => 1,
'label' => 'Frühstück',
'config' => array(
'type' => 'check',
'default' => 0
)
),
'dinner' => array(
'exclude' => 1,
'label' => 'Abendbrot',
'config' => array(
'type' => 'check',
'default' => 0
)
),
);
// Add new fields to pages:
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('pages', $fields);
// Make fields visible in the TCEforms:
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes(
'pages', // Table name
'--div--;Buchungskalender;accomodation', // Field list to add
'', // List of specific types to add the field list to. (If empty, all type entries are affected)
'' // Insert fields before (default) or after one, or replace a field
);
// Add the new palette:
$GLOBALS['TCA']['pages']['palettes']['accomodation'] = array(
'showitem' => 'use_as_room,--linebreak--,check_in_out,--linebreak--,price,persons,--linebreak--,disabled_access,children,dinner,breakfast,'
);

JQuery Carousel TYPO3 Plugin

Ich habe das Agile Carousel jQuery Plugin in TYPO3 als Extension eingebunden. Konfiguriert wird das Plugin über eine einfache Flexform.

Flexform der Extension

Dem Plugin wird der Pfad zu einem Verzeichnis übergeben in welchem sich Bilder, Flashfilme oder HTML Dateien befinden. Alle Einzelheiten gibts es hier zu lesen.

Download: agile_carousel-1_0_0.t3x ( Downloads)

TYPO3 PHP/AJAX Lightbox Galerie

Wir haben ein kleines Galerie Plugin für TYPO3 geschrieben

Features :

  • Klickvergrösserung via Lightbox JS v2.0
  • Konfiguration über Flexform
  • läuft als Ajax oderPhp Anwendung (wählbar überFlexform)
  • erkennt automatisch clientseitig aktives Javascript ( bei deaktivietem JS automatisches Fallback zur Php Version)
  • Frontent Miniconsole für clientseitige Konfigurationen

Demoversion ansehen

Screenshot

Screenshot

Screenshot

Screenshot

Screenshot

Screenshot

Download der Extension

Downloads: