Ejemplo n.º 1
0
 public function loadByType(&$model)
 {
     $C = new ModelCriteria();
     $C->addClause(ModelCriteria::EQUALS, 'type', $model->type);
     $models = self::select($model->modelName, $C);
     if (count($models) > 0) {
         $model = $models[0];
         return TRUE;
     }
     return FALSE;
 }
Ejemplo n.º 2
0
 /**
  * Find all relatives of $this Model according to the given arguments.
  *
  * In most cases this method will return a ModelCollection instance.
  * However, in some cases it will return an indexed array, depending on which
  * arguments have been omitted/included.
  *
  * For example, if you do not specify a $modelName then an array of several
  * ModelCollections may be returned, indexed by the model names of all related
  * models.
  *
  * Also, if you do not specify a relationship reference when finding relatives
  * in a recursive relationship then you can expect to be given an array of
  * ModelCollections indexed by each relationship reference.
  *
  * If given, the second argument is either a ModelCriteria instance to filter
  * the results, or a relationship reference.
  *
  * @param string $modelName Find relatives of this Model type
  * @param ModelCriteria|string ** see notes above **
  * @param string $relationRef Relationship reference
  * @return ModelCollection|array
  */
 public function findRelatives($modelName = null, $criteriaOrRelationRef = null, $relationRef = null)
 {
     // No specific model name has been specified so we need to build a
     // collection of Models from ALL relationships with $this Model.
     // In this case the returned value is an array indexed by model name. If
     // multiple relationship references exist between $this and $modelName (such
     // as child/parent in recursive relationships) then each array element is
     // further broken down into an array indexed by the relationship reference.
     if ($modelName === null) {
         $collection = [];
         $relations = ModelRelation::getRelation($this->modelName);
         /** @var ModelRelation $relation */
         foreach ($relations as $relation) {
             $tm = $relation->getTargetModel();
             $rr = $relation->getReference();
             if (isset($collection[$tm])) {
                 if (isset($collection[$tm][$rr])) {
                     $collection[$tm][$rr]->append($this->findRelatives($tm, $rr));
                 } else {
                     $collection[$tm][$rr] = $this->findRelatives($tm, $rr);
                 }
             } else {
                 $collection[$tm] = $this->findRelatives($tm, $rr);
             }
         }
         return $collection;
     }
     // A specific model name has been specified.
     // First of all, determine if a relationship reference has been specified
     // and use that throughout, otherwise get all possible relations and
     // recursively call $this->findRelatives() for each one.
     if (is_string($criteriaOrRelationRef)) {
         $criteria = null;
         $relationRef = $criteriaOrRelationRef;
     } else {
         if ($criteriaOrRelationRef instanceof \Buan\ModelCriteria) {
             $criteria = $criteriaOrRelationRef;
         } else {
             $criteria = null;
         }
     }
     $relation = ModelRelation::getRelation($this->modelName, $modelName, $relationRef);
     // If multiple relations are available between $this and $modelName, and the
     // caller hasn't specified which of these relationships to use (ie.
     // $relationRef===NULL) then assume we're dealing with a recursive
     // relationship and return an array of ModelCollections for each
     // relationship, indexed by the relationship reference.
     if (is_array($relation)) {
         if (isset($relation[ModelRelation::REF_DEFAULT]) && count($relation) == 1) {
             $relation = $relation[ModelRelation::REF_DEFAULT];
         } else {
             $collection = [];
             foreach ($relation as $ref => $rel) {
                 $collection[$ref] = $this->findRelatives($modelName, $criteria, $ref);
             }
             return $collection;
         }
     }
     // So by now we should be dealing with a specific model name, some criteria
     // (if defined) and a specific relationship reference. So let's do some
     // loading and retrieving from the db with respect to the cardinality of the
     // relationship.
     switch ($relation->getCardinality()) {
         /* No relationship */
         case ModelRelation::NONE:
             break;
             /* 1:1 */
         /* 1:1 */
         case ModelRelation::ONE_TO_ONE:
             // Such relations are held as 1:M,1 relations internally so it'll be
             // handled by the 1:M case below.
             break;
             /* 1:M */
         /* 1:M */
         case ModelRelation::ONE_TO_MANY:
             // First, gather all the in-memory relatives attached to $this model.
             // If $criteria has been specified then we also check that these models
             // satisfy those criteria.
             $cd = ModelRelation::ONE_TO_MANY;
             $tm = $relation->getTargetModel();
             $rr = $relation->getReference();
             if (isset($this->relatives[$cd][$tm][$rr])) {
                 $collection = new ModelCollection($this->relatives[$cd][$tm][$rr]);
                 if ($criteria !== null) {
                     // TODO: ::applyTo() isn't implemented yet! so this will create an empty collection every time
                     $collection = $criteria->applyTo($collection);
                 }
             } else {
                 $collection = new ModelCollection();
             }
             // If $this model is in the db then query the db to find all matching
             // relatives and append them to the collection.
             // TODO: Need to handle composite or NULL PKs
             if ($this->isInDatabase()) {
                 // With no specific criteria to follow we'll load ALL relatives from
                 // persistent storage
                 $targetModelName = $relation->getTargetModel();
                 $targetModel = Model::create($targetModelName);
                 if ($criteria === null) {
                     $pkv = $this->{$relation->getNativeKey()};
                     //$this->getPrimaryKeyValue();
                     $c = new ModelCriteria();
                     $c->addClause(ModelCriteria::EQUALS, "`{$targetModel->getDbTableName()}`." . $targetModel->getForeignKey($this, $relation->getReference()), $pkv);
                     try {
                         $collection->append(ModelManager::select($targetModelName, $c));
                     } catch (Exception $e) {
                     }
                 } else {
                     $pkv = $this->{$relation->getNativeKey()};
                     //$this->getPrimaryKeyValue();
                     $criteria->addClause(ModelCriteria::EQUALS, "`{$targetModel->getDbTableName()}`." . $targetModel->getForeignKey($this, $relation->getReference()), $pkv);
                     $collection->append(ModelManager::select($targetModelName, $criteria));
                 }
             }
             // For recursive 1:M relationships we now need to load Models on the
             // M:1 side of the relationship in order to establish a link between
             // the loaded instance on the 1 and M sides, so don't break and instead
             // pass through to the next switch case ...
             if ($relation->isRecursive()) {
                 $relation = $relation->getInverseRelation();
                 $loadingTheInverse = true;
             } else {
                 return $collection;
                 break;
             }
             /* M:1 */
         /* M:1 */
         case ModelRelation::MANY_TO_ONE:
             // First, check if an in-memory model exists on the 1-side of this
             // relationship
             $cd = ModelRelation::MANY_TO_ONE;
             $tm = $relation->getTargetModel();
             $rr = $relation->getReference();
             $col = new ModelCollection();
             if (isset($this->relatives[$cd][$tm][$rr])) {
                 $col = new ModelCollection($this->relatives[$cd][$tm][$rr]);
             } else {
                 $fk = $this->getForeignKey($tm, $rr);
                 //if($this->{$fk}!==NULL && $this->{$fk}!==0 && $this->{$fk}!=='0') {
                 if (!empty($this->{$fk})) {
                     // If the foreign key does not match the target model's primary key
                     // do some manual labour
                     if ($relation->getForeignKey() !== Model::create($tm)->getPrimaryKey()) {
                         $criteria = $criteria === null ? new ModelCriteria() : $criteria;
                         $target = Model::create($tm);
                         $criteria->addClause(ModelCriteria::EQUALS, $target->getDbTableName() . '.' . $relation->getForeignKey(), $this->{$fk});
                         $col = ModelManager::select($tm, $criteria);
                     } else {
                         $target = Model::create($tm);
                         $criteria = $criteria === null ? new ModelCriteria() : $criteria;
                         $criteria->addClause(ModelCriteria::EQUALS, $target->getDbTableName() . '.' . $target->getPrimaryKey(), $this->{$fk});
                         $col = ModelManager::select($tm, $criteria);
                         if (!$col->isEmpty()) {
                             $target = $col->get(0);
                             /*$target = Model::create($tm);
                               $mmTarget = ModelManager::create($tm);
                               $target->setPrimaryKeyValue($this->{$fk});
                               if($mmTarget->load($target)) {
                                   $col = new ModelCollection($target);*/
                             // If the relationship is recursive, then remember we can only
                             // add recursive related Models via 1:M relationships, so we have
                             // to reverse the way we add a related Model here.
                             if ($relation->isRecursive()) {
                                 $ir = $relation->getInverseRelation();
                                 $cd = $ir->getCardinality();
                                 $target->relatives[$cd][$tm][$ir->getReference()][] = $this;
                             } else {
                                 $this->relatives[$cd][$tm][$rr] = $target;
                             }
                         }
                     }
                 }
             }
             // If this switch case has been arrived at by the 1:M case not breaking
             // then return the 1:M collection, other return the M:1 collection
             return empty($loadingTheInverse) ? $col : $collection;
             break;
             /* M:M */
         /* M:M */
         case ModelRelation::MANY_TO_MANY:
             /*// First, find any in-memory instances of the target model (via linking-
             				// model instances)
             				$linkRelation = ModelRelation::getRelation($this->modelName, $relation->getLinkModel(), $relation->getReference());
             				$scd = ModelRelation::ONE_TO_MANY;
             				$stm = $linkRelation->getTargetModel();
             				$srr = $linkRelation->getReference();
             				$collection = new ModelCollection();
             				if(isset($this->relatives[$scd][$stm][$srr])) {
             					foreach($this->relatives[$scd][$stm][$srr] as $link) {
             						$tcd = ModelRelation::MANY_TO_ONE;
             						$ttm = $relation->getTargetModel();
             						$trr = $linkRelation->getInverseRelation()->getReference();
             						if(isset($link->relatives[$tcd][$ttm][$trr])) {
             							$collection->append(new ModelCollection($link->relatives[$tcd][$ttm][$trr]));
             						}
             					}
             				}
             
             				// TODO: Look in DB for more links*/
             // First, find all instances of the linking model that are related to
             // $this model
             $links = $this->findRelatives($relation->getLinkModel(), $relation->getReference());
             // Now find all instances of the target model that are related to each
             // of the linking models we just found
             $collection = new ModelCollection();
             $r = $relation->isRecursive() ? $relation->getInverseRelation() : $relation;
             foreach ($links as $l) {
                 $crt = $criteria !== null ? clone $criteria : null;
                 $collection->append($l->findRelatives($r->getTargetModel(), $crt, $r->getReference()));
             }
             // Result
             return $collection;
             break;
             /* THE FOLLOWING HAS JUST BEEN COPIED OVER FROM OLD MODEL CLASS, SO GO THROUGH
                IT AND PICK OUT WHAT'S NEEDED AS NECESSARY */
             // Find any linking models in the db
             $c = new ModelCriteria();
             $c->addClause(ModelCriteria::EQUALS, $linkModel->getDbTableName() . '.' . $linkModel->getForeignKey($this), $this->getPrimaryKeyValue());
             $c->addClause(ModelCriteria::EQUALS, $linkModel->getDbTableName() . '.' . $linkModel->getForeignKey($model), $model->getPrimaryKeyValue());
             $collection = ModelManager::select($linkModel->modelName, $c);
             if (!$links->isEmpty()) {
                 // A link already exists so don't do anything
                 return;
             }
             // First of all we need to load all instances of the Model that links
             // the source Model type to the target Model type in this relationship.
             // The $criteria is ignored at this point, because it (should) applies
             // to the target model, NOT the linking model.
             $linkModelName = $relation->getLinkModel();
             $linkForeignKey = Model::create($linkModelName)->getForeignKey($this, $relation->getReference());
             $linkDbTableName = Model::create($linkModelName)->getDbTableName();
             $c = new ModelCriteria();
             $c->addClause(ModelCriteria::EQUALS, $linkDbTableName . '.' . $linkForeignKey, $this->getPrimaryKeyValue());
             $linkModels = ModelManager::select($linkModelName, $c);
             // TODO: WHAT IS THIS BIT FOR? COMMENTS JAMES, USEFUL COMMENTS!!
             // Move all Models from $this->relatedModels that match entries
             // in $linkModels into $linkModels.
             foreach ($linkModels as $k => $lModel) {
                 $relatedModel = $this->getRelatedModelByInstance($lModel);
                 if (!is_null($relatedModel)) {
                     $linkModels[$k] = $relatedModel;
                 }
             }
             // Get all instances of target model
             // If the relationship is recursive then we need to get
             // models on the reverse side of the relationship, ie.
             // REF_PARENT/REF_CHILD.
             $ref = $relation->isRecursive() ? $relation->getInverseRelation()->getReference() : $relation->getReference();
             $tModelName = $relation->getTargetModel();
             $tModelManager = ModelManager::create($tModelName);
             $lForeignKey = Model::create($linkModelName)->getForeignKey($tModelName, $ref);
             foreach ($linkModels as $linkModel) {
                 $tModel = Model::create($tModelName);
                 $tModel->setPrimaryKeyValue($linkModel->{$lForeignKey});
                 if ($tModelManager->load($tModel)) {
                     // TODO: Check that $tModel is not already loaded into $linkModel, and $linkModel is not already loaded into $this
                     $linkModel->addRelatives($tModel, $ref);
                     $this->addRelatives($linkModel, $rel->getReference());
                 }
                 unset($tModel);
             }
             // Now retrieve
             if ($relation->isRecursive()) {
                 $allLinkModels = $this->findRelatives($relation->getLinkModel());
                 foreach ($allLinkModels as $ref => $linkModels) {
                     foreach ($linkModels as $linkModel) {
                         $rModels = $linkModel->findRelatives($modelName);
                         unset($rModels[$relationRef]);
                         foreach ($rModels as $rModel) {
                             if ($rModel !== $this) {
                                 $collection->append($rModel);
                             }
                         }
                     }
                 }
             } else {
                 $linkModelName = $relation->getLinkModel();
                 if (isset($this->relatives[ModelRelation::ONE_TO_MANY][$linkModelName][$relation->getReference()])) {
                     $linkModels = $this->relatives[ModelRelation::ONE_TO_MANY][$linkModelName][$relation->getReference()];
                     foreach ($linkModels as $linkModel) {
                         $collection->append($linkModel->findRelatives($modelName, $relation->getReference()));
                     }
                 }
             }
             break;
             /* Unknown case */
         /* Unknown case */
         default:
             break;
     }
 }
Ejemplo n.º 3
0
 public function isDenied($permissions, $resource, $ignoreInheritance = FALSE)
 {
     // Load resource from a given alias
     $alias = $resource;
     if (is_string($resource) && !($resource = $this->loadResourceByAlias($resource))) {
         throw new BuanException("Could not find AclResource with an alias of '{$alias}'");
         return FALSE;
     }
     // Convert $permissions to an array
     if (!is_array($permissions)) {
         $permissions = explode(",", preg_replace("/[^a-z0-9_\\-\\*,]/i", "", strtolower($permissions)));
     }
     $permissions = array_unique($permissions);
     // Travel up through $resource and it's parent AclResources to find a
     // usable AclEntry
     $tmpEntry = Model::create('AclEntry');
     $pAclResource = $resource;
     while ($pAclResource !== NULL) {
         // Load all AclEntry Models related to $pAclResource
         $C = new ModelCriteria();
         $C->addClause(ModelCriteria::EQUALS, $tmpEntry->getForeignKey($this->modelName), $this->id);
         $pAclResource->loadRelatedModels('AclEntry', $C);
         $entry = $pAclResource->getLinkingModel($this);
         if ($entry !== NULL) {
             // Wildcard permissions
             if ($entry->pdeny == '*') {
                 return TRUE;
             }
             if ($entry->pallow == '*') {
                 return FALSE;
             }
             // All specified permissions are denied
             $unknownDenyPerms = array_diff($permissions, explode(",", $entry->pdeny));
             if (count($unknownDenyPerms) == 0) {
                 return TRUE;
             } else {
                 // If any of the permissions are listed in the "pallow" column,
                 // then we need to return FALSE
                 $permissions = $unknownDenyPerms;
                 $unknownAllowPerms = array_diff($permissions, explode(",", $entry->pallow));
                 if (count($unknownAllowPerms) != count($permissions)) {
                     return FALSE;
                 }
             }
         }
         // No AclEntry was found, so try $pAclResource's parent AclResource
         if (!$ignoreInheritance) {
             $pAclResource->loadRelatedModels('AclResource', NULL, ModelRelation::REF_CHILD);
             $pAclResource = $pAclResource->getRelatedModels('AclResource', ModelRelation::REF_CHILD);
         } else {
             $pAclResource = NULL;
         }
     }
     // If ALL the permissions are not yet satisfied, then start testing
     // permissions on the parents $role
     if (count($permissions) > 0 && !$ignoreInheritance) {
         $rModel = $this->loadAndGetAclRole(NULL, ModelRelation::REF_CHILD);
         foreach ($rModel as $rm) {
             if ($rm->isDenied($permissions, $resource)) {
                 return TRUE;
             }
         }
         return FALSE;
     } else {
         return FALSE;
     }
 }