'Document' ); /** * Get the property keys for this Document Set * * @return array */ public function getPropertyKeys() { $keys = parent::getPropertyKeys(); sort($keys, SORT_NUMERIC); return $keys; } /** * Get a property * * @param mixed $property */ public function getProperty($index = null) { $new = is_null($index); // If property exists and initialised then return it if (!$new && array_key_exists($index, $this->_data)) { return $this->_data[$index]; } // Make sure we are not trying to create a document that is supposed to be saved as a reference if ($new && $this->hasRequirement(static::DYNAMIC_INDEX, 'AsReference')) { require_once 'Thinkopen/Mongodb/Mongo/Exception.php'; throw new Mooses_Mongodb_Mongo_Exception("Can not create a new document from documentset where document must be saved as a reference"); } if (!$new) { // Fetch clean data for this property if it exists if (array_key_exists($index, $this->_cleanData)) $data = $this->_cleanData[$index]; else return null; } else $data = array(); // If property is a reference to another document then fetch the reference document if (MongoDBRef::isRef($data)) { $collection = $data['$ref']; $data = MongoDBRef::get($this->_getMongoDB(false), $data); // If this is a broken reference then no point keeping it for later if (!$data) { $this->_data[$index] = null; return $this->_data[$index]; } $reference = true; } else { $reference = false; $collection = $this->getConfigAttribute('collection'); } $config = array (); $config['new'] = $new; $config['requirementModifiers'] = $this->getRequirements(self::DYNAMIC_INDEX.'.'); $config['parentIsDocumentSet'] = true; $config['connectionGroup'] = $this->getConfigAttribute('connectionGroup'); $config['db'] = $this->getConfigAttribute('db'); $config['collection'] = $collection; if (!$reference) { // If this is a new array element. We will $push to the array when saving if ($new) $path = $this->getPathToDocument(); else $path = $this->getPathToProperty($index); $config['pathToDocument'] = $path; $config['criteria'] = $this->getCriteria(); $config['hasId'] = $this->hasRequirement(self::DYNAMIC_INDEX, 'hasId'); } // get the document class $documentClass = $this->hasRequirement(self::DYNAMIC_INDEX, 'Document'); if (isset($data['_type']) && !empty($data['_type'][0])) { $documentClass = $data['_type'][0]; } $document = new $documentClass($data, $config); // if this document was a reference then remember that if ($reference) { $this->_references->attach($document); } // If this is not a new document cache it if (!$new) { $this->_data[$index] = $document; } return $document; } /** * Set property * * @param $index * @param $document */ public function setProperty($index, $document) { $new = is_null($index); // Make sure index is numeric if (!$new && !is_numeric($index)) { require_once 'Thinkopen/Mongodb/Mongo/Exception.php'; throw new Mooses_Mongodb_Mongo_Exception("Index must be numeric '{$index}' given"); } // Unset element if (!$new && is_null($document)) { $this->_data[$index] = null; return; } // Make sure we are not keeping a copy of the old document in reference memory if (!$new && isset($this->_data[$index]) && !is_null($this->_data[$index])) { $this->_references->detach($this->_data[$index]); } // Throw exception if value is not valid $validators = $this->getValidators(self::DYNAMIC_INDEX); if (!$validators->isValid($document)) { require_once 'Thinkopen/Mongodb/Mongo/Exception.php'; throw new Mooses_Mongodb_Mongo_Exception(implode($validators->getMessages(), "\n")); } if ($new) { $keys = $this->getPropertyKeys(); $index = empty($keys) ? 0 : max($keys)+1; } // Filter value // $value = $this->getFilters(self::DYNAMIC_INDEX)->filter($document); if (!$this->hasRequirement(self::DYNAMIC_INDEX, 'AsReference')) { // Make a new document if it has been saved somewhere else if (!$document->isNewDocument()) { $documentClass = get_class($document); $document = new $documentClass($document->export(), array('new' => false, 'pathToDocument' => $this->getPathToProperty($index))); } else { $document->setPathToDocument($this->getPathToProperty($index)); } // Inform the document of it's surroundings $document->setConfigAttribute('connectionGroup', $this->getConfigAttribute('connectionGroup')); $document->setConfigAttribute('db', $this->getConfigAttribute('db')); $document->setConfigAttribute('collection', $this->getConfigAttribute('collection')); $document->setConfigAttribute('criteria', $this->getCriteria()); $document->applyRequirements($this->getRequirements(self::DYNAMIC_INDEX.'.')); } $this->_data[$index] = $document; } /** * Export all data * * @return array */ public function export($skipRequired = false) { // Since this is an array, fill in empty index's with null $exportData = parent::export($skipRequired); // Fix PHP "max(): Array must contain at least one element" bug // if DocumentSet has no data if (count($exportData) > 0) { $maxKey = max(array_keys($exportData)); for ($i = 0; $i<$maxKey; $i++) { if (array_key_exists($i, $exportData)) { continue; } $exportData[$i] = null; } ksort($exportData); } return $exportData; } /** * Add a document to this set * * @param Mooses_Mongodb_Mongo_Document $document */ public function addDocument(Mooses_Mongodb_Mongo_Document $document) { return $this->setProperty(null, $document); } /** * Add a document to the push queue * * @param Mooses_Mongodb_Mongo_Document $document */ public function pushDocument(Mooses_Mongodb_Mongo_Document $document) { $this->push(null, $document); } /** * Get all operations * * @param Boolean $includingChildren Get operations from children as well */ public function getOperations($includingChildren = false) { if ($this->hasRequirement(self::DYNAMIC_INDEX, 'AsReference')) $includingChildren = false; return parent::getOperations($includingChildren); } /** * Remove all operations * * @param Boolean $includingChildren Remove operations from children as wells */ public function purgeOperations($includingChildren = false) { if ($this->hasRequirement(self::DYNAMIC_INDEX, 'AsReference')) $includingChildren = false; return parent::purgeOperations($includingChildren); } public function __call($name, $arguments = array()) { switch ($name) { case 'new': return $this->getProperty(); } require_once 'Thinkopen/Mongodb/Mongo/Exception.php'; throw new Mooses_Mongodb_Mongo_Exception("Captured in __call. Method $name does not exist."); } }