/** * Commits an object * @param object $o * @return bool $force (ignored - treated as false!) * @access public */ public function commit(&$o, $force = false) { // make sure we are dealing with an epObject if (!$o instanceof epObject) { return false; } // check if the object should be commited if (!$force && !$o->epNeedsCommit()) { return true; } // get class map for class if (!($cm =& $o->epGetClassMap())) { return false; } // get class name if (!($class = $cm->getName())) { return false; } // check if class has any non-primitive fields if (!($npfs = $cm->getNonPrimitive())) { return $this->_commit_o($o); } // set object is being commited $o->epSetCommitting(true); // get all modified relationship vars $modified_rvars = $o->epGetModifiedVars(epObject::VAR_RELATIONSHIP); // array to keep track of 1-to-many relations $relations = array(); // go through each non-primitive field $status = true; foreach ($npfs as $name => $fm) { // initialize arrays to hold relation oids if (isset($modified_rvars[$name])) { $relations[$name] = array(); $relations[$name][$fm->getBase_b()] = array('new' => array(), 'old' => null); } // var field value if (!($v =& $o->epGet($name))) { continue; } // check if value is array if (is_array($v) || $v instanceof epArray) { // check if it is a "many" field if (!$fm->isMany()) { throw new epExceptionManager('Value (array) of variable [' . $cm->getName() . "::" . $fm->getName() . '] and its field map mismatch'); continue; } // no convertion from oid to object if ($v instanceof epArray) { $convert_oid_0 = $v->getConvertOid(); $v->setConvertOid(false); } // go through each value in $v $oids = array(); foreach ($v as &$w) { if (is_string($w)) { $oids[] = $w; } else { if (is_object($w) && $w instanceof epObject) { // ignore deleted object if ($w->epIsDeleted()) { continue; } // commit the value (object) if ($w->epIsCommitting()) { if (!$w->epGetObjectId()) { // if the object is to be commited, do a simple commit to get the oid $status &= $this->_commit_o($w, true); // true: simple commit } } else { // for not in to-be-committed queue $status &= $this->commit($w); } if ($w->epIsCommittable()) { // collect oid $oids[] = $this->encodeUoid($w); } } } } // set convert id flag back if ($v instanceof epArray) { $v->setConvertOid($convert_oid_0); } // put oids into the relation array if (isset($modified_rvars[$name])) { $new = $oids; $old = null; if ($v instanceof epArray) { $old = array(); $new = array(); $origArray = $v->getOrigArray(); // figure out how many of each object is in the relationships $oidscount = array(); $oidsduplicate = array(); foreach ($oids as $oid) { if (!isset($oidscount[$oid])) { $oidscount[$oid] = 0; } $oidscount[$oid]++; if ($oidscount[$oid] > 1) { // keep track of the duplicate ones $oidsduplicate[$oid] = $oidscount[$oid]; } } $origcount = array(); $origduplicate = array(); foreach ($origArray as $oid) { if (!isset($origcount[$oid])) { $origcount[$oid] = 0; } $origcount[$oid]++; if ($origcount[$oid] > 1) { // keep track of the duplicate ones $origduplicate[$oid] = $origcount[$oid]; } } // grab the differences between the original and the new one $new = array_diff($oids, $origArray); $old = array_diff($origArray, $oids); // check for duplicates because array_diff doesn't care about them if (count($origduplicate) > 0 || count($oidsduplicate) > 0) { // find out if there are any duplicate counts // This is done by going through all the original duplicates // and checking: // 1. Are they even in the new oids // a. If not, the array_diff already took care of it // b. If so, check the count to see if there is a difference // i. If not, leave it alone // ii. If so, check if greater or lesser // I. orig is greater: delete them all and add them back to new // II. new is greater: add the difference to new // // Also, delete the oidsduplicates that we see so we can check if we have // any new duplicates. // Just add one less than the count to the new for the new duplicates. This // is because if they are brand new, $new will already have on entry, and if // there are not new, the relationship already contains one of them. foreach ($origduplicate as $oid => $count) { if (isset($oidscount[$oid])) { if ($oidscount[$oid] > $count) { $new = array_merge($new, array_fill(0, $oidscount[$oid] - $count, $oid)); } elseif ($oidscount[$oid] < $count) { $new = array_merge($new, array_fill(0, $oidscount[$oid], $oid)); $old[] = $oid; } unset($oidsduplicate[$oid]); } } foreach ($oidsduplicate as $oid => $count) { $new = array_merge($new, array_fill(0, $count - 1, $oid)); } } // set the new original Array $v->setOrigArray($oids); } $relations[$name][$fm->getBase_b()]['new'] = $new; $relations[$name][$fm->getBase_b()]['old'] = $old; } } else { $oid = false; if (is_string($v)) { $oid = $v; } else { if (is_object($v) && $v instanceof epObject) { // check if it is a "One" field map if (!$fm->isSingle()) { throw new epExceptionManager('Variable value (array) and field map (One) mismatch'); continue; } // ignore deleted object if ($v->epIsDeleted()) { continue; } // commit the value (object) if ($v->epIsCommitting()) { if (!$v->epGetObjectId()) { // if the object is to be commited, do simple commit to get the oid $status &= $this->_commit_o($v, true); // true: simple commit } } else { // object not in to-be-committed queue. force commit $status &= $this->commit($v); } if ($v->epIsCommittable()) { // collect oid $oid = $this->encodeUoid($v); } } } // put oid into the relation array if ($oid !== false) { if (isset($modified_rvars[$name])) { $relations[$name][$fm->getBase_b()]['new'] = array($oid); $relations[$name][$fm->getBase_b()]['old'] = null; } } } } // make object committable $o->epSetCommitting(false); if ($o->epNeedsCommit()) { $status &= $this->_commit_o($o); } // update object relation for has_many or composed_of_many fields foreach ($relations as $var_a => $relation) { $base_a = $cm->getField($var_a)->getBase_a(); foreach ($relation as $base_b => $b_oids) { $status &= $this->_updateRelations($base_a, $class, $o->epGetObjectId(), $var_a, $base_b, $b_oids['new'], $b_oids['old']); } } return $status; }
/** * Commits an object * @param object $o * @return bool $force (ignored - treated as false!) * @access public */ public function commit(&$o, $force = false) { // make sure we are dealing with an epObject if (!$o instanceof epObject) { return false; } // check if the object should be commited if (!$force && !$o->epNeedsCommit()) { return true; } // get class name if (!($class = $this->_getClass($o))) { return false; } // get class map for class if (!($cm =& $this->_getMap($class))) { return false; } // check if class has any non-primitive fields if (!($npfs = $cm->getNonPrimitive())) { return $this->_commit_o($o); } // set object is being commited $o->epSetCommitting(true); // get all modified relationship vars $modified_rvars = $o->epGetModifiedVars(epObject::VAR_RELATIONSHIP); // array to keep track of 1-to-many relations $relations = array(); // go through each non-primitive field $status = true; foreach ($npfs as $name => $fm) { // initialize arrays to hold relation oids if (isset($modified_rvars[$name])) { $relations[$name] = array(); $relations[$name][$fm->getBase_b()] = array(); } // var field value if (!($v =& $o->epGet($name))) { continue; } // check if value is array if (is_array($v) || $v instanceof epArray) { // check if it is a "many" field if (!$fm->isMany()) { throw new epExceptionManager('Value (array) of variable [' . $cm->getName() . "::" . $fm->getName() . '] and its field map mismatch'); continue; } // no convertion from oid to object if ($v instanceof epArray) { $convert_oid_0 = $v->getConvertOid(); $v->setConvertOid(false); } // go through each value in $v $oids = array(); foreach ($v as &$w) { if (is_string($w)) { $oids[] = $w; } else { if (is_object($w) && $w instanceof epObject) { // ignore deleted object if ($w->epIsDeleted()) { continue; } // commit the value (object) if ($w->epIsCommitting()) { if (!$w->epGetObjectId()) { // if the object is to be commited, do a simple commit to get the oid $status &= $this->_commit_o($w, true); // true: simple commit } } else { // for not in to-be-committed queue $status &= $this->commit($w); } if ($w->epIsCommittable()) { // collect oid $oids[] = $this->encodeUoid($w); } } } } // set convert id flag back if ($v instanceof epArray) { $v->setConvertOid($convert_oid_0); } // put oids into the relation array if (isset($modified_rvars[$name])) { $relations[$name][$fm->getBase_b()] = $oids; } } else { $oid = false; if (is_string($v)) { $oid = $v; } else { if (is_object($v) && $v instanceof epObject) { // check if it is a "One" field map if (!$fm->isSingle()) { throw new epExceptionManager('Variable value (array) and field map (One) mismatch'); continue; } // ignore deleted object if ($v->epIsDeleted()) { continue; } // commit the value (object) if ($v->epIsCommitting()) { if (!$v->epGetObjectId()) { // if the object is to be commited, do simple commit to get the oid $status &= $this->_commit_o($v, true); // true: simple commit } } else { // object not in to-be-committed queue. force commit $status &= $this->commit($v); } if ($v->epIsCommittable()) { // collect oid $oid = $this->encodeUoid($v); } } } // put oid into the relation array if ($oid !== false) { if (isset($modified_rvars[$name])) { $relations[$name][$fm->getBase_b()] = array($oid); } } } } // make object committable $o->epSetCommitting(false); if ($o->epNeedsCommit()) { $status &= $this->_commit_o($o); } // update object relation for has_many or composed_of_many fields foreach ($relations as $var_a => $relation) { $base_a = $cm->getField($var_a)->getBase_a(); foreach ($relation as $base_b => $b_oids) { $status &= $this->_updateRelations($base_a, $class, $o->epGetObjectId(), $var_a, $base_b, $b_oids); } } return $status; }
/** * Overrides {@link epManagerBase::commit()} to deal with object relationships. * @param object $o * @return bool $force (ignored - treated as false!) * @access public */ public function commit(&$o, $force = false) { // check if the object should be commited if (!$force && !$o->epNeedsCommit()) { return true; } // get class name if (!($class = $this->_getClass($o))) { return false; } // get class map for class if (!($cm =& $this->_getMap($class))) { return false; } // check if class has any non-primitive fields if (!($npfs = $cm->getNonPrimitive())) { // shouldn't happen return parent::commit($o, $force); } // set object is being commited $o->epSetCommitting(true); // array to keep track of 1-to-many relations $relations = array(); // go through each non-primitive field $status = true; foreach ($npfs as $name => $fm) { // initialize arrays to hold relation oids $relations[$name] = array(); $relations[$name][$fm->getClass()] = array(); // var field value if (!($v =& $o->epGet($name))) { continue; } // check if value is array if (is_array($v) || $v instanceof epArray) { // check if it is a "many" field if (!$fm->isMany()) { throw new epExceptionManager('Value (array) of variable [' . $cm->getName() . "::" . $fm->getName() . '] and its field map mismatch'); continue; } // go through each value in $v $oids = array(); foreach ($v as &$w) { if (is_string($w)) { $oids[] = $w; } else { if (is_object($w) && $w instanceof epObject) { // ignore deleted object if ($w->epIsDeleted()) { continue; } // commit the value (object) if ($w->epIsCommitting()) { // if the object is in the to-be-commited array, // let's do a simple commit first to get the oid. // but we need to set it dirty, so its relation // vars can be stored $status &= parent::_commit_o($w); $w->epSetDirty(true); } else { // for not in to-be-committed queue $status &= $this->commit($w); } // collect oid $oids[] = $this->encodeClassOid($w); } } } // put oids into the relation array $relations[$name][$fm->getClass()] = $oids; } else { $oid = false; if (is_string($v)) { $oid = $v; } else { if (is_object($v) && $v instanceof epObject) { // check if it is a "One" field map if (!$fm->isSingle()) { throw new epExceptionManager('Variable value (array) and field map (One) mismatch'); continue; } // ignore deleted object if ($v->epIsDeleted()) { continue; } // commit the value (object) if ($v->epIsCommitting()) { // if the object is to be commited, // let's do a simple commit first to get the oid $status &= parent::_commit_o($v); $v->epSetDirty(true); } else { // object not in to-be-committed queue. force commit $status &= $this->commit($v); } $oid = $this->encodeClassOid($v); } } // put oid into the relation array if ($oid !== false) { $relations[$name][$fm->getClass()] = array($oid); } } } // reset flag object being commited for parent::commit() to work $o->epSetCommitting(false); // call the usual commit $status &= parent::commit($o, $force); // update object relation for has_many or composed_of_many fields foreach ($relations as $var_a => $relation) { $base_a = $cm->getField($var_a)->getClassMap()->getName(); foreach ($relation as $base_b => $b_oids) { $status &= $this->_updateRelations($base_a, $class, $o->epGetObjectId(), $var_a, $base_b, $b_oids); } } return $status; }