Typo3: TCA Default-Werte dynamisch setzen, per TSConfig oder Script

Problem: Man möchte, dass beim Anlegen eines neuen Datensatzes in Typo3 (z.B. News- oder Kalender-Eintrag) im Backend automatisch bestimmte Default-Werte für die Eingabefelder (TCA) gesetzt werden. Die default-Werte des TCA sollen sich aber dynamisch ändern, z.B. abhängig von der aktuell gewählten Seite (pid).

Anwendungsbeispiel: Mehrere Redakteure legen News für unterschiedliche Zentren an. Für jedes Zentrum gibt es einen eigenen SysFolder. Abhängig von Ordner soll die News direkt einer bestimmten News-Kategorie zugeordnet werden.

Für Suchmaschinen: Setzen von default-Werten TCA Typo3. Typo3 dynamically set default TCA values with TypoScript. Hook Signal Slot for setting TCA default value. News (tx_news) automatisch einer News-Kategorie / sys_category zuweisen, abhängig von der pid. SysFolder automatisch bestimmte default-Werte oder News-Kategorie. TCAdefaults per Hook setzen. TCA default-Werte dynamisch in Signal Slot setzen. Typo3 7.6 FormEngine getSingleField_preProcess getSingleFieldClass Hook. Typo3 TCA default Werte dynamisch per Script setzen, abhängig von der pid aktueller Seite.

Einfache Anwendungsfälle

Lösung per PageCondition in page TSconfig mit TCAdefaults

Definition in der pageTsConfig: Beim Durchlesen der Typo3 Dokumentation zu dem Thema klingt die page TSconfig für TCEFORM zunächst relativ vielversprechend:

TCEFORM.[table name].[field].config.[key] = Wert

Diese Einstellung funktioniert allerdings nur, wenn man damit z.B. die Anzahl der Zeilen eines Textfeldes ändern möchte, hier am Beispiel der Extension News (tx_news):

TCEFORM.tx_news_domain_model_news.title.config.type = text
TCEFORM.tx_news_domain_model_news.title.config.rows = 10

Irreführend ist, dass das Setzen eines default-Wertes damit nicht möglich, dafür aber mit TCAdefaults:

# No chance!!
TCEFORM.tx_news_domain_model_news.title.config.default = Mein Default-Titel
# So geht es:
TCAdefaults.tx_news_domain_model_news.title = Wundervoll!

Mit Hilfe einer einfache Page-Condition kann damit die Aufgabe für simple Anwendungsfälle gelöst werden:

[PIDinRootline = 21]
   TCAdefaults.tx_deineextension_domain_model_entry.title = Artikel auf Seite 21
[PIDinRootline = 23]
   TCAdefaults.tx_deineextension_domain_model_entry.title = Artikel auf Seite 23
[global]

Kleines Wunder nebenbei: das Setzen der Werte funktioniert auch mit MM-Relationen, z.B. für sys_category! Solle eine News direkt bestimmten sys_category-Kategorien zugeordnet werden, kann das über eine kommaseparierte Liste mit den uids der sys_category gemacht werden:

TCAdefaults.tx_news_domain_model_news.categories = 1,2,7

Hier ein Beispiel, wie die Extension tx_news für eine Jobbörse „mißbraucht“ werden kann: In einem bestimmten Ast des Seitenbaums (pid = 118) werden verschiedene Labels für den News-Datensatz geändert bzw. ausgeblendet, um für den Redakteur eine möglichst klare Darstellung zu erreichen. Dieses Script muss in die page TSconfig:

[PIDinRootline = 118]
   TCEFORM.tx_news_domain_model_news {
      title.label = Stellenname
      teaser.label = Arbeitgeber und Ort
      istopnews.disabled = 1
      author.disabled = 1
      author_email.disabled = 1
      datetime.disabled = 1
      archive.disabled = 1
   }
   TCAdefaults.tx_news_domain_model_news {
      type = 2
   }
[global]

Komplexere Anwendungsfälle

Lösung per Hook – bis Typo3 Version 4.7

Wie in einem schönen Artikel von Irene Höppner beschrieben, gab es bis zu Typo3 Version 4.7 einen wundervollen Hook (getSingleField_preProcess bzw. getSingleFieldClass), um das Problem zu lösen. Ein Artikel auf StackOverflow bringt die Lösung auf den Punkt: tt_news Autor automatisch per Hook setzen
Seit dem Einsatz der neuen FormEngine wurden aber ersatzlos alle Hooks und Signal/Slots entfernt.

Stefan Frömken schlägt für Typo3 > 6.2 eine modernere Lösung vor, die sich aber für die meisten Anwendungsfälle etwas zu aufwändig anfühlt.

Lösung per dynamischem User TSconfig in der ext_localconf.php

In einem Artikel von Netzhaut beschrieben, besteht die Möglichkeit, dass User TSconfig dynamisch einzubinden. Das erlaubt z.B. auch die Verwendung von PHP Code.

Entgegen des TCA (dessen final generiertes Array im Cache landet), wird der Inhalt der ext_localconf.php bei jedem Seitenaufruf im Backend neu gerendert. Dadurch wird in dem Beispiel der TimeStamp jedes Mal neu generiert:

Dazu kommt diese Zeile in die ext_localconf.php der eigenen Extension:

 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addUserTSConfig(
   'TCAdefaults.tx_nnportfolio_domain_model_entry.title = Aktueller tstamp: '.mktime()
);

Lösung per dynamischem Page TSconfig in der ext_localconf.php

Das Gleiche funktioniert mit einer dynamischen Erweiterung der PageTSconfig:

\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPageTSConfig(
   'TCAdefaults.tx_nnportfolio_domain_model_entry.title = Aktueller tstamp: '.mktime()
);

Maximal komplexe Anwendungsfälle

Wem das noch nicht reicht, der könnte das Problem noch deutlich flexibler lösen. In folgendem Beispiel sollen die Default-Werte für einen Datensatz per TypoScript-Setup definierbar sein. Dazu definieren wir alle Default-Werte im Setup – key ist dabei die pid der entsprechenden Seite:

plugin.tx_nnportfolio_nnportfolio {
   settings {
      defaultValuesByPid {
         21 {
            title = Hallo! Du bist auf Seite 21.
            addresses = 2,3
            categories = 1,2,3,4,5
         }
         23 {
            title = Das ist Seite 23.
            addresses = 1
            categories = 5
         }

      }      
   }
}

In die ext_tables.php kommt eine Funktion, die unseren eigenen „Hook“ aufruft und die TCA-Spalten für unsere Extension übergibt:

if (TYPO3_MODE == 'BE') {
   \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('Nng\\Nnportfolio\\Hooks\\TCAdefaultValuesHook')
      ->setDefaultValuesFromTS( $GLOBALS['TCA']['tx_nnportfolio_domain_model_entry']['columns'] );
}

Dann fehlt nur noch der entsprechende Hook. Er enthält einige zusätzliche Methoden, um im Backend an das TypoScript Setup für die aktuell ausgewählte Seite zu kommen.


getRootLine($pageUid);
      
      $TSObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\ExtendedTemplateService');
      $TSObj->tt_track = 0;
      $TSObj->init();
      $TSObj->runThroughTemplates($rootLine);
      $TSObj->generateConfig();

      $typoscriptService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\Extbase\\Service\\TypoScriptService');

      return $typoscriptService->convertTypoScriptArrayToPlainArray(
         (array) $TSObj->setup['plugin.']['tx_nnportfolio_nnportfolio.']
      );
      
   }
   
   /**
   *   Get current PID in backend.
   *   Uses various fallbacks depending on current view and backend module.
   *   ToDo: Ask somebody, how this can be done simple :)
   */
   public static function get_current_pid ( $pageUid = null ) {
      if (!$pageUid) $pageUid = (int) $GLOBALS['_REQUEST']['popViewId'];
      if (!$pageUid) $pageUid = (int) preg_replace( '/(.*)(id=)([0-9]*)(.*)/i', '\\3', $GLOBALS['_REQUEST']['returnUrl'] );
      if (!$pageUid) $pageUid = (int) preg_replace( '/(.*)(id=)([0-9]*)(.*)/i', '\\3', $GLOBALS['_POST']['returnUrl'] );
      if (!$pageUid) $pageUid = (int) preg_replace( '/(.*)(id=)([0-9]*)(.*)/i', '\\3', $GLOBALS['_GET']['returnUrl'] );
      if (!$pageUid) $pageUid = (int) $GLOBALS['TSFE']->id;
      if (!$pageUid) $pageUid = (int) $_GET['id'];
      if (!$pageUid) {
         list($page) = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordsByField('pages', 'pid', 0);
          $pageUid = intval($page['uid']);
      }
      return $pageUid;
   }
   

   /**
   *   Set TCA default value from TypoScript setup
   *
   */
   public static function setDefaultValuesFromTS ( &$columns ) {
      
      $settings = self::getTsSetup();
      $pid = self::get_current_pid();
      
      if ($defaultValuesByPid = $settings['settings']['defaultValuesByPid'][$pid]) {      
         foreach ($defaultValuesByPid as $k=>$v) {
            $columns[$k]['config']['default'] = $v;
         }
      }
   }
   
      
}

Grunt auf Mac installieren

Schnelldurchlauf, um auf Mac OSX (10.11 El Capitan) Grunt zu installieren. Vielen Dank an Martin Wagner für die Starthilfe!

1. NodeJS/npm Installer für Mac downloaden und installieren:

https://nodejs.org/en/download/

2. Im Terminal diese Befehle ausführen:

sudo npm update -g npm
sudo npm install -g grunt-cli

3. Config-Dateien anlegen

Ins Projekt-Verzeichnis gehen und in der Root diese beiden Dateien anlegen:
package.json

{
  "name": "testgrunt",
  "version": "1.0.0",
  "description": "MyTest",
  "main": "index.html",
  "scripts": {
    "test": ""
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "grunt": "^1.0.1",
    "grunt-autoprefixer": "^3.0.4",
    "grunt-bootstrap": "^0.1.0",
    "grunt-bootstrap-prefix": "^0.1.0",
    "grunt-contrib-uglify": "^1.0.1",
    "grunt-contrib-watch": "^1.0.0",
    "grunt-css-prefix": "^0.2.3",
    "grunt-sass": "^1.2.0"
  }
}

gruntfile.js (Pfade müssen angepasst werden)

module.exports = function(grunt) {
	
	// Configure task(s)
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		
		uglify: {
			build: {
				src: 'grunt_test/js/*.js',
				dest: 'grunt_test/ugliy-js.js'
			},
			dev: {
				options: {
					beautify: true,
					mangle: false,
					compress: false,
					preserveComments: 'all'
				},
				src: 'grunt_test/js/*.js',
				dest: 'grunt_test/ugliy-dev-js.js'
			}
		},
		
		watch: {
			options: {
				livereload: true,
			},
			js: {
				files: ['grunt_test/**/*.js'],
				tasks: ['uglify:dev']
			
			},
			html: {
				files: ['grunt_test/**/*.html']

			},
			css: {
				files: ['grunt_test/**/*.scss'],
				tasks: ['sass:dev']
			},
			typoscript: {
				files: ['grunt_test/**/*.ts']
			}
		},
		sass: {
			dev: {
				options: {
					outputStyle: 'expanded'
				},
				files: {
					'grunt_test/dev-merged.css' : 'grunt_test/scss/main.scss',
					// 'css/bootstrap.css' : 'src/scss/bootstrap.scss'
				}
			},
			build: {
				options: {
					outputStyle: 'compressed'
				},
				files: {
					'grunt_test/merged.css' : 'grunt_test/scss/main.scss',
					// 'css/bootstrap.css' : 'src/scss/bootstrap.scss'
				}
			}
		},
	});

	
	// Load PlugIns
	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-sass');
	
	// Register Tasks
	// grunt.registerTask('default', ['uglify:dev', 'sass:dev', 'watch']);
	// grunt.registerTask('build', ['uglify:build', 'sass:build', 'watch']);

	grunt.registerTask('default', ['uglify:dev', 'sass:dev']);
	grunt.registerTask('build', ['uglify:build', 'sass:build']);

};

4. Grunt initialisieren

Per Terminal ins Projektverzeichnis wechseln und das hier ausführen:

npm install
npm install grunt --save-dev

5. Befehle testen

Ab dann können folgende Befehle ausgeführt werden:

grunt (alle dateien uncompressed etc…)
grunt build (alles fertig für live version)
grunt watch (beobachten im Browser, dazu dann die Seite im Browser nochmal nach neu laden per Hand, danach übernimmt „Liverelad“ das Neuladen)

„Live-Reload“ Chrome-PlugIn installieren:
https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei

Typo3 hreflang-Metatag per TypoScript erstellen

SEO in Typo3: Mit Hilfe des hreflang-Tags kann man Google verständlich machen, dass die gewählte Seite in anderen Sprachen existiert. Hier eine Möglichkeit den hreflang-Tag inklusive des x-default-Tags per TypoScript zu generieren. Dabei wird der x-default-Tag auf „EN“ (L=1) gestellt, falls eine Englische Übersetzung der Sprache existiert und auf „DE“ (L=0), falls die Seite „EN“ nicht existiert.

page.headerData.22 = HMENU
page.headerData.22 {
   
   special = language
   special.normalWhenNoLanguage = 0
   special.value = 0,1,2,3,4,5,6,7,8,9,10
   
   1 = TMENU
   1 {
      NO = 1
      NO {
         stdWrap.cObject = TEXT
         stdWrap.cObject {   
            value = de || en || nl || ru || tr || dk || fr || it || sw || no || es
         }
         linkWrap = 
            }
            stdWrap.typolink.parameter.data = page:uid
            stdWrap.typolink.additionalParams = &L=0 || &L=1 || &L=2 || &L=3 || &L=4 || &L=5 || &L=6 || &L=7 || &L=8 || &L=9 || &L=10
            stdWrap.typolink.returnLast = url
         }

         before.cObject = TEXT
         before.cObject {
            stdWrap.wrap.cObject = TEXT
            stdWrap.wrap.cObject {
               value =
               stdWrap.wrap = ||  || || || || || || || ||
               stdWrap.typolink.additionalParams = &L=1
               stdWrap.typolink.parameter.data = page:uid
               stdWrap.typolink.returnLast = url
               stdWrap.typolink.forceAbsoluteUrl = 1

               if.isTrue.cObject = TEXT
               if.isTrue.cObject.stdWrap.wrap = || 1 || ||
            }
         }
      }
      
      CUR = 1
      CUR {
         doNotShowLink = 1
      }
      
      # Seite existiert nicht in Übersetzung!
      USERDEF1 < .NO
      USERDEF1 {
         doNotShowLink = 1
         doNotLinkIt = 1
         linkWrap >
         stdWrap >
         after >
         before.cObject {
            stdWrap.wrap.cObject {
               stdWrap.typolink.additionalParams = &L=0
            }
         }
      }
   }
}

Typo3 DCE – Dynamic Content Elements – Spickzettel


Überschrift (header) in DCE nutzen

Den normalen Header der Inhaltselemente inkl. der Felder für Header-Layout (header_layout), Header-Ausrichtung (header_align) im DCE nutzen.

Im DCE unter dem Reiter Miscellaneous / Sonstiges in das Feld DCE palette fields folgendes eintragen:

header,--linebreak--,header_layout,header_position,--linebreak--,header_link,--linebreak--,subheader,--linebreak--,sys_language_uid,l18n_parent,colPos,spaceBefore,spaceAfter,section_frame,hidden

Und dann im Fluid-Template diese Anweisung zum Rendern nutzen:



The package „cdsrc_sass“ depends on „leafo/scssphp“ which is not present in the system

Beim Update der Typo3 Extension cdsrc_sass erscheint – abhängig von der Server-Umgebung – in der Version 2.0 die Fehlermeldung „The package „cdsrc_sass“ depends on „leafo/scssphp“ which is not present in the system“. Dadurch ist der Extension-Manager im Backend nicht mehr aufrufbar.

Um das Problem zu lösen, einfach in dem Ordner typo3conf/ext/cdsrc_sass die Datei composer.json löschen und den Typo3 Konfigurations-Cache leeren. Danach läuft alles wieder problemlos.

Typo3 page / pages_language_overlay um eigenes Feld erweitern, mit slide per TypoScript vererben

Aufgabe: Man möchte bei Typo3 in die Seiteneigenschaften einer Seite ein Feld ergänzen, z.B. eine Telefon-Nummer. Dieses Feld soll auf die Unterseiten per slide vererbt werden, wenn in einem Auswahlfeld der Wert „zeigen“ gewählt wurde. Wählt man in dem Auswahlfeld nichts aus, wird die Einstellung der darüberliegenden Seite verwendet. Dadurch kann für einen Ast im Seitenbaum die Einstellung der darüberliegenden Seite komplett überschrieben werden.

Das Auswahlfeld soll für alle Sprachen gelten (ist also nur in der Tabelle „pages“ vorhanden), das Textfeld für die Telefon-Nummer soll aber für jede Sprache getrennt voneinander angegeben werden können.

Das alles hier spiel sich in einer eigenen Extension ab.

Für Suchmaschinen: pageoverlayfields typo3, Seiteneigenschaften um eigenes Feld erweitern. Mehrsprachigkeit und sys_language_overlay bei eigenem Feld der Tabelle pages. levelfield mit slide bei eigenem Feld und Mehrsprachigkeit. pageOverlayFields und addRootLineFields um Wert auf Unterseiten zu vererben und mit slide per TypoScript auslesen. Tabelle pages_language_overlay um eigenes Feld erweitern. Mehrsprachigkeit bei eigenem Feld der Tabelle pages wird nicht angezeigt. Problem mit slide mit localization von pages_language_overlay. Tabellen pages, pages_language_overlay erweitern und das neue Feld slide-bar machen.

Wonach ich alles gesucht habe: „page field language_overlay typoscript typo3“, „languageOverlay typo3 tca“, „page typo3 field overlay language“, „typo3 slide typo3script text“, „addToAllTCAtypes(‚pages_language_overlay'“, „addToAllTCAtypes pages_language_overlay“, „page field language_overlay typoscript typo3“


Am Ende soll das ganze so aussehen:

Seiteneigenschaften in der Standard-Sprache
Hier sind zwei Felder: phone_btn zur Auswahl, ob das Feld angezeigt werden soll und phone_text mit der eigentlichen Texteingabe. Beide Felder sind neue Felder der Datenbank-Tabelle pages.

Seiteneigenschaften in den fremden (lokalisierten) Sprachversionen
Hier gibt es nur das Feld phone_text. Dieses Feld wurde der Tabelle pages_language_overlay hinzugefügt.


ext_tables.sql

CREATE TABLE pages (
   phone_btn varchar(15) DEFAULT '' NOT NULL,
   phone_text varchar(255) DEFAULT '' NOT NULL
);

CREATE TABLE pages_language_overlay (
   phone_text varchar(255) DEFAULT '' NOT NULL
);

ext_tables.php

// Feld, das nur in der Standardsprache existiert
$addPagesColumn = array (
   'phone_btn' => array(
      'exclude' => 0,
      'label' => 'Telefon-Nr zeigen',
      'config' => array(
         'type' => 'select',
         'default' => '',
         'items' => array(
            array('', ''),
            array('nicht zeigen', '-1'),
            array('zeigen', '1'),
         )
      ),
   ),
);

// Feld, das in allen Sprachen existiert
$addLangPagesColumn = array(
   'phone_text' => array(
      'exclude' => 0,
      'label' => 'Telefon-Nr',
      'config' => array(
         'type' => 'input',
         'default' => '',
      ),
   ),
);

// Feld im TCA der Tabelle 'pages' hinzufügen
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('pages',$addPagesColumn,1);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('pages',$addLangPagesColumn,1);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('pages_language_overlay',$addLangPagesColumn,1);

// Ort der Feldes in den Backendeinstellungen definieren
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addFieldsToPalette('pages', 'layout', '--linebreak--,phone_btn,phone_text', '');
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('pages_language_overlay', '--linebreak--,phone_text');

ext_localconf.php

$rootlinefields = &$GLOBALS["TYPO3_CONF_VARS"]["FE"]["addRootLineFields"];
if($rootlinefields != '') $rootlinefields .= ' , ';
$rootlinefields .= 'phone_btn,phone_text';

$GLOBALS['TYPO3_CONF_VARS']['FE']['pageOverlayFields'] .= ',phone_text';

TypoScript Setup Beispiel

lib.phone_text = TEXT
lib.phone_text {
    override.data = levelfield:-1, phone_text, slide
    override.if.isPositive.cObject = TEXT
    override.if.isPositive.cObject {
       data = levelfield:-1, phone_btn, slide
    }
}

Bidirektionale MM-Relation in Typo3 (ab Version 6.2). Feld wird nicht gespeichert, Feld bleibt leer. uid_local und uid_foreign vertauscht.

Problem: Man hat eine MM-Tabelle in Typo3 angelegt, z.B. um eine Verbindung zwischen den Tabellen „Firma“ und „Mitarbeiter“ zu schaffen. Beim Bearbeiten eines Datensatzes „Firma“ möchte man Mitarbeiter auswählen können. Anders herum (bidirektional) soll man beim Öffnen eines Datensatzes „Mitarbeiter“ sehen können, welchen Firmen er zugeordnet wurde und auch von dieser Seite aus die MM-Relation bearbeiten können. Man kann die MM-Relation also von beiden Seiten aus (bidirectional) bearbeiten.

Vorab: Ich habe sie alle probiert. Alle Tutorials die bei Google auftauchen, z.B.
http://de.kimpixel.wikia.com/wiki/TCA_Beispiele
http://blog.undkonsorten.com/datenbankrelationen-typo3-irre-extension
http://www.andreas-buergel.com/kb/typo3/typo3-mm-relation-beidseitig-in-extension.html
http://www.typo3tiger.de/blog/post/typo3-bidirektionale-mm-relation-tca-extbase.html
… und sie haben alle nicht funktioniert. Am Ende scheiterte es immer daran, dass beim Einfügen folgender Zeile ins TCA

'MM_opposite_field' => 'xxx'

keine Relationen mehr im dem bidirektionalen Datensatz gespeichert wurden. Das Feld blieb einfach leer. Wenn ich dagegen die Zeile auskommentiert hatte, wurden die uid_foreign und uid_local in der MM-Tabelle vertauscht.

Für Suchmaschinen: Typo3 bidirectional m:m relationship not working. Problem birdirektionale mm-Relation extbase. Bidrektionale MM-Relation Problem Feld wird nicht gespeichert. uid_local uid_foreign vertauscht. MM_opposite_field funktioniert nicht. MM-Datensätze beidseitig bearbeiten. uk Datenbank Tutorial Fehler. t3uk_db_tutorial für Typo3 6.2.

Lösung (Kurzversion)

:
1. Im TCA muss (neben dem Feld MM_opposite_field) zwingend die Einstellung ‚multiple‘ => ‚1‘ gesetzt werden

'multiple' => 1

2. In der MM-Tabelle muss es ein Feld für sorting_foreign geben:

sorting_foreign int(11) DEFAULT '0' NOT NULL

Lösung (Langversion und Beispiel)

Die entscheidenden Felder in der Tabelle ext_tables.sql:

#
# Die MM-Tabelle 'tx_beispiel_mitarbeiter_firma_mm'
#
CREATE TABLE tx_beispiel_mitarbeiter_firma_mm (
  uid_local int(11) DEFAULT '0' NOT NULL,
  uid_foreign int(11) DEFAULT '0' NOT NULL,
  tablenames varchar(30) DEFAULT '' NOT NULL,
  sorting int(11) DEFAULT '0' NOT NULL,
  sorting_foreign int(11) DEFAULT '0' NOT NULL,
  KEY uid_local (uid_local),
  KEY uid_foreign (uid_foreign)
);

#
# Die Tabelle für die Firmen
#
CREATE TABLE tx_beispiel_firma (
   ...
   mitarbeiter tinyint(1) DEFAULT '1' NOT NULL,
   ...
);

#
# Die Tabelle für die Mitarbeiter
#
CREATE TABLE tx_beispiel_mitarbeiter (
   ...
   firmen tinyint(1) DEFAULT '1' NOT NULL,
   ...
);

Die Feld-Definitionen im TCA für die Tabelle der Firma (tx_beispiel_firma). Hier ist entscheidend, dass ‚multiple‘ => 1 gesetzt ist:

'mitarbeiter' => array(
   'label'   => 'Mitarbeiter',
   'config' => array(
      'type' => 'select',            
      'size' => 10,
      'maxitems' => 9999,
      'autoSizeMax' => 10,
      'foreign_table' => 'fe_users',
      'multiple' => 1,
      'MM' => 'tx_beispiel_mitarbeiter_firma_mm',
   )
),

Die Feld-Definitionen im TCA für die Tabelle der Mitarbeiter (tx_beispiel_mitarbeiter). Hier ist entscheidend, dass ‚multiple‘ => 1 und ‚MM_opposite_field‘ => ‚mitarbeiter‘ gesetzt ist. ‚mitarbeiter‘ ist dabei der „gegenüberliegende“ Feld-Name in der Tabelle tx_beispiel_firma.

'firmen' => Array (
   'label' => 'Firmen',
   'config' => array(
      'type' => 'select',
      'size' => 10,
      'maxitems' => 9999,
      'multiple' => 1,
      'foreign_table' => 'tx_beispiel_firma',
      'MM' => 'tx_beispiel_mitarbeiter_firma_mm',
      'MM_opposite_field' => 'mitarbeiter',
   )
),

composer auf HostEurope Server installieren

So kann man composer auf einem HostEurope WebServer (hier: Dedicated WebServer Managed) installieren.

  1. Verzeichnis anlegen, z.B. „scripts“
  2. per SSH ins Verzeichnis wechseln
  3. curl -sS https://getcomposer.org/installer | php -d suhosin.executor.include.whitelist=phar
  4. Ins Verzeichnis wechseln, in welches das Alias genutzt werden soll
  5. alias composer=’php -d suhosin.executor.include.whitelist=phar,http://,https:// /is/htdocs/wp_xxx_xxx/scripts/composer/composer.phar‘ aufrufen (Pfad zum Verzeichnis entsprechend anpassen!)
  6. Alternativ (für PHP 5.6 bei HostEurope) alias composer=’php5.6 -d allow_url_fopen=1 -d suhosin.executor.include.whitelist=phar,http://,https:// /is/htdocs/wp_xxx_xxx/scripts/composer/composer.phar‘

Danach sollte composer über den Terminal normal aufrufbar sein, z.B. „composer require omnipay/omnipay:~2.0“

Konvertieren von Indesign-Dokumenten zu Photoshop mit Ebenen und editierbarem Text

Konvertieren von Indesign zu Photoshop

Für Suchmaschinen: Konvertieren von Indesign zu Photoshop. Indesign Texte als editierbare Texte in Photoshop kopieren. Indesign Ebenen zu Photoshop Ebenen. Convert Indesign layers to Photoshop layers. Indesign in Photoshop öffnen. Indesign kopieren von Textformaten in Photoshop. Exportieren aller InDesign Elemente als getrennte Ebenen in Photoshop. Convert Adobe InDesign Layers to Photoshop and keep text editable. indesign zu photoshop exportieren. Indesign Ebenen zu Photoshop exportieren. Indesign typesheet erstellen mit Übersicht aller Schriften in einem Dokument. Übersicht aller Schriften in InDesign Datei erstellen.

InDesign für Web- und App-Design?

In Zeiten der vektorbasierten SVGs und responsiven Webdesigns kommt es immer öfter vor, dass Designer für Ihre Layouts von Web + App nach InDesign oder Illustrator greifen.

Layout in diesen Programmen hat gegenüber Photoshop viele Vorteile:

  • Der Export zu SVGs ist möglich
  • Die Vektor-Funktionen sind schneller und leichter zu handhaben
  • Mehrere Objekte können auf einer Ebene sein – das Dokument bleibt deutlich übersichtlicher als eine PSD
  • Texte lassen sich schneller formatieren
  • Stilvorlagen, Absatzformate und Objektformate beschleunigen massiv die Arbeit
  • Mehrere Seiten innerhalb eines Dokumentes sind möglich

Dumm nur, wenn man 215 Seiten in InDesign gelayoutet hat und die Produktionsfirma oder Programmierer – aus welchen irrationalen Gründen auch immer – auf Photoshop-Dokumente mit Ebenen bestehen.

Nach einigen Recherchen im Netz haben wir keine wirklich brauchbare Lösung gefunden, die Elemente aus InDesign in Photoshop zu kopieren oder exportieren. Die perfekte Lösung wäre:

  • Es wird automatisch ein PSD Dokument erstellt mit den gleichen Pixelmaßen wie in InDesign
  • Beim Exportieren kann man selbst entscheiden, wann Elemente zu einem Smartobject gruppiert werden – oder auf seperaten Ebenen landen
  • Die Elemente werden pixelgenau platziert
  • Texte bleiben editierbar
  • Textformatierungen innerhalb eines Textabschnitts werden mit übernommen

Statt alles in einem Skript abzufertigen, haben wir uns für die Aufteilung in einzelne Teilfunktionen entschieden. Es sind zwar ein paar Klicks mehr – dafür hat man aber auch das Ergebnis besser unter Kontrolle und kann direkt in InDesign entscheiden, welche Elemente später in Photoshop als Gruppe / Smartobjekt und welche auf einer eigenen Ebene landen sollen.

Download

Paket mit allen nötigen Scripten downloaden

Installation (Mac)

1. Paket mit allen nötigen Scripten downloaden und Ordner entpacken.
2. Die Distiller Voreinstellung ExportToPS_bleedmarks durch Doppelklick installieren oder in den Ordner /Users/[NAME]/Library/Application Support/Adobe/Adobe PDF kopieren.
3. Alle jsx-Dateien aus dem Ordner scripts nach /Programme/Adobe InDesign CS6/Scripts/Scripts Panel kopieren
4. Den Ordner xtools nach /Programme/Adobe Photoshop CS6/ kopieren.

Tools nutzen

1. Indesign und Photoshop öffnen.
2. In InDesign das Skripte-Fenster öffnen unter Fenster -> Hilfsprogramme -> Skripte. Darin gibt es einen Ordner „Anwendung“ in dem die neuen jsx-Dateien auftauchen sollten. Falls nicht, InDesign neu starten.
3. InDesign-Datei öffnen. Darauf achten, dass InDesign als Farbraum sRGB und bei den Maßeinheiten überall auf Pixel steht.

Beschreibung der Tools

00 – Neues leeres PSD erstellt einfach ein leeres, neues PSD mit den gleichen Maßen wir das InDesign.
01 – Neues PSD mit Vorschau wie oben, zusätzlich wird eine Ebene mit Vorschau des InDesign-Dokumentes angelegt. Dient als Positionierungshilfe, falls etwas schief geht.
02 – Auswahl -> getrennte PSD Ebenen Macht aus jedem augewählten Objekt in InDesign eine eigene Photoshop-Ebene mit einem Smartobject.
03 – Auswahl -> eine PSD Ebene wie 02, aber die einzelnen Elemente werden zu einem Smartobject verschmolzen
04 – Text -> PSD Textfelder Konvertiert die Textfelder aus InDesign zu editierbaren Photoshop Textebenen
05 – Auswahl -> einzelne PDF, SVG, PNG Konvertiert jedes ausgewählte Element in InDesign zu einem eigenen PDF, SVG und PNG mit den Maßen des jeweiligen Elementes zzgl. etwas Platz (5 px) am Rand. Der Abstand kann in der JavaScript Datei sehr leicht angepasst werden.
06 – Elemente auf ganze Pixelwerte Bringt die ausgewählten Objekte auf exakte, gerundete Pixelwerte.
07 – TypeSheet erstellt ein neues InDesign-Dokument mit einer Übersicht aller verwendeten Schriften des Quell-Dokumentes. Legt eine neue Ebene im Quelldokument an und beschriftet die Textfelder mit Etiketten um die Schriften leichter zuordnen zu können.

Danke

Keine falschen Lorbeeren! Die Hälfte der Skripten ist aus dem Netz zusammengesucht und neu aufgemischt bzw. erweitert oder gefixed. Danke an die Community dafür!
https://www.oss-usa.com/blog/exporting-indesign-photoshop
https://github.com/fabiantheblind/extendscript/wiki/Pages-And-Margins
http://jongware.mit.edu/idcs4js/pc_DocumentPreference.html
http://www.adobe.com/content/dam/Adobe/en/devnet/indesign/cs5_docs/indesign_scripting/guide-en-US/InDesignCS5_ScriptingGuide_JS.pdf
https://forums.adobe.com/thread/456608