public function closeTransaction($succesMessage = 'Updated', $checkAllConjucts = true, $databaseCommit = false, $setNewContent = true) { $session = Session::singleton(); Hooks::callHooks('preDatabaseCloseTransaction', get_defined_vars()); Notifications::addLog('========================= CLOSING TRANSACTION =========================', 'DATABASE'); if ($checkAllConjucts) { Notifications::addLog("Check all conjuncts", 'DATABASE'); // Evaluate all invariant conjuncts. Conjuncts are cached. $invariantRulesHold = RuleEngine::checkInvariantRules(); // Evaluate all signal conjuncts. Conjuncts are cached RuleEngine::checkProcessRules(); } else { Notifications::addLog("Check all affected conjuncts", 'DATABASE'); // Evaluate all affected invariant conjuncts. Conjuncts are cached. $invariantRulesHold = RuleEngine::checkInvariantRules(RuleEngine::getAffectedInvConjuncts($this->affectedConcepts, $this->affectedRelations), true); // Evaluate all affected signal conjuncts. Conjuncts are cached RuleEngine::checkConjuncts(RuleEngine::getAffectedSigConjuncts($this->affectedConcepts, $this->affectedRelations), true); // Check only those process rules that are relevant for the activate roles RuleEngine::checkProcessRules($session); } unset($this->affectedConcepts, $this->affectedRelations); $this->affectedConcepts = array(); $this->affectedRelations = array(); if ($setNewContent && isset($session->atom)) { $session->atom->setNewContent($session->interface); } // e.g. not needed in Atom::delete() function if ($invariantRulesHold && $databaseCommit) { $this->commitTransaction(); // commit database transaction Notifications::addSuccess($succesMessage); } elseif (Config::get('ignoreInvariantViolations', 'transactions') && COMMIT_INV_VIOLATIONS) { $this->commitTransaction(); Notifications::addError("Transaction committed with invariant violations"); } elseif ($invariantRulesHold) { $this->rollbackTransaction(); // rollback database transaction Notifications::addInfo($succesMessage); } else { $this->rollbackTransaction(); // rollback database transaction } Hooks::callHooks('postDatabaseCloseTransaction', get_defined_vars()); return $invariantRulesHold; }
public static function run($allRules = false) { $database = Database::singleton(); Notifications::addLog('------------------------- EXEC ENGINE STARTED -------------------------', 'ExecEngine'); // Load the execEngine functions (security hazard :P) $files = getDirectoryList(__DIR__ . '/functions'); foreach ($files as $file) { if (substr($file, -3) !== 'php') { continue; } require_once __DIR__ . '/functions/' . $file; Notifications::addLog('Included file: ' . __DIR__ . '/functions/' . $file, 'ExecEngine'); } self::$roleName = Config::get('execEngineRoleName', 'execEngine'); $role = Role::getRoleByName(self::$roleName); $maxRunCount = Config::get('maxRunCount', 'execEngine'); self::$runCount = 0; self::$autoRerun = Config::get('autoRerun', 'execEngine'); if ($role) { // Get all rules that are maintained by the ExecEngine while (self::$doRun) { self::$doRun = false; self::$runCount++; if (self::$runCount > $maxRunCount) { throw new Exception('Maximum reruns exceeded for ExecEngine (rules with violations:' . implode(', ', $rulesThatHaveViolations) . ')', 500); } Notifications::addLog("ExecEngine run #" . self::$runCount . " (auto rerun: " . var_export(self::$autoRerun, true) . ") for role '" . $role->label . "'", 'ExecEngine'); // Determine affected rules that must be checked by the exec engine $affectedConjuncts = (array) RuleEngine::getAffectedInvConjuncts($database->getAffectedConcepts(), $database->getAffectedRelations()); $affectedConjuncts = array_merge($affectedConjuncts, (array) RuleEngine::getAffectedSigConjuncts($database->getAffectedConcepts(), $database->getAffectedRelations())); $affectedRules = array(); foreach ($affectedConjuncts as $conjunctId) { $conjunct = RuleEngine::getConjunct($conjunctId); foreach ($conjunct['invariantRuleNames'] as $ruleName) { $affectedRules[] = $ruleName; } foreach ($conjunct['signalRuleNames'] as $ruleName) { $affectedRules[] = $ruleName; } } // Check rules $rulesThatHaveViolations = array(); foreach ($role->maintains() as $ruleName) { if (!in_array($ruleName, $affectedRules) && !$allRules) { continue; } // skip this rule $rule = RuleEngine::getRule($ruleName); $violations = RuleEngine::checkRule($rule, false); if (count($violations)) { $rulesThatHaveViolations[] = $rule['name']; // Fix violations for every rule ExecEngine::fixViolations($rule, $violations); // Conjunct violations are not cached, because they are fixed by the ExecEngine // If $autoRerun, set $doRun to true because violations have been fixed (this may fire other execEngine rules) if (self::$autoRerun) { self::$doRun = true; } } } } } else { Notifications::addInfo("ExecEngine extension included but role '" . self::$roleName . "' not found."); } Notifications::addLog('------------------------- END OF EXEC ENGINE -------------------------', 'ExecEngine'); }