/**
  * 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;
 }
Exemple #2
0
 /**
  * Cache an object
  * @param epObject $o The object to be added into cache
  * @param boolean $force Whether to force replace object in cache
  * @return boolean
  */
 public function add(epObject &$o, $force = false)
 {
     // don't cache objects that haven't been committed
     if (!($oid = $o->epGetObjectId())) {
         return false;
     }
     // get class
     if (!($class = $o->epGetClass())) {
         return false;
     }
     // generate key
     $key = $this->_key($class);
     // get all objects for the class
     if (!($os = $this->cache->get($key))) {
         $os = array();
     }
     // done if not forced -and- oid already in cache
     if (!$force && in_array($o->oid, array_keys($os))) {
         return true;
     }
     // put object into array
     $os[$o->oid] = $o;
     // is class write locked?
     if ($this->isLocked($class, self::LOCK_WRITE)) {
         return false;
     }
     // lock write
     $this->_lock($class, self::LOCK_WRITE);
     // cache array
     $status = $this->cache->set($key, $os);
     // unlock write
     $this->_unlock($class, self::LOCK_WRITE);
     return $status;
 }
 /**
  * test array access
  */
 function testArrayAccess()
 {
     // make an eptTest object
     $this->assertTrue($o = new eptTest("XXX", "YYY", "ZZZ"));
     // wrap it with epObject
     $this->assertTrue($w = new epObject($o));
     // test new object is not dirty
     $this->assertFalse($w->epIsDirty());
     // test epGet('x') against direct object property access ($o->x)
     $this->assertTrue($w['x'] === $o->x);
     // test epSet('x'), epGet('x'), and $w->x (overloading __get())
     $value = md5($w['x']);
     $this->assertTrue($w['x'] = $value);
     $this->assertTrue($o->x === $value);
     $this->assertTrue($w['x'] === $o->x);
     $this->assertTrue($w->epIsDirty());
     // check if 'x' is in modified list
     $this->assertTrue($modified = $w->epGetModifiedVars());
     $this->assertTrue(array_key_exists('x', $modified));
     $this->assertTrue($modified['x'] === $value);
     // getting protected 'y' gets exception
     try {
         $this->assertTrue($w['y'] === false);
     } catch (Exception $e) {
         // !!!simpletest seem to ignore assert in catch block
         $this->assertTrue($e instanceof epExceptionObject);
     }
     // setting protected 'y' gets exception
     try {
         $w['y'] = 'YYY|YYY';
     } catch (Exception $e) {
         // !!!simpletest seem to ignore assert in catch block
         $this->assertTrue($e instanceof epExceptionObject);
     }
     // getting protected 'z' gets exception
     try {
         $this->assertTrue($w['z'] === false);
     } catch (Exception $e) {
         // !!!simpletest seem to ignore assert in catch block
         $this->assertTrue($e instanceof epExceptionObject);
     }
     // setting protected 'z' gets exception
     try {
         $w['z'] = 'ZZZ|ZZZ';
     } catch (Exception $e) {
         // !!!simpletest seem to ignore assert in catch block
         $this->assertTrue($e instanceof epExceptionObject);
     }
     // test foreach
     $vars = array();
     foreach ($w as $var => $value) {
         $vars[$var] = $value;
     }
     // check var number
     $this->assertTrue(count($vars) == $w->count());
 }
Exemple #4
0
 /**
  * Generate a string that can be used to uniquely identify an object.
  * False is returned if invalid object or object does not have oid yet.
  * @param epObject $o
  * @return false|string
  */
 public function encodeUoid(epObject $o)
 {
     if (!$o || !($oid = $o->epGetObjectId())) {
         return false;
     }
     // put class name and id into simple format: "<class>:<id>"
     return $this->_encodeUoid($this->_getClass($o), $oid);
 }
 /**
  * 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;
 }
 /**
  * Make where part of a SQL select to get children values
  * @param epDbObject $db the db connection  
  * @param epObject $o the child object for query
  * @param int $depth how many children down we are
  * @param string $parent the parent of this child
  * @return array('from', 'where')
  * @author Oak Nauhygon <*****@*****.**>
  * @author Trevan Richins <*****@*****.**>
  */
 public static function sqlSelectChildren($db, $o, $depth, $parent)
 {
     // array to keep new tables in 'from'
     $from = array();
     // array to keep new expression in 'where'
     $where = array();
     // get the class map for the child object
     $cm = $o->epGetClassMap();
     // get all vars in the object
     $vars = $o->epGetVars();
     // if object has oid, select use oid
     if ($oid = $o->epGetObjectId()) {
         $where[] = $db->quoteId($cm->getOidColumn()) . ' = ' . $oid;
         return array('from' => $from, 'where' => $where);
     }
     // mark child object under search (to avoid loops)
     $o->epSetSearching(true);
     // total number of vars (primitive or non-primitive) collected
     $n = 0;
     // new depth
     $depth++;
     // number of non-primitive (relationship) fields collected
     $nprim_id = 0;
     // loop through vars
     while (list($var, $val) = each($vars)) {
         // get field map
         if (!($fm =& $cm->getField($var))) {
             // should not happen
             continue;
         }
         // exclude null values (including empty strings)
         if (is_null($val) || !$val && $fm->getType() == epFieldMap::DT_CHAR) {
             continue;
         }
         // is it a primitive var?
         if ($fm->isPrimitive()) {
             $where[] = $db->quoteId($parent) . '.' . $db->quoteId($fm->getColumnName()) . ' = ' . $db->quote($val, $fm);
             // done for this var
             $n++;
             continue;
         }
         // okay we are dealing with a non-primitive (relationship) var
         if ($val instanceof epArray) {
             foreach ($val as $obj) {
                 // skip object that is under searching
                 if (!$obj || $obj->epIsSearching()) {
                     continue;
                 }
                 // get 'where' and 'from' from relationship
                 $from_where = epObj2Sql::sqlSelectRelations($db, $fm, $cm, $obj->epGetClassMap()->getTable(), $depth . $nprim_id, $parent);
                 $where = array_merge($where, $from_where['where']);
                 $from = array_merge($from, $from_where['from']);
                 // get 'where' and 'from' from relationship
                 $from_where = epObj2Sql::sqlSelectChildren($db, $obj, $depth, '_' . $depth . $nprim_id);
                 $where = array_merge($where, $from_where['where']);
                 $from = array_merge($from, $from_where['from']);
                 $nprim_id++;
             }
         } else {
             if ($val instanceof epObject && !$val->epIsSearching()) {
                 // get 'where' and 'from' from relationship
                 $from_where = epObj2Sql::sqlSelectRelations($db, $fm, $cm, $val->epGetClassMap()->getTable(), $depth . $nprim_id, $parent);
                 $where = array_merge($where, $from_where['where']);
                 $from = array_merge($from, $from_where['from']);
                 // get 'where' and 'from' from relationship
                 $from_where = epObj2Sql::sqlSelectChildren($db, $val, $depth, '_' . $depth . $nprim_id);
                 $where = array_merge($where, $from_where['where']);
                 $from = array_merge($from, $from_where['from']);
                 $nprim_id++;
             }
         }
         $n++;
     }
     // reset search flag on child object
     $o->epSetSearching(false);
     return array('from' => $from, 'where' => $where);
 }
 /**
  * Update the value of the inverse var
  * @param epFieldMap
  * @param epObject $o the opposite object
  * @param string $actoin UPDATE_INVERSE_ADD or UPDATE_INVERSE_REMOVE
  * @return boolean
  */
 protected function _updateInverse($fm, &$o, $action = self::UPDATE_INVERSE_ADD)
 {
     // check if object is epObject
     if (!$o || !$o instanceof epObject) {
         return false;
     }
     // no action if an object is updating (to prevent endless loop)
     if ($o->epIsUpdating()) {
         return true;
     }
     // get inverse var
     if (!($ivar = $fm->getInverse())) {
         return true;
     }
     // set inverse updating flag
     $o->epSetUpdating(true);
     // a single-valued field
     if (!$o->epIsMany($ivar)) {
         switch ($action) {
             case self::UPDATE_INVERSE_ADD:
                 $o[$ivar] = $this;
                 break;
             case self::UPDATE_INVERSE_REMOVE:
                 $o[$ivar] = null;
                 break;
         }
     } else {
         switch ($action) {
             case self::UPDATE_INVERSE_ADD:
                 $o[$ivar][] = $this;
                 break;
             case self::UPDATE_INVERSE_REMOVE:
                 $o[$ivar]->remove($this);
                 break;
         }
     }
     // reset inverse updating flag
     $o->epSetUpdating(false);
     return true;
 }
 /**
  * Builds SQL statement from an object
  * @param epObject &$o the object 
  * @param epFieldMap &$fm the field map of the var that the object is assigned to
  * @param string $alias
  * @return array
  */
 protected function _buildSqlObject(epObject &$o, epFieldMap &$fm, $alias = self::DUMMY_ALIAS)
 {
     $o->epSetSearching(true);
     // get class map
     $cm = $this->em->getClassMap($fm->getClass());
     // for a committed object, simply use OID
     if ($oid = $o->epGetObjectId()) {
         $sql = $this->qid($alias) . '.' . $this->qid($cm->getOidColumn());
         $sql .= '=' . $this->q($oid);
         return array($sql);
     }
     // arrays to keep expressions for primitve and relationship vars
     $exprs_prm = array('');
     $exprs_rel = array('');
     // go through each var
     foreach ($o as $var => $val) {
         // get field map for var
         if (!($fm = $cm->getField($var))) {
             continue;
         }
         // primitive var
         if ($fm->isPrimitive() && !is_null($val)) {
             $expr = $this->qid($alias) . '.' . $this->qid($fm->getColumnName());
             $expr .= '=' . $this->q($val, $fm);
             $exprs_prm[] = $expr;
             continue;
         }
         // relationship var
         if (!$val) {
             // done if empty value or has been visited
             continue;
         }
         // is it a many-valued var?
         $vals = $val;
         if (!$fm->isMany()) {
             // arrayize it if not an array
             $vals = array($val);
         }
         // go through each value in array
         foreach ($vals as $val) {
             // build sql for the relationship field map
             $exprs_rf = $this->_buildSqlFieldMapRelationship($fm, $alias);
             // is it an error message?
             if (is_string($exprs_rf)) {
                 throw new epExceptionQueryBuilder($this->_e($exprs));
                 continue;
             }
             // concat sql for field map ($exprs_rf) and sql for var value ($exprs_rv)
             foreach ($exprs_rf as $alias_ => $expr_rf) {
                 // recursion: build sql for the relationship var
                 $exprs_rv = $this->_buildSqlObject($val, $fm, $alias_);
                 // collect expression for relationship var
                 foreach ($exprs_rv as $expr_rv) {
                     $exprs_rel[] = $expr_rf . ' AND ' . $expr_rv;
                 }
             }
         }
     }
     // array to hold final results
     $exprs_obj = array();
     // concat sql for primitive and relationship fields
     foreach ($exprs_rel as $expr_rel) {
         foreach ($exprs_prm as $expr_prm) {
             if (!$expr_rel && $expr_prm) {
                 $exprs_obj[] = $expr_prm;
             } else {
                 if ($expr_rel && !$expr_prm) {
                     $exprs_obj[] = $expr_rel;
                 } else {
                     if ($expr_rel && $expr_prm) {
                         $exprs_obj[] = $expr_rel . ' AND ' . $expr_prm;
                     }
                 }
             }
         }
     }
     $o->epSetSearching(false);
     return $exprs_obj;
 }