Skip to content
This repository
tree: 5c36d63fb1
Fetching contributors…

Cannot retrieve contributors at this time

file 329 lines (295 sloc) 7.297 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
<?php
/**
* @package Morph
* @author Jonathan Moss <xirisr@gmail.com>
* @copyright Jonathan Moss 2009
*/
namespace morph;
/**
* This class provides the Morph_Object <--> MongoDB
* storage provider.
*
* @package Morph
*/
class Storage
{

/**
* @var Morph_Storage
*/
private static $instance;

/**
* @var MongoDB
*/
private $db;

private $useSafe = false;

/**
* Returns the singleton instance of this class
* @return Morph_Storage
*/
public static function instance()
{
if (!isset(self::$instance)) {
throw new \RuntimeException("Morph Storage has not been initialised");
}
return self::$instance;
}

/**
* Initialises the storage object
*
* @param MongoDB $db
* @return Morph_Storage
*/
public static function init(\MongoDB $db)
{
self::$instance = new self($db);
return self::$instance;
}

/**
* De-initilises the storage object
*
* @return void
*/
public static function deInit()
{
self::$instance = null;
}

/**
*
* @param MongoDB $db
* @return Morph_Mapper
*/
private function __construct(\MongoDB $db)
{
$this->db = $db;
}

/**
* If set to true then the 'safe' option for saves is used
*
* @param boolean $useSafe
*/
public function useSafe($useSafe)
{
$this->useSafe = (bool)$useSafe;
return $this;
}

/**
* Returns the associated MongoDB object
*
* @return MongoDB
*/
public function getDatabase()
{
return $this->db;
}

/**
* Retrieves the contents of the specified $id
* and assigns them into $object
*
* By default Morph sets the id to be an instance of MongoId(). When searching you need
* to ensure you do the same by wrapping your id string in a MongoId object
*
* @param Morph\\Object $object
* @param mixed $id
* @return Morph\\Object
*/
public function fetchById(Object $object, $id)
{
$query = array('_id' => $id);
$data = $this->db->selectCollection($object->collection())->findOne($query);
        return $this->setData($object, $data);
}

/**
* Returns all objects with an _id in $ids
*
* By default Morph sets the id to be an instance of MongoId(). When searching you need
* to ensure you do the same by wrapping your id string in a MongoId object
*
* @param Morph\\Object $object
* @param array $Ids
* @return Morph\\Iterator
*/
public function fetchByIds(Object $object, array $ids)
{
$query = new Query();
$query->property('_id')->in($ids);
return $this->findByQuery($object, $query);
}

/**
* Retrieves the contents of the specified $dbRef
* and assigns them into $object
*
* @param Morph_Object $object
* @param array $dbRef
* @return Morph_Object
*/
public function fetchByDbRef(Object $object, array $dbRef)
{
$data = $this->db->getDBRef($dbRef);
        return $this->setData($object, $data);
}

/**
* Saves the provided object if necessary
*
* @param $object
* @return Morph_Object
*/
public function save(Object $object)
{
$response = $object;
if ($object->state() == Enum::STATE_DIRTY){
$response = $this->update($object);
} elseif ($object->state() == Enum::STATE_NEW) {
$response = $this->insert($object);
}
return $response;
}

/**
* Inserts a new object into the database
*
* @param \morph\Object $object
* @param array $options
* @return \morph\Object
*/
private function insert(Object $object, array $options = array())
{
$data = $object->__getData();

//set an id if we do not have one
if(!\array_key_exists('_id', $data)){
$id = array(
                '_id' => new \MongoId()
);
$data = \array_merge($id, $data);
}

$options = array_merge(array('safe'=>$this->useSafe), $options);

$savedOk = $this->db->selectCollection($object->collection())->save($data, $options);
if($savedOk){
$object->__setData($data, Enum::STATE_CLEAN);
}
return $object;
}

/**
* Updates object in the database
*
* @param Morph_Object $object
* @return Morph_Object
*/
private function update(Object $object)
{
return $this->insert($object);
}


/**
* Deletes the object passed in from the database
* @param Morph_Object $object
* @return boolean
*/
public function delete(Object $object)
{
$query = array('_id' => $object->id());
return $this->db->selectCollection($object->collection())->remove($query, true);
}

/**
* Runs query against the database
*
* The results come packages up in a Morph_Iterator object
*
* @param \morph\Object $object Required to determine the correct collection query against
* @param Morph_IQuery $query
* @return Morph_Iterator
*/
public function findByQuery(Object $object, IQuery $query = null)
{
$class = get_class($object);

$query = (is_null($query)) ? new Query() : $query;

$rawQuery = $this->getRawQuery($object, $query);
$cursor = $this->db->selectCollection($object->collection())->find($rawQuery);

$limit = $query->getLimit();
if (!\is_null($limit)) {
$cursor->limit($limit);
}

$skip = $query->getSkip();
if (!\is_null($skip)) {
$cursor->skip($skip);
}

$sort = $query->getRawSort();
if (!\is_null($sort)) {
$cursor->sort($sort);
}

$iterator = new Iterator($object, $cursor);

return $iterator;
}

/**
* Finds one object matching the passed in query
*
* @param Morph_Object $object
* @param Morph_IQuery $query
* @return Morph_Object
*/
public function findOneByQuery(Object $object, IQuery $query = null)
{
$result = null;
$class = \get_class($object);

$query = (is_null($query)) ? new Query() : $query;
$rawQuery = $this->getRawQuery($object, $query);
$data = $this->db->selectCollection($object->collection())->findOne($rawQuery);
        return $this->setData($object, $data);
}

/**
* Ensures that aliased properties are correctly converted in query
*
* @param Object $object
* @param IQuery $query
*/
private function getRawQuery(Object $object, IQuery $query)
{
$rawQuery = array();
foreach ($query->getRawQuery() as $field => $value) {
$storageName = $object->__getPropertySet()->getStorageName($field);
$rawQuery[$storageName] = $value;
}
return $rawQuery;
}

/**
* Fetches a object representing a file in MongoDB
*
* @param mixed $id
* @return MongoGridFSFile
*/
public function fetchFile($id)
{
$query = array('_id' => $id);
return $this->db->getGridFS()->findOne($query);
}

/**
* Saves a file to MongoDB
*
* @param string $filePath
* @param array $oldReference
* @return mixed The id of the stored file
*/
public function saveFile($filePath, $oldReference = null)
{
$id = null;
if (file_exists($filePath)) {
if (!empty($oldReference)) {
$this->db->getGridFS()->remove(array('_id' => $oldReference), true); //remove existing file
}
$id = $this->db->getGridFS()->storeFile($filePath);
} else {
throw new \InvalidArgumentException("The file $filePath does not exist");
}
return $id;
}

    /**
* @param Morph_Object $object
* @param array $data
* @return Morph_Object
*/
    private function setData(Object $object, $data)
    {
        if (empty($data)) {
            throw new \morph\exception\ObjectNotFound();
        }
        $object->__setData($data, Enum::STATE_CLEAN);
return $object;
    }
}
Something went wrong with that request. Please try again.