Meilleures pratiques du système de fichiers

11

Je travaille sur une extension Magento 2 qui nécessite la lecture de fichiers à partir du système de fichiers.
Lorsque vous exécutez le renifleur php en utilisant les normes ECGM2, il se plaint du fait que j'utilise des fonctions comme basenameou dirname.

L'utilisation de la fonction dirname () est interdite

ou

L'utilisation de la fonction basename () est interdite

Quel emballage devrais-je utiliser à la place de ceux pour obtenir le même effet?

[EDIT]
Voici du code, mais ce n'est pas très pertinent pour la question.
J'ai une classe de collection qui étend la \Magento\Framework\Data\Collection\Filesystemclasse et je veux lister cette collection dans une grille (ui-components) et l'une des actions dans la grille est une action de téléchargement.
Pour cela, je dois obtenir le nom réel du fichier afin de pouvoir l'envoyer à l'action de téléchargement.

    // 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
la source
pouvez-vous partager une partie de votre code, ce que vous avez essayé de lire le fichier du système.
Dhiren Vasoya
J'ai ajouté du code, mais cela n'a absolument rien à voir avec la question. La question est en quelque sorte abstraite. que dois-je utiliser à la place du nom de base pour que le renifleur de code ne se plaint pas?
Marius
Cela ressemble à un problème d'autorisation uniquement.
Ashish Jagnani
Cela n'a rien à voir avec les autorisations. Le code fonctionne correctement, mais le renifleur de code indique qu'il ne devrait pas être utilisé basenamelà-dedans. Veuillez lire attentivement la question.
Marius

Réponses:

16

J'ai aussi eu besoin de quelque chose comme ça récemment. La seule solution que j'ai trouvé pour obtenir basenameet dirnameutilisais:

\ 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'];
}

Avant cela, j'ai essayé d'utiliser Magento\Framework\Filesystem\Directory\Writeet getDriver()sans succès. Avec eux, vous pouvez obtenir à peu près tout, mais pas le basename.

Jalogut
la source
OUI. C'est ça. Je vous remercie. J'attribuerai la prime dès que j'y serai autorisé.
Marius
Marius, allez-vous vraiment l'implémenter de cette façon? [\ Magento \ Framework \ Filesystem \ Io \ File-> getpathinfo] [1] n'appelle littéralement que [pathinfo] [2] qui à son tour appelle nom de base et 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. J'ai vu ça. Pour l'instant, j'ai besoin / je veux éviter certaines fonctions. Et dans mon cas spécifique, cela correspond bien parce que j'avais déjà une instance d' \Magento\Framework\Filesystem\Io\Fileinjecté dans ma propre classe pour une fonctionnalité différente. Je ne savais tout simplement pas d'avance sur la getPathInfométhode.
Marius
3

Heureusement, git nous permet de voir quand dirname et basename étaient interdits , la raison en est clairement: "Fichiers ajoutés"

En regardant le problème du projet ECG, vous pouvez voir des problèmes fermés tels que quelque chose de mauvais dans file_exists? # 33 , Fonctions d'erreur # 26 , quelque chose de mal dans ces fonctions? # 17 , Contexte / Explication des règles # 12 , L'utilisation de la fonction iconv () est interdite # 14 ce qui me ferait penser que la liste initiale des fonctions interdites n'a pas été trop considérée, et magento est probablement susceptible de changer la liste des interdits.

La recherche dans la base de code m2 affiche ~ = 78 résultats pour le nom de base, un mélange de variables et le code appelant réellement le nom de base, y compris mon préféré .

Je pense que si j'étais vous, je posterais un problème sur github et demanderais à zlik s'il pense toujours qu'ils appartiennent à cet endroit ou si M2 fournit un wrapper

Richard
la source
2

Vous pouvez utiliser un objet de SplFileInfo()classe peut-être que cela fonctionnera.

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

peut-être que cela fonctionnera.

vous pouvez également renvoyer cette URL.

chirag
la source
Merci pour cela. Il semble plus propre, mais avez-vous un exemple de code qui fait cela? Je veux suivre les normes fondamentales.
Marius
vous pouvez référer php.net/manual/en/splfileinfo.getfilename.php cette url.
chirag
2

Ma suggestion serait d'utiliser le Magento/Backupmodule comme exemple.

La façon dont la classe d'actions de téléchargement est écrite serait intéressante à regarder car elle traite également des vrais fichiers à télécharger:

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

Pour moi, vous devriez regarder la façon dont cette méthode génère le fichier à télécharger en utilisant \Magento\Framework\App\Response\Http\FileFactoryet à generateBackupDownloadNamepartir de Magento\Backup\Helper\Data(notez l'utilisation recommandée de l'OM;))

Un autre morceau intéressant

Une autre chose intéressante que vous devriez regarder est la getStorageDataméthode à partir de Magento\MediaStorage\Model\ResourceModel\File\Storage\Filelaquelle elle-même appelle directement dirnameet basenamemais si vous appelez cette méthode principale dans votre module, vous n'obtiendrez pas les erreurs interdites;)

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

Dans une idée similaire, il y a aussi le collectFileInfodeMagento\MediaStorage\Helper\File\Media

Raphael chez Digital Pianism
la source
generateBackupDownloadNameutilise des getters magiques du modèle de sauvegarde. Ils doivent donc faire appeler des arrangeurs magiques avant. Je ne vois rien lié au nom de base ou une alternative à celui-ci.
Marius
@Marius voir ma réponse mise à jour pour une autre façon possible
Raphael au Digital Pianism
Cela pourrait fonctionner. Je vais essayer et revenir avec les résultats.
Marius
@Marius vérifie également à collectFileInfopartir de Magento\MediaStorage\Helper\File\Media;)
Raphael au Digital Pianism
collectFileInfone m'aidera pas car il attend un fichier dans le dossier multimédia. Le mien est dans le dossier var. N'a getStorageDatarien à voir avec ce dont j'ai besoin. Je ne veux pas collecter tous les fichiers dans un dossier. J'ai déjà le nom du fichier.
Marius