Mejores prácticas del sistema de archivos

11

Estoy trabajando en alguna extensión de Magento 2 que requiere leer archivos del sistema de archivos.
Al ejecutar el sniffer php usando los estándares ECGM2, se queja del hecho de que estoy usando funciones como basenameo dirname.

El uso de la función dirname () está prohibido

o

El uso de la función basename () está prohibido

¿Qué envoltorio debo usar en lugar de aquellos para obtener el mismo efecto?

[EDITAR]
Aquí hay un código, pero no es tan relevante para la pregunta.
Tengo una clase de colección que extiende la \Magento\Framework\Data\Collection\Filesystemclase y quiero enumerar esta colección en una cuadrícula (ui-components) y una de las acciones en la cuadrícula es una acción de descarga.
Para esto, necesito obtener el nombre real del archivo para poder enviarlo a la acción de descarga.

    // 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
fuente
¿Puede compartir parte de su código, lo que ha intentado leer el archivo del sistema?
Dhiren Vasoya el
Agregué un código, pero es totalmente irrelevante para la pregunta. La pregunta es de alguna manera abstracta. ¿Qué debo usar en lugar de basename para que el sniffer de código no se queje?
Marius
Parece solo un problema de permiso.
Ashish Jagnani
No tiene nada que ver con los permisos. El código funciona correctamente, pero el sniffer de código dice que no debería usarse basenameallí. Por favor lea la pregunta cuidadosamente.
Marius

Respuestas:

16

También necesitaba algo así recientemente. La única solución que encontré para obtener basenamey dirnameestaba 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'];
}

Antes de eso intenté usar Magento\Framework\Filesystem\Directory\Writey getDriver()sin éxito. Con ellos puedes obtener casi todo, pero no el basename.

Jalogut
fuente
SI. Eso es. Gracias. Otorgaré la recompensa tan pronto como se me permita.
Marius
Marius, ¿realmente lo vas a implementar de esa manera? [\ Magento \ Framework \ Filesystem \ Io \ File-> getpathinfo] [1] literalmente solo llama a [pathinfo] [2] que a su vez llama a basename y 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
@Ricardo. Vi eso. Por ahora necesito / quiero evitar ciertas funciones. Y en mi caso específico, encaja muy bien porque ya me \Magento\Framework\Filesystem\Io\Fileinyectaron en mi propia clase para una funcionalidad diferente. Simplemente no sabía por adelantado sobre el getPathInfométodo.
Marius
3

Afortunadamente, git nos permite ver cuándo se prohibieron dirname y basename , la razón es claramente, "Archivos agregados"

Mirando el problema para el proyecto de ECG, ¿puede ver problemas cerrados como algo malo en file_exists? # 33 , Funciones de error # 26 , ¿ algo malo en estas funciones? # 17 , Contexto / Explicación de las Reglas # 12 , El uso de la función iconv () está prohibido # 14, lo que me haría pensar que la lista inicial de funciones prohibidas no se consideró demasiado, y que probablemente Magento sea susceptible de cambios La lista prohibida.

La búsqueda en la base de código m2 muestra ~ = 78 resultados para basename, una combinación de variables y el código que realmente llama a basename, incluido mi favorito .

Creo que si fuera usted, publicaría un problema en github y le preguntaría a zlik si todavía cree que pertenecen allí o si M2 proporciona un contenedor

Ricardo
fuente
2

Puede usar el objeto de SplFileInfo()clase si puede funcionar.

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

Puede ser que funcione.

También puede consultar esta url.

chirag
fuente
Gracias por esto. Parece más limpio, pero ¿tienes un ejemplo de código que haga esto? Quiero seguir los estándares básicos.
Marius
puede consultar php.net/manual/en/splfileinfo.getfilename.php esta url.
chirag
2

Mi sugerencia sería utilizar el Magento/Backupmódulo como ejemplo.

Sería interesante observar la forma en que se escribe la clase de acción de descarga porque también trata con archivos reales para descargar:

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 mí, debe observar la forma en que este método genera el archivo para descargar usando \Magento\Framework\App\Response\Http\FileFactoryy generateBackupDownloadNamedesde Magento\Backup\Helper\Data(observe el uso recomendado del OM;))

Otro poco interesante

Otra cosa interesante que debe observar es el getStorageDatamétodo desde el Magento\MediaStorage\Model\ResourceModel\File\Storage\Filecual se llama directamente dirnamey, basenamepero si llama a ese método central en su módulo, no obtendrá los errores prohibidos;)

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

En una idea similar, también está el collectFileInfodeMagento\MediaStorage\Helper\File\Media

Raphael en Digital Pianism
fuente
generateBackupDownloadNameutiliza algunos captadores de magia del modelo de respaldo. Por lo tanto, deben tener setters mágicos llamados antes. No veo nada relacionado con el nombre base o una alternativa a él.
Marius
@Marius ve mi respuesta actualizada de otra manera posible
Raphael en Digital Pianism el
Esto podría funcionar Lo intentaré y volveré con los resultados.
Marius
@Marius también verifica collectFileInfodesde Magento\MediaStorage\Helper\File\Media;)
Raphael en Digital Pianism
collectFileInfono me ayudará porque espera un archivo dentro de la carpeta multimedia. El mío está en la carpeta var. Tampoco getStorageDatatiene nada que ver con lo que necesito. No quiero recopilar todos los archivos en una carpeta. Ya tengo el nombre del archivo.
Marius