phplaravelstoragechain

Laravel 5.5 Storage chain call add dir file filter class


i'am not very well OO, and search a few web site to write this class

now my problem is how to use this class just like the Laravel 5.5 build in Storage class

i want use like this

MyStorage::disk('dropbox')
    ->addDirFilter('(school|travel)')
    ->addDirFilter('\d{4}-\d{2}-\d{2}')
    ->addFileFilter('.*\.jpg')
    ->getMatch();

here is MyStorage class

<?php

namespace App\MySupport;

class MyStorage
{
    private $flag;
    private $disk;
    private $matches;

    public function __construct()
    {
        $this->flag = false;
        $this->disk = '';
        $this->matches = [];
    }

    public function disk($disk)
    {
        $this->disk = $disk;
        return $this;
    }

    public function addDirFilter($filter)
    {
        if (! $this->flag)
        {
            $this->flag = true;
            $subDirs[] = \Storage::disk($this->disk)->directories();
        }
        else
        {
            foreach ($this->matches as $dir)
            {
                $subDirs[] = \Storage::disk($this->disk)->directories($dir);
            }
        }

        $this->findMatch($subDirs, $filter);
        return $this;
    }

    public function addFileFilter($filter)
    {
        if (! $this->flag)
        {
            $this->flag = true;
            $subFiles[] = \Storage::disk($this->disk)->files();
        }
        else
        {
            foreach ($this->matches as $dir)
            {
                $subFiles[] = \Storage::disk($this->disk)->files($dir);
            }
        }

        $this->findMatch($subFiles, $filter);
        return $this;
    }

    public function findMatch($subItems, $filter)
    {
        // set empty before update
        $this->matches = [];

        // if call this method by addDirFilter() , $subItem contain the Dir path, eg, DirA/DirB
        // if call this method by addFileFilter() , $subItem contain the File path, eg, DirX/File.txt
        foreach (array_collapse($subItems) as $subItem)
        {
            // get the last str, eg, DirB OR File.txt
            $lastStr = @end(explode('/', $subItem));

            if ( preg_match('/^' . $filter . '$/u', $lastStr) )
            {
                // update new matches
                $this->matches[] = $subItem;
            }
        }
    }

    public function getMatch()
    {
        return $this->matches;
    }
}

Usage

<?php

namespace App\Http\Controllers;
use App\MySupport\MyStorage;

class TestController extends Controller
{
    public function storageTest()
    {
        $MyStorage = new MyStorage();
        
        // for example in my dropbox disk have
        // 
        // school/2018-01-01/emails.txt
        // school/2018-02-02/Peter.jpg
        // travel/2017-06-06/TW.jpg

        $folders = $MyStorage->disk('dropbox')
                             ->addDirFilter('school')
                             ->addDirFilter('\d{4}-\d{2}-\d{2}')
                             ->getMatch();
        // $folders result is:
        // school/2018-01-01
        // school/2018-02-02

        $files = $MyStorage->disk('dropbox')
                           ->addDirFilter('(school|travel)')
                           ->addDirFilter('\d{4}-\d{2}-\d{2}')
                           ->addFileFilter('.*\.jpg')
                           ->getMatch();
        // $files result is:
        // school/2018-02-02/Peter.jpg
        // travel/2017-06-06/TW.jpg
    }
}

i tested seems all fine

can anyone point me to the direction, how to use MyStorage class just like Laravel 5.5 build in Storage class, thanks


Solution

  • You should use static function. Try replace your function as code below.

     public static function disk($disk)
     {
         $instance = new MyStorage();
         $instance->disk = $disk;
         return $instance;
    

    Furthermore, I would suggest you learn singleton design pattern