0

Does any one know why $this->driverFile->isExists('pub/media/') doesn't work in Cron Job ?

I've a Cron Job look like this:

<?php

namespace Namespace\Module\Cron;

use Namespace\Module\Helper\Data;

class Scan
{
    public function __construct(
        Data $helperData,
    ) {
        $this->helperData = $helperData;
    }

    public function execute()
    {
        $data = $this->helperData->scanFiles();
        // do something
    }
}

and a Helper call to $this->driverFile->isExists('pub/media/') but it return false when pub/media/ is actually exists and run manual by Controller still return true (i mean only Cron Job have this issue):

<?php

namespace Namespace\Module\Helper;

use Magento\Framework\App\Helper\Context;
use Magento\Framework\Filesystem\Driver\File as DriverFile;

class Helper extends AbstractHelper 
{
    public function __construct(
        Context $context,
        DriverFile $driverFile
    ) {
        $this->driverFile = $driverFile;
        parent::__construct($context);
    }

    public function scanFiles() {
        $directory = 'pub/media';
        if ($this->checkIfFileExists($directory)) {
            $files = $this->driverFile->readDirectoryRecursively($directory);
            foreach ($files as $file) {
                $fileSize = $this->driverFile->stat($file)['size'];
                // do something
            }
        }
    }

    public checkIfFileExists($directory) {
        return $this->driverFile->isExists($directory) && $this->driverFile->isReadable($directory);
    }
}

Thanks for reading.

1 Answer 1

0

After debugging with my team, i've found that cron doesn't run from root directory, so $this->driverFile->isExists('pub/media/') should be $this->driverFile->isExists(YOUR_DIRECTORY_DIR . 'pub/media/')

Example: $this->driverFile->isExists('/var/www/html/Magento233/pub/media/')
So i've copy the content of Magento\Framework\Filesystem\Driver\File to my helper and make it look like this:

<?php

namespace Namespace\Module\Helper;

use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Framework\Exception\FileSystemException;
use Magento\Framework\Filesystem\DriverInterface;
use Magento\Framework\Filesystem\Glob;
use Psr\Log\LoggerInterface;

/**
 * Class FileCron
 * copy from Magento233/vendor/magento/framework/Filesystem/Driver/File.php
 * but add (BP . '/') in directory path, so that will not causing issue with check file in cron job
 * @package Jajuma\ImageOptimizerUltimate\Helper
 */
class FileCron extends AbstractHelper
{
    /**
     * @var string
     */
    protected $scheme = '';

    public function __construct(
        LoggerInterface $logger,
        Context $context
    ) {
        $this->logger = $logger;
        parent::__construct($context);
    }

    /**
     * Returns last warning message string
     *
     * @return string
     */
    protected function getWarningMessage()
    {
        $warning = error_get_last();
        if ($warning && $warning['type'] == E_WARNING) {
            return 'Warning!' . $warning['message'];
        }
        return null;
    }

    /**
     * Is file or directory exist in file system
     *
     * @param string $path
     * @return bool
     * @throws FileSystemException
     */
    public function isExists($path)
    {
        clearstatcache();
        $result = @file_exists(BP . '/' . $this->getScheme() . $path);
        if ($result === null) {
            throw new FileSystemException(
                new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()])
            );
        }
        return $result;
    }

    /**
     * Gathers the statistics of the given path
     *
     * @param string $path
     * @return array
     * @throws FileSystemException
     */
    public function stat($path)
    {
        clearstatcache();
        $result = @stat($this->getScheme() . $path);
        if (!$result) {
            throw new FileSystemException(
                new \Magento\Framework\Phrase('Cannot gather stats! %1', [$this->getWarningMessage()])
            );
        }
        return $result;
    }

    /**
     * Check permissions for reading file or directory
     *
     * @param string $path
     * @return bool
     * @throws FileSystemException
     */
    public function isReadable($path)
    {
        clearstatcache();
        $result = @is_readable(BP . '/' . $this->getScheme() . $path);
        if ($result === null) {
            throw new FileSystemException(
                new \Magento\Framework\Phrase('An error occurred during "%1" execution.', [$this->getWarningMessage()])
            );
        }
        return $result;
    }

    /**
     * Read directory recursively
     *
     * @param string $path
     * @return string[]
     * @throws FileSystemException
     */
    public function readDirectoryRecursively($path = null)
    {
        $result = [];
        $flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS;
        try {
            $iterator = new \RecursiveIteratorIterator(
                new \RecursiveDirectoryIterator(BP . '/' . $path, $flags),
                \RecursiveIteratorIterator::CHILD_FIRST
            );
            /** @var \FilesystemIterator $file */
            foreach ($iterator as $file) {
                $result[] = $file->getPathname();
            }
        } catch (\Exception $e) {
            throw new FileSystemException(new \Magento\Framework\Phrase($e->getMessage()), $e);
        }
        return $result;
    }

    /**
     * Return path with scheme
     *
     * @param null|string $scheme
     * @return string
     */
    protected function getScheme($scheme = null)
    {
        return $scheme ? $scheme . '://' : '';
    }
}

As you can see, I added BP . '/' . before $this->getScheme() . $path so it look like: @file_exists(BP . '/' . $this->getScheme() . $path).
Why is BP? It's because BP is YOUR_DIRECTORY_DIR which supported by PHP.
You can read about BP here.

After create helper, you can call it to replace the old function isExists() of original file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.