Best Practices für Dateisysteme

10

Ich arbeite an einer Magento 2-Erweiterung, die das Lesen von Dateien aus dem Dateisystem erfordert.
Wenn der PHP-Sniffer unter Verwendung der ECGM2-Standards ausgeführt wird, beschwert er sich über die Tatsache, dass ich Funktionen wie basenameoder verwende dirname.

Die Verwendung der Funktion dirname () ist verboten

oder

Die Verwendung der Funktion basename () ist verboten

Welchen Wrapper sollte ich anstelle dieser verwenden, um den gleichen Effekt zu erzielen?

[BEARBEITEN]
Hier ist ein Code, der jedoch für die Frage nicht so relevant ist.
Ich habe eine Sammlungsklasse, die die \Magento\Framework\Data\Collection\FilesystemKlasse erweitert, und ich möchte diese Sammlung in einem Raster (UI-Komponenten) auflisten. Eine der Aktionen im Raster ist eine Download-Aktion.
Dazu muss ich den tatsächlichen Namen der Datei erhalten, damit ich sie an die Download-Aktion senden kann.

    // here $file is dynamic and it can be
    // folder/filename.xml or folder/subfolder/file.tar.gz
    //so there is no strict number of folders and subfolders.
    $file = $downloader->getRelativePath($packageName);
    $relativeFile = UmcFilesystem::VAR_DIR_NAME . '/' .$file;
    $absoluteFile = $rootDir->getAbsolutePath($relativeFile);
    if ($rootDir->isFile($relativeFile) && $rootDir->isReadable($relativeFile)){
        //I don't want to use `explode` just for the sake of avoiding basename
        $fileName = basename($absoluteFile);
        $this->fileFactory->create(
            $fileName,
            null,
            DirectoryList::VAR_DIR,
            'application/octet-stream',
            $rootDir->stat($relativeFile)['size']
        );

        $resultRaw = $this->resultRawFactory->create();
        $resultRaw->setContents($rootDir->readFile($relativeFile));
        return $resultRaw;
    } else {
       ...
    }
Marius
quelle
Können Sie einen Teil Ihres Codes freigeben, was Sie versucht haben, Datei aus dem System zu lesen.
Dhiren Vasoya
Ich habe Code hinzugefügt, aber er ist für die Frage völlig irrelevant. Die Frage ist irgendwie abstrakt. Was soll ich anstelle des Basisnamens verwenden, damit sich der Code-Sniffer nicht beschwert?
Marius
Es sieht nur nach einer Berechtigungsfrage aus.
Ashish Jagnani
Es hat nichts mit Berechtigungen zu tun. Der Code funktioniert ordnungsgemäß, aber der Code-Sniffer sagt, dass er dort nicht verwendet basenamewerden sollte. Bitte lesen Sie die Frage sorgfältig durch.
Marius

Antworten:

15

Ich brauchte in letzter Zeit auch so etwas. Einzige Lösung, die ich gefunden habe basenameund die ich dirnameverwendet habe:

\ Magento \ Framework \ Dateisystem \ Io \ Datei

protected function someFunction()
{
    /** @var \Magento\Framework\Filesystem\Io\File $fileSystemIo **/
    $fileInfo = $this->fileSystemIo->getPathInfo('<absolutePath>');
    $basename = $fileInfo['basename'] 
    $dirname = $fileInfo['dirname'];
}

Vorher habe ich versucht Magento\Framework\Filesystem\Directory\Writeund getDriver()ohne Erfolg. Mit ihnen kann man so ziemlich alles bekommen, aber nicht das basename.

Jalogut
quelle
JA. Das ist es. Vielen Dank. Ich werde das Kopfgeld vergeben, sobald ich darf.
Marius
Marius, wirst du es wirklich so umsetzen? [\ Magento \ Framework \ Filesystem \ Io \ File-> getpathinfo] [1] ruft buchstäblich nur [pathinfo] [2] auf, das wiederum den Basisnamen und den Verzeichnisnamen [1] aufruft: github.com/magento/magento2/blob/develop/ lib / internal / Magento /… [2]: github.com/php/php-src/blob/master/ext/standard/string.c#L1662
Richard
1
@ Richard. Das habe ich gesehen. Im Moment muss / möchte ich bestimmte Funktionen vermeiden. Und in meinem speziellen Fall passt es gut, weil ich bereits eine Instanz von \Magento\Framework\Filesystem\Io\Filein meiner eigenen Klasse für eine andere Funktionalität injiziert hatte. Ich wusste einfach nicht im Voraus über die getPathInfoMethode Bescheid .
Marius
3

Zum Glück können wir mit git sehen, wann dirname und basename verboten waren. Der Grund dafür ist eindeutig "Hinzugefügte Dateien".

Wenn Sie sich das Problem für das EKG-Projekt ansehen, sehen Sie geschlossene Probleme, z. B. etwas Schlechtes in file_exists? # 33 , Fehlerfunktionen # 26 , etwas Schlechtes an diesen Funktionen? # 17 , Kontext / Erklärung für die Regeln # 12 , Die Verwendung der Funktion iconv () ist verboten # 14, was mich denken lassen würde, dass die anfängliche Liste der verbotenen Funktionen nicht zu sehr berücksichtigt wurde und Magento wahrscheinlich geändert werden kann die verbotene Liste.

Das Durchsuchen der m2-Codebasis zeigt ~ = 78 Ergebnisse für den Basisnamen, eine Mischung aus Variablen und den Code, der tatsächlich den Basisnamen aufruft, einschließlich meines Favoriten .

Ich denke, wenn ich du wäre, würde ich ein Problem auf Github posten und zlik fragen, ob er immer noch glaubt, dass sie dorthin gehören oder ob M2 einen Wrapper bereitstellt

Richard
quelle
2

Sie können ein Objekt der SplFileInfo()Klasse verwenden, möglicherweise funktioniert es.

$info = new SplFileInfo('/path/to/foo.txt');
var_dump($info->getFilename())

Vielleicht wird es funktionieren.

Sie können auch auf diese URL verweisen .

Chirag
quelle
Danke dafür. Es sieht sauberer aus, aber haben Sie ein Codebeispiel, das dies tut? Ich möchte den Kernstandards folgen.
Marius
Sie können php.net/manual/en/splfileinfo.getfilename.php diese URL verweisen .
Chirag
2

Mein Vorschlag wäre, das Magento/BackupModul als Beispiel zu verwenden.

Es wäre interessant zu sehen, wie die Download-Aktionsklasse geschrieben ist, da sie sich auch mit realen Dateien zum Herunterladen befasst:

public function execute()
{
    /* @var $backup \Magento\Backup\Model\Backup */
    $backup = $this->_backupModelFactory->create(
        $this->getRequest()->getParam('time'),
        $this->getRequest()->getParam('type')
    );

    if (!$backup->getTime() || !$backup->exists()) {
        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultRedirectFactory->create();
        $resultRedirect->setPath('backup/*');
        return $resultRedirect;
    }

    $fileName = $this->_objectManager->get('Magento\Backup\Helper\Data')->generateBackupDownloadName($backup);

    $this->_fileFactory->create(
        $fileName,
        null,
        DirectoryList::VAR_DIR,
        'application/octet-stream',
        $backup->getSize()
    );

    /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */
    $resultRaw = $this->resultRawFactory->create();
    $resultRaw->setContents($backup->output());
    return $resultRaw;
}

Für mich sollten Sie sich ansehen, wie diese Methode die Datei generiert, die mit \Magento\Framework\App\Response\Http\FileFactoryund generateBackupDownloadNamevon heruntergeladen werden soll Magento\Backup\Helper\Data(beachten Sie die empfohlene Verwendung des OM;))

Ein weiteres interessantes Stück

Eine weitere interessante Sache , die Sie betrachten sollten , ist die getStorageDataMethode aus Magento\MediaStorage\Model\ResourceModel\File\Storage\Filedem sich Anrufe direkt dirnameund basenameaber , wenn Sie diese Kernmethode in Ihrem Modul aufrufen, werden Sie nicht die verbotenen Fehler bekommen;)

public function getStorageData($dir = '/')
{
    $files = [];
    $directories = [];
    $directoryInstance = $this->_filesystem->getDirectoryRead(DirectoryList::MEDIA);
    if ($directoryInstance->isDirectory($dir)) {
        foreach ($directoryInstance->readRecursively($dir) as $path) {
            $itemName = basename($path);
            if ($itemName == '.svn' || $itemName == '.htaccess') {
                continue;
            }
            if ($directoryInstance->isDirectory($path)) {
                $directories[] = [
                    'name' => $itemName,
                    'path' => dirname($path) == '.' ? '/' : dirname($path),
                ];
            } else {
                $files[] = $path;
            }
        }
    }

    return ['files' => $files, 'directories' => $directories];
}

In einer ähnlichen Idee gibt es auch die collectFileInfovonMagento\MediaStorage\Helper\File\Media

Raphael beim digitalen Pianismus
quelle
generateBackupDownloadNameverwendet einige magische Getter aus dem Backup-Modell. Also müssen sie vorher magische Setter haben. Ich sehe nichts im Zusammenhang mit dem Basisnamen oder einer Alternative dazu.
Marius
@Marius sehen meine aktualisierte Antwort für einen anderen möglichen Weg
Raphael bei Digital Pianism
Das könnte funktionieren. Ich werde es versuchen und mit den Ergebnissen zurückkommen.
Marius
@Marius überprüfen auch collectFileInfovon Magento\MediaStorage\Helper\File\Media;)
Raphael bei Digital Pianism
collectFileInfohilft mir nicht, weil es eine Datei im Medienordner erwartet. Meins befindet sich im Ordner var. Hat getStorageDataauch nichts mit dem zu tun was ich brauche. Ich möchte nicht alle Dateien in einem Ordner sammeln. Ich habe bereits den Dateinamen.
Marius