function compile_engine() { global $BASEDIR; global $APPEND; $order = "bp_name,rule_prio"; $data = db_read("rules,bps", null, array(), $order, 0, 0); $table = array(); foreach ($data as $def) { $bp_name = $def["bp_name"]; $rule_prio = $def["rule_prio"]; $statefield = $def["bp_statefield"]; if ($bp_name == "GLOBAL") { $statefield = "GLOBAL.GLOBAL"; } if (!$statefield) { // use default: bpstates $statefield = "states.state_value:state_env"; } $def["rule_location"] = split("\n", $def["rule_location"]); $def["rule_condition"] = split("\n", $def["rule_condition"]); $def["rule_action"] = split("\n", $def["rule_action"]); $startvalue = $def["rule_startvalue"]; echo "compiling business process '{$bp_name}' prio {$rule_prio}: acts on {$statefield}<br>\n"; $subcond = array("bp_name" => $bp_name, "rule_prio" => $rule_prio); $subdata = db_read("conts", null, $subcond, "cont_prio", 0, 0); foreach ($subdata as $subidx => $subdef) { $subdata[$subidx]["cont_action"] = split("\n", $subdef["cont_action"]); } $def["CONTI"] = array_merge($subdata, $APPEND); $split = split(":", $statefield); $state_base = $split[0]; $def["bp_statefield"] = $state_base; $def["ENV_FIELD"] = @$split[1]; $newsplit = split("\\.", $split[0]); $def["TABLE"] = $newsplit[0]; $def["FIELD"] = $newsplit[1]; $table[$state_base][] = $def; } echo "done.<br>\n"; $code = "<?php // this file was automatically generated by the engine compiler from database tables.\n\n// ====> DO NOT EDIT! <===\n\n"; $code .= "\$ENGINE =\n" . db_data_to_code($table); $code .= "\n\n?>\n"; $outname = "{$BASEDIR}/compiled/engine_table.php"; $tmpname = "{$outname}.tmp"; $fp = fopen($tmpname, "w"); if (!$fp) { die("cannot create file '{$outname}'\n"); } $len = fwrite($fp, $code); if ($len != strlen($code)) { die("cannot write temporary file '{$tmpname}'\n"); } fclose($fp); rename($tmpname, $outname); }
} $new_schema = "{$BASEDIR}/schema/{$new_schema_name}"; echo "NEW schema: '{$new_schema}'<br><br>\n"; unset($SCHEMA); unset($EXTRA); require_once $new_schema; if (@$EXTRA) { $SCHEMA = array_merge_recursive($SCHEMA, $EXTRA); } $check = db_check_syntax($SCHEMA, $SYNTAX); if ($check) { die("bad syntax in NEW: {$check}\n"); } $NEW = db_mangle_schema($SCHEMA); $text = "<?php // this file was automatically generated by the schema precompiler from '{$new_schema}'.\n\n// ====> DO NOT EDIT! <===\n\n"; $text .= "\$SCHEMA =\n" . db_data_to_code($NEW); $text .= ";\n?>\n"; $outname = "{$BASEDIR}/compiled/{$new_schema_name}"; _writefile($outname, $text); $outname = "{$BASEDIR}/compiled/schema.php"; _writefile($outname, $text); echo "done.<br>\n"; $SCHEMA = $NEW; echo "<br>---------------------------------------------------<br><br>\n"; foreach ($CONFIG["CONNECTIONS"] as $database => $ddef) { $DB_NAME = $ddef["BASE"]; echo "-----> Database '{$database}' name='{$DB_NAME}' <------<br><br>\n"; $connection = _db_open($database, true, true); if (!$connection) { die("Cannot connect to database '{$database}' (fix connection and/or sourcecode in config.php<br>\n"); }
function do_action(&$env, $action) { global $RAW_ID; global $ERROR; if (is_array($action)) { foreach ($action as $sub) { if (!do_action($env, $sub)) { return false; } if (@$env["HAS_FORKED"] || @$env["DO_BREAK"]) { return true; } } return true; } if (!$action) { return true; } //echo "ACTION: $action\n"; $oldlevel = $env["LEVEL"]; $env["LEVEL"]++; $ok = false; if (!$action) { $ok = true; } elseif (preg_match("/\\A(script|url)\\s+(.*)/", $action, $matches)) { $op = $matches[1]; $cmd = $matches[2]; if ($op == "url") { $cmd = "wget -O - '{$cmd}'"; } $cmd = subst_macros($env, $cmd); $ok = run_script($env, $cmd); } else { if (preg_match("/\\A(insert|update|delete)\\s+(?:({$RAW_ID})\\s+)?({$RAW_ID}\\s*=.*)/", $action, $matches)) { $mode = $matches[1]; $table = $env["TABLE"]; if (@$matches[2]) { $table = $matches[2]; } $rest = $matches[3]; $data = array(); //echo "MODE: $mode\n"; if ($mode == "update" || $mode == "delete") { $primary = _db_primary($table); foreach (split(",", $primary) as $pri) { if (isset($env[$pri])) { $data[0][$pri] = $env[$pri]; } } } while (preg_match("/\\A\\s*({$RAW_ID})\\s*=\\s*'((?:[^\\']|\\.)*)'(.*)/", $rest, $matches)) { $field = $matches[1]; $value = $matches[2]; $rest = $matches[3]; $data[0][$field] = subst_macros($env, $value, "'", "\\'"); } echo_rule($env); echo "{$mode} {$table}:"; foreach ($data[0] as $field => $value) { echo " {$field} = '{$value}'"; } echo "\n"; if ($mode == "delete") { $ok = db_delete($table, $data) && !$ERROR; check_answer($env, "DELETE {$ok}"); } elseif ($mode == "update") { $ok = db_update($table, $data) && !$ERROR; check_answer($env, "UPDATE {$ok}"); } else { $ok = db_insert($table, $data) && !$ERROR; check_answer($env, "INSERT {$ok}"); } if (!$ok) { check_answer($env, "DB_ERROR {$mode} ({$ERROR})"); } } else { if (preg_match("/\\Aquery\\s+({$RAW_ID})\\s+({$RAW_ID})\\s+({$RAW_ID}\\s*=.*)/", $action, $matches)) { $var = $matches[1]; $table = $matches[2]; $rest = $matches[3]; $cond = array(); while (preg_match("/\\A\\s*({$RAW_ID})\\s*=\\s*'((?:[^\\']|\\.)*)'(.*)/", $rest, $matches)) { $field = $matches[1]; $value = $matches[2]; $rest = $matches[3]; $cond[$field] = subst_macros($env, $value, "'", "\\'"); } $data = db_read($table, null, $cond, null, 0, 0); //echo "got....."; print_r($data); echo "\n"; $env[$var] = $data; $ok = true; } else { if (preg_match("/\\Avar\\s+({$RAW_ID}(?:->{$RAW_ID})*)\\s*=\\s*'((?:[^\\']|\\.)*)'/", $action, $matches)) { $var = $matches[1]; $expr = $matches[2]; $lvalue =& $env; while (preg_match("/\\A(?:->)?({$RAW_ID})(.*)/", $var, $matches)) { $field = $matches[1]; $var = $matches[2]; $lvalue =& $lvalue[$field]; } if ($var) { engine_error("cannot assign to variable '{$var}'"); } else { $lvalue = subst_macros($env, $expr, "'", "\\'"); $ok = true; } } else { if (preg_match("/\\A(call|start)\\s+({$RAW_ID})(.*)/", $action, $matches)) { $ok = false; $mode = $matches[1]; $call = $matches[2]; $rest = $matches[3]; $cond = array("bp_name" => $call); $data = db_read("bps", null, $cond); if (!$data || $ERROR) { check_answer($env, "DB_ERROR read ({$ERROR})"); } else { $newenv = array(); while (preg_match("/\\A\\s*({$RAW_ID})\\s*=\\s*'((?:[^\\']|\\.)*)'(.*)/", $rest, $matches)) { $field = $matches[1]; $value = $matches[2]; $rest = $matches[3]; $newenv[$field] = subst_macros($env, $value, "'", "\\'"); } if ($rest) { engine_error("bad call '{$call}', syntax rest '{$rest}'"); } else { $statefield = $data[0]["bp_statefield"]; $newrec = array(); $newrec["state_id"] = null; $newrec["bp_name"] = $call; if ($mode == "start") { // asynchronous call: make "return" later a nop $newenv["NO_RETURN"] = true; } $newrec["state_env"] = db_data_to_code($newenv); if (@$newenv["state_value"]) { $newrec["state_value"] = $newenv["state_value"]; } $table = $env["TABLE"]; $primary = _db_primary($table); $field = $env["FIELD"]; $newrec["state_returnfield"] = "{$table}.{$field}"; $id_rec = array(); foreach (split(",", $primary) as $pri) { $id_rec[$pri] = $env[$pri]; } $newrec["state_returnid"] = db_data_to_code($id_rec); $ok = db_insert("states", array($newrec)) && !$ERROR; if ($ok) { if (true) { echo_rule($env); echo "call {$table}.{$field} to states\n"; } // decide whether to finish the caller or not if ($mode == "call") { //echo "SHOULD_BREAK....\n"; $env["DO_BREAK"] = true; } else { } } else { check_answer($env, "DB_ERROR insert ({$ERROR})"); } } } } else { if (preg_match("/\\Areturn\\s+'((?:[^\\']|\\.)*)'(.*)/", $action, $matches)) { $returnvalue = subst_macros($env, $matches[1], "'", "\\'"); $rest = $matches[2]; if (@$env["NO_RETURN"]) { // original call was asynchronous: ignore return statement check_answer($env, "NO_RETURN"); if (true) { $table = $env["TABLE"]; $field = $env["FIELD"]; echo_rule($env); echo "done asynchronous call {$table}.{$field}\n"; } $ok = true; } else { // advance the caller's state $split = split("\\.", $env["state_returnfield"]); $tablename = $split[0]; $fieldname = $split[1]; $oldrec = eval("return " . $env["state_returnid"] . ";"); $data = db_read($tablename, null, $oldrec); if (!$data || $ERROR) { engine_error("cannot re-read caller's data from table {$tablename}"); } else { if ($test = @$data[0]["state_env"]) { // original caller had an environment $oldenv = eval("return {$test};"); while (preg_match("/\\A\\s*({$RAW_ID})\\s*=\\s*'((?:[^\\']|\\.)*)'(.*)/", $rest, $matches)) { $field = $matches[1]; $value = $matches[2]; $rest = $matches[3]; $oldenv[$field] = subst_macros($env, $value, "'", "\\'"); } if ($rest) { engine_warn("return statement has unparsable rest '{$rest}'"); } $oldrec["state_env"] = db_data_to_code($oldenv); } $oldrec[$fieldname] = $returnvalue; if (true) { echo_rule($env); echo "return to {$tablename}.{$fieldname} = '{$returnvalue}'\n"; } $ok = db_update($tablename, array($oldrec)) && !$ERROR; //echo "RETURN $tablename $fieldname='$returnvalue' ok='$ok' ERROR='$ERROR'\n"; if (!$ok) { check_answer($env, "DB_ERROR update ({$ERROR})"); } } } } else { engine_error("cannot parse action '{$action}'. correct your rules!"); } } } } } } if ($ok) { $env["HIT_FLAG"] = true; } $env["LEVEL"] = $oldlevel; return $ok; }
function db_write_code($tablename, $fieldname, $data) { return "return " . db_data_to_code($data); }
function write_syncstatus() { global $SYNC_STATUS; global $BASEDIR; $tmp_name = "{$BASEDIR}/compiled/sync_status.tmp"; $fin_name = "{$BASEDIR}/compiled/sync_status.php"; $fp = fopen($tmp_name, "w"); if (!$fp) { die("cannot open syncstatus file\n"); } fwrite($fp, "<?php // this file is automatically generated by the DB syncing system.\n\n// ====> DO NOT EDIT unless you EXACTLY know what you are doing! <===\n\n"); fwrite($fp, "\$SYNC_STATUS =\n" . db_data_to_code($SYNC_STATUS)); fwrite($fp, ";\n?>\n"); fclose($fp); rename($tmp_name, $fin_name); }