Hallo, lieber Forum Benutzer. Wir haben in letzter Zeit festgestellt, dass die Kommunikation via https://slack.com/ viel schneller und zielführender ist als ein Beitrag im Forum. Aufgrund der neuen Möglichkeiten der Kommunikation ist das Forum ein wenig eingeschlafen und weniger Nutzer benutzen das Forum aktiv (trotzdem lohnt es sich evtl. hier nach Lösungen zu suchen oder seine Frage zu stellen).

Wir empfehlen bei Fragen/Problemen aktuell die Frage (zusätzlich) im Slack zu stellen. Dort sind viele kompetente REDAXO Benutzer aktiv und beantworten gerne (Anfänger)Fragen.

Selbst einladen kannst Du dich hier: http://redaxo.org/slack/

Slack wird von uns sehr intensiv und meistens "rund um die Uhr" benutzt :-)
dpf_dd
Beiträge: 151
Registriert: 20. Dez 2007, 14:07

rex_form-Element entfernen?

22. Mai 2017, 10:30

Hallo Leute,

ich stehe mal wieder auf dem Schlauch und denke diese Frage ist im Forum besser aufgehoben als im Slack-Channel...
Ich habe ein eigenes AddOn gebaut und nutze dafür u.a. eine extended rex_form-Klasse um rex_form-Elemente zu manipulieren:

Code: Alles auswählen

class my_rex_form extends rex_form {
	function preSave($fieldsetName, $fieldName, $fieldValue, &$saveSql){
		$out = '';
		switch($fieldName){
			default:
				return $fieldValue;
			case "TSTAMP":
				$fieldValue = str_replace('-',' ',$fieldValue);
				$rohdatum = new DateTime($fieldValue);
				$out = $rohdatum->format('Y-m-d H:i:s');
			return $out;
		}
	}
	function preView($fieldsetName, $fieldName, $fieldValue){
		$out = '';
		switch($fieldName){
			default:
				return $fieldValue;
			case "TSTAMP":
				$rohdatum = new DateTime($fieldValue);
				$out = $rohdatum->format('d.m.Y-H:i');			
			return $out;					
		}
	}
}
Damit erreiche ich eine Manipulation der Eingabe-Variable und kann dann den Timestamp besser verarbeiten.
Wie muss ich die Klasse aber ausgestalten, wenn ich ein rex_form-Objekt nicht manipulieren, sondern komplett entfernen möchte?

Was habe ich vor:
Ich habe eine Checkbox in der AddOn-Eingabe, die den Zeitstempel aktualisieren soll. Das Checkbox-Feld gibt es aber nicht in der Datenbank, was zu "Fehler beim Speichern." führt... Ich brauche die Checkbox ja auch nur zur Steuerung und dachte ich kann das in etwas so umsetzen:

Code: Alles auswählen

function preSave($fieldsetName, $fieldName, $fieldValue, &$saveSql){
	$out = '';
	switch($fieldName){
		default:
			return $fieldValue;
		case "CHECKBOX":
			if($fieldValue == 0)
			{
				### rex_form-Element "TSTAMP" NICHT MODIFIZIEREN
			}
			else {
				### rex_form-Element "TSTAMP" soll mit time() überschrieben werden...
			}
			### In beiden Fällen nach Durchlauf das aktuelle rex_form-Element ("CHECKBOX") entfernen (sonst gibt es "Fehler beim Speichern"...)				
		case "TSTAMP":
			$fieldValue = str_replace('-',' ',$fieldValue);
			$rohdatum = new DateTime($fieldValue);
			$out = $rohdatum->format('Y-m-d H:i:s');
		return $out;
	}
}
Ich habe nun zwei elementare Probleme:
1) Wie kann ich den $fieldValue von "TSTAMP" ändern, wenn sich die Schleife aber gerade im Objekt "CHECKBOX" befindet?
2) Wie kann ich das gesamte rex_form-Element "CHECKBOX" entfernen, sodass es NICHT in der Datenbank gespeichert wird?

Kann mir da jemand evtl. auf die Sprünge helfen?
Vielen Dank und eine angenehme Woche...

Stefan / dpf_dd

Benutzeravatar
runstop64
Beiträge: 353
Registriert: 23. Okt 2012, 21:34
Wohnort: Hamburg
Kontaktdaten: Website Facebook Twitter

Re: rex_form-Element entfernen?

22. Mai 2017, 10:51

Wenn ich rex_form richtig lese, ist das ohne Umschreiben der Speicherfunktionen nicht so einfach möglich. Wenn Du die Daten umschreiben möchtest, wäre es am sinnvollsten, die save() Methode anzupassen und das $elements bzw. $fieldset-Array zu manipulieren, da nach preSave() auf jeden Fall etwas in die DB geschrieben wird.
Reichen Dir die Standard-Timestamps nicht aus? Sie müssen nur in der DB vorhanden sein, den Rest macht dan rex_form.
Viele Grüße,
Daniel


studio-ahoi.de | Referenzen | Friends Of REDAXO

dpf_dd
Beiträge: 151
Registriert: 20. Dez 2007, 14:07

Re: rex_form-Element entfernen?

22. Mai 2017, 14:26

Ui, danke für deine 2 Cent... Natürlich reichen mir die Standard-Zeitstempel-Felder, aber das hilft mir nicht weiter....

Folgender Usecase:
Ich schreibe eine "News 1", am gleichen Tag folgen noch "News 2" und meinetwegen "News 3".
Im Frontend wird die neueste News immer ganz oben angezeigt, da stünde als von oben nach unten die News 3, 2 und am Ende 1.
Einen Tag später wird ein Fehler in der News 1 entdeckt und ich muss den Datensatz editieren.
Ich klicke also in den Datensatz und mache meine Änderungen. Allerdings möchte ich JETZT steuern können, ob der editierte Datensatz wieder ganz oben erscheinen soll (also TSTAMP neu schreiben) oder ob er in der alten Reihenfolge angezeit wird (also TSTAMP nicht neu schreiben)

Die einfachste Lösung für mich ist die technisch unsaubere: Ich werde meine AddOn-Datenbanktabelle einfach um das Feld "CHECKBOX" erweitern...
Wird ein Datensatz aus dem AddOn geladen => Checkbox soll IMMER deaktiviert sein.
Beim Speichern klinke ich mich dann mit obiger Methode in den Durchlauf von TSTAMP prüfe, ob das Feld CHECKBOX angehakt ist. Wenn ja, dann soll "return ###aktueller Zeitstempel###" und wenn nicht, dann halt "return ###alter Zeitstempel aus Datenbank###".

Bleibt also nur noch Problem 1. Wie kann ich aus dem case "TSTAMP" den $fieldValue von "CHECKBOX" abfragen?

Benutzeravatar
runstop64
Beiträge: 353
Registriert: 23. Okt 2012, 21:34
Wohnort: Hamburg
Kontaktdaten: Website Facebook Twitter

Re: rex_form-Element entfernen?

22. Mai 2017, 14:49

Hi,

wie geschrieben würde ich für den Fall die save() Methode überschreiben und für Deine Zwecke anpassen, weil du in der preSave() Methode den Lauf der Schleife nicht beeinflussen kannst. Dafür müsstest du allerdings das Elements-Array direkt manipulieren, sonst kommst Du innerhalb der Schleife nicht an andere Werte heran.

Eine andere Möglichkeit wäre, ein echtes Prio-Feld zu nutzen (sauberste Lösung und bereits eingebaut: https://github.com/redaxo/redaxo4/blob/ ... #L372-L383) In Kombination mit den Update-Feldern solltest eine passende Sortierung möglich sein.

Andere Variante wäre, einen Link per Javascript abzufragen und daraufhin z.B. ein (verstecktes) Feld, das mit dem letzten Timestamp vorbelegt ist, direkt zu manipulieren. Dann würde der passende Wert gleich in die DB wandern und du könntest dir das durchforsten des Feld-Arrays sparen.
Viele Grüße,
Daniel


studio-ahoi.de | Referenzen | Friends Of REDAXO

dpf_dd
Beiträge: 151
Registriert: 20. Dez 2007, 14:07

Re: rex_form-Element entfernen?

23. Mai 2017, 08:15

Hmm, das mit "save()" ist ähnlich wie mit diesem extended rex_form... Wenn ich den Code sehe, dann verstehe ich ihn und kann mir den für meine Zwecke abstrahieren. Aber von selbst auf so eine Idee und Umsetzung zu kommen, da fehlen mir die Körner :D

Hast du vielleicht ein kleines Schnipsel zur Hand, sowas wie eine "Vorlage". Keine Ahnung wie save() aufgebaut ist und welche Daten es in welcher Form benötigt. Gibt es da evtl. ein anderes AddOn, von dem ich mich beim Vorgehen etwas inspirieren lassen kann? :oops:

PS: Die Prio-Felder habe ich schon nicht durchschaut. Da wollte mal eine Sortierung (wie in der Strukturverwaltung) für mein AddOn bauen und dachte ich nehme diese PrioFelder... Es war ein Desaster... Habs dann sein lassen und mir die Funktion selbst gebaut mit normalen Input-Textfeldern und Berechnungsfunktion... NIE wieder so ein Aufwand, also da ist Redaxo echt anstrengend an der Stelle :D

Benutzeravatar
runstop64
Beiträge: 353
Registriert: 23. Okt 2012, 21:34
Wohnort: Hamburg
Kontaktdaten: Website Facebook Twitter

Re: rex_form-Element entfernen?

23. Mai 2017, 10:46

Ich hatte oben passende stellen bei Github verlinkt. Ich arbeite inzwischen nur noch mit Xform/Yform, weil ich das flexibler finde, daher habe ich keine Beispiele zur Hand.

Die save() Methode würde ich einfach aus der Original-rex_form in eine eigene Klasse kopieren und an den nötigen Stellen anpassen. Das halte ich jedoch für die umständlichste Variante.

Das Prio-Feld ist ziemlich einfach einzubinden:

Code: Alles auswählen

$field = &$form->addPrioField('prio', $form->getParam('prio'));
Es muss außer dem Prio-Feld in der Tabelle auch eine Spalte mit dem Namen 'updatdate' vorhanden sein (sonst funktioniert es nicht).

Das wäre ein Ansatz für einen Timestamp mit jQuery (ungetestet). #lorem müsste mit der passenden Timestamp-Feld-ID ersetzt werden:

Code: Alles auswählen

<button id="changedate">Datum ändern</button>
<script>
$(document).ready(function(){
  $("#changedate").on('click', function(){
    $("#lorem").val(Math.floor(new Date().getTime() / 1000));
  });
});
</script>
Du könntest das über ein HTML-Feld einbauen.
Viele Grüße,
Daniel


studio-ahoi.de | Referenzen | Friends Of REDAXO

dpf_dd
Beiträge: 151
Registriert: 20. Dez 2007, 14:07

Re: rex_form-Element entfernen?

23. Mai 2017, 11:29

Danke dir erstmal... Ich schaue es mir die Tage nochmal an, hab aber was dringenderes reinbekommen :(
Es muss außer dem Prio-Feld in der Tabelle auch eine Spalte mit dem Namen 'updatdate' vorhanden sein (sonst funktioniert es nicht).
Haha, mit dem Wissen hätte ich mehrere Stunden sparen können. Meine Prio-Feldern funzten nämlich einfach nicht (weil ich nicht auf den SQL-Fieldname geachtet habe) und in der rex_form Befehlsreferenz war da nichts zu lesen drüber... :roll:
Das meinte ich mit "mir fehlen die Körner"... Wo zum Henker habt ihr dieses KnowHow her? Ich versuche ja wirklich Dokus zu wälzen und Befehls-Referenzen zu nutzen, aber es ist ein einziger Kampf (zumindest bei Rex 4.x). Gleiches bei EPs... Da gibt es tolle Extension Points, aber in der alten Page waren die wenigsten davon gelistet...

Ok, aber ich will ni rumjammern. Ich sehe da auch deutlichen Fortschritt bei Redaxo 5 und mit dem Slack-Channel entwickelt sich das in eine gute Richtung :)

Benutzeravatar
runstop64
Beiträge: 353
Registriert: 23. Okt 2012, 21:34
Wohnort: Hamburg
Kontaktdaten: Website Facebook Twitter

Re: rex_form-Element entfernen?

23. Mai 2017, 11:46

Ich lese mir inzwischen stets den entsprechenden Quellcode durch, das spart viel Raterei und ist bei Redaxo meist ziemlich aufschlussreich, da das System recht unkompliziert geschrieben ist. Nebenbei lernt man auch noch den einen oder anderen PHP-Trick. Auf Github geht das ziemlich bequem.

Ansonsten kann ich nur das Nutzen einer IDE oder eines vergleichbaren Editors empfehlen. Da wird dir einiges an Sucherei abgenommen und du kannst z.B. Klassen- und Funktionsdefinitionen direkt anspringen und musst nicht erst herausfinden, in welcher Datei sie versteckt sind.

Für das Listen der EPs hat Thomas Blum Extensions geschrieben:
Rex 4: https://github.com/tbaddade/redaxo_sherlock
Rex 5: https://github.com/tbaddade/redaxo_cheatsheet
Viele Grüße,
Daniel


studio-ahoi.de | Referenzen | Friends Of REDAXO

Ingo
Beiträge: 782
Registriert: 24. Jun 2010, 00:34

Re: rex_form-Element entfernen?

30. Mai 2017, 11:41

Ich würde einen Datetimepicker nutzen, der beim Anlegen der News (wenn kein Datum hinterlegt ist) automatisch den Timestamp setzt, ansonsten nur manuell.

dpf_dd
Beiträge: 151
Registriert: 20. Dez 2007, 14:07

Re: rex_form-Element entfernen?

15. Jun 2017, 17:15

Ok, kich habe jetzt eine Woche immer mal ein wenig probiert (mangels exaktem Wissen) - und gebe jetzt auf.
Danke Ingo für deinen Input, aber das ist diesmal am Thema vorbei - ich suche eine andere Funktion.

Ich habe also versucht, den vorgeschlagenen Weg über save() zu gehen und bin grandios gescheitert. Irgendwie macht der nicht das was ich denke was er tun soll.

Das Feld "NEWS_TSTAMP" ist ein Hidden-Feld, das nur bei $func=='add' in das rex_form-Objekt wandert und den aktuellen Zeitstempel time() als default-value übergibt. Wenn ich also einen Datensatz editiere, dann wird das Feld gar nicht erst ins rex_form-Objekt aufgenommen und somit dann auch nicht in die Datenbank geschrieben - womit das Ziel erreicht wäre, dass der NEWS_TSTAMP einmal geschrieben (beim Erstellen) sich nie mehr ändert (was auch so gewünscht ist)

Das Feld "RENEW_TSTAMP" ist ein Select-Feld, das entweder 0 oder 1 zurückgeben kann und wiederum nur bei $func=="edit" in das rex_form-Objekt geschrieben wird. Der Plan war, dass ich bei Auswahl von "0" dann hintenrum den "NEWS_TSTAMP" neu schreibe, damit eben der Erstellungs-Zeitstempel aktualisert wird.

Code: Alles auswählen

class nachrichten_rex_form extends rex_form {
	function save(){
	$out = '';
	$myfield = array('RENEW_TSTAMP');
	$elements = $this->getFieldsetElements();
	foreach($elements as $fieldsetName => $fieldsetElements)
	{
		foreach($fieldsetElements as $field){
			if (in_array($field->getFieldName(), $myfield))
			{
				### Wenn die Variable 0 ist => dann soll der NEWS_TSTAMP aktualisiert werden
				if($field->getValue() == 0)
				{
					### nur beim Editieren, nicht beim Erstellen
					$params = $this->getParams();
					if($params['func'] == 'edit')
					{
						$update = new rex_sql();
						$update->setQuery("UPDATE sql_tabelle SET NEWS_TSTAMP = ".time()." WHERE ID = ".$params['ID']);
						### DAS KLAPPT SCHONMAL NICHT
					}
					### Jetzt müsste ich in der foreach-Schleife mit unset(???) das aktuell durchlaufende Array "RENEW_TSTAMP" aus dem gesamten rex_form Objekt entfernen => und da ist bei mir Ende Gelände...
					### Ich habe es am Ende auch HART versucht => Das Element wird tatsächlich entfernt, ändert aber nichts am unten beschriebenen "Erfolg"...
					unset($this->elements['Nachrichten'][9]);		
				}
			}
		}
	}
	return $this;
}
Egal was ich ausprobiert habe, die editierten Werte werden nicht gespeichert und ich erhalten immer "Fehler beim speichern!". Vermutlich muss ich da noch irgendwo anders in dem Objekt eingreifen, das ist ja ein Riesenvieh über HUNDERTE Zeilen. Aber das ist mir jetzt wirklich zu hoch weil ich auch gar nicht mehr weiß was ich überhaupt tue und wie das modifizierte rex_form Objekt denn überhaupt aussehen muss, um keinen "Fehler beim speichern!" zu verursachen.
Ich vermute der "Fehler beim speichern!" wird daran liegen, dass RENEW_TSTAMP eben nur eine Steuerungsvariable sein soll und dazu kein korrespondierendes SQL-Feld existiert. Nur hilft mir die Vermutung auch nicht weiter ^^


So, Frust ist abgelassen - dafür hasse ich jetzt rex_form... :evil: :evil: :evil:
Gedanklich hab ich das Thema (fast) abgehakt und werde dann diese Frage demnächst auch im Redaxo 5 Forum mal stellen :mrgreen:

Grüße und schönen Feierabend
dpf_dd

Benutzeravatar
runstop64
Beiträge: 353
Registriert: 23. Okt 2012, 21:34
Wohnort: Hamburg
Kontaktdaten: Website Facebook Twitter

Re: rex_form-Element entfernen?

16. Jun 2017, 10:39

Hi,

ist die gepostete Methode die komplette Save-Methode? Dann ist es kein Wunder, dass deine Versuche scheitern.
Du musst die Methode, wenn du sie ergänzen willst, kopieren und innerhalb des kopierten Codes deine Anpassungen vornehmen. Sonst existiert der Originalcode für deine neue Klasse nicht und wird auch nicht ausgeführt.
Das Original-Save gibt einen Booleschen Wert zurück, der je nach Ergebnis true oder false ist. Du gibst dein rex_form-Objekt zurück, damit kann die aufrufende Methode natürlich nichts anfangen und gibt eine Fehlermeldung aus.

Code: Alles auswählen

class nachrichten_rex_form extends rex_form
{
  //
  // Dies ist eine vollständige Kopie der save-Methode
  // 
    
   /**
     * Speichert das Formular.
     *
     * Übernimmt die Werte aus den FormElementen in die Datenbank.
     *
     * Gibt true zurück wenn alles ok war, false bei einem allgemeinen Fehler,
     * einen String mit einer Fehlermeldung oder den von der Datenbank gelieferten ErrorCode.
     */
    /*protected*/ function save()
    {
        $sql = rex_sql::factory();
        $sql->debugsql = & $this->debug;
        $sql->setTable($this->tableName);
        foreach ($this->getSaveElements() as $fieldsetName => $fieldsetElements) {
            foreach ($fieldsetElements as $element) {
                // read-only-fields nicht speichern
                if (strpos($element->getAttribute('class'), 'rex-form-read') !== false) {
                    continue;
                }
                
                //
                //
                // Hier kannst du deine Felder prüfen und manipulieren
                7/
                //
                
                $fieldName = $element->getFieldName();
                $fieldValue = $element->getSaveValue();
                // Callback, um die Values vor dem Speichern noch beeinflussen zu können
                $fieldValue = $this->preSave($fieldsetName, $fieldName, $fieldValue, $sql);
                // Den POST-Wert in die DB speichern (inkl. slashes)
                if ($fieldValue === null) {
                    $sql->setValue($fieldName, null);
                } else {
                    $sql->setValue($fieldName, addslashes($fieldValue));
                }
            }
        }
        if ($this->isEditMode()) {
            $sql->setWhere($this->whereCondition);
            $saved = $sql->update();
        } else {
            $saved = $sql->insert();
        }
        // ----- EXTENSION POINT
        if ($saved) {
            $saved = rex_register_extension_point('REX_FORM_SAVED', $saved, array('form' => $this, 'sql' => $sql));
        } else {
            $saved = $sql->getErrno();
        }
        return $saved;
    }
Viele Grüße,
Daniel


studio-ahoi.de | Referenzen | Friends Of REDAXO

dpf_dd
Beiträge: 151
Registriert: 20. Dez 2007, 14:07

Re: rex_form-Element entfernen?

16. Jun 2017, 16:40

Danke Daniel, das ist ein guter Einwurf.

Ich kenne das vorgehen halt von preView() und preSave() etc. und habe damit regelmäßig schon die Klasse erweitert, um Eingaben zu manipulieren.
Nun war ich deswegen in der Annahme, dass Save() genauso funktioniert - aber leuchtet natürlich ein was du sagt und mit einem Blick in die rex_form-Referenz hätte ich da auch drauf kommen können...

Jetzt sehe ich auch den Unterschied: preView() etc. bekommen ja schon Werte, durchlaufen dann die Funktion, return der (dann manipulierten) Werte und Rückgabe an den Programmablauf.. also quasi ein "Boxenstopp" vor der finalen Verarbeitung.
Die save()-Methode ist halt die komplette Verarbeitung und kein "Boxenstopp", weswegen ich diese duplizieren und dann im Ganzen manipulieren muss.

OK, hab ich gerafft. Morgen soll es regnen, da hab ich Zeit das mal zu testen. Ich berichte dann hier nochmal vom Resultat...

Vielen Dank Daniel, ich denke damit bekomme ich das hin! 8)

Ein Schönes Wochenende wünsche ich :!:
Gruß
Stefan

dpf_dd
Beiträge: 151
Registriert: 20. Dez 2007, 14:07

Re: rex_form-Element entfernen?

18. Jun 2017, 20:17

Hallo Daniel,

schönes Ding - mit dem neuen Wissen ging das ganz geschmeidig :)
Ich habe es jetzt genau so eingestellt, wie ich es mir vorher gewünscht hatte. Ein Traum.

Für Interessierte mit gleichem Problem:
Man nehme runstops Codeschnipsel und füge dann an die entsprecht von runstop markierte Stelle z.B. folgenden Code ein:

Code: Alles auswählen

### Wenn Element "RENEW_TSTAMP" durchlaufen wird...
if (strpos($element->getAttribute('name'), 'Nachrichten[RENEW_TSTAMP]') !== false)
{
	### ...dann den Wert des Select-Feldes abfragen
	if($element->value == "0")
	{
		### ...und Originalzeitstempel manipulieren, wenn das so ausgewählt wurde (= 0)
		$update = new rex_sql();
		$update->setQuery("UPDATE ".$this->tableName." SET NEWS_TSTAMP = ".time()." WHERE ".$element->table->whereCondition);
	}
	### Element "RENEW_TSTAMP" soll nicht gespeichert werden => nächstes Element durchlaufen...
	continue;
}			
Schönes Ding, danke Daniel! :)

Benutzeravatar
runstop64
Beiträge: 353
Registriert: 23. Okt 2012, 21:34
Wohnort: Hamburg
Kontaktdaten: Website Facebook Twitter

Re: rex_form-Element entfernen?

18. Jun 2017, 20:38

Immer gerne! :)
Viele Grüße,
Daniel


studio-ahoi.de | Referenzen | Friends Of REDAXO

Zurück zu „AddOns [R4]“