Zum Inhalt springen

File_Reference in GridElements via Flexform geht nicht?!

Erstellt am 22. November 2012 · 14 Antworten · letzte Antwort am 6. April 2013

Tags: FlexForms, Gridelements, Frage

Typo3Cuckoo ·

Hi,

ich versuche gerade in einem Gridelement ein neues Feld via Flexform für das Hinzufügen eines Bildes einzubauen.

Das Bild soll nicht hochgeladen werden können, sondern soll aus den vorhandenen Bildern ausgesucht werden. Dazu habe ich folgendes FLEXFORM in das Gridelement eingefügt:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3DataStructure>
	<ROOT>
		<type>array</type>
		<el>
			<image>
				<TCEforms>
					<label>Bild</label>
					<config>
						<type>group</type>
						<internal_type>file_reference</internal_type>
						<uploadfolder></uploadfolder>
						<allowed>jpg,gif,png</allowed>
						<max_size>10240</max_size>
						<show_thumbs>1</show_thumbs>
						<size>1</size>
						<minitems>0</minitems>
						<maxitems>1</maxitems>
					</config>
				</TCEforms>
			</image>
		</el>
	</ROOT>
</T3DataStructure>

Im Anhang seht ihr nun das Gridelement mit dem neuen Eingabefeld (linke Seite). Wenn ich ein Bild auswähle und auf Speichern klicke erscheinte diese Fehlermeldung (rechte Seite im Anhang). Die abgeschnittene Fehlermeldung in dem Kasten des Vorschaubildes lautet:

File is missing!
This content element references a file which seems to not exist: ..//is/htdocs/www/fileadmin/images/typo3_logo.png

Wieso bekomme ich hier den absoluten Pfad zu dem Bild und nicht den Pfad ab "fileadmin"?

Habe noch folgende Bug-Meldung mit einem ähnlichen Problem dazu gefunden, aber eine Lösung wurde da noch nicht gefunden: http://forge.typo3.org/issues/40839

Ich hab keine Ahnung was da passiert. Habt ihr diesen Fehler bei euch auch beobachten können? Stimmt meine Flexform Definition nicht?

gridelement_filereference.jpg

LuP ·

Hallo,

wie aus dem Bug-Eintrag hervorgeht, scheint es Probleme mit dem DS-Handling zu geben. Notfalls könntest Du versuchen, die DS direkt im TCA von tt_content zu setzen.

$GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config']['ds']['*,gridelements_pi1'] = 'hier Deine DS';

VG,
LuP

Typo3Cuckoo ·

Hi,

sorry für meine verspätete Rückmeldung.

Du meinst ich soll die komlette Flexform direkt da reinschreiben?

Gilt das dann nicht automatisch für alle Grid Elemente?

Typo3Cuckoo ·

Folgendes habe ich nun versucht, jedoch ohne Erfolg:

Bevor ich jetzt eine eigene Extension anlege, habe ich kurzerhand die Datei "/typo3conf/extTables.php" um folgendes erweitert:

$TCA['tt_content']['columns']['pi_flexform']['config']['ds']['*,gridelements_pi1'] = '<?xml version="1.0" encoding="utf-8"?>
<T3DataStructure>
      <meta>
            <langDisable>1</langDisable>
      </meta>
      <sheets>
            <sDEF>
                  <ROOT>
                        <TCEforms>
                              <sheetTitle>Content</sheetTitle>
                        </TCEforms>
                        <type>array</type>
                        <el>
                              <text>
                              <TCEforms>
                     <config>
                        <type>text</type>
                        <cols>40</cols>
                        <rows>5</rows>
                        <eval>trim</eval>
                     </config>
                     <label>Text</label>
                  </TCEforms>
               </text>
               <image>
                  <TCEforms>
                     <label>Bild</label>
                     <config>
                        <type>group</type>
                        <internal_type>file_reference</internal_type>
                        <uploadfolder></uploadfolder>
                        <allowed>jpg,gif,png</allowed>
                        <max_size>10240</max_size>
                        <show_thumbs>1</show_thumbs>
                        <size>1</size>
                        <minitems>0</minitems>
                        <maxitems>1</maxitems>
                     </config>
                  </TCEforms>
               </image>
            </el>
         </ROOT>
      </sDEF>
   </sheets>
</T3DataStructure>';

Im Backend unter "Admin Tools -> Configuration" sehe ich, dass die Änderung geladen wurde.

Dann habe ich das Flexform, was ich zuvor direkt im Backend in den Datensatz des Gridelements eingetragen hatte, entfernt.

Wenn ich jetzt ein neues Content Element vom Typ meines Gridelements anlege, sind alle Flexform Felder verschwunden. Der Bereich "Plugin Options" ist also leer.

Was habe ich falsch gemacht?

Typo3Cuckoo ·

Ok das konnte so gar nicht funktionieren #paralyzed#

In der Extension "gridelements" wird in der Klasse tx_gridelements_TCEformsHook (EXT:gridelements/lib/class.tx_gridelements_tceformshook.php) abgeprüft ob das Flexform Feld des Gridelements gefüllt ist. Wenn ja, dann wird der Inhalt dieses Feldes dem TCA Array übergeben, ansonsten wird ein vordefiniertes Flexform geladen (also eins ohne jegliche Felder). Das ganze ist ab Zeile 37 in der oben genannten Klasse zu finden.

Die IF-Abfrage in der Klasse sieht folgendermaßen aus:

<?php
if ($layoutSetup['pi_flexform_ds']) {
   $parentObject['fieldConf']['config']['ds']['*,gridelements_pi1'] = $layoutSetup['pi_flexform_ds'];
} else {
   $parentObject['fieldConf']['config']['ds']['*,gridelements_pi1'] = '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3DataStructure>
   <meta type="array">
      <langDisable>1</langDisable>
   </meta>
   <ROOT type="array">
      <tx_templavoila type="array">
         <title>ROOT</title>
      </tx_templavoila>
      <type>array</type>
      <el type="array">
         <field_content type="array">
            <TCEforms type="array">
               <config type="array">
                  <type>none</type>
               </config>
            </TCEforms>
         </field_content>
      </el>
   </ROOT>
</T3DataStructure>
';
}
?>

Ich habe jetzt einfach mal die IF-Abfrage umgangen und unterhalb folgendes eingefügt:

<?php
$parentObject['fieldConf']['config']['ds']['*,gridelements_pi1'] = '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3DataStructure>
   <meta>
      <langDisable>1</langDisable>
   </meta>
   <sheets>
      <sDEF>
         <ROOT>
            <TCEforms>
               <sheetTitle>Content</sheetTitle>
            </TCEforms>
            <type>array</type>
            <el>
               <text>
                  <TCEforms>
                     <config>
                        <type>text</type>
                        <cols>40</cols>
                        <rows>5</rows>
                        <eval>trim</eval>
                     </config>
                     <label>Text</label>
                  </TCEforms>
               </text>
               <image>
                  <TCEforms>
                     <label>Bild</label>
                     <config>
                        <type>group</type>
                        <internal_type>file_reference</internal_type>
                        <uploadfolder></uploadfolder>
                        <allowed>jpg,gif,png</allowed>
                        <max_size>10240</max_size>
                        <show_thumbs>1</show_thumbs>
                        <size>1</size>
                        <minitems>0</minitems>
                        <maxitems>1</maxitems>
                     </config>
                  </TCEforms>
               </image>
            </el>
         </ROOT>
      </sDEF>
   </sheets>
</T3DataStructure>';
?>

Nun werden meine Flexform Felder geladen.

Problem: Ich erhalte genau die gleiche Fehlermeldung wie oben beschrieben (siehe Screenshots in vorherigen Posts). Auch wird der Pfad zum Bild nach wie vor absolut angegeben.

Es hat also absolut nichts gebracht :x

Hoffe das Problem wird schnell gefixt!

LuP ·

Eins vorweg, wie ich in meinem ersten Post geschrieben habe, ist der von mir vorgeschlagene Ansatz nur für den Notfall gedacht und sollte nur als Notlösung dienen, bis der Bug gefixt wird.

Typo3Cuckoo schrieb

Du meinst ich soll die komlette Flexform direkt da reinschreiben?

nicht alles, nur die vom Feld image, das ja Probleme macht.

Typo3Cuckoo schrieb

Gilt das dann nicht automatisch für alle Grid Elemente?

ja. Wenn Du einzig der Admin bist und flexform pflegst, dürfte das nicht zu sehr stören.

Typo3Cuckoo schrieb

Bevor ich jetzt eine eigene Extension anlege, habe ich kurzerhand die Datei "/typo3conf/extTables.php" um folgendes erweitert:

Du brauchst hier nur die DS vom Feld image.

$GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config']['ds']['*,gridelements_pi1'] = '
    <T3DataStructure>
        <ROOT>
            <type>array</type>
            <el>
                <image>
                    <TCEforms>
                        <label>Bild</label>
                        <config>
                            <type>group</type>
                            <internal_type>file_reference</internal_type>
                            <uploadfolder></uploadfolder>
                            <allowed>jpg,gif,png</allowed>
                            <max_size>10240</max_size>
                            <show_thumbs>1</show_thumbs>
                            <size>1</size>
                            <minitems>0</minitems>
                            <maxitems>1</maxitems>
                        </config>
                    </TCEforms>
                </image>
            </el>
        </ROOT>
    </T3DataStructure>
';
Typo3Cuckoo schrieb

Dann habe ich das Flexform, was ich zuvor direkt im Backend in den Datensatz des Gridelements eingetragen hatte, entfernt.

Du darfst sie nicht entfernen.

VG,
LuP

Typo3Cuckoo ·

Danke für deine Rückmeldung. Hast du meinen letzten Beitrag gesehen? Auch wenn ich das Flexform hardgecoded in die Extension schreibe funktioniert das ganze nicht. Die Extension kommt mit Bildreferenzierungen nicht klar (und laut der Bug-Meldung anscheinend auch nicht, wenn man ein Bild hochlädt).

LuP ·

Anbei der Beweis, dass es bei mir mit dem o.g. Ansatz klappt.

Ein paar Eckdaten:

gridelements 1.3.12
TYPO3 4.6.15

VG,
LuP

gridelements_filereference_img.jpg

Typo3Cuckoo ·

Wow, das hat wirklich funktioniert! Aber wieso?

Meine Config sieht nun folgendermaßen so aus:

Im Flexform Feld des Datensatzes meines Gridelements steht folgendes Flexform:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3DataStructure>
   <meta>
      <langDisable>1</langDisable>
   </meta>
   <sheets>
      <sDEF>
         <ROOT>
            <TCEforms>
               <sheetTitle>Content</sheetTitle>
            </TCEforms>
            <type>array</type>
            <el>
               <text>
                  <TCEforms>
                     <config>
                        <type>text</type>
                        <cols>40</cols>
                        <rows>5</rows>
                        <eval>trim</eval>
                     </config>
                     <label>Text</label>
                  </TCEforms>
               </text>
               <image>
                  <TCEforms>
                     <label>Bild</label>
                     <config>
                        <type>group</type>
                        <internal_type>file_reference</internal_type>
                        <uploadfolder></uploadfolder>
                        <allowed>jpg,gif,png</allowed>
                        <max_size>10240</max_size>
                        <show_thumbs>1</show_thumbs>
                        <size>1</size>
                        <minitems>0</minitems>
                        <maxitems>1</maxitems>
                     </config>
                  </TCEforms>
               </image>
            </el>
         </ROOT>
      </sDEF>
   </sheets>
</T3DataStructure>

Dann habe ich die Datei /typo3conf/extTables.php um folgendes erweitert:

<?php
$GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config']['ds']['*,gridelements_pi1'] = '<T3DataStructure>
   <ROOT>
      <type>array</type>
      <el>
         <image>
            <TCEforms>
               <label>Bild</label>
               <config>
                  <type>group</type>
                  <internal_type>file_reference</internal_type>
                  <uploadfolder></uploadfolder>
                  <allowed>jpg,gif,png</allowed>
                  <max_size>10240</max_size>
                  <show_thumbs>1</show_thumbs>
                  <size>1</size>
                  <minitems>0</minitems>
                  <maxitems>1</maxitems>
               </config>
            </TCEforms>
         </image>
      </el>
   </ROOT>
</T3DataStructure>
';
?>

Ergebnis siehe Anhang.

Super, vielen Dank für deine Hilfe!!! 🙂

Als Ergänzung noch mein Typoscript, um zu zeigen, wie man die Flexform Felder nun verwenden kann:

tt_content.gridelements_pi1.20.10.setup {
   # Grid Element Bild + Text
   # 5 ist die UID des Gridelement-Datensatzes
   5 < temp.gridelements.defaultGridSetup
   5 {
      stdWrap.cObject = COA
      stdWrap.cObject {
         10 = TEXT
         10 {
            data = field:flexform_text
            wrap = <div class="textContent"><p>|</p></div>
         }
         20 = IMAGE
         20 {
            file {
               import.data = field:flexform_image
               width = 164
               height = 60
            }
            wrap = <div class="imageContent">|</div>
         }
      }
      wrap = <div class="mainWrapper">|</div>
   }
}

Bildschirmfoto-2012-11-28-um-16.27.15.png

Typo3Cuckoo ·

Dann gleich noch ein Tipp:

Wenn man das Flexform in eine externe Datei auslagen möchte kann man das folgendermaßen machen (siehe Screenshot).

gridelement_flexform.png

sunixzs ·

Ahoi,

seit Typo3 6.0 habe ich auch mit der Tabelle sys_file_reference zu tun und möchte hier einfach mal meine Lösung posten, wie ich die Referenzen in einem Flexform definiere und in einem Plugin wieder raushole. Die Lösung wird wahrscheinlich nicht der Standard-Weg sein, funktioniert aber auf's erste, bis ich mehr Infos zum FAL bekomme.

Das Plugin, welches ich erstellen musste, ist eine simple kleine Bilder-Galerie. Einfach ein paar Bilder in einem Slider. Dazu bekommt der Redakteur ein Inhaltselement vom Typ Plugin an die Hand, in dessen Einstellungen er einfach Datei-Referenzen zu Bildern setzt.

Hier der Bilder-Bereich im Plugin-Flexform (myext/Configuration/FlexForms/flexform_pi1.xml). Sämtliche Parameter habe ich im Backend-Modul "Konfiguration" unter "TCA -> tt_content -> columns -> image -> config" entnommen:

<settings.images>
	<TCEforms>
		<label>Bilder</label>
		<config>
			<appearance>
				<createNewRelationLinkTitle>LLL:EXT:cms/locallang_ttc.xlf:images.addFileReference</createNewRelationLinkTitle>
				<enabledControls>
					<delete>1</delete>
					<dragdrop>1</dragdrop>
					<hide>1</hide>
					<info></info>
					<localize></localize>
					<new></new>
					<sort></sort>
				</enabledControls>
				<headerThumbnail>
					<field>uid_local</field>
					<width>64</width>
					<height>64</height>
				</headerThumbnail>
				<showPossibleLocalizationRecords>1</showPossibleLocalizationRecords>
				<showRemovedLocalizationRecords>1</showRemovedLocalizationRecords>
				<showSynchronizationLink>1</showSynchronizationLink>
				<useSortable>1</useSortable>
			</appearance>
			<behaviour>
				<localizationMode>select</localizationMode>
				<localizeChildrenAtParentLocalization>1</localizeChildrenAtParentLocalization>
			</behaviour>
			<filter>
				<numIndex index="0">
					<parameters>
						<allowedFileExtensions>gif,jpg,jpeg,tif,tiff,bmp,pcx,tga,png,pdf,ai</allowedFileExtensions>
						<disallowedFileExtensions></disallowedFileExtensions>
						<userFunc>TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter->filterInlineChildren</userFunc>
					</parameters>
				</numIndex>
			</filter>
			<foreign_field>uid_foreign</foreign_field>
			<foreign_label>uid_local</foreign_label>
			<fieldname>galleryimages</fieldname>
			<foreign_selector>uid_local</foreign_selector>
			<foreign_selector_fieldTcaOverride>
				<config>
					<appearance>
						<elementBrowserAllowed>gif,jpg,jpeg,tif,tiff,bmp,pcx,tga,png,pdf,ai</elementBrowserAllowed>
						<elementBrowserType>file</elementBrowserType>
					</appearance>
				</config>
			</foreign_selector_fieldTcaOverride>
			<foreign_sortby>sorting_foreign</foreign_sortby>
			<foreign_table>sys_file_reference</foreign_table>
			<foreign_table_field>tablenames</foreign_table_field>
			<foreign_types>
				<numIndex index="2">
					<showitem>--palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette</showitem>
				</numIndex>
			</foreign_types>
			<maxitems>50</maxitems>
			<minitems>1</minitems>
			<type>inline</type>
		</config>
	</TCEforms>
</settings.images>

In der tabelle sys_file_reference werden nun Einträge erzeugt, bei denen das Feld "uid_foreign" die UID des Inhaltselements besitzt und im Feld "tablenames" "tt_content" steht.

Um diese Daten im Plugin wieder auszulesen, hole ich die Daten des Inhaltselements in meiner Controller-Action, beauftrage das FileRepository die Daten zu holen und erstelle Datei-Objekte.

Im FileRepository gibt es die Methode "findByRelation()", bei der man uid_foreign, tablenames und fieldname übergibt. Leider fehlt aber im Datensatz die Information fieldname. Deswegen habe ich diese Methode überschrieben, indem ich im Plugin die Repository-Klasse erweiterte.

FileRepository im Plugin (myext/Classes/Domain/Repository/FileRepository.php):

namespace VENDOR\Myext\Domain\Repository;
class FileRepository extends \TYPO3\CMS\Core\Resource\FileRepository {
  
	/**
	 * Find FileReference objects by relation to other records
	 *
	 * @param int $tableName Table name of the related record
	 * @param int $uid The UID of the related record (needs to be the localized uid, as translated IRRE elements relate to them)
	 * @return array An array of objects, empty if no objects found
	 * @throws \InvalidArgumentException
	 * @api
	 */
	public function findByRelation($tableName, $uid) {
		$itemList = array();
		if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($uid)) {
			throw new \InvalidArgumentException('Uid of related record has to be an integer.', 1316789798-);
		}
		$references = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
			'*',
			'sys_file_reference',
			'tablenames=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($tableName, 'sys_file_reference') .
				' AND deleted = 0' .
				' AND hidden = 0' .
				' AND uid_foreign=' . intval($uid),
			'',
			'sorting_foreign'
		);
		foreach ($references as $referenceRecord) {
			$itemList[] = $this->createFileReferenceObject($referenceRecord);
		}
		return $itemList;
	}	
	
}

Diese Methode nutze ich in der Action, um die Referenzen zu holen. Dazu muss ich im Controller zuerst das Repo bekannt machen, dann die Referenzen holen und aus den Referenz-Objekten Datei-Objekte erzeugen.

Hier der relevante Teil des Controllers zur Übersicht (myext/Classes/Controller/Pi1Controller.php):

namespace VENDOR\Myext\Controller;
class Pi1Controller extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
  /**
   * @var VENDOR\Myext\Domain\Repository\FileRepository
   * @inject
   */
  protected $fileRepository;


  /**
   * action show
   *
   * @return void
   */
  public function showAction() {

    /*
     * get the data of this content-element
     */
    $data = $this->configurationManager->getContentObject()->data;

    /*
     * try to find the relations
     */
    $fileReferences = $this->fileRepository->findByRelation("tt_content", $data['uid']);

    /*
     * create file-objects
     */
    $images = array();
    if ($fileReferences) {
      foreach ($fileReferences as $fileReference) {
        try {
          $images[] = $fileReference->toArray();
        } catch (Exception $e) {

        }
      }
    }
    
    /*
     * assign the view
     */
    $this->view->assignMultiple(array(
      'images' => $images,
      'data'   => $data
    ));
  }

}

Anm. 1: Der try-catch-Part ist nur ein Versuch auf fehlende Original-Dateien zu reagieren, der aber noch nicht funktioniert).

Anm. 2: Wie sich das mit Übersetzungen verhält, weiß ich noch nicht.

LG sun

Typo3Cuckoo ·

Super, danke für deinen Beitrag! 🙂

Habs nur mal schnell überflogen (grad keine Zeit) aber werds mir später mal genauer anschauen 😉

dauerN00b ·

Vielen Dank sunixzs! Das hat mir ordentlich auf die Sprünge geholfen.
Einen kleinen Zusatz, der mir beim Testen mit Deiner Lösung aufgefallen ist hätte ich noch:

Wenn du in der config noch

<foreign_match_fields><fieldname>[DeinFeldName]</fieldname></foreign_match_fields><fieldname>

einträgst, wird der Feldname auch in die sys_file_reference geschrieben und du musst die findByRelation Methode nicht überschreiben.