Zum Inhalt springen

Rückgabe der TMENU IProcFunc ???

Erstellt am 4. September 2012 · 6 Antworten · letzte Antwort am 12. September 2012

Tags: PHP, Frage

bugblatterbeast ·

Hallo,

ich habe eine Extension, die Referenzprojekte verwaltet und ausgibt. Ich möchte jetzt, dass unter dem Menupunkt "Referenzen" das TMENU mit Werten aus einer von mir geschriebenen php-Funktion gefüllt wird, die meine Tabelle mit den angelegten Projekten durchsucht und es für den Betrachter so aussehen läßt, als wenn jedes Projekt eine Unterseite wär (realUrl ist schon konfiguriert).

Nach zahlreichen Wutanfällen habe ich jetzt gelernt, das TypoScript nur bereit ist, php-Funktionen aufzurufen, wenn deren Klassenname mit "user_" beginnt und frage mich nun, ob TMENU tatsächlich exakt die Array-Struktur des ersten Parameters als Rückgabewert erwartet. Ich habe ja gar nicht vor, die vorhandenen Werte zu modifizieren, sondern möchte nur eigene Werte in das Menu schreiben. Daher hatte ich gehofft, dass TMENU für mich das ganze Wrapping und so übernehmen würde.

So sieht das Array aus, das ich in Parameter 1 bekomme, wenn eine Testseite unter Projekte existiert:

Array
(
    [key] => 0
    [INPfix] => _55cd_0
    [val] => Array
        (
            [stdWrap.] => Array
                (
                    [htmlSpecialChars] => 1
                )

            [linkWrap] => <div class="nav-lv1">|</div>
            [ATagParams] =>  class="lnk-lv1"
            [doNotLinkIt] => 0
        )

    [title] => Testpage
    [uid] => 50
    [mount_pid] => 0
    [pid] => 5
    [spacer] => 0
    [accessKey] => Array
        (
        )

    [linkHREF] => Array
        (
            [HREF] => de/projekte/testpage/
            [TARGET] => _top
            [onClick] => 
            [onFocus] => blurLink(this);
        )

    [A1] => <a href="de/projekte/testpage/" target="_top" onfocus="blurLink(this);"  class="lnk-lv1">
    [A2] => </a>
    [parts] => Array
        (
            [before] => 
            [stdWrap2_begin] => 
            [notATagBeforeWrap_begin] => <div class="nav-lv1">
            [ATag_begin] => <a href="de/projekte/testpage/" target="_top" onfocus="blurLink(this);"  class="lnk-lv1">
            [ATagBeforeWrap_begin] => 
            [title] => Testpage
            [ATagBeforeWrap_end] => 
            [ATag_end] => </a>
            [notATagBeforeWrap_end] => </div>
            [stdWrap2_end] => 
            [after] => 
        )

)

Ich habe leider trotz intensiver Suche keine verständlichen Dokumentationen oder funktionierenden Beispiele für meine Anforderung gefunden und würde mich schon freuen, wenn mir jemand einen Link auf eine gute Doku posten könnte, da die TSREF, die ich zu diesem Thema finde, leider noch "document in progress" ist und mir nicht weiterhilft.

Vielen Dank im Voraus und Gruß, bbb

einpraegsam.​net ·

Deine UserFunc ruft eine Funktion auf und gibt dieser zwei Parameter mit. Du gibst ein Array zurück mit Titel, Link und ITEM_STATE (wenn du willst).

Beispiel:

public function createMenu($arr = array(), $conf = array()) {
	$arr = array();
	for ($i = 0; $i < 10; $i++) {
		$arr[] = array(
			'title' => 'neu',
			'_OVERRIDE_HREF' => 'index.php?id=123',
			'ITEM_STATE' => 'CUR'
		);
	}
	
	return $arr;
}
bugblatterbeast ·

Vielen Dank, für das gute Beispiel. Ich fürchte nur, es fehlt noch irgendetwas. Ich habe jetzt folgende php-Datei eingebunden:

<?php

require_once(PATH_tslib.'class.tslib_pibase.php');

class user_myExtension_menu extends tslib_pibase {

  function main($menuArr, $conf) {
    $pageID = $conf["parentObj"]->parent_cObj->data["uid"];
    $langID = $_GET["L"];
    $selected = $_GET["tx_myExtension"]["project"];
    $new_menuArr = array();
    $category = intval($conf['category']);
    
    $query =
      "SELECT uid, title, alias\n" .
      "FROM tx_myExtensionData_projects\n" .
      "WHERE\n" .
      "  (hidden = 0) AND\n" .
      "  (deleted = 0) AND\n" .
      "  (sys_language_uid = $langID)";
    if($category) $query .= " AND\n  (category = $category)";
    $query .= ";";
echo "\$query = <pre>$query</pre><br />\n";
    $res = $GLOBALS["TYPO3_DB"]->sql_query($query);
    
    if($res) while($row = $GLOBALS["TYPO3_DB"]->sql_fetch_assoc($res)) {
      
      if($row["alias"] == $selected) $state = "ACT";
      else $state = "NO";
      
      $new_menuArr[] = array(
        "title" => $row["title"],
        "_OVERRIDE_HREF" => $this->pi_getPageLink($pageID, "", array("tx_myExtension" => array("project" => $row["alias"]), "L" => $langID)),
        "ITEM_STATE" => $state
      );
      
    }
echo "\$new_menuArr = <pre>" . print_r($new_menuArr, true) . "</pre><br />\n";
    
    return $new_menuArr;
  }

}

?>

Die echos sind zum Debuggen und liefern folgende Ausgabe:

$query =

SELECT uid, title, alias
FROM tx_myExtensionData_projects
WHERE
  (hidden = 0) AND
  (deleted = 0) AND
  (sys_language_uid = 0);


$new_menuArr =

Array
(
    [0] => Array
        (
            [title] => Testprojekt 1
            [_OVERRIDE_HREF] => de/projekte/show/test1/
            [ITEM_STATE] => NO
        )

    [1] => Array
        (
            [title] => Testprojekt 2
            [_OVERRIDE_HREF] => de/projekte/show/test2/
            [ITEM_STATE] => NO
        )

    [2] => Array
        (
            [title] => Testprojekt 3
            [_OVERRIDE_HREF] => de/projekte/show/test3/
            [ITEM_STATE] => NO
        )

)

leider bleibt das TMENU trotzdem leer. Übersehe ich etwas?

bugblatterbeast ·

Anscheinend, gibt es hier noch mehr Ungereimtheiten. Ich habe zum Test mal zwei Unterseiten angelegt und musste feststellen, dass meine Funktion jetzt für jedes Element aufgerufen wird. Womöglich ist die IProcFunc doch gar nicht der richtige Ansatz um mein Problem zu lösen.

Ich bräuchte halt eine Art Entsprechung der "itemsProcFunc", wie man sie im $TCE verwenden kann.

bugblatterbeast ·

Ich denke, nun habe ich es durchschaut.

@einpraegsam.net: Deine Antwort war sehr hilfreich, bezog sich aber (glaube ich) auf HMENU.special.userFunc. Damit funktioniert es jetzt auch so, wie ich wollte.

Folgendes TypoScript bette ich jetzt auf der Seite mit den Referenzen ein:

page.includeLibs.user_myExtension_menu = typo3conf/ext/myExtension/include/user_myExtension_menu.inc
page.10.subparts.CONTENT_MAIN.subparts.LEFTNAV.special = userfunction
page.10.subparts.CONTENT_MAIN.subparts.LEFTNAV.special.userFunc = user_myExtension_menu->main

und so sieht nun meine etwas angepasste php-Datei aus:

<?php

require_once(PATH_tslib.'class.tslib_pibase.php');

class user_myExtension_menu extends tslib_pibase {

  function main($content, $conf) {
    $pageID = $this->cObj->data["uid"];
    $langID = $_GET["L"];
    $selected = $_GET["tx_myExtension"]["project"];
    $new_menuArr = array();
    $category = intval($conf['category']);
    
    $query =
      "SELECT uid, title, alias\n" .
      "FROM tx_myExtensionData_projects\n" .
      "WHERE\n" .
      "  (hidden = 0) AND\n" .
      "  (deleted = 0) AND\n" .
      "  (sys_language_uid = $langID)";
    if($category) $query .= " AND\n  (category = $category)";
    $query .= ";";
    $res = $GLOBALS["TYPO3_DB"]->sql_query($query);
    
    if($res) while($row = $GLOBALS["TYPO3_DB"]->sql_fetch_assoc($res)) {
      if(!$selected) $selected = $row["alias"]; // select first by default
      if($row["alias"] == $selected) $state = "ACT";
      else $state = "NO";
      $new_menuArr[] = array(
        "title" => $row["title"],
        "_OVERRIDE_HREF" => $this->pi_getPageLink($pageID, "", array("tx_myExtension" => array("project" => $row["alias"]), "L" => $langID)),
        "ITEM_STATE" => $state
      );
      
    }
    
    return $new_menuArr;
  }

}

?>

Jetzt funktioniert alles. Leider musste ich das caching an der Seite deaktivieren(was zu diesem unschönen "no_cache=1"-QueryString führt), damit die aktiven Links auch richtig formatiert werden - aber damit kann ich leben.

Gruß, bbb

bugblatterbeast ·

Das Beispiel, das ich beschrieben hatte, ersetzt das gesamte Menu durch Werte aus der php-Funktion. Kaum hatte ich es umgesetzt, wollte der Auftraggeber nun plötzlich die Projektseite verschieben, so dass erst ab der 2. Menuebene (unter Projekte) die Einträge durch die php-Funktion gesetzt werden.

Ich habe zuerst folgendes ausprobiert:

page.includeLibs.user_myExtension_menu = typo3conf/ext/myExtension/include/user_myExtension_menu.inc
page.10.subparts.CONTENT_MAIN.subparts.LEFTNAV.2 = HMENU
page.10.subparts.CONTENT_MAIN.subparts.LEFTNAV.2.special = userfunction
page.10.subparts.CONTENT_MAIN.subparts.LEFTNAV.2.special.userFunc = user_myExtension_menu->main

dann so etwas wie:

page.includeLibs.user_myExtension_menu = typo3conf/ext/myExtension/include/user_myExtension_menu.inc
tempMenu = HMENU
tempMenu.special = userfunction
tempMenu.special.userFunc = user_myExtension_menu->main
page.10.subparts.CONTENT_MAIN.subparts.LEFTNAV.2 < tempMenu

Es hat alles nicht funktioniert.

Tatsache ist anscheinend, dass bei den unteren Menuebenen mein erster Ansatz der Richtige war und es genauso funktioniert, wie einpraegsam.net geschrieben hat.

page.includeLibs.user_myExtension_menu = typo3conf/ext/myExtension/include/user_myExtension_menu.inc
page.10.subparts.CONTENT_MAIN.subparts.LEFTNAV.2.itemArrayProcFunc = user_myExtension_menu->main

FUNKTIONIERT EINWANDFREI OHNE ANPASSUNGEN IN DER PHP-FUNKTION
Wichtiger Hinweis: es handelt sich bei den Beispielen nur um ein Seiten-Template. Das gesamte Menu ist natürlich bereits im Haupttemplate konfiguriert und wird hier nur überschrieben.

Das tollste wäre, wenn mir jetzt noch jemand einen Trick sagen könnte, wie man verhindert, dass das Ergebnis der php-Funktion gecached wird ohne das man den ganzen Seitencache ausschalten muss und so nervige "no_cache=1" anhänge an den URLs bekommt.