Exemplo n.º 1
0
 /**
  * Returns the related record(s).
  * This method will return the related record(s) of the current record.
  * If the relation is 'one' it will return a single object
  * or null if the object does not exist.
  * If the relation is 'many' it will return an array of objects
  * or an empty iterator.
  * @param string $name the relation name (see {@link relations})
  * @param boolean $refresh whether to reload the related objects from database. Defaults to false.
  * @param mixed $params array with additional parameters that customize the query conditions as specified in the relation declaration.
  * @return mixed the related object(s).
  * @throws EMongoException if the relation is not specified in {@link relations}.
  */
 public function getRelated($name, $refresh = false, $params = [])
 {
     if (!$refresh && $params === [] && (isset($this->_related[$name]) || array_key_exists($name, $this->_related))) {
         return $this->_related[$name];
     }
     $relations = $this->relations();
     if (!isset($relations[$name])) {
         throw new EMongoException(Yii::t('yii', '{class} does not have relation "{name}".', ['{class}' => get_class($this), '{name}' => $name]));
     }
     Yii::trace('lazy loading ' . get_class($this) . '.' . $name, 'extensions.MongoYii.EMongoModel');
     $cursor = [];
     $relation = $relations[$name];
     // Let's get the parts of the relation to understand it entirety of its context
     $cname = $relation[1];
     $fkey = $relation[2];
     $pk = isset($relation['on']) ? $this->{$relation['on']} : $this->getPrimaryKey();
     // This takes care of cases where the PK is an DBRef and only one DBRef, where it could
     // be mistaken as a multikey field
     if ($relation[0] === 'one' && is_array($pk) && array_key_exists('$ref', $pk)) {
         $pk = [$pk];
     }
     // Form the where clause
     $where = $params;
     if (isset($relation['where']) && !$params) {
         $where = array_merge($relation['where'], $params);
     }
     if ($pk instanceof MongoDB\Model\BSONDocument) {
         $rel = [];
         foreach ($pk as $i => $item) {
             $rel[$i] = $item;
         }
         $pk = [$rel];
     }
     if ($pk instanceof MongoDB\Model\BSONArray) {
         $rel = [];
         foreach ($pk as $i => $doc) {
             foreach ($doc as $j => $item) {
                 $rel[$i][$j] = $item;
             }
         }
         $pk = $rel;
     }
     // Find out what the pk is and what kind of condition I should apply to it
     if (is_array($pk)) {
         if (empty($pk)) {
             if ($relation[0] === 'one') {
                 return null;
             } else {
                 return [];
             }
         }
         //It is an array of references
         if (EMongoDBRef::isRef(reset($pk))) {
             $result = [];
             foreach ($pk as $singleReference) {
                 $row = $this->populateReference($singleReference, $cname);
                 // When $row does not exists it will return null. It will not add it to $result
                 array_push($result, $row);
             }
             // When $row is null count($result) will be 0 and $result will be an empty array
             // Because we are a one relation we want to return null when a row does not exists
             // Currently it was returning an empty array
             if ($relation[0] === 'one' && count($result) > 0) {
                 $result = $result[0];
             }
             return $this->_related[$name] = $result;
         }
         // It is an array of _ids
         $clause = array_merge($where, [$fkey => ['$in' => $pk]]);
     } else {
         // It is just one _id
         $clause = array_merge($where, [$fkey => $pk]);
     }
     $o = $cname::model($cname);
     if ($relation[0] === 'one') {
         // Lets find it and return it
         return $this->_related[$name] = $o->findOne($clause);
     } elseif ($relation[0] === 'many') {
         // Lets find them and return them
         $clause['sort'] = isset($relation['sort']) ? $relation['sort'] : null;
         $clause['skip'] = isset($relation['skip']) ? $relation['skip'] : null;
         $clause['limit'] = isset($relation['limit']) ? $relation['limit'] : null;
         $cursor = $o->find($clause);
         if (!isset($relation['cache']) || $relation['cache'] === true) {
             return $this->_related[$name] = $cursor;
         }
     }
     return $cursor;
     // FAIL SAFE
 }