/**
  * Build links to interfaces to solve the violation
  * @return array
  */
 public function getLinks()
 {
     $session = Session::singleton();
     $links = array();
     foreach ($session->getInterfacesToReadConcept($this->src->concept) as $interface) {
         $links[] = "#/{$interface->id}/{$this->src->getJsonRepresentation()}";
     }
     foreach ($session->getInterfacesToReadConcept($this->tgt->concept) as $interface) {
         $links[] = "#/{$interface->id}/{$this->tgt->getJsonRepresentation()}";
     }
     return array_unique($links);
 }
 /**
  * Get session variables (from 'SessionVars' interface)
  * @return mixed|false session variables (if interface 'SessionVars' is defined in &-script) or false otherwise
  */
 public function getSessionVars()
 {
     if (InterfaceObject::interfaceExists('SessionVars')) {
         try {
             $this->logger->debug("Getting interface 'SessionVars' for {$this->sessionAtom->__toString()}");
             return $this->sessionAtom->ifc('SessionVars')->read(['metaData' => false, 'navIfc' => false]);
         } catch (Exception $e) {
             $this->logger->warning("Error while getting SessionVars interface: " . $e->getMessage());
             return false;
         }
     } else {
         return false;
     }
 }
 /**
  * How to use Relation::deleteLink() to delete link (a1,b1) from r:
  * r :: A * B
  * deleteLink(a1[A], b1[B], false);
  * deleteLink(b1[B], a1[A], true);
  * 
  * @param Atom $leftAtom
  * @param Atom $rightAtom
  * @param boolean $isFlipped
  * @param string $source specifies who calls this function (e.g. 'User' or 'ExecEngine')
  * @return void
  */
 public function deleteLink($leftAtom, $rightAtom, $isFlipped = false, $source = 'User')
 {
     $this->logger->debug("Delete link ({$leftAtom->__toString()},{$rightAtom->__toString()}) from relation '{$this->__toString()}{({$isFlipped} ? '~' : '')}'");
     // Determine src and tgt atom based on $isFlipped
     $srcAtom = $isFlipped ? $rightAtom : $leftAtom;
     $tgtAtom = $isFlipped ? $leftAtom : $rightAtom;
     // Checks
     if (!in_array($srcAtom->concept, $this->srcConcept->getSpecializationsIncl())) {
         throw new Exception("Cannot delete link ({$srcAtom->__toString()},{$tgtAtom->__toString()}) from relation '{$this->__toString()}', because source concept does not match relation source or its specializations", 500);
     }
     if (!in_array($tgtAtom->concept, $this->tgtConcept->getSpecializationsIncl())) {
         throw new Exception("Cannot delete link ({$srcAtom->__toString()},{$tgtAtom->__toString()}) from relation '{$this->__toString()}', because target concept does not match relation target or its specializations", 500);
     }
     // Delete link from relation table
     $this->db->deleteLink($this, $srcAtom, $tgtAtom);
     // Flag session var as affected when src or tgt concept of this relation is SESSION
     if ($srcAtom->concept->isSession() || $tgtAtom->concept->isSession()) {
         Session::singleton()->setSessionVarAffected();
     }
 }
Exemple #4
0
 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);
});
 /**
  * 
  * @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');
                 }
             }
         }
     }
 }
 /**
  * Add (src,tgt) tuple in relation provided in this interface
  * @var array $patch
  * @throws Exception
  * @return void
  */
 public function doPatchAdd($patch)
 {
     // CRUD check
     if (!$this->crudU) {
         throw new Exception("Update is not allowed for path '{$this->path}'", 403);
     }
     if ($this->isRef()) {
         throw new Exception("Cannot update on reference interface in '{$this->path}'. See #498", 501);
     }
     // Check if patch value is provided
     if (!array_key_exists('value', $patch)) {
         throw new Exception("Cannot patch add. No 'value' specfied in '{$this->path}'", 400);
     }
     $tgtAtom = new Atom($patch['value'], $this->tgtConcept);
     // Interface is property
     if ($this->isProp()) {
         // Properties must be treated as a 'replace', so not handled here
         throw new Exception("Cannot patch add for property '{$this->path}'. Use patch replace instead", 500);
         // Interface is a relation to an object
     } elseif ($this->tgtConcept->isObject) {
         // Check if atom exists and may be created (crudC)
         if (!$tgtAtom->atomExists()) {
             if ($this->crudC) {
                 $tgtAtom->addAtom();
             } else {
                 throw new Exception("Resource '{$tgtAtom->__toString()}' does not exist and may not be created in {$this->path}", 403);
             }
         }
         // Add link when possible (relation is specified)
         if (is_null($this->relation)) {
             $this->logger->debug("addLink skipped because '{$this->path}' is not an editable expression");
         } else {
             $this->relation()->addLink($this->srcAtom, $tgtAtom, $this->relationIsFlipped);
         }
         // Interface is a relation to a scalar (i.e. not an object)
     } elseif (!$this->tgtConcept->isObject) {
         // Check: If interface is univalent, throw exception
         if ($this->isUni) {
             throw new Exception("Cannot patch add for univalent interface {$this->path}. Use patch replace instead", 500);
         }
         $this->relation()->addLink($this->srcAtom, $tgtAtom, $this->relationIsFlipped);
     } else {
         throw new Exception("Unknown patch add. Please contact the application administrator", 500);
     }
 }
 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);
 }
 /**
  * Return content of all atoms for this concept
  * @return mixed[]
  */
 public function getAllAtomObjects()
 {
     // Query all atoms in table
     if (isset($this->def['allAtomsQuery'])) {
         $query = $this->def['allAtomsQuery'];
     } else {
         $firstCol = current($this->mysqlConceptTable->getCols());
         // We can query an arbitrary concept col for checking the existence of an atom
         $query = "SELECT DISTINCT `{$firstCol->name}` as `atomId` FROM `{$this->mysqlConceptTable->name}` WHERE `{$firstCol->name}` IS NOT NULL";
     }
     $arr = array();
     foreach ((array) $this->database->Exe($query) as $row) {
         $tgtAtom = new Atom($row['atomId'], $this, null, $row);
         $arr[] = $tgtAtom->getAtom();
     }
     return $arr;
 }
 /**
  * Remove all occurrences of $atom in the database (all concept tables and all relation tables)
  * In tables where the atom may not be null, the entire row is removed.
  * TODO: If all relation fields in a wide table are null, the entire row could be deleted, but this doesn't happen now. As a result, relation queries may return some nulls, but these are filtered out anyway.
  * @param \Ampersand\Core\Atom $atom
  * @return void
  */
 function deleteAtom($atom)
 {
     $this->logger->debug("deleteAtom({$atom->__toString()})");
     // This function is under control of transaction check!
     if (!isset($this->transaction)) {
         $this->startTransaction();
     }
     $concept = $atom->concept;
     // Delete atom from concept table
     $conceptTable = $concept->getConceptTableInfo();
     $query = "DELETE FROM `{$conceptTable->name}` WHERE `{$conceptTable->getFirstCol()->name}` = '{$atom->idEsc}' LIMIT 1";
     $this->Exe($query);
     // Check if query resulted in an affected row
     $this->checkForAffectedRows();
     $this->addAffectedConcept($concept);
     // add concept to affected concepts. Needed for conjunct evaluation.
     // Delete atom from relation tables where atom is mentioned as src or tgt atom
     foreach (Relation::getAllRelations() as $relation) {
         $tableName = $relation->getMysqlTable()->name;
         $cols = array();
         if ($relation->srcConcept->inSameClassificationTree($concept)) {
             $cols[] = $relation->getMysqlTable()->srcCol();
         }
         if ($relation->tgtConcept->inSameClassificationTree($concept)) {
             $cols[] = $relation->getMysqlTable()->tgtCol();
         }
         foreach ($cols as $col) {
             // If n-n table, remove row
             if (is_null($relation->getMysqlTable()->tableOf)) {
                 $query = "DELETE FROM `{$tableName}` WHERE `{$col->name}` = '{$atom->idEsc}'";
             } elseif ($col->null) {
                 $query = "UPDATE `{$tableName}` SET `{$col->name}` = NULL WHERE `{$col->name}` = '{$atom->idEsc}'";
             } else {
                 $query = "DELETE FROM `{$tableName}` WHERE `{$col->name}` = '{$atom->idEsc}'";
             }
             $this->Exe($query);
             $this->addAffectedRelations($relation);
         }
     }
     $this->logger->debug("Atom '{$atom->__toString()}' (and all related links) deleted in database");
     Hooks::callHooks('postDatabaseDeleteAtom', get_defined_vars());
 }
function DelAtom($concept, $atomId)
{
    Logger::getLogger('EXECENGINE')->info("DelAtom({$concept},{$atomId})");
    if (func_num_args() != 2) {
        throw new Exception("Wrong number of arguments supplied for function DelAtom(): " . func_num_args() . " arguments", 500);
    }
    try {
        $atom = new Atom($atomId, Concept::getConceptByLabel($concept));
        $atom->deleteAtom();
        // delete atom + all relations with other atoms
        Logger::getLogger('EXECENGINE')->debug("Atom '{$atom}' deleted");
    } catch (Exception $e) {
        Logger::getUserLogger()->error('DelAtom: ' . $e->getMessage());
    }
}