/** * Add one object into objects and its associated db to watch * @param epObject $o * @param epDbObject $db * @return bool */ public function addObject($o, $db) { // validate input if (!$o instanceof epObject) { return false; } // has object been kept? $uid = $o->epGetUId(); if (!isset($this->objects[$uid])) { // check if object is in transaction. start if not if (!$o->epInTransaction()) { $o->epStartTransaction(); } // add the associated db to watch $this->addDb($db); // add if not $this->objects[$uid] = $o; } return true; }
/** * Checks if the variables of this object matches all the * non-null variables in another object * * <b> * Note: for now we only match primitive fields. For relational * fields, things can get complicated as we may be dealing with * very "deep" comparisons and recursions. * </b> * * @param epObject $o the example object * @param bool $deep should this be a deep search * @return bool */ public function epMatches($o, $deep = false) { // make sure param is epObject if (!$o instanceof epObject) { return false; } // same object if same object uid if ($this->ep_uid == $o->epGetUId()) { return true; } // matches if the example object does not have any non-null variable if (!($vars_o = $o->epGetVars())) { return true; } // get vars of this object $vars = $this->epGetVars(); // set 'matching' flag to avoid endless loop $this->epSetMatching(true); $o->epSetMatching(true); // go through each var from the example object foreach ($vars_o as $var => $value) { // skip 'oid' if ($var == 'oid') { continue; } // ignore null values (including empty string) if (is_null($value) || is_string($value) && !$value) { continue; } // for primitive var, mismatch if var is not in object or two vars unequal if ($this->epIsPrimitive($var)) { if (!isset($vars[$var]) || $vars[$var] != $value) { $this->epSetMatching(false); $o->epSetMatching(false); return false; } continue; } // done if no deep matching (see method comments) if (!$deep) { continue; } // deep matching for relationship fields // many-valued relationship var if ($value instanceof epArray) { // the epArray can have different order between the // two objects, so we have to do an n^2 loop to see // if they are the same (ugly) // oak: shall we match array count? strict mode? // foreach ($value as $obj) { if (!$obj) { continue; } // skip object already under matching if ($obj->epIsMatching()) { continue; } // flag indicates object being matched $matched = false; // go through each var in array foreach ($vars[$var] as $tmp) { if (!$tmp->epIsMatching() && !$obj->epIsMatching()) { if ($tmp->epMatches($obj, true)) { $matched = true; break; } } } // no match to $obj. done. if (!$matched) { $this->epSetMatching(false); $o->epSetMatching(false); return false; } } } else { if ($value instanceof epObject && !$value->epIsMatching()) { // we need to check this if (!isset($vars[$var])) { $vars[$var] = $this->epGet($var); } // match only when vars are not flagged 'matching' if (!$value->epIsMatching() && !$vars[$var]->epIsMatching()) { if (!$vars[$var]->epMatches($value, true)) { $this->epSetMatching(false); $o->epSetMatching(false); return false; } } else { $this->epSetMatching(false); $o->epSetMatching(false); return false; } } } } // reset matching flags $this->epSetMatching(false); $o->epSetMatching(false); return true; }
/** * Low level create (called by {@link create()}) * Create a new instance of a class * * Although this method is made public for {@link epDbObject} to be able * to call in assembling objects from database rows, it is <b>not</b> * recommended to be used. Please use {@epManager::create()} instead. * * @param string|object $class_or_obj class name or an object * @param boolean $caching whether to cache the newly created object * @param boolean $dispatch_event whether to dispatch event * @return null|epObject * @access public * @throws epExceptionManagerBase */ public function &_create($class_or_obj, $caching = true, $dispatch_event = true, $args = array()) { // check if the argument is a string (class name) $class = ''; $o = false; if (is_string($class_or_obj)) { $class = $class_or_obj; } else { if (is_object($class_or_obj)) { $o =& $class_or_obj; $class = get_class($o); } else { throw new epExceptionManagerBase('Argument unrecognized. It should be either object or class name (string)'); return self::$null; } } // check if class has been compiled if (!($cm =& $this->_getMap($class))) { // if not, check if auto_compile is enabled if (!$this->getConfigOption('auto_compile')) { // if not (auto_compile off), throw throw new epExceptionManagerBase('Class ' . $class . ' has not been compiled. ' . 'It cannot be made persistable. Either enable ' . 'auto_compile or compile manually'); return self::$null; } // otherwise (auto compile enabled) if (!($cm =& $this->_compileClass($class))) { // return false if auto-compile fails return self::$null; } } // event: onPreCreate if ($dispatch_event) { $this->_dispatchEvent(array('onPreCreate'), $class, $args); } // in case the argument is not object, create it if (!$o) { // make a new instance if (!($o =& epNewObject($class, $args))) { // throw if failed to create an object throw new epExceptionManagerBase('Cannot create object for class [' . $class . ']'); return self::$null; } } // wrap object if it doesn't have epObject ifc if (!$o instanceof epObject) { if (!($o = new epObject($o, $cm))) { throw new epExceptionManagerBase('Cannot wrap object of [' . $class . ']'); return self::$null; } } // cache it in the array of uncommited objects (only when auto_flush is on) if ($caching) { $this->objects_uc[$o->epGetUId()] =& $o; } // event: onCreate, onPostCreate if ($dispatch_event) { $this->_dispatchEvent(array('onCreate', 'onPostCreate'), $o); } return $o; }
/** * Checks if the variables of this object matches all the * non-null variables in another object * * <b> * Note: for now we only match primitive fields. For relational * fields, things can get complicated as we may be dealing with * very "deep" comparisons and recursions. * </b> * * @param epObject $o the example object * @param bool $deep should this be a deep search * @return bool */ public function epMatches($o, $deep = false) { if (!$o instanceof epObject) { return false; } // same object if same object uid if ($this->ep_uid == $o->epGetUId()) { return true; } // matches if the example object does not have any non-null variable if (!($vars_o = $o->epGetVars())) { return true; } $this->epSetMatching(true); $o->epSetMatching(true); // get vars of this object $vars = $this->epGetVars(); // go through each var from the example object foreach ($vars_o as $var => $value) { if ($var == 'oid') { continue; } // ignore null values (including empty string) if (is_null($value) || is_string($value) && !$value) { continue; } // skip non-primitive fields (see note in method comment above) // unless we are doing a deep search if (!$this->epIsPrimitive($var)) { if ($deep) { if ($value instanceof epArray) { // the epArray can have different order between the // two objects, so we have to do an n^2 loop to see // if they are the same (ugly) foreach ($value->getIterator() as $obj) { if (!$obj) { continue; } $matches = array(); $matched = false; // we are working on this one already, don't mess with it if ($obj->epIsMatching()) { continue; } foreach ($vars[$var]->getIterator() as $temp) { if (in_array($temp->epGetUId(), $matches)) { continue; } if (!$temp->epIsMatching() && !$obj->epIsMatching()) { if ($temp->epMatches($obj, true)) { // we have matched this temp object // we don't want to check it again $matches[] = $temp->epGetUId(); $matched = true; break; } } } if (!$matched) { $this->epSetMatching(false); $o->epSetMatching(false); return false; } } } elseif ($value instanceof epObjectWrapper && !$value->epIsMatching()) { if (!isset($vars[$var])) { // we need to check this $vars[$var] = $this->epGet($var); } if (!$value->epIsMatching() && !$vars[$var]->epIsMatching()) { if (!$vars[$var]->epMatches($value, true)) { $this->epSetMatching(false); $o->epSetMatching(false); return false; } } elseif ($value->epIsMatching() && !$vars[$var]->epIsMatching()) { // if one is matching and the other is not, they are not equal $this->epSetMatching(false); $o->epSetMatching(false); return false; } elseif (!$value->epIsMatching() && $vars[$var]->epIsMatching()) { $this->epSetMatching(false); $o->epSetMatching(false); return false; } } } continue; } // is var in the objects's vars? if (!isset($vars[$var])) { $this->epSetMatching(false); $o->epSetMatching(false); return false; } // are the values same? if ($vars[$var] != $value) { $this->epSetMatching(false); $o->epSetMatching(false); return false; } } $this->epSetMatching(false); $o->epSetMatching(false); return true; }