/** * Returns view array of key-value pairs for this atom * @return array */ private function getView() { // If view is not already set if (!isset($this->view)) { $this->logger->debug("Get view for atom '{$this->__toString()}'"); $this->view = array(); // If parentIfc is set, use view as defined by interface (can be null) if (isset($this->parentIfc)) { $viewDef = $this->parentIfc->view; } else { $viewDef = $this->concept->getDefaultView(); } // If there is a view definition if (!is_null($viewDef)) { foreach ($viewDef->segments as $viewSegment) { $key = is_null($viewSegment->label) ? $viewSegment->seqNr : $viewSegment->label; switch ($viewSegment->segType) { case "Text": $this->view[$key] = $viewSegment->text; break; case "Exp": try { // Try to get view segment from atom query data $this->view[$key] = $this->getQueryData('view_' . $key); // column is prefixed with view_ // $this->logger->debug("VIEW <{$viewDef->label}:{$key}> #217 Query saved due to reusing data from source atom"); } catch (Exception $e) { // Column not defined, perform query if ($e->getCode() == 1001) { // TODO: fix this 1001 exception code handling by proper construct $query = "/* VIEW <{$viewDef->label}:{$key}> */ SELECT DISTINCT `tgt` FROM ({$viewSegment->expSQL}) AS `results` WHERE `src` = '{$this->idEsc}' AND `tgt` IS NOT NULL"; $tgtAtoms = array_column((array) $this->database->Exe($query), 'tgt'); $this->view[$key] = count($tgtAtoms) ? $tgtAtoms[0] : null; } else { throw $e; } } break; default: throw new Exception("Unsupported segmentType '{$viewSegment->segType}' in VIEW <{$viewDef->label}:{$key}>", 501); // 501: Not implemented break; } } } } return $this->view; }
/** * Return Relation object * @param string $relationSignature * @param Concept $srcConcept * @param Concept $tgtConcept * @throws Exception if Relation is not defined * @return Relation */ public static function getRelation($relationSignature, Concept $srcConcept = null, Concept $tgtConcept = null) { $relations = self::getAllRelations(); if (is_string($srcConcept)) { $srcConcept = Concept::getConceptByLabel($srcConcept); } if (is_string($tgtConcept)) { $tgtConcept = Concept::getConceptByLabel($tgtConcept); } // If relation can be found by its fullRelationSignature return the relation if (array_key_exists($relationSignature, $relations)) { $relation = $relations[$relationSignature]; // If srcConceptName and tgtConceptName are provided, check that they match the found relation if (!is_null($srcConcept) && !in_array($srcConcept, $relation->srcConcept->getSpecializationsIncl())) { throw new Exception("Provided src concept '{$srcConcept}' does not match the relation '{$relation->__toString()}'", 500); } if (!is_null($tgtConcept) && !in_array($tgtConcept, $relation->tgtConcept->getSpecializationsIncl())) { throw new Exception("Provided tgt concept '{$tgtConcept}' does not match the relation '{$relation->__toString()}'", 500); } return $relation; } // Else try to find the relation by its name, srcConcept and tgtConcept if (!is_null($srcConcept) && !is_null($tgtConcept)) { foreach ($relations as $relation) { if ($relation->name == $relationSignature && in_array($srcConcept, $relation->srcConcept->getSpecializationsIncl()) && in_array($tgtConcept, $relation->tgtConcept->getSpecializationsIncl())) { return $relation; } } } // Else throw new Exception("Relation '{$relationSignature}' is not defined", 500); }
} $database = Database::singleton(); include_once Config::get('absolutePath') . Config::get('logPath') . "{$file}"; // check if all concepts and relations are defined foreach ((array) $allAtoms as $cpt => $atoms) { if (!empty($atoms)) { Concept::getConcept($cpt); } } foreach ((array) $allLinks as $rel => $links) { if (!empty($links)) { Relation::getRelation($rel); } } foreach ((array) $allAtoms as $cpt => $atoms) { $concept = Concept::getConcept($cpt); foreach ($atoms as $atomId) { $atom = new Atom($atomId, $concept); $atom->addAtom(); } } foreach ((array) $allLinks as $rel => $links) { if (!empty($links)) { $relation = Relation::getRelation($rel); } foreach ($links as $link) { if (is_null($link['src']) || is_null($link['tgt'])) { continue; } // skip $relation->addLink(new Atom($link['src'], $relation->srcConcept), new Atom($link['tgt'], $relation->tgtConcept));
$result = array('patches' => $app->request->getBody(), 'content' => $content, 'notifications' => Notifications::getAll(), 'invariantRulesHold' => $session->database->getInvariantRulesHold(), 'requestType' => $session->database->getRequestType(), 'sessionRefreshAdvice' => $session->getSessionRefreshAdvice()); print json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); }); $app->post('/resources/:resourceType/:resourceId/:ifcPath+', function ($resourceType, $resourceId, $ifcPath) use($app) { $session = Session::singleton(); $roleIds = $app->request->params('roleIds'); $session->activateRoles($roleIds); $options = $app->request->params(); $ifcPath = implode('/', $ifcPath); $atom = new Atom($resourceId, Concept::getConcept($resourceType)); $atomOrIfc = $atom->walkIfcPath($ifcPath); // Perform create $content = $atomOrIfc->create($app->request->getBody(), $options); // Return result $result = array('content' => $content, 'notifications' => Notifications::getAll(), 'invariantRulesHold' => $session->database->getInvariantRulesHold(), 'requestType' => $session->database->getRequestType(), 'sessionRefreshAdvice' => $session->getSessionRefreshAdvice()); print json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); }); $app->delete('/resources/:resourceType/:resourceId/:ifcPath+', function ($resourceType, $resourceId, $ifcPath) use($app) { $session = Session::singleton(); $roleIds = $app->request->params('roleIds'); $session->activateRoles($roleIds); $options = $app->request->params(); $ifcPath = implode('/', $ifcPath); $atom = new Atom($resourceId, Concept::getConcept($resourceType)); $atomOrIfc = $atom->walkIfcPath($ifcPath); // Perform delete $atomOrIfc->delete($options); // Return result $result = array('notifications' => Notifications::getAll(), 'invariantRulesHold' => $session->database->getInvariantRulesHold(), 'requestType' => $session->database->getRequestType(), 'sessionRefreshAdvice' => $session->getSessionRefreshAdvice()); print json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); });
/** * Rule constructor * Private function to prevent outside instantiation. Use Rule::getRule($ruleName) * * @param array $ruleDef * @param boolean $type */ private function __construct($ruleDef, $type = null) { $this->logger = Logger::getLogger('FW'); $this->id = $ruleDef['name']; $this->origin = $ruleDef['origin']; $this->ruleAdl = $ruleDef['ruleAdl']; $this->srcConcept = Concept::getConcept($ruleDef['srcConceptId']); $this->tgtConcept = Concept::getConcept($ruleDef['tgtConceptId']); $this->meaning = $ruleDef['meaning']; $this->message = $ruleDef['message']; // Conjuncts foreach ($ruleDef['conjunctIds'] as $conjId) { $this->conjuncts[] = Conjunct::getConjunct($conjId); } $this->violationSegments = (array) $ruleDef['pairView']; switch ($type) { case 'sig': $this->isSignal = true; break; case 'inv': $this->isInvariant = true; break; case null: break; default: throw new Exception("Unknown/unsupported rule type. Allowed types are signal or invariant", 500); } }
/** * * @param array $lines */ private function ParseLines($lines) { $relations = $concept = $separator = $flipped = array(); foreach ($lines as $linenr => $line) { $totalcolumns = count($line); // First line specifies relation names if ($linenr == 0) { for ($col = 0; $col < $totalcolumns; $col++) { $relations[$col] = trim($line[$col]); // No leading/trailing spaces around relation names. } // Second line specifies concepts (and optionally: separators) } elseif ($linenr == 1) { // In the Haskell importer, separators are the last character before the ']' if the concept is surrounded by such block quotes. Alternatively, you could specify a separator following such block-quotes, allowing for multiple-character separators. for ($col = 0; $col < $totalcolumns; $col++) { $cellvalue = trim($line[$col]); // No leading/trailing spaces around cell values in second line if ($cellvalue == '') { $concept[$col] = null; // The cell contains either 'Concept' or '[Conceptx]' where x is a separator character (e.g. ';', ',', ...) } elseif (substr($cellvalue, 0, 1) == '[' && substr($cellvalue, -1) == ']') { if ($col == 0) { throw new Exception("Seperator character not allowed for first column of excel import. Specified '{$line[$col]}'", 500); } $concept[$col] = Concept::getConceptByLabel(substr($cellvalue, 1, -2)); $separator[$col] = substr($cellvalue, -2, 1); } else { $concept[$col] = Concept::getConceptByLabel($cellvalue); $separator[$col] = false; } // Determine relations for all cols except col 0 if ($col > 0) { if ($relations[$col] == '' || $concept[$col] == '') { $relations[$col] = null; } elseif (substr($relations[$col], -1) == '~') { // Relation is flipped is last character is a tilde (~) $relations[$col] = Relation::getRelation(substr($relations[$col], 0, -1), $concept[$col], $concept[0]); $flipped[$col] = true; } else { $relations[$col] = Relation::getRelation($relations[$col], $concept[0], $concept[$col]); $flipped[$col] = false; } } } // All other lines specify atoms } else { $line[0] = trim($line[0]); // Trim cell content (= dirty identifier) // Determine left atom (column 0) of line if ($line[0] == '') { continue; } elseif ($line[0] == '_NEW') { $leftAtom = $concept[0]->createNewAtom(); } else { $leftAtom = new Atom($line[0], $concept[0]); } // Insert $leftAtom into the DB if it does not yet exist $leftAtom->addAtom(); // Process other columns of line for ($col = 1; $col < $totalcolumns; $col++) { if (is_null($concept[$col])) { continue; } // If no concept is specified, the cell is skipped if (is_null($relations[$col])) { continue; } // If no relation is specified, the cell is skipped // Determine right atom(s) $rightAtoms = array(); $cell = trim($line[$col]); // Start of check for multiple atoms in single cell if ($cell == '') { continue; } elseif ($cell == '_NEW') { $rightAtoms[] = $leftAtom; } elseif ($separator[$col]) { $atomsIds = explode($separator[$col], $cell); // atomnames may have surrounding whitespace foreach ($atomsIds as $atomId) { $rightAtoms[] = new Atom(trim($atomId), $concept[$col]); } } else { $rightAtoms[] = new Atom($line[$col], $concept[$col]); // DO NOT TRIM THIS CELL CONTENTS as it contains an atom that may need leading/trailing spaces } foreach ($rightAtoms as $rightAtom) { $relations[$col]->addLink($leftAtom, $rightAtom, $flipped[$col], 'ExcelImport'); } } } } }
/** * Function to create a new Atom at the given interface. * @param array $data * @param array $options * @throws Exception * @return mixed */ public function create($data, $options = array()) { $this->logger->debug("create() called on {$this->path}"); // CRUD check if (!$this->crudC) { throw new Exception("Create not allowed for '{$this->path}'", 405); } if (!$this->tgtConcept->isObject) { throw new Exception("Cannot create non-object '{$this->tgtConcept}' in '{$this->path}'. Use PATCH add operation instead", 405); } if ($this->isRef()) { throw new Exception("Cannot create on reference interface in '{$this->path}'. See #498", 501); } // Handle options if (isset($options['requestType'])) { $this->database->setRequestType($options['requestType']); } // Perform create $newAtom = $this->tgtConcept->createNewAtom(); // Special case for CREATE in I[Concept] interfaces if ($this->srcAtom->id === '_NEW') { $this->srcAtom->setId($newAtom->id); $this->path = str_replace('_NEW', $newAtom->getJsonRepresentation(), $this->path); } // If interface expression is a relation, also add tuple(this, newAtom) in this relation if ($this->relation) { $this->relation()->addLink($this->srcAtom, $newAtom, $this->relationIsFlipped); } else { $newAtom->addAtom(); } // Walk to new atom $newAtom = $this->atom($newAtom->id); // Set requested state (using patches) $patches = is_array($data) ? $data['patches'] : array(); $newAtom->doPatches($patches); // Special case for file upload. TODO: make extension with hooks if ($this->tgtConcept->isFileObject()) { $conceptFilePath = Concept::getConceptByLabel('FilePath'); $conceptFileName = Concept::getConceptByLabel('FileName'); if (is_uploaded_file($_FILES['file']['tmp_name'])) { $tmp_name = $_FILES['file']['tmp_name']; $new_name = time() . '_' . $_FILES['file']['name']; $absolutePath = Config::get('absolutePath') . Config::get('uploadPath') . $new_name; $relativePath = Config::get('uploadPath') . $new_name; $result = move_uploaded_file($tmp_name, $absolutePath); if ($result) { Logger::getUserLogger()->notice("File '{$new_name}' uploaded"); } else { throw new Exception("Error in file upload", 500); } // Populate filePath and originalFileName relations in database $relFilePath = Relation::getRelation('filePath', $newAtom->concept, $conceptFilePath); $relOriginalFileName = Relation::getRelation('originalFileName', $newAtom->concept, $conceptFileName); $relFilePath->addLink($newAtom, new Atom($relativePath, $conceptFilePath)); $relOriginalFileName->addLink($newAtom, new Atom($_FILES['file']['name'], $conceptFileName)); } else { throw new Exception("No file uploaded", 500); } } // Close transaction $this->database->closeTransaction($newAtom->concept . ' created', null, $newAtom); // temp store content of $newAtom (also when not crudR) // Return atom content (can be null) return $newAtom->getStoredContent(); }
private function login($email) { if (empty($email)) { throw new Exception("No emailaddress provided to login", 500); } $session = Session::singleton(); $db = Database::singleton(); $conceptUserID = Concept::getConceptByLabel('UserID'); $conceptDomain = Concept::getConceptByLabel('Domain'); $conceptDateTime = Concept::getConceptByLabel('DateTime'); $conceptOrg = Concept::getConceptByLabel('Organization'); $conceptAccount = Concept::getConceptByLabel('Account'); $conceptSession = Concept::getConceptByLabel('SESSION'); // Set sessionUser $atom = new Atom($email, $conceptUserID); $accounts = $atom->ifc('AccountForUserid')->getTgtAtoms(); // create new user if (empty($accounts)) { $newAccount = Concept::getConceptByLabel('Account')->createNewAtom(); // Save email as accUserid $relAccUserid = Relation::getRelation('accUserid', $newAccount->concept, $conceptUserID); $relAccUserid->addLink($newAccount, new Atom($email, $conceptUserID), false, 'OAuthLoginExtension'); // If possible, add account to organization(s) based on domain name $domain = explode('@', $email)[1]; $atom = new Atom($domain, $conceptDomain); $orgs = $atom->ifc('DomainOrgs')->getTgtAtoms(); $relAccOrg = Relation::getRelation('accOrg', $newAccount->concept, $conceptOrg); foreach ($orgs as $org) { $relAccOrg->addLink($newAccount, $org, false, 'OAuthLoginExtension'); } // Account created, add to $accounts list (used lateron) $accounts[] = $newAccount; } if (count($accounts) > 1) { throw new Exception("Multiple users registered with email {$email}", 401); } $relSessionAccount = Relation::getRelation('sessionAccount', $conceptSession, $conceptAccount); $relAccMostRecentLogin = Relation::getRelation('accMostRecentLogin', $conceptAccount, $conceptDateTime); $relAccLoginTimestamps = Relation::getRelation('accLoginTimestamps', $conceptAccount, $conceptDateTime); foreach ($accounts as $account) { // Set sessionAccount $relSessionAccount->addLink($session->sessionAtom, $account, false, 'OAuthLoginExtension'); // Timestamps $ts = new Atom(date(DATE_ISO8601), $conceptDateTime); $relAccMostRecentLogin->addLink($account, $ts, false, 'OAuthLoginExtension'); $relAccLoginTimestamps->addLink($account, $ts, false, 'OAuthLoginExtension'); } $db->closeTransaction('Login successfull', true); }
/** * Returns largest generalization concept (can be itself) * @return Concept */ public function getLargestConcept() { return Concept::getConcept($this->largestConceptId); }
function OverwritePopulation($rArray, $relationName, $conceptName) { try { $database = Database::singleton(); $concept = Concept::getConceptByLabel($conceptName); $relation = Relation::getRelation($relationName, $concept, $concept); $relationTable = $relation->getMysqlTable(); $srcCol = $relationTable->srcCol(); $tgtCol = $relationTable->tgtCol(); $query = "DELETE FROM `{$relationTable->name}`"; // Do not use TRUNCATE statement, this causes an implicit commit $database->Exe($query); foreach ($rArray as $src => $tgtArray) { foreach ($tgtArray as $tgt => $bool) { if ($bool) { $query = "INSERT INTO `{$relationTable->name}` (`{$srcCol->name}`, `{$tgtCol->name}`) VALUES ('{$src}','{$tgt}')"; $database->Exe($query); } } } } catch (Exception $e) { throw new Exception('OverwritePopulation: ' . $e->getMessage(), 500); } }
function ClearConcept($concept, $atom) { Logger::getLogger('EXECENGINE')->info("ClearConcept({$concept},{$atom})"); if (func_num_args() != 2) { throw new Exception("Wrong number of arguments supplied for function ClearConcept(): " . func_num_args() . " arguments", 500); } try { $database = Database::singleton(); $atom = new Atom($atom, Concept::getConceptByLabel($concept)); $database->atomClearConcept($atom); Logger::getLogger('EXECENGINE')->debug("Atom '{$atom->__toString()}' removed as member from concept '{$concept}'"); } catch (Exception $e) { Logger::getUserLogger()->error('ClearConcept: ' . $e->getMessage()); } }
/** * Delete provided Ampersand session atom from database * @param string $sessionAtomId ampersand session atom id * @return void */ private function destroyAmpersandSession($sessionAtomId) { $this->database->Exe("DELETE FROM `__SessionTimeout__` WHERE SESSION = '{$sessionAtomId}'"); $atom = new Atom($sessionAtomId, Concept::getConceptByLabel('SESSION')); $atom->deleteAtom(); $this->database->commitTransaction(); }