/** * Returns list of target atoms given the srcAtom for this interface * @throws Exception * @return Atom[] [description] */ public function getTgtAtoms() { $tgtAtoms = array(); try { // If interface isIdent (i.e. expr = I[Concept]) we can return the srcAtom if ($this->isIdent && $this->srcConcept == $this->tgtConcept) { $tgtAtoms[] = new Atom($this->srcAtom->id, $this->tgtConcept, $this, $this->srcAtom->getQueryData()); // Else try to get tgt atom from srcAtom query data (in case of uni relation in same table) } else { $tgt = $this->srcAtom->getQueryData('ifc_' . $this->id); // column is prefixed with ifc_ // $this->logger->debug("#217 One query saved due to reusing data from source atom"); if (!is_null($tgt)) { $tgtAtoms[] = new Atom($tgt, $this->tgtConcept, $this); } } } catch (Exception $e) { // Column not defined, perform sub interface query if ($e->getCode() == 1001) { // TODO: fix this 1001 exception code handling by proper construct $data = (array) $this->database->Exe($this->getQuery($this->srcAtom)); // Integrity check if ($this->isUni && count($data) > 1) { throw new Exception("Univalent (sub)interface returns more than 1 resource: '{$this->path}'", 500); } foreach ($data as $row) { $tgtAtoms[] = new Atom($row['tgt'], $this->tgtConcept, $this, $row); } } else { throw $e; } } return $tgtAtoms; }
/** * Generate a new atom identifier for this concept * @return string */ public function createNewAtomId() { static $prevTime = null; if (strpos($this->name, '_AI') !== false && $this->isInteger()) { $firstCol = current($this->mysqlConceptTable->getCols()); $query = "SELECT MAX(`{$firstCol->name}`) as `MAX` FROM `{$this->mysqlConceptTable->name}`"; $result = array_column((array) $this->database->Exe($query), 'MAX'); if (empty($result)) { $atomId = 1; } else { $atomId = $result[0] + 1; } } else { $now = explode(' ', microTime()); // yields ["microseconds", "seconds"] both in seconds, e.g. ["0.85629400", "1322761879"] $time = $now[1] . substr($now[0], 2, 6); // we drop the leading "0." and trailing "00" from the microseconds // Guarantee that time is increased if ($time <= $prevTime) { $time = ++$prevTime; } else { $prevTime = $time; } $atomId = $this->name . '_' . $time; } return $atomId; }
/** * 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(); }
/** * 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 array with all links (pair of Atoms) in this relation * @return array[] */ public function getAllLinks() { // Query all atoms in table $query = "SELECT `{$this->mysqlTable->srcCol()->name}` as `src`, `{$this->mysqlTable->tgtCol()->name}` as `tgt` FROM `{$this->mysqlTable->name}`"; return (array) $this->db->Exe($query); }