Created
July 7, 2015 02:14
-
-
Save psrpinto/1fe7ff7b9336b197c0d8 to your computer and use it in GitHub Desktop.
Support local filesystems with a large number of directories or files (using Flysystem)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Acme\Adapter; | |
use League\Flysystem\Adapter\Local; | |
/** | |
* A local adapter that works around filesystems' limit of subdirectories in a | |
* directory. | |
* | |
* For files or directories in the root of the filesystem, we SHA1-hash their | |
* name and use the first 4 chars of the hash as four levels of subdirs. The file | |
* or directory is then placed inside the last level. | |
* | |
* Thus, a directory with name 'foo' will be interpreted as "0/b/e/e/foo", where | |
* "0bee" are the first four characters of sha1('foo') | |
*/ | |
class LocalSpread extends Local | |
{ | |
public function applyPathPrefix($path) | |
{ | |
// Only apply the prefix if it's not already present | |
if (empty($path) || preg_match('/^([a-fA-F0-9]\/){4}/', $path)) { | |
return parent::applyPathPrefix($path); | |
} | |
// We're only interested in prefixing the first level, imediately under | |
// the filesystem root | |
$pos = strpos($path, DIRECTORY_SEPARATOR); | |
if (false === $pos) { | |
$prefix = $this->getPrefix($path); | |
} else { | |
$prefix = $this->getPrefix(substr($path, 0, $pos)); | |
} | |
return parent::applyPathPrefix($prefix.DIRECTORY_SEPARATOR.$path); | |
} | |
private function getPrefix($path) | |
{ | |
return implode(DIRECTORY_SEPARATOR, str_split(substr(hash('sha1', $path), 0, 4))); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Acme\Tests\Adapter; | |
use Memeoirs\StorageBundle\Adapter\LocalSpread; | |
class LocalSpreadTest extends \PHPUnit_Framework_TestCase | |
{ | |
const ROOT = '/tmp'; | |
public function setUp() | |
{ | |
$this->adapter = new LocalSpread(self::ROOT); | |
} | |
public function testApplyPathPrefix() | |
{ | |
$this->doTestApplyPathPrefix('', ''); | |
$this->doTestApplyPathPrefix('foo', '0/b/e/e/foo'); | |
$this->doTestApplyPathPrefix('foo/bar', '0/b/e/e/foo/bar'); | |
$this->doTestApplyPathPrefix('0/b/e/e/foo/bar', '0/b/e/e/foo/bar'); | |
} | |
private function doTestApplyPathPrefix($path, $realPath) | |
{ | |
$this->assertEquals( | |
$this->adapter->applyPathPrefix($path), | |
self::ROOT.DIRECTORY_SEPARATOR.$realPath | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment