public function repos($params) { $view = new View(); if (!Core::hasAdminAccess()) { return Core::getLoginView($view); } $view->setSource(Config::get('ext.acl.dir.views') . '/repos.tpl'); if (isset($_GET['id'])) { $view->setSource(Config::get('ext.acl.dir.views') . '/repos.edit.tpl'); $repo = Model::create('AclRepo'); if ($_GET['id'] > 0) { $repo->id = (int) $_GET['id']; if (!$repo->getModelManager()->load($repo)) { SystemLog::add(array('Failed to load repository #%s', $repo->id), SystemLog::WARNING); $view->setSource(NULL); return $view; } } // Save if (isset($_POST['name'])) { $repo->name = $_POST['name']; if ($repo->getModelManager()->save($repo)) { SystemLog::add('Data saved!', SystemLog::INFO); } else { SystemLog::add('Failed to save data.', SystemLog::WARNING); } } else { if (isset($_GET['remove']) && $repo->isInDatabase()) { if ($repo->getModelManager()->delete($repo)) { SystemLog::add('Data removed!', SystemLog::INFO); $repo = Model::create('AclRepo'); } else { SystemLog::add('Failed to remove data.', SystemLog::WARNING); } } } // View $view->repo = $repo; return $view; } // View $view->repos = ModelManager::select('AclRepo'); return $view; }
/** * 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; } }