Merge pull request #390 from kijin/pr/read-write-php-data

PHP 데이터를 파일에 쉽게 쓰고 읽는 함수 추가
This commit is contained in:
Kijin Sung 2016-03-20 19:58:55 +09:00
commit 9e6e7efbfd
2 changed files with 117 additions and 9 deletions

View file

@ -148,17 +148,48 @@ class Storage
* Get the content of a file.
*
* This method returns the content if it exists and is readable.
* Otherwise, it returns false.
* If $stream is true, it will return the content as a stream instead of
* loading the entire content in memory. This may be useful for large files.
* If the file cannot be opened, this method returns false.
*
* @param string $filename
* @return string|false
* @param bool $stream (optional)
* @return string|resource|false
*/
public static function read($filename)
public static function read($filename, $stream = false)
{
$filename = rtrim($filename, '/\\');
if (self::exists($filename) && @is_file($filename) && @is_readable($filename))
{
return @file_get_contents($filename);
if ($stream)
{
return @fopen($filename, 'r');
}
else
{
return @file_get_contents($filename);
}
}
else
{
return false;
}
}
/**
* Read PHP data from a file, formatted for easy retrieval.
*
* This method returns the data on success and false on failure.
*
* @param string $filename
* @return mixed
*/
public static function readPHPData($filename)
{
$filename = rtrim($filename, '/\\');
if (@is_file($filename) && @is_readable($filename))
{
return @include $filename;
}
else
{
@ -169,10 +200,12 @@ class Storage
/**
* Write $content to a file.
*
* If $content is a stream, this method will copy it to the target file
* without loading the entire content in memory. This may be useful for large files.
* This method returns true on success and false on failure.
*
* @param string $filename
* @param string $content
* @param string|resource $content
* @param string $mode (optional)
* @param int $perms (optional)
* @return string|false
@ -190,9 +223,26 @@ class Storage
}
}
$flags = ($mode === 'a') ? (\FILE_APPEND | \LOCK_EX) : (\LOCK_EX);
$write_success = @file_put_contents($filename, $content, $flags);
$result = ($write_success === strlen($content)) ? true : false;
if ($fp = fopen($filename, $mode))
{
flock($fp, \LOCK_EX);
if (is_resource($content))
{
$result = stream_copy_to_stream($content, $fp) ? true : false;
}
else
{
$result = fwrite($fp, $content) ? true : false;
}
fflush($fp);
flock($fp, \LOCK_UN);
fclose($fp);
}
else
{
return false;
}
@chmod($filename, ($perms === null ? (0666 & ~umask()) : $perms));
if (function_exists('opcache_invalidate') && substr($filename, -4) === '.php')
{
@ -201,6 +251,21 @@ class Storage
return $result;
}
/**
* Write PHP data to a file, formatted for easy retrieval.
*
* This method returns true on success and false on failure.
* Resources and anonymous functions cannot be saved.
*
* @param string $filename
* @param mixed $data
* @return string|false
*/
public static function writePHPData($filename, $data)
{
return self::write($filename, '<' . '?php return unserialize(' . var_export(serialize($data), true) . ');');
}
/**
* Copy $source to $destination.
*

View file

@ -116,20 +116,63 @@ class StorageTest extends \Codeception\TestCase\Test
public function testRead()
{
// Simple read test
$this->assertEquals(file_get_contents(__FILE__), Rhymix\Framework\Storage::read(__FILE__));
$this->assertFalse(Rhymix\Framework\Storage::read(__FILE__ . '.nonexistent.suffix'));
$this->assertFalse(Rhymix\Framework\Storage::read(__DIR__));
$this->assertFalse(Rhymix\Framework\Storage::read('/dev/nonexistent'));
// Stream read test
$fp = Rhymix\Framework\Storage::read(__FILE__, true);
$this->assertTrue(is_resource($fp));
$this->assertEquals(file_get_contents(__FILE__), fread($fp, filesize(__FILE__)));
fclose($fp);
}
public function testWrite()
{
$testfile = \RX_BASEDIR . 'tests/_output/subdirectory/testfile.txt';
$copyfile = \RX_BASEDIR . 'tests/_output/subdirectory/copyfile.txt';
$this->assertFalse(file_exists($testfile));
// Simple write test
$this->assertTrue(Rhymix\Framework\Storage::write($testfile, 'foobarbazzjazz'));
$this->assertTrue(file_exists($testfile));
$this->assertEquals('foobarbazzjazz', file_get_contents($testfile));
$this->assertEquals(0666 & ~umask(), fileperms($testfile) & 0777);
// Append test
$this->assertTrue(Rhymix\Framework\Storage::write($testfile, 'rhymix', 'a', 0666));
$this->assertTrue(file_exists($testfile));
$this->assertEquals('foobarbazzjazzrhymix', file_get_contents($testfile));
$this->assertEquals(0666, fileperms($testfile) & 0777);
// Stream copy test
$stream = fopen($testfile, 'r');
$this->assertTrue(Rhymix\Framework\Storage::write($copyfile, $stream));
$this->assertEquals('foobarbazzjazzrhymix', file_get_contents($copyfile));
fclose($stream);
// Stream append test
$stream = fopen($testfile, 'r');
$this->assertTrue(Rhymix\Framework\Storage::write($copyfile, $stream, 'a'));
$this->assertEquals('foobarbazzjazzrhymixfoobarbazzjazzrhymix', file_get_contents($copyfile));
fclose($stream);
// Partial stream append test
$stream = fopen($testfile, 'r');
fseek($stream, 14);
$this->assertTrue(Rhymix\Framework\Storage::write($copyfile, $stream, 'a'));
$this->assertEquals('foobarbazzjazzrhymixfoobarbazzjazzrhymixrhymix', file_get_contents($copyfile));
fclose($stream);
}
public function testReadWritePHPData()
{
$testfile = \RX_BASEDIR . 'tests/_output/test.php';
$data = array('foo' => 'bar', 'baz' => array('rhymix' => '\'"special\\chars' . chr(0) . chr(255), 'test' => 'wow'));
$this->assertTrue(Rhymix\Framework\Storage::writePHPData($testfile, $data));
$this->assertEquals($data, Rhymix\Framework\Storage::readPHPData($testfile));
}
public function testCopy()