Commit 04fb75b6 by Paul Klimov

File retrieve methods added to Mongo File Active Record.

parent c0d5c785
...@@ -129,12 +129,30 @@ class Query extends Component implements QueryInterface ...@@ -129,12 +129,30 @@ class Query extends Component implements QueryInterface
* @throws Exception on failure. * @throws Exception on failure.
* @return array|boolean result. * @return array|boolean result.
*/ */
protected function fetchRows(\MongoCursor $cursor, $all = true, $indexBy = null) protected function fetchRows($cursor, $all = true, $indexBy = null)
{ {
$token = 'Querying: ' . Json::encode($cursor->info()); $token = 'Querying: ' . Json::encode($cursor->info());
Yii::info($token, __METHOD__); Yii::info($token, __METHOD__);
try { try {
Yii::beginProfile($token, __METHOD__); Yii::beginProfile($token, __METHOD__);
$result = $this->fetchRowsInternal($cursor, $all, $indexBy);
Yii::endProfile($token, __METHOD__);
return $result;
} catch (\Exception $e) {
Yii::endProfile($token, __METHOD__);
throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
}
}
/**
* @param \MongoCursor $cursor Mongo cursor instance to fetch data from.
* @param boolean $all whether to fetch all rows or only first one.
* @param string|callable $indexBy value to index by.
* @return array|boolean result.
* @see Query::fetchRows()
*/
protected function fetchRowsInternal($cursor, $all, $indexBy)
{
$result = []; $result = [];
if ($all) { if ($all) {
foreach ($cursor as $row) { foreach ($cursor as $row) {
...@@ -156,12 +174,7 @@ class Query extends Component implements QueryInterface ...@@ -156,12 +174,7 @@ class Query extends Component implements QueryInterface
$result = false; $result = false;
} }
} }
Yii::endProfile($token, __METHOD__);
return $result; return $result;
} catch (\Exception $e) {
Yii::endProfile($token, __METHOD__);
throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
}
} }
/** /**
......
...@@ -205,7 +205,7 @@ class ActiveRecord extends \yii\mongo\ActiveRecord ...@@ -205,7 +205,7 @@ class ActiveRecord extends \yii\mongo\ActiveRecord
/** /**
* Returns the associated file content. * Returns the associated file content.
* @return null|string file content. * @return null|string file content.
* @throws \yii\base\InvalidParamException on invalid file value. * @throws \yii\base\InvalidParamException on invalid file attribute value.
*/ */
public function getFileContent() public function getFileContent()
{ {
...@@ -227,6 +227,67 @@ class ActiveRecord extends \yii\mongo\ActiveRecord ...@@ -227,6 +227,67 @@ class ActiveRecord extends \yii\mongo\ActiveRecord
} elseif (is_string($file)) { } elseif (is_string($file)) {
if (file_exists($file)) { if (file_exists($file)) {
return file_get_contents($file); return file_get_contents($file);
} else {
throw new InvalidParamException("File '{$file}' does not exist.");
}
} else {
throw new InvalidParamException('Unsupported type of "file" attribute.');
}
}
/**
* Writes the the internal file content into the given filename.
* @param string $filename full filename to be written.
* @return boolean whether the operation was successful.
* @throws \yii\base\InvalidParamException on invalid file attribute value.
*/
public function writeFile($filename)
{
$file = $this->getAttribute('file');
if (empty($file) && !$this->getIsNewRecord()) {
$file = $this->refreshFile();
}
if (empty($file)) {
throw new InvalidParamException('There is no file associated with this object.');
} elseif ($file instanceof \MongoGridFSFile) {
return ($file->write($filename) == $file->getSize());
} elseif ($file instanceof UploadedFile) {
return copy($file->tempName, $filename);
} elseif (is_string($file)) {
if (file_exists($file)) {
return copy($file, $filename);
} else {
throw new InvalidParamException("File '{$file}' does not exist.");
}
} else {
throw new InvalidParamException('Unsupported type of "file" attribute.');
}
}
/**
* This method returns a stream resource that can be used with all file functions in PHP,
* which deal with reading files. The contents of the file are pulled out of MongoDB on the fly,
* so that the whole file does not have to be loaded into memory first.
* @return resource file stream resource.
* @throws \yii\base\InvalidParamException on invalid file attribute value.
*/
public function getFileResource()
{
$file = $this->getAttribute('file');
if (empty($file) && !$this->getIsNewRecord()) {
$file = $this->refreshFile();
}
if (empty($file)) {
throw new InvalidParamException('There is no file associated with this object.');
} elseif ($file instanceof \MongoGridFSFile) {
return $file->getResource();
} elseif ($file instanceof UploadedFile) {
return fopen($file->tempName, 'r');
} elseif (is_string($file)) {
if (file_exists($file)) {
return fopen($file, 'r');
} else {
throw new InvalidParamException("File '{$file}' does not exist.");
} }
} else { } else {
throw new InvalidParamException('Unsupported type of "file" attribute.'); throw new InvalidParamException('Unsupported type of "file" attribute.');
......
...@@ -33,20 +33,14 @@ class Query extends \yii\mongo\Query ...@@ -33,20 +33,14 @@ class Query extends \yii\mongo\Query
} }
/** /**
* Fetches rows from the given Mongo cursor. * @param \MongoGridFSCursor $cursor Mongo cursor instance to fetch data from.
* @param \MongoCursor $cursor Mongo cursor instance to fetch data from.
* @param boolean $all whether to fetch all rows or only first one. * @param boolean $all whether to fetch all rows or only first one.
* @param string|callable $indexBy the column name or PHP callback, * @param string|callable $indexBy value to index by.
* by which the query results should be indexed by.
* @throws Exception on failure.
* @return array|boolean result. * @return array|boolean result.
* @see Query::fetchRows()
*/ */
protected function fetchRows(\MongoCursor $cursor, $all = true, $indexBy = null) protected function fetchRowsInternal($cursor, $all, $indexBy)
{ {
$token = 'Querying: ' . Json::encode($cursor->info());
Yii::info($token, __METHOD__);
try {
Yii::beginProfile($token, __METHOD__);
$result = []; $result = [];
if ($all) { if ($all) {
foreach ($cursor as $file) { foreach ($cursor as $file) {
...@@ -72,11 +66,6 @@ class Query extends \yii\mongo\Query ...@@ -72,11 +66,6 @@ class Query extends \yii\mongo\Query
$result = false; $result = false;
} }
} }
Yii::endProfile($token, __METHOD__);
return $result; return $result;
} catch (\Exception $e) {
Yii::endProfile($token, __METHOD__);
throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
}
} }
} }
\ No newline at end of file
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
namespace yiiunit\extensions\mongo\file; namespace yiiunit\extensions\mongo\file;
use Yii;
use yii\helpers\FileHelper;
use yiiunit\extensions\mongo\MongoTestCase; use yiiunit\extensions\mongo\MongoTestCase;
use yii\mongo\file\ActiveQuery; use yii\mongo\file\ActiveQuery;
use yiiunit\data\ar\mongo\file\ActiveRecord; use yiiunit\data\ar\mongo\file\ActiveRecord;
...@@ -22,15 +24,31 @@ class ActiveRecordTest extends MongoTestCase ...@@ -22,15 +24,31 @@ class ActiveRecordTest extends MongoTestCase
parent::setUp(); parent::setUp();
ActiveRecord::$db = $this->getConnection(); ActiveRecord::$db = $this->getConnection();
$this->setUpTestRows(); $this->setUpTestRows();
$filePath = $this->getTestFilePath();
if (!file_exists($filePath)) {
FileHelper::createDirectory($filePath);
}
} }
protected function tearDown() protected function tearDown()
{ {
$filePath = $this->getTestFilePath();
if (file_exists($filePath)) {
FileHelper::removeDirectory($filePath);
}
$this->dropFileCollection(CustomerFile::collectionName()); $this->dropFileCollection(CustomerFile::collectionName());
parent::tearDown(); parent::tearDown();
} }
/** /**
* @return string test file path.
*/
protected function getTestFilePath()
{
return Yii::getAlias('@yiiunit/runtime') . DIRECTORY_SEPARATOR . basename(get_class($this)) . '_' . getmypid();
}
/**
* Sets up test rows. * Sets up test rows.
*/ */
protected function setUpTestRows() protected function setUpTestRows()
...@@ -256,4 +274,50 @@ class ActiveRecordTest extends MongoTestCase ...@@ -256,4 +274,50 @@ class ActiveRecordTest extends MongoTestCase
$this->assertEquals($record->status, $record2->status); $this->assertEquals($record->status, $record2->status);
$this->assertEquals($updateFileContent, $record2->getFileContent()); $this->assertEquals($updateFileContent, $record2->getFileContent());
} }
/**
* @depends testInsertFileContent
*/
public function testWriteFile()
{
$record = new CustomerFile;
$record->tag = 'new new';
$record->status = 7;
$newFileContent = 'Test new file content';
$record->setAttribute('newFileContent', $newFileContent);
$record->save();
$outputFileName = $this->getTestFilePath() . DIRECTORY_SEPARATOR . 'out.txt';
$this->assertTrue($record->writeFile($outputFileName));
$this->assertEquals($newFileContent, file_get_contents($outputFileName));
$record2 = CustomerFile::find($record->_id);
$outputFileName = $this->getTestFilePath() . DIRECTORY_SEPARATOR . 'out_refreshed.txt';
$this->assertTrue($record2->writeFile($outputFileName));
$this->assertEquals($newFileContent, file_get_contents($outputFileName));
}
/**
* @depends testInsertFileContent
*/
public function testGetFileResource()
{
$record = new CustomerFile;
$record->tag = 'new new';
$record->status = 7;
$newFileContent = 'Test new file content';
$record->setAttribute('newFileContent', $newFileContent);
$record->save();
$fileResource = $record->getFileResource();
$contents = stream_get_contents($fileResource);
fclose($fileResource);
$this->assertEquals($newFileContent, $contents);
$record2 = CustomerFile::find($record->_id);
$fileResource = $record2->getFileResource();
$contents = stream_get_contents($fileResource);
fclose($fileResource);
$this->assertEquals($newFileContent, $contents);
}
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment