Melhores práticas do sistema de arquivos

10

Estou trabalhando em uma extensão do Magento 2 que requer a leitura de arquivos do sistema de arquivos.
Ao executar o php sniffer usando os padrões ECGM2, ele reclama do fato de estar usando funções como basenameou dirname.

É proibido o uso da função dirname ()

ou

É proibido o uso da função basename ()

Que invólucro devo usar em vez desses para obter o mesmo efeito?

[EDIT]
Aqui está um código, mas não é relevante para a questão.
Eu tenho uma classe de coleção que estende a \Magento\Framework\Data\Collection\Filesystemclasse e quero listar essa coleção em uma grade (componentes da interface do usuário) e uma das ações na grade é uma ação de download.
Para isso, preciso obter o nome real do arquivo para enviá-lo à ação de 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 {
       ...
    }
Marius
fonte
você pode compartilhar parte do seu código, o que você tentou ler arquivo do sistema.
Dhiren Vasoya
Eu adicionei algum código, mas é totalmente irrelevante para a pergunta. A questão é de alguma forma abstrata. o que devo usar em vez de basename para que o sniffer de código não reclame?
Marius
Parece apenas uma questão de permissão.
Ashish Jagnani 8/16 '12
Não tem nada a ver com permissões. O código funciona corretamente, mas o sniffer de código diz que não deve ser usado basenamelá. Por favor, leia a pergunta com atenção.
Marius

Respostas:

15

Eu também precisava de algo assim recentemente. Única solução que encontrei para obter basenamee dirnameestava usando:

\ Magento \ Framework \ Sistema de Arquivos \ Io \ File

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

Antes disso, tentei usar Magento\Framework\Filesystem\Directory\Writee getDriver()sem sucesso. Com eles, você pode obter praticamente tudo, mas não o basename.

Jalogut
fonte
SIM. É isso aí. Obrigado. Eu concederei a recompensa assim que me for permitido.
Marius
Marius, você realmente vai implementá-lo dessa maneira? [\ Magento \ Framework \ Sistema de Arquivos \ Io \ Arquivo-> getpathinfo] [1] literalmente apenas chama [pathinfo] [2] que, por sua vez, chama o nome de base e o nome do diretório [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. Eu vi isso. Por enquanto eu preciso / quero evitar certas funções. E no meu caso específico, ele se encaixa perfeitamente porque eu já tinha uma instância de \Magento\Framework\Filesystem\Io\Fileinjeção na minha própria classe para uma funcionalidade diferente. Eu simplesmente não sabia de antemão sobre o getPathInfométodo.
Marius
3

Felizmente, o git nos permite ver quando o nome do diretório e o nome da base foram proibidos , o motivo é claramente "Arquivos adicionados"

Olhando para a questão do projeto ECG, você pode ver questões fechadas, como algo ruim em file_exists? # 33 , Funções de erro # 26 , algo de ruim nessas funções? # 17 , Contexto / explicação das regras # 12 , O uso da função iconv () é proibido # 14, o que me faria pensar que a lista inicial de funções proibidas não recebeu muita consideração, e o magento provavelmente está sujeito a alterações a lista proibida.

A pesquisa na base de código m2 mostra ~ = 78 resultados para basename, uma mistura de variáveis ​​e o código que está chamando basename, incluindo o meu favorito .

Acho que se eu fosse você, publicaria um problema no github e perguntaria ao zlik se ele ainda acha que eles pertencem a ele ou se o M2 fornece um invólucro

Richard
fonte
2

Você pode usar o objeto de SplFileInfo()classe, se ele funcionar.

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

pode ser que vai funcionar.

você também pode consultar este URL.

chirag
fonte
Obrigado por isso. Parece mais limpo, mas você tem um exemplo de código que faz isso? Eu quero seguir os principais padrões.
Marius
você pode consultar php.net/manual/en/splfileinfo.getfilename.php este URL.
21416
2

Minha sugestão seria usar o Magento/Backupmódulo como exemplo.

A maneira como a classe de ação de download é escrita seria interessante, pois também lida com arquivos reais para download:

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

Para mim, você deve observar a maneira como esse método gera o arquivo para download usando \Magento\Framework\App\Response\Http\FileFactorye generateBackupDownloadNamede Magento\Backup\Helper\Data(observe o uso recomendado do OM;))

Outra parte interessante

Outra coisa interessante que você deve observar é o getStorageDatamétodo do Magento\MediaStorage\Model\ResourceModel\File\Storage\Filequal ele chama diretamente dirnamee, basenamemas se você chamar esse método principal no seu módulo, não receberá os erros proibidos;)

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

Em uma idéia semelhante, há também o collectFileInfodeMagento\MediaStorage\Helper\File\Media

Raphael na Digital Pianism
fonte
generateBackupDownloadNameusa alguns getters mágicos do modelo de backup. Então eles devem ter setters mágicos chamados antes. Não vejo nada relacionado ao nome da base ou uma alternativa a ele.
Marius
@Marius ver minha resposta actualizado para uma outra maneira possível
Raphael em Digital pianismo
Isso pode funcionar. Vou tentar e voltar com os resultados.
Marius
@Marius também check collectFileInfofrom Magento\MediaStorage\Helper\File\Media;)
Raphael no Digital Pianism
collectFileInfonão vai me ajudar porque espera um arquivo dentro da pasta de mídia. O meu está na pasta var. Também getStorageDatanão tem nada a ver com o que eu preciso. Não quero coletar todos os arquivos em uma pasta. Eu já tenho o nome do arquivo.
Marius