EMongoGridFS.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. <?php
  2. /**
  3. * EMongoGridFS.php
  4. *
  5. * PHP version 5.2+
  6. *
  7. * @author Jose Martinez <jmartinez@ibitux.com>
  8. * @author Philippe Gaultier <pgaultier@ibitux.com>
  9. * @author Dariusz Górecki <darek.krk@gmail.com>
  10. * @author Invenzzia Group, open-source division of CleverIT company http://www.invenzzia.org
  11. * @copyright 2011 Ibitux
  12. * @license http://www.yiiframework.com/license/ BSD license
  13. * @version SVN: $Revision: $
  14. * @category ext
  15. * @package ext.YiiMongoDbSuite
  16. * @since v1.3
  17. */
  18. /**
  19. * EMongoGridFS
  20. *
  21. * @author Jose Martinez <jmartinez@ibitux.com>
  22. * @author Philippe Gaultier <pgaultier@ibitux.com>
  23. * @author Dariusz Górecki <darek.krk@gmail.com>
  24. * @author Invenzzia Group, open-source division of CleverIT company http://www.invenzzia.org
  25. * @copyright 2011 Ibitux
  26. * @license http://www.yiiframework.com/license/ BSD license
  27. * @version SVN: $Revision: $
  28. * @category ext
  29. * @package ext.YiiMongoDbSuite
  30. * @since v1.3
  31. *
  32. */
  33. abstract class EMongoGridFS extends EMongoDocument
  34. {
  35. /**
  36. * MongoGridFSFile will be stored here
  37. * @var MongoGridFSFile
  38. */
  39. private $_gridFSFile;
  40. /**
  41. * Every EMongoGridFS object has to have one
  42. * @var String $filename
  43. * @since v1.3
  44. */
  45. public $filename = null; // mandatory
  46. /**
  47. * Returns current MongoGridFS object
  48. * By default this method use {@see getCollectionName()}
  49. * @return MongoGridFS
  50. * @since v1.3
  51. */
  52. public function getCollection()
  53. {
  54. if(!isset(self::$_collections[$this->getCollectionName()]))
  55. self::$_collections[$this->getCollectionName()] = $this->getDb()->getGridFS($this->getCollectionName());
  56. return self::$_collections[$this->getCollectionName()];
  57. }
  58. /**
  59. * Inserts a row into the table based on this active record attributes.
  60. * If the table's primary key is auto-incremental and is null before insertion,
  61. * it will be populated with the actual value after insertion.
  62. * Note, validation is not performed in this method. You may call {@link validate} to perform the validation.
  63. * After the record is inserted to DB successfully, its {@link isNewRecord} property will be set false,
  64. * and its {@link scenario} property will be set to be 'update'.
  65. * @param array $attributes list of attributes that need to be saved. Defaults to null,
  66. * meaning all attributes that are loaded from DB will be saved.
  67. * @return boolean whether the attributes are valid and the record is inserted successfully.
  68. * @throws CException if the record is not new
  69. * @since v1.3
  70. */
  71. public function insert(array $attributes=null)
  72. {
  73. if(!$this->getIsNewRecord())
  74. throw new CDbException(Yii::t('yii','The EMongoDocument cannot be inserted to database because it is not new.'));
  75. if($this->beforeSave())
  76. {
  77. Yii::trace('Trace: '.__CLASS__.'::'.__FUNCTION__.'()', 'ext.MongoDb.EMongoGridFS');
  78. $rawData = $this->toArray();
  79. // free the '_id' container if empty, mongo will not populate it if exists
  80. if(empty($rawData['_id']))
  81. unset($rawData['_id']);
  82. // filter attributes if set in param
  83. if($attributes!==null)
  84. {
  85. foreach($rawData as $key=>$value)
  86. {
  87. if(!in_array($key, $attributes))
  88. unset($rawData[$key]);
  89. }
  90. }
  91. // check file
  92. $filename = "";
  93. if(!array_key_exists('filename', $rawData))
  94. throw new CException(Yii::t('yii', 'We need a filename'));
  95. else
  96. {
  97. $filename = $rawData['filename'];
  98. unset($rawData['filename']);
  99. }
  100. $result = $this->getCollection()->put($filename, $rawData);
  101. if($result !== false) // strict comparsion driver may return empty array
  102. {
  103. $this->_id = $result;
  104. //TODO: should be set in parent class
  105. $this->_gridFSFile = $this->getCollection()->findOne(array('_id'=>$this->_id));
  106. $this->setIsNewRecord(false);
  107. $this->setScenario('update');
  108. $this->afterSave();
  109. return true;
  110. }
  111. throw new CException(Yii::t('yii', 'Can\t save document to disk, or try to save empty document!'));
  112. }
  113. return false;
  114. }
  115. /**
  116. * Insertion by Primary Key inserts a MongoGridFSFile forcing the MongoID
  117. * @param MongoId $pk
  118. * @param array $attributes
  119. * @throws CDbException
  120. * @throws CException
  121. * @return boolean whether the insert success
  122. * @since v1.3
  123. */
  124. public function insertWithPk($pk, array $attributes=null) {
  125. if(!($pk instanceof MongoId))
  126. throw new CDbException(Yii::t('yii','The EMongoDocument cannot be inserted to database primary key is not defined.'));
  127. if($this->beforeSave())
  128. {
  129. Yii::trace('Trace: '.__CLASS__.'::'.__FUNCTION__.'()', 'ext.MongoDb.EMongoGridFS');
  130. $rawData = $this->toArray();
  131. $rawData['_id'] = $pk;
  132. // filter attributes if set in param
  133. if($attributes!==null)
  134. {
  135. foreach($rawData as $key=>$value)
  136. {
  137. if(!in_array($key, $attributes))
  138. unset($rawData[$key]);
  139. }
  140. }
  141. // check file
  142. $filename = "";
  143. if(!array_key_exists('filename', $rawData))
  144. throw new CException(Yii::t('yii', 'We need a filename'));
  145. else
  146. {
  147. $filename = $rawData['filename'];
  148. unset($rawData['filename']);
  149. }
  150. $result = $this->getCollection()->put($filename, $rawData);
  151. if($result !== false) // strict comparsion driver may return empty array
  152. {
  153. $this->_id = $result;
  154. //TODO: should be set in parent class
  155. $this->_gridFSFile = $this->getCollection()->findOne(array('_id'=>$this->_id));
  156. $this->setIsNewRecord(false);
  157. $this->setScenario('update');
  158. $this->afterSave();
  159. return true;
  160. }
  161. throw new CException(Yii::t('yii', 'Can\'t save document to disk, or try to save empty document!'));
  162. }
  163. return false;
  164. }
  165. /**
  166. * Updates the row represented by this active record.
  167. * All loaded attributes will be saved to the database.
  168. * Note, validation is not performed in this method. You may call {@link validate} to perform the validation.
  169. * @param array $attributes list of attributes that need to be saved. Defaults to null,
  170. * meaning all attributes that are loaded from DB will be saved.
  171. * @return boolean whether the update is successful
  172. * @throws CException if the record is new
  173. * @since v1.3
  174. */
  175. public function update(array $attributes=null)
  176. {
  177. Yii::trace('Trace: '.__CLASS__.'::'.__FUNCTION__.'()', 'ext.MongoDb.EMongoGridFS');
  178. if($this->getIsNewRecord())
  179. throw new CDbException(Yii::t('yii','The EMongoDocument cannot be updated because it is new.'));
  180. if(is_file($this->filename) === true) {
  181. if($this->deleteByPk($this->_id) !== false)
  182. {
  183. $result = $this->insertWithPk($this->_id, $attributes);
  184. if($result === true)
  185. return true;
  186. else
  187. return false;
  188. }
  189. } else {
  190. return parent::update($attributes, true);
  191. }
  192. }
  193. /**
  194. * Creates an EMongoGridFS with the given attributes.
  195. * This method is internally used by the find methods.
  196. * @param MongoGridFSFile $document mongo gridFSFile
  197. * @param array $attributes attribute values (column name=>column value)
  198. * @param boolean $callAfterFind whether to call {@link afterFind} after the record is populated.
  199. * This parameter is added in version 1.0.3.
  200. * @return EMongoDocument the newly created document. The class of the object is the same as the model class.
  201. * Null is returned if the input data is false.
  202. * @since v1.3
  203. */
  204. public function populateRecord($document, $callAfterFind=true)
  205. {
  206. Yii::trace('Trace: '.__CLASS__.'::'.__FUNCTION__.'()', 'ext.MongoDb.EMongoGridFS');
  207. if($document instanceof MongoGridFSFile)
  208. {
  209. $model = parent::populateRecord($document->file, $callAfterFind);
  210. $model->_gridFSFile = $document;
  211. return $model;
  212. }
  213. else
  214. return parent::populateRecord($document, $callAfterFind);
  215. }
  216. /**
  217. * Returns the file size
  218. * GetSize wrapper of MongoGridFSFile function
  219. * @return integer file size
  220. * False is returned if error
  221. * @since v1.3
  222. */
  223. public function getSize()
  224. {
  225. Yii::trace('Trace: '.__CLASS__.'::'.__FUNCTION__.'()', 'ext.MongoDb.EMongoGridFS');
  226. if(method_exists($this->_gridFSFile, 'getSize') === true)
  227. return $this->_gridFSFile->getSize();
  228. else
  229. return false;
  230. }
  231. /**
  232. * Returns the filename
  233. * GetFilename wrapper of MongoGridFSFile function
  234. * @return string filename
  235. * False is returned if error
  236. * @since v1.3
  237. */
  238. public function getFilename()
  239. {
  240. Yii::trace('Trace: '.__CLASS__.'::'.__FUNCTION__.'()', 'ext.MongoDb.EMongoGridFS');
  241. if (method_exists($this->_gridFSFile, 'getFilename') === true)
  242. return $this->_gridFSFile->getFilename();
  243. else
  244. return false;
  245. }
  246. /**
  247. * Returns the file's contents as a string of bytes
  248. * getBytes wrapper of MongoGridFSFile function
  249. * @return string string of bytes
  250. * False is returned if error
  251. * @since v1.3
  252. */
  253. public function getBytes()
  254. {
  255. Yii::trace('Trace: '.__CLASS__.'::'.__FUNCTION__.'()', 'ext.MongoDb.EMongoGridFS');
  256. if (method_exists($this->_gridFSFile, 'getBytes') === true)
  257. return $this->_gridFSFile->getBytes();
  258. else
  259. return false;
  260. }
  261. /**
  262. * Writes this file to the system
  263. * @param string $filename The location to which to write the file. If none is given, the stored filename will be used.
  264. * @return integer number of bytes written
  265. * @since v1.3
  266. */
  267. public function write($filename=null)
  268. {
  269. Yii::trace('Trace: '.__CLASS__.'::'.__FUNCTION__.'()', 'ext.MongoDb.EMongoGridFS');
  270. if (method_exists($this->_gridFSFile, 'write') === true)
  271. return $this->_gridFSFile->write($filename);
  272. else
  273. return false;
  274. }
  275. /**
  276. * Deletes documents with the specified primary keys.
  277. * See {@link find()} for detailed explanation about $condition and $params.
  278. * @param mixed $pk primary key value(s). Use array for multiple primary keys. For composite key, each key value must be an array (column name=>column value).
  279. * @param array|EMongoCriteria $condition query criteria.
  280. * @return array whether the delete succeeds
  281. * @since v1.3
  282. */
  283. public function deleteAll($criteria=null)
  284. {
  285. Yii::trace('Trace: '.__CLASS__.'::'.__FUNCTION__.'()', 'ext.MongoDb.EMongoGridFS');
  286. $this->applyScopes($criteria);
  287. return $this->getCollection()->remove($criteria->getConditions(), array(
  288. 'fsync'=>$this->getFsyncFlag(),
  289. 'safe'=>$this->getSafeFlag(),
  290. ));
  291. }
  292. }