Best practice per il filesystem


11

Sto lavorando su alcune estensioni di Magento 2 che richiedono la lettura di file dal file system.
Quando si esegue lo sniffer php utilizzando gli standard ECGM2, si lamenta del fatto che sto usando funzioni come basenameo dirname.

L'uso della funzione dirname () è proibito

o

L'uso della funzione basename () è vietato

Quale wrapper dovrei usare al posto di quelli per ottenere lo stesso effetto?

[EDIT]
Ecco un po 'di codice, ma non è così rilevante per la domanda.
Ho una classe di raccolta che estende la \Magento\Framework\Data\Collection\Filesystemclasse e voglio elencare questa raccolta in una griglia (componenti ui) e una delle azioni nella griglia è un'azione di download.
Per questo, ho bisogno di ottenere il nome effettivo del file in modo da poterlo inviare all'azione di download.

    // 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 {
       ...
    }

puoi condividere parte del tuo codice, cosa hai provato a leggere il file dal sistema.
Dhiren Vasoya,

Ho aggiunto del codice, ma è del tutto irrilevante per la domanda. La domanda è in qualche modo astratta. cosa devo usare al posto di basename in modo che lo sniffer di codice non si lamenta?
Marius

Sembra solo un problema di autorizzazione.
Ashish Jagnani,

Non ha nulla a che fare con le autorizzazioni. Il codice funziona correttamente, ma lo sniffer di codice dice che non dovrebbe essere utilizzato basenamelì. Si prega di leggere attentamente la domanda.
Marius

Risposte:


16

Ho anche avuto bisogno di qualcosa del genere di recente. L'unica soluzione che ho trovato per ottenere basenamee dirnamestava usando:

\ Magento \ Framework \ Filesystem \ Io \ File

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

Prima ho provato a usare Magento\Framework\Filesystem\Directory\Writee getDriver()senza successo. Con loro puoi ottenere praticamente tutto ma non il basename.


SÌ. Questo è tutto. Grazie. Assegnerò la taglia non appena mi sarà permesso.
Marius

Marius, lo implementerai davvero in quel modo? [\ Magento \ Framework \ Filesystem \ Io \ File-> getpathinfo] [1] chiama letteralmente solo [pathinfo] [2] che a sua volta chiama basname e dirname [1]: 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. L'ho visto. Per ora ho bisogno / voglio evitare determinate funzioni. E nel mio caso specifico si adatta bene perché avevo già un'istanza di \Magento\Framework\Filesystem\Io\Fileiniettata nella mia classe per una diversa funzionalità. Non sapevo in anticipo il getPathInfometodo.
Marius

3

Fortunatamente git ci fa vedere quando sono stati vietati dirname e basename , il motivo è chiaramente "File aggiunti"

Guardando il problema per il progetto ECG puoi vedere problemi chiusi come qualcosa di negativo in file_exists? # 33 , Funzioni di errore # 26 , qualcosa di negativo in queste funzioni? # 17 , Contesto / Spiegazione per le Regole # 12 , L'uso della funzione iconv () è proibito # 14 che mi farebbe pensare che l'elenco iniziale delle funzioni proibite non sia stato preso troppo in considerazione, e che probabilmente il magento è suscettibile di cambiare l'elenco proibito.

La ricerca nella base di codice m2 mostra ~ = 78 risultati per basename, un mix di variabili e il codice che in realtà chiama basename, incluso il mio preferito .

Penso che se fossi in te pubblicherei un problema su Github e chiedere a Zlik se pensa ancora che appartengano a loro o se M2 fornisce un wrapper


2

È possibile utilizzare l'oggetto di SplFileInfo()classe potrebbe funzionare.

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

potrebbe essere che funzionerà.

puoi anche fare riferimento a questo URL.


Grazie per questo. Sembra più pulito, ma hai un esempio di codice che lo fa? Voglio seguire gli standard di base.
Marius

puoi fare riferimento a php.net/manual/en/splfileinfo.getfilename.php questo URL.
Chirag,

2

Il mio consiglio sarebbe di usare il Magento/Backupmodulo come esempio.

Il modo in cui viene scritta la classe di azioni di download sarebbe interessante perché si occupa anche di file reali da scaricare:

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;
}

Per me dovresti guardare come questo metodo genera il file da scaricare usando \Magento\Framework\App\Response\Http\FileFactorye generateBackupDownloadNameda Magento\Backup\Helper\Data(nota l'uso raccomandato dell'OM;))

Un altro pezzo interessante

Un'altra cosa interessante che dovresti guardare è il getStorageDatametodo da Magento\MediaStorage\Model\ResourceModel\File\Storage\Filecui stesso chiama direttamente dirnamee basenamema se chiami quel metodo di base nel tuo modulo, non otterrai gli errori proibiti;)

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 un'idea simile, c'è anche il collectFileInfodaMagento\MediaStorage\Helper\File\Media


generateBackupDownloadNameutilizza alcuni getter magici dal modello di backup. Quindi devono avere chiamati setter magici prima. Non vedo nulla di correlato a basename o un'alternativa ad esso.
Marius

@Marius vedi la mia risposta aggiornata per un altro modo possibile
Raffaello al Pianismo digitale,

Questo potrebbe funzionare. Ci proverò e tornerò con i risultati.
Marius

@ Mario controlla anche collectFileInfoda Magento\MediaStorage\Helper\File\Media;)
Raffaello al Pianismo digitale,

collectFileInfonon mi aiuterà perché si aspetta un file all'interno della cartella multimediale. Il mio è nella cartella var. Inoltre getStorageDatanon ha nulla a che fare con ciò di cui ho bisogno. Non voglio raccogliere tutti i file in una cartella. Ho già il nome del file.
Marius
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.