You are not logged in.

  • "Sebastian S." is male
  • "Sebastian S." started this thread

Posts: 595

Location: Stuttgart

Occupation: KFZ-Mechatroniker

  • Send private message

1

Tuesday, July 31st 2012, 4:07am

UserException wird nicht dargestellt

Wunderscönen guten Morgen,
ich möchte gerne per Eventlistener ein bzw. mehr Felder zur ThreadAddForm hinzufügen. Soweit funktioniert auch alles tadellos, allerdings bekommt der Benutzer nicht angezeigt, welches Feld denn Fehlerhaft ist, sondern nur die globale Meldung (nur für die nachträglich eingebauten Felder). Ich dachte mir, um möglichst viele Fehlerquellen zu vermeiden, bleibe ich beim Stil der ThreadAddForm und so ist ein weiteres Feld dazugekommen.

Template source code

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="formElement{if $errorField == 'startAmount'} formError{/if}">
	<div class="formFieldLabel">
		<label for="startAmount">{lang}wbb.threadAdd.startAmount{/lang}</label>
	</div>
	<div class="formField">
		<input type="text" class="inputText" name="startAmount" id="startAmount" value="{$startAmount}" tabindex="{counter name='tabindex'}" />
		{if $errorField == 'startAmount'}
			<p class="innerError">
				{if $errorType == 'empty'}{lang}wcf.global.error.empty{/lang}{/if}
			</p>
		{/if}
	</div>
</div>


Wie gesagt wird das Element trotz Fehler nicht als formError angezeigt. Der EL dazu sieht im Ausschnitt dazu so aus:

PHP Source code

1
2
3
4
5
case 'validate':
    if(empty($this->startAmount)) {
        throw new UserInputException('startAmount');
    }
break;


Ein Kleiner Hinweiß zum Schluss. Trotz einbezogener ThreadAddForm wurde die Variable $errorField nie übergeben (fatal error) - Abhilfe habe ich mir durch manuelles Hinzufügen der zeile

PHP Source code

1
public $errorField '';
geschaffen
Mit freundlichen Grüßen
Sebastian S.


0xLeon

Member

  • "0xLeon" is male

Posts: 710

Location: Furtwangen

Occupation: Student (Medieninformatik)

  • Send private message

2

Tuesday, July 31st 2012, 7:44am

In dem Fall wird die Exception wohl erst vom globalen Exception Handler abgearbeitet. Wenn du dir aber mal ThreadAddForm::submit() anschaust, müssen die UserInputExceptions von der Klasse selbst gefangen und verarbeitet werden. Versuch mal, das ganze im EventListener auf folgende Art zu lösen:

PHP Source code

1
2
3
4
5
6
7
8
9
10
11
case 'validate':
    try {
        if (empty($this->startAmount)) {
            throw new UserInputException('startAmount');
        }
    }
    catch (UserInputException $e) {
        $eventObj->errorField $e->getField();
        $eventObj->errorType $e->getType();
    }
break;
Meine Pakete
Invitation System – Plugin StoreGithub
Update Files Delete PIP – Plugin StoreGithub
Kein Support via PN oder E-Mail.

  • "frmwrk_123" is male

Posts: 1,122

Location: Hamburg

Occupation: Informatikstudent

  • Send private message

3

Tuesday, July 31st 2012, 2:46pm

Du musst mit deinem EL mehrere Events bedienen, dann klappt das auch. Die Validierung hängst du in das Event validate ein, dann wird die Exception in der validate-Methode von ThreadAddForm gefangen und entsprechend weitergegeben. Die Parameter liest du bei readFormParameters aus, etc.
Mit freundlichen Grüßen
frmwrk_123

Nützliche Plugins zum Selberbauen

  • "Sebastian S." is male
  • "Sebastian S." started this thread

Posts: 595

Location: Stuttgart

Occupation: KFZ-Mechatroniker

  • Send private message

4

Tuesday, July 31st 2012, 3:08pm

Musste das ganze letztendlich so aufbauen, damit es funktionieren konnte - und merkwürdigerweiße musste ich auch errorType nochmal definieren.

PHP Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
case 'submit':
    try {
        $this->validateStartAmount();
    }
    catch (UserInputException $e) {
        $this->errorField $e->getField();
        $this->errorType $e->getType();
    }
    break;
            
    case 'validate':
        $this->validateStartAmount();
    break;
    }
}
    
protected function validateStartAmount() {
    if(empty($this->startAmount)) {
        throw new UserInputException('startAmount');
    }
}
Mit freundlichen Grüßen
Sebastian S.

This post has been edited 1 times, last edit by "Sebastian S." (Jul 31st 2012, 4:21pm)


  • "frmwrk_123" is male

Posts: 1,122

Location: Hamburg

Occupation: Informatikstudent

  • Send private message

5

Thursday, August 2nd 2012, 11:54am

Wie ich schon schrieb, hätte es ausgereicht, wenn du dein Eventlistener auch beim Event validate eingehängt hättest und dann den entsprechenden Code nur dort ausführst. Bei submit darfst du natürlich keine Exception werfen, was aber hier passieren kann, da das Event vor dem Try-Block der AbstractForm ausgeführt wird. Von daher kann es so nicht funktionieren. Und submit wird vor validate aufgerufen. Nimm dein Eventlistener aus submit heraus und lasse die Validierungsfunktion nur beim Event validate laufen und alles wird wie geplant funktionieren.

Hier mal die submit-Methode von AbstractForm:

PHP Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
     * @see Form::submit()
     */
    public function submit() {
        // call submit event
        EventHandler::fireAction($this'submit'); // das ist der falsche Platz dazu
        
        $this->readFormParameters();
        
        try {
            $this->validate(); // hier musst du dein Eventlistener hereinhängen, beim Event validate
            // no errors
            $this->save();
        }
        catch (UserInputException $e) {
            $this->errorField $e->getField();
            $this->errorType $e->getType();
        }
    }
Mit freundlichen Grüßen
frmwrk_123

Nützliche Plugins zum Selberbauen

  • "Sebastian S." is male
  • "Sebastian S." started this thread

Posts: 595

Location: Stuttgart

Occupation: KFZ-Mechatroniker

  • Send private message

6

Thursday, August 2nd 2012, 11:43pm

Wenn ich es alleine stehen lasse kommt ein fatalError
Mit freundlichen Grüßen
Sebastian S.


  • "frmwrk_123" is male

Posts: 1,122

Location: Hamburg

Occupation: Informatikstudent

  • Send private message

7

Friday, August 3rd 2012, 10:28am

Also mal sehen, ob du diese Voraussetzungen erfüllst:

  1. Dein Eventlistener liegt im Ordner wcf/lib/event/listener?
  2. Deine Datei heißt Klassenname.class.php?
  3. Die Klasse heißt XYZListener?
  4. Die Klasse implementiert EventListener?
  5. Der EventListener ist bei der Installation für alle genutzten Events (readFormParameters, validate, save, etc.) registriert worden?
  6. In der Klasse wird abhängig vom EventName das Passende gemacht?
Wenn diese Bedingungen erfüllt sind, dann müssten alle Funktionen vernünftig aufgerufen werden.
Wie sieht denn der Eventlistener komplett aus (die ganze Klasse)? Vielleicht entdecken wir ja dort den Fehler. Über welche Variable führst du denn switch aus?
Mit freundlichen Grüßen
frmwrk_123

Nützliche Plugins zum Selberbauen

  • "Sebastian S." is male
  • "Sebastian S." started this thread

Posts: 595

Location: Stuttgart

Occupation: KFZ-Mechatroniker

  • Send private message

8

Saturday, August 4th 2012, 12:33am

Also ich habe ein wenig nachgedacht und auch herausgefunden, warum $errorField und $errorType nicht gefunden werden - ich hab die Klasse nie erweitert und vor allem die Elternmethoden nie aufgerufen. Stand jetzt ist, dass ich an der Klasse etwas experimnetiert habe, und auf etwas für mich unklares gestoßen bin.
Und zwar werden die Formularfelder bei jetzigem Stand der Codes nicht angezeigt. Kommentiere ich aber "extends ThreadAddForm" und "parent::assignVairables" aus nehme dafür aber die variablendefinition sowie deren Übergabe ans Template rein, erscheinen diese wieder.
Außerdem eine kleine Frage - Werden beim switch/case verfahren irgendwie automatisch Methoden erzeugt? Denn ich frage mich die ganze Zeit, ob ich z.B in case "submit" folgendes einsetzen soll oder wenn nichts anderes als in AbstractForm passiert das gar nicht nötig ist, der Teil also komplett weggelassen werden kann.

Zudem frage ich mich, wenn ich jetzt in submit $this->validate(); wird dann case 'validate': ausgeführt oder tatsächlich die der ThreadAddForm - es verwirrt mich ein wenig.

Achso bevor ichs vergesse - der EL landet von mir beabsichtigt im WBB verzeichnis, da es ein WBB Plugin ist, weil ohne ThreadAddForm nichts geht.

PHP Source code

1
2
3
case 'submit':
parent::submit();
break;

PHP Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php
//wcf imports
require_once(WCF_DIR.'lib/system/event/EventListener.class.php');

//wbb imports
require_once(WBB_DIR.'lib/form/ThreadAddForm.class.php');

class AdditionalMarketplaceFormFieldsListener extends ThreadAddForm implements EventListener {
    
    //define variables
    public $startAmount;
    public $buyImmediately;
    //public $errorField = '';
    //public $errorType = '';
    
    public function execute($eventObj$className$eventName) {
        
        //execute commands depending on eventName
        switch($eventName) {
            case 'assignVariables':
                parent::assignVariables();
                
                WCF::getTPL()->assign(array(
                'startAmount' => $this->startAmount,
                'buyImmediately' => $this->buyImmediately,
                //'errorField' => $this->errorField,
                //'errorType' => $this->errorType
                ));
                
                WCF::getTPL()->append('additionalInformationFields'WCF::getTPL()->fetch('additionalMarketplaceFormFields'));
            break;
            
            case 'submit':
            break;
            
            case 'readFormParameters':
                if(isset($_POST['startAmount'])) $this->startAmount intval($_POST['startAmount']);
                if(isset($_POST['buyImmediately'])) $this->buyImmediately intval($_POST['buyImmediately']);
            break;
            
            case 'validate':
            break;
            
            case 'save':
            break;
        }
    }
}
?>
Mit freundlichen Grüßen
Sebastian S.

This post has been edited 3 times, last edit by "Sebastian S." (Aug 4th 2012, 1:26am)


0xLeon

Member

  • "0xLeon" is male

Posts: 710

Location: Furtwangen

Occupation: Student (Medieninformatik)

  • Send private message

9

Saturday, August 4th 2012, 8:06am

Dein EventListener muss in keinem Fall von ThreadAddForm erben. Es gibt spezielle Fälle, wo soetwas nötig wäre, aber das ist hier nicht der Fall. Es ist nicht so, dass der Code sozusagen in die Klasse integriert wird. $this und parent verweisen in deinem EventListener nicht auf das Object von ThreadAddForm oder deren Elternklasse. Im EventListener zeigt $this auf das für einen Request gleiche Object deines EventListeners. parent ist für einfache EventListener, die nur das entsprechende Interface implementieren und sonst von keiner Klasse ergeben, irrelevant.
P.S.: Der Aufruf von WCF::getTPL()->append() sollte meiner Meinung nach im show-Event ausgeführt werden, da erst dort alle Variablen in der Templateengine verfügbar sind, die die Klasse an selbige übergibt. Darunter eben auch die Fehlervariablen.
Meine Pakete
Invitation System – Plugin StoreGithub
Update Files Delete PIP – Plugin StoreGithub
Kein Support via PN oder E-Mail.

  • "frmwrk_123" is male

Posts: 1,122

Location: Hamburg

Occupation: Informatikstudent

  • Send private message

10

Saturday, August 4th 2012, 9:55am

Du musst jetzt das extend ThreadAddForm herausnehmen. Als nächstes brauchst du keinen Verweis auf validate, etc. in einem anderen Event hereinzumachen, denn dein Eventlistener wird automatisch bei jedem der Events aufgerufen, für das er registriert wurde.

Die eventlistener.xml muss dann so aussehen:

XML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="UTF-8"?>
<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/eventListener.xsd">
	<import>
		<eventlistener>
			<eventclassname>ThreadAddForm</eventclassname>
			<eventname>readFormParameters</eventname>
			<environment>user</environment>
			<listenerclassname>lib/system/event/listener/AdditionalMarketplaceFormFieldsListener</listenerclassname>
		</eventlistener>
		<eventlistener>
			<eventclassname>ThreadAddForm</eventclassname>
			<eventname>validate</eventname>
			<environment>user</environment>
			<listenerclassname>lib/system/event/listener/AdditionalMarketplaceFormFieldsListener</listenerclassname>
		</eventlistener>
		<eventlistener>
			<eventclassname>ThreadAddForm</eventclassname>
			<eventname>save</eventname>
			<environment>user</environment>
			<listenerclassname>lib/system/event/listener/AdditionalMarketplaceFormFieldsListener</listenerclassname>
		</eventlistener>
                <eventlistener>
			<eventclassname>ThreadAddForm</eventclassname>
			<eventname>assignVariables</eventname>
			<environment>user</environment>
			<listenerclassname>lib/system/event/listener/AdditionalMarketplaceFormFieldsListener</listenerclassname>
		</eventlistener>
	</import>
</data>
Mit freundlichen Grüßen
frmwrk_123

Nützliche Plugins zum Selberbauen

  • "Sebastian S." is male
  • "Sebastian S." started this thread

Posts: 595

Location: Stuttgart

Occupation: KFZ-Mechatroniker

  • Send private message

11

Saturday, August 4th 2012, 11:00am

Okay, dann habe ich das schonmal soweit verstanden. Es funktioniert jetzt auch FAST alles, wie es soll. Und zu letzterem denke ich mir schon fast wie es abläuft.
Und zwar soll das Feld "buyImmediately" geprüft werden, ob nur zahlen darin vorkommen und sobald ein Buchstabe darin vorkommt, soll es eine Fehlermeldung zurückgeben.

Jetzt habe ich den verdacht, dass die Zeile mir die Buchstaben einfach herausnimmt, und wenn gar keine Zahl darin vorkommt, eine 0 (leer) übergeben wird. Hab ich das richtig verstanden?

PHP Source code

1
if(isset($_POST['buyImmediately'])) $this->buyImmediately intval($_POST['buyImmediately']);

PHP Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?php
//wcf imports
require_once(WCF_DIR.'lib/system/event/EventListener.class.php');

class AdditionalMarketplaceFormFieldsListener implements EventListener {
    
    //define variables
    public $startAmount;
    public $buyImmediately;
    
    public function execute($eventObj$className$eventName) {
        
        //execute commands depending on eventName
        switch($eventName) {
            case 'show':
                WCF::getTPL()->append('additionalInformationFields'WCF::getTPL()->fetch('additionalMarketplaceFormFields'));
            break;
            
            case 'assignVariables':                
                WCF::getTPL()->assign(array(
                'startAmount' => $this->startAmount,
                'buyImmediately' => $this->buyImmediately,
                ));
            break;
            
            case 'readFormParameters':
                if(isset($_POST['startAmount'])) $this->startAmount intval($_POST['startAmount']);
                if(isset($_POST['buyImmediately'])) $this->buyImmediately intval($_POST['buyImmediately']);
            break;
            
            case 'validate':
                $this->validateStartAmount();
                $this->validateBuyImmediately();
            break;
            
            case 'save':
            break;
        }
    }
    
    protected function validateStartAmount() {
        if(empty($this->startAmount)) {
            throw new UserInputException('startAmount');
        }
    }
    
    protected function validateBuyImmediately() {
        if(!empty($this->buyImmediately)) {
            if($this->buyImmediately <= $this->startAmount) {
                throw new UserInputException('buyImmediately','tooSmall');
            }
            if(!preg_match('/^[0-9]+/',$this->buyImmediately)) {
                throw new UserInputExcpetion('buyImmediately''illegalCharacters');
            }
        }
    }
}
?>
Mit freundlichen Grüßen
Sebastian S.

This post has been edited 3 times, last edit by "Sebastian S." (Aug 4th 2012, 4:46pm)


0xLeon

Member

  • "0xLeon" is male

Posts: 710

Location: Furtwangen

Occupation: Student (Medieninformatik)

  • Send private message

12

Saturday, August 4th 2012, 6:26pm

Lass den Aufruf von intval() in dem Fall einfach weg. Dein RegEx stellt danach ja sowieso sicher, dass nur Ziffer in diesem String enthalten sind. Wird das dann an die Datenbank übergeben, ist so auch sichergestellt, dass kein SQL-Injection stattfinden kann.
Meine Pakete
Invitation System – Plugin StoreGithub
Update Files Delete PIP – Plugin StoreGithub
Kein Support via PN oder E-Mail.

  • "Sebastian S." is male
  • "Sebastian S." started this thread

Posts: 595

Location: Stuttgart

Occupation: KFZ-Mechatroniker

  • Send private message

13

Saturday, August 4th 2012, 7:48pm

Ah alles klar, danke.
Mit freundlichen Grüßen
Sebastian S.


0xLeon

Member

  • "0xLeon" is male

Posts: 710

Location: Furtwangen

Occupation: Student (Medieninformatik)

  • Send private message

14

Saturday, August 4th 2012, 11:10pm

Wurde eben noch auf etwas hingewiesen. Und da ich mir nur deine Aussage durchlas und weniger genau den Code angesehen hab, ist mir das nicht aufgefallen: Dein RegEx überprüft nur, ob der String mit Ziffern beginnt. Folgen auf Ziffern am Anfang andere Zeichen, würde keine Exception ausgelöst werden.
Meine Pakete
Invitation System – Plugin StoreGithub
Update Files Delete PIP – Plugin StoreGithub
Kein Support via PN oder E-Mail.

  • "Sebastian S." is male
  • "Sebastian S." started this thread

Posts: 595

Location: Stuttgart

Occupation: KFZ-Mechatroniker

  • Send private message

15

Saturday, August 4th 2012, 11:45pm

Auch gemerkt. Ein dollarzeichen hat das für mich aber behoben ;)

PHP Source code

1
2
3
if(!preg_match('/^[0-9]+$/',$this->startAmount)) {
            throw new UserInputException('startAmount','illegalCharacters');
        }
Mit freundlichen Grüßen
Sebastian S.

This post has been edited 1 times, last edit by "Sebastian S." (Aug 4th 2012, 11:57pm)