Erweiterung Form TagLib file

Dieser Bereich dient dazu, eure Tricks und Erweiterungen vorzustellen, damit diese auch andere Anwender nutzen können. // This area can be used to publish your tricks and extensions to the APF to be used by other developers.
Thalo
Beiträge: 240
Registriert: 10.08.2009, 16:56:52

Erweiterung Form TagLib file

Beitrag von Thalo » 10.01.2010, 19:39:37

Hi,

wie mit Doc bereits per PM besprochen möcht ich einen kurzen Vorschlag zur Erweiterung der TagLib posten, womit es möglich sein soll, Files direkt aus der TagLib abzufragen:


Single File Upload:

template:

Code: Alles auswählen

<form:file name="file1" />

controller:

Code: Alles auswählen

$formular = $this->__getForm('formular');
$element = $formular->getFormElementByName('file1');

Code: Alles auswählen

// gibt true zurück sofern der User eine Datei übertragen hat, andernfalls false
$element->hasFile()

Code: Alles auswählen

// gibt ein File Model zurück wenn hasFile true, sonst false
$file = $element->getFile();

Code: Alles auswählen

$file->getOriginalName() // Dateinamen
$file->getSize() // Dateigröße
$file->getExtension() // Dateiende
$file->getMimeType() // Mime-Type
$file->getHash() //CRC32  Hash
$file->getTemporaryName() // Temporärname
$file->getBlob() // Binärdaten
ein Multiupload könnte so ausschauen:

template:

Code: Alles auswählen

<form:file name="file1" />
<form:file name="file2" />
<form:file name="file3" />
<form:file name="file4" />
<form:file name="file5" />

controller:

Code: Alles auswählen

$formular = $this->__getForm('formular');
$elements = $formular->getFormElementsByTagName('form:file');

foreach($elements AS $element) {
    echo ($element->hasFile() ? "Ja" : "Nein")."<br>";
}
durch das hinzufügen einiger neuer Validatoren könnte man dann auch die Prüfung zentral abhandeln.


Meinungen?
Zuletzt geändert von Thalo am 10.01.2010, 20:08:00, insgesamt 1-mal geändert.

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: Erweiterung Form TagLib file

Beitrag von Screeze » 10.01.2010, 19:48:38

wenn das ausreichend transparent für die validatoren ist, zwecks dateityp/grösse prüfung etc. finde ich das eine gute Idee.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4527
Registriert: 04.11.2007, 16:13:53

Re: Erweiterung Form TagLib file

Beitrag von dr.e. » 10.01.2010, 21:04:22

Hallo Thalo,

klingt für mich - wie per PN schon angesprochen - nach einer sehr sinnvollen Erweiterung. Wichtig - wie Screeze das schon anmerkte - sind die Möglichkeit, Validatoren und Filter anzuhängen. Gerade das Http-File-Upload ist eine Sache, bei der man immer wieder die selbe Funktionalität schreiben muss, weil das nicht vernünftig abstrahierbar ist. Ein idealer Ansatzpunkt eines Frameworks.
gibt ein File Model zurück wenn hasFile true, sonst false
Wie soll das Model aussehen und welche Funktionen besitzt es umsetzungstechnisch? Wird die Datei direkt in einen Ordner "hochgeladen"?
Viele Grüße,
Christian

Thalo
Beiträge: 240
Registriert: 10.08.2009, 16:56:52

Re: Erweiterung Form TagLib file

Beitrag von Thalo » 10.01.2010, 21:42:13

Hi Doc,
gibt ein File Model zurück wenn hasFile true, sonst false
Wie soll das Model aussehen und welche Funktionen besitzt es umsetzungstechnisch? Wird die Datei direkt in einen Ordner "hochgeladen"?
Das Model hatte ich ja oben schon einmal kurz angeschnitten:

Code: Alles auswählen

$file->getOriginalName() // Dateinamen
$file->getSize() // Dateigröße
$file->getExtension() // Dateiende
$file->getMimeType() // Mime-Type
$file->getHash() //CRC32  Hash
$file->getTemporaryName() // Temporärname
$file->getBlob() // Binärdaten
neben den üblichen Informationen aus dem $_FILES - Array bietet es noch einen CRC32 Hash zur Redundanzprüfung und die oft benötigte Extension.

Ob es sinvoll ist die Datei direkt zu verschieben weiß ich nicht. Schließt natürlich die Möglichkeit, weitere Operationen an der Datei vorzunehmen bevor sie verschoben wird aus. Ursprünglich war es geplant das File über den FileSystemHandler im Controller selbst zu verschieben. Vielleicht sollte man hier ein weiteres Attribut zum file-Element hinzufügen, sofern gesetzt verschieben nach Validation, ansonsten dem Programmierer überlassen.

Für Leute die (lieber) PHP Modul als die CGI Version einsetzen, muss auch noch die Möglichkeit für chmod und chown gegeben sein.

Vielleicht hat jemand von euch ja noch eine bessere Idee? :)

Benutzeravatar
dr.e.
Administrator
Beiträge: 4527
Registriert: 04.11.2007, 16:13:53

Re: Erweiterung Form TagLib file

Beitrag von dr.e. » 10.01.2010, 22:22:09

Hallo Thalo,

ich finde die Idee wirklich gut. Magst du das implementieren, dann integriere ich das ins APF. Voraussetzung dafür ist, dass die Komponenten eine deutsche und englische Dokumentation sowie kommentierten Code beinhaltet. Relevanter Namespace für die Taglib ist tools::form::taglib, das Model sollte unter tools::form::model liegen.

Was die Validierung angeht, sollte es Validatoren geben, die definierte Werte wie Größe oder Extension/Mime-Type prüfen. Falls nicht korrekt, soll das Formular - wie bei allen anderen Validatoren auch - als invalid gekennzeichnet werden. Filter machen in diesem Zusammenhang recht wenig Sinn (habe darüber nochmal nachgedacht), denn es soll ja nichts am Inhalt verändert werden.

Was die automatische Verschiebung angeht, so würde ich hier meiner vorherigen Meinung gerne wiedersprechen und mich dir anschließen: es macht fast keinen Sinn, das automatisch anzubieten, denn die Funktion ist a) bereits implementierung und nahezu immer eine dynamische Angelegenheit. Das kann nicht statisch in einer Taglib konfigriert werden.
Viele Grüße,
Christian

Thalo
Beiträge: 240
Registriert: 10.08.2009, 16:56:52

Re: Erweiterung Form TagLib file

Beitrag von Thalo » 14.01.2010, 20:26:28

Hallo,

hat etwas gedauert..

ich poste hier mal meinen Vorschlag:

File Model:

Code: Alles auswählen

<?php

/**
 * Represents the User domain object
 *
 * @version
 * Version 0.1, 14.01.2010<br>
 *
 */

class FileModel {
    private $__name;
    private $__size;
    private $__extension;
    private $__mimeType;
    private $__temporaryName;

    public function getName() {
        return $this->__name;
    }

    public function setName($name) {
        $this->__name = $name;
    }

    public function getSize() {
        return $this->__size;
    }

    public function setSize($size) {
        $this->__size = (int)$size;
    }

    public function getExtension() {
        return $this->__extension;
    }

    public function setExtension($extension) {
        return $this->__extension = $extension;
    }

    public function getMimeType() {
        return $this->__mimeType;
    }

    public function setMimeType($mimeType) {
        $this->__mimeType = $mimeType;
    }

    public function getTemporaryName() {
        return $this->__temporaryName;
    }

    public function setTemporaryName($temporaryName) {
        $this->__temporaryName = $temporaryName;
    }
}

?>
Form Taglib:

Code: Alles auswählen

      /**
       * @public
       *
       * Checks whether a file has been transferred
       *
       * @return bool Returns TRUE if a file has been transferred, FLASE otherwise.
       *
       * @version
       * Version 0.1 12.01.2010<br />
       */
      public function hasFile() {
          if(isset($_FILES[$this->getAttribute('name')]) && $_FILES[$this->getAttribute('name')]['error'] === 0){
                 return true;
          }

          return false;
      }

      /**
       * @public
       *
       * Returns the File Domain Object
       *
       * @return obj|null Returns a File Domain Object if TRUE, NULL otherwise.
       *
       * @version
       * Version 0.1 12.01.2010<br />
       */
      public function getFile() {
          if(!$this->hasFile()){
              return null;
          }

          return $this-> __mapFileArray2DomainObject($_FILES[$this->getAttribute('name')]);
      }

      /**
       * @private
       *
       * Maps the File Array to the File Domain Object
       *
       * @param File Array
       *
       * @version
       * Version 0.1 12.01.2010<br />
       */
      private function __mapFileArray2DomainObject($file) {
          if(class_exists('finfo', false)) {
	       $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME;

                     $finfo = finfo_open($const);
	    		$mime = finfo_file($finfo, $file['tmp_name']);
        }
	 else if(function_exists('mime_content_type')) {
	     $mime = mime_content_type($file['tmp_name']);
        }
	 else
	 {
            $mime = $file['type'];
	 }

            $fileModel = new FileModel();
            $fileModel->setMimeType($mime);
            $fileModel->setName($file['name']);
            $fileModel->setSize(filesize($file['tmp_name']));
            $fileModel->setTemporaryName($file['tmp_name']);
            $fileModel->setExtension(substr(strrchr($file['name'],"."), 1));

             return $fileModel;
        } 
hier würde mich besonders interessen, ist das zu viel Logik im Mapper? Wie könnte ich das mit dem MimeType eleganter lösen?

beispiel eines Validators:

Code: Alles auswählen

class MimeTypeValidator extends TextFieldValidator {

    public function validate($value) {
        if(!$this->__Control->hasFile()) {
            return false;
        }
 
        $fileModel = $this->__Control->getFile();

        $accepts = $this->__Control->getAttribute('accepts');
        $this->__Control->deleteAttribute('accepts');

        $accepts = explode('|', $accepts);

        if(in_array($fileModel->getMimeType(), $accepts) {
            return true;
        }

        return false;
    }
}
Würde eure Kritiken begrüßen :)

Benutzeravatar
dr.e.
Administrator
Beiträge: 4527
Registriert: 04.11.2007, 16:13:53

Re: Erweiterung Form TagLib file

Beitrag von dr.e. » 15.01.2010, 00:50:19

Hallo Thalo,

die Implementierung gefällt mir gut. Hier einige Anmerkungen:
  • hasFile() würde ich besser hasUploadedFile() nennen, das ist intuitiver. Ebenso getFile() -> getUploadedFile()
  • um finfo_open() nutzen zu können braucht es PHP 5.3 als minimale Version. Deshalb finde ich es schön, dass du gleich einen Backport mitlieferst!
hier würde mich besonders interessen, ist das zu viel Logik im Mapper? Wie könnte ich das mit dem MimeType eleganter lösen?
Nein, das ist völlig ok so. An dieser Stelle kannst du ja auch nicht anders agieren, denn die Logik muss IMHO in der Taglib gekapselt sein. Andernfalls würde das für die APF-Formulare keinen Mehrwert bieten.
beispiel eines Validators:
Gute Umsetzung! Schön finde ich die Möglichkeit, MIME-Typen bzw. Endungen spezifizieren zu können.

Wenn du möchtest, nehme ich das in den Code von 1.12 auf, einen derartigen Branch erzeuge ich am Wochenende.
Viele Grüße,
Christian

Thalo
Beiträge: 240
Registriert: 10.08.2009, 16:56:52

Re: Erweiterung Form TagLib file

Beitrag von Thalo » 17.01.2010, 23:32:08

Hi Doc,

ich hatte das total vergessen. :oops: kannst du gerne in den Branch mit aufnehmen.

Bist du der Meinung ich sollte das Model einfach mit dem Mime-Type aus dem $_FILES - Array füllen?

Benutzeravatar
dr.e.
Administrator
Beiträge: 4527
Registriert: 04.11.2007, 16:13:53

Re: Erweiterung Form TagLib file

Beitrag von dr.e. » 17.01.2010, 23:36:12

Hi,

kein Ding!
Bist du der Meinung ich sollte das Model einfach mit dem Mime-Type aus dem $_FILES - Array füllen?
Nein, mir gefällt die Implementierung so, weil du Fallbacks eingebaut hast. Das passt also! :geek:
Viele Grüße,
Christian

Thalo
Beiträge: 240
Registriert: 10.08.2009, 16:56:52

Re: Erweiterung Form TagLib file

Beitrag von Thalo » 18.01.2010, 00:36:55

Hi Doc,

ich werde deine Anmerkungen noch ändern und dir dann ein Archiv mit weiteren Validatoren posten.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4527
Registriert: 04.11.2007, 16:13:53

Re: Erweiterung Form TagLib file

Beitrag von dr.e. » 03.02.2010, 23:39:07

Hallo Thalo,

ich hab deinen Code in den 1.12er Branch integriert (lokal) und getestet - passt soweit. Hast du noch weitere Validatoren vorgesehen? Falls nicht, checke ich das ein.

Schön finde ich, dass File-Upload jetzt mit einer Zeile erledigt werden kann (hier ausgeschrieben; Beispielcode):

Code: Alles auswählen

$file = $image->getFile();
$fileName = $file->getName();
$tmpFile = $file->getTemporaryName();
FilesystemManager::copyFile($tmpFile,'./upload/'.$fileName, true);
Das ist ein echter Mehrwert für das Framework. Danke für die Idee und die Arbeit! :geek:

EDIT: ich habe ein kurzes HOWTO im Wiki unter http://wiki.adventure-php-framework.org ... rm-Taglibs geschrieben. Update der Doku erfolgt demnächst.
Viele Grüße,
Christian

Thalo
Beiträge: 240
Registriert: 10.08.2009, 16:56:52

Re: Erweiterung Form TagLib file

Beitrag von Thalo » 18.02.2010, 21:13:53

Hi,

hier sind noch 2 Validatoren:

Extension Validator:

Code: Alles auswählen

import('tools::form::validator','TextFieldValidator');


class FileExtensionValidator extends TextFieldValidator {

	public function validate($value) {

		if(!$this->__Control->hasFile()) {
			return false;
		}

		$extensions = $this->__Control->getAttribute('extensions');
		$extension = explode('|', $extensions);
		
		$fileModel = $this->__Control->getFile();

		$this->__Control->deleteAttribute('extensions');
		
		return in_array($fileModel->getExtension(), $extension);
	}
}
Attribute: extensions

File Size Validator:

Code: Alles auswählen

import('tools::form::validator','TextFieldValidator');

class FileSizeValidator extends TextFieldValidator {

    public function validate($value) {
        if(!$this->__Control->hasFile()) {
            return false;
        }

        $fileModel = $this->__Control->getFile();

        $minSize = $this->__Control->getAttribute('minsize');
        $this->__Control->deleteAttribute('minsize');

        $maxSize = $this->__Control->getAttribute('maxsize');
        $this->__Control->deleteAttribute('maxsize');

        if($fileModel->getSize() >= $minSize && $fileModel->getSize() <= $maxSize) {
            return true;
        }

        return false;
    }
}
Attribute: min und max

viele Frameworks (bzw Librarys) bieten noch einen Validator basierend auf getimagesize an. Meines Wissens nach arbeitet dieser aber intern genauso wie Finfo (Anhand der Magischen Zahl den Mime-Type zuordnen). Kann das jemand bestätigen?

Sonst würde ich vorschlagen noch eine Methode getNameWithoutExtension zu implementieren.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4527
Registriert: 04.11.2007, 16:13:53

Re: Erweiterung Form TagLib file

Beitrag von dr.e. » 19.02.2010, 22:13:22

Hallo Thalo,

ich habe bereits zwei Validatoren in den 1.12-er Branch integriert: MimeTypeValidator und FileSizeValidator. Diese validieren nach MIME-Typen und maximaler Datei-Größe. Ich würde daher nur den FileExtensionValidator mit aufnehmen, sonst ist das File-Size-Thema doppelt belegt. Einverstanden?
Viele Grüße,
Christian

Thalo
Beiträge: 240
Registriert: 10.08.2009, 16:56:52

Re: Erweiterung Form TagLib file

Beitrag von Thalo » 19.02.2010, 22:36:41

dr.e. hat geschrieben:Hallo Thalo,

ich habe bereits zwei Validatoren in den 1.12-er Branch integriert: MimeTypeValidator und FileSizeValidator. Diese validieren nach MIME-Typen und maximaler Datei-Größe. Ich würde daher nur den FileExtensionValidator mit aufnehmen, sonst ist das File-Size-Thema doppelt belegt. Einverstanden?
Klar. Aber soweit mir das aus dem Artikel hervorgeht bietet der Validator keine Möglichkeit auf minsize zu prüfen. Optional wäre das noch super wenn du das implementieren würdest. So hält man sich auch die 0-Byte-Dateien vom Server :)

Benutzeravatar
dr.e.
Administrator
Beiträge: 4527
Registriert: 04.11.2007, 16:13:53

Re: Erweiterung Form TagLib file

Beitrag von dr.e. » 20.02.2010, 13:31:36

Hallo Thalo,

kein Problem, das baue ich noch ein. Melde mich, sobald ich die Änderung eingecheckt habe.
Viele Grüße,
Christian

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast