Najlepsze praktyki systemu plików

11

Pracuję nad jakimś rozszerzeniem Magento 2, które wymaga odczytu plików z systemu plików.
Podczas uruchamiania sniffera php przy użyciu standardów ECGM2 narzeka on na fakt, że używam funkcji takich jak basenamelub dirname.

Używanie funkcji dirname () jest zabronione

lub

Korzystanie z funkcji basename () jest zabronione

Jakiego opakowania należy użyć zamiast tych, aby uzyskać ten sam efekt?

[EDYCJA]
Oto trochę kodu, ale nie jest tak istotny dla pytania.
Mam klasę kolekcji, która ją rozszerza \Magento\Framework\Data\Collection\Filesystemi chcę wyświetlić tę kolekcję w siatce (komponenty interfejsu użytkownika), a jedną z akcji w siatce jest akcja pobierania.
W tym celu muszę uzyskać rzeczywistą nazwę pliku, aby móc wysłać go do akcji pobierania.

    // 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
źródło
czy możesz udostępnić część kodu, co próbujesz odczytać plik z systemu.
Dhiren Vasoya
Dodałem trochę kodu, ale nie ma to znaczenia dla pytania. Pytanie jest w jakiś sposób abstrakcyjne. czego powinienem używać zamiast basename, aby sniffer kodu nie narzekał?
Marius
Wygląda jak tylko kwestia uprawnień.
Ashish Jagnani
Nie ma to nic wspólnego z uprawnieniami. Kod działa poprawnie, ale sniffer kodu mówi, że nie należy go basenametam używać . Przeczytaj uważnie pytanie.
Marius

Odpowiedzi:

18

Potrzebowałem też czegoś takiego ostatnio. Jedyne rozwiązanie, które znalazłem basenamei dirnameużywałem:

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

Wcześniej próbowałem używać Magento\Framework\Filesystem\Directory\Writei getDriver()bez powodzenia. Dzięki nim możesz uzyskać prawie wszystko, ale nie basename.

Jalogut
źródło
TAK. Otóż ​​to. Dziękuję Ci. Przyznam nagrodę, gdy tylko będę mógł.
Marius
Marius, czy naprawdę zamierzasz to tak wdrożyć? [\ Magento \ Framework \ Filesystem \ Io \ File-> getpathinfo] [1] dosłownie wywołuje tylko [pathinfo] [2], który z kolei wywołuje basename i 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. Widziałem to. Na razie potrzebuję / chcę uniknąć niektórych funkcji. A w moim konkretnym przypadku pasuje to ładnie, ponieważ miałem już instancję \Magento\Framework\Filesystem\Io\Filewstrzykniętą we własnej klasie dla innej funkcjonalności. Po prostu nie wiedziałem z góry o getPathInfometodzie.
Marius
3

Na szczęście git pozwala nam zobaczyć, kiedy dirname i basename były zabronione , powód jest wyraźnie „Dodane pliki”

Patrząc na problem dotyczący projektu EKG, możesz zobaczyć zamknięte problemy, takie jak coś złego w pliku_istniejące? # 33 , Funkcje błędów # 26 , coś złego w tych funkcjach? # 17 , Kontekst / objaśnienia do reguł # 12 , Zabronione jest użycie funkcji iconv () # 14, co sprawiłoby, że pomyślałem, że początkowa lista zabronionych funkcji nie była zbytnio rozważana, a Magento prawdopodobnie można zmienić zabroniona lista.

Przeszukiwanie bazy kodu m2 pokazuje ~ = 78 wyników dla nazwy basename, mieszanki zmiennych i kodu faktycznie wywołującego basename, w tym mojego ulubionego .

Myślę, że gdybym był tobą, opublikowałbym problem na githubie i zapytał Zlik, czy nadal uważa, że ​​one tam są, czy M2 zapewnia opakowanie

Richard
źródło
2

Możesz użyć obiektu SplFileInfo()klasy, może to zadziała.

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

być może zadziała.

możesz również skierować ten adres URL.

chirag
źródło
Dzięki za to. Wygląda na czystsze, ale czy masz przykład kodu, który to robi? Chcę przestrzegać podstawowych standardów.
Marius
możesz skierować php.net/manual/en/splfileinfo.getfilename.php do tego adresu URL.
chirag
2

Moją sugestią byłoby użycie Magento/Backupmodułu jako przykładu.

Ciekawie byłoby zobaczyć, w jaki sposób napisano klasę działania pobierania, ponieważ dotyczy ona również rzeczywistych plików do pobrania:

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

Do mnie należy spojrzeć na sposób metoda ta generuje plik do pobrania przy użyciu \Magento\Framework\App\Response\Http\FileFactoryi generateBackupDownloadNameod Magento\Backup\Helper\Data(powiadomienia zalecanego użycia OM;))

Kolejny interesujący kawałek

Inną ciekawą rzeczą, należy spojrzeć na to getStorageDatametoda z Magento\MediaStorage\Model\ResourceModel\File\Storage\Filektórych sam nazywa bezpośrednio dirnamei basenametylko jeśli wywołanie tej metody rdzenia w module, nie dostanie zabronione błędy;)

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

W podobnym pomyśle jest też coś collectFileInfozMagento\MediaStorage\Helper\File\Media

Raphael at Digital Pianism
źródło
generateBackupDownloadNamewykorzystuje niektóre magiczne metody pobierania z modelu zapasowego. Więc muszą wcześniej wezwać seterów magii. Nie widzę nic związanego z basename ani alternatywy dla niego.
Marius
@Marius zobacz moją zaktualizowaną odpowiedź na inny możliwy sposób
Raphael w Digital Pianism
To może zadziałać. Spróbuję i wrócę z wynikami.
Marius
@Marius również sprawdzić collectFileInfood Magento\MediaStorage\Helper\File\Media;)
Raphael w Digital Pianism
collectFileInfonie pomoże mi, ponieważ oczekuje pliku w folderze multimediów. Mój jest w folderze var. Nie getStorageDatama też nic wspólnego z tym, czego potrzebuję. Nie chcę zbierać wszystkich plików w folderze. Mam już nazwę pliku.
Marius