/** * Action handler */ function client($item = null) { $node = Core::lib("ClusterCli"); // get command $cmd = DS::field("cmd", self::$_table, "id=?", "", "", [$node->id]); // keep alive signal $d = @file_get_contents("/proc/loadavg"); $l = !empty($d) ? explode(" ", $d)[0] : "1.0"; if (empty(DS::exec("UPDATE " . self::$_table . " SET modifyd=CURRENT_TIMESTAMP,cmd='',load=? WHERE id=?", [$l, $node->id]))) { DS::exec("INSERT INTO " . self::$_table . " (id,name,load,type,created,modifyd) VALUES (?,?,?,'" . ($node->_loadbalancer ? "lb" : "worker") . "',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP)", [$node->id, gethostbyaddr($node->id), $l]); } // execute commands if ($cmd == "invalidate") { Cache::invalidate(); } elseif ($cmd == "shutdown") { exec("sudo poweroff"); } elseif ($cmd == "restart") { exec("sudo restart"); } elseif ($cmd == "reload" && $node->_loadbalancer) { // generate bind config $bind = Core::lib("ClusterCli")->bindcfg(); // call the shell hook and pass the config to it's stdin if (!empty($bind) && file_exists(static::$_cmd)) { $p = popen(". " . static::$_cmd . " " . $cmd, "w"); if ($p) { pwrite($p, $bind); pclose($p); } } } }
/** * default action */ function action($item) { //! create a fake page parameter $name = "layoutadd"; $_SESSION['cms_param'][sha1("layoutadd_")] = new \PHPPE\AddOn\layoutadd([], $name, $name); //! if layout not given if (empty($item)) { //! check if we have to activate a sitebuild if (!empty($_REQUEST['set'])) { DS::exec("UPDATE " . Views::$_table . " SET id=sitebuild WHERE sitebuild!='' AND id='frame'"); DS::exec("UPDATE " . Views::$_table . " SET id='frame' WHERE sitebuild=?", trim($_REQUEST['set'])); Http::redirect(); } //! load layouts and sitebuilds $this->layouts = Views::find([], "sitebuild=''", "name"); $this->sitebuilds = Views::find([], "sitebuild!=''", "name"); } else { //! load layout $this->layout = new Views($item); if (!empty($this->layout->jslib)) { foreach ($this->layout->jslib as $j) { View::jslib($j); } } if (!empty($this->layout->css)) { foreach ($this->layout->css as $c) { View::css($c); } } $this->numPages = Page::getNum($item); //! get user input $layout = Core::req2arr("layout"); //! merge the new data with the loaded layout's properties if (!empty($this->layout->sitebuild) && !empty($layout)) { Core::$core->noframe = 1; $layout['sitebuild'] = $layout['id']; } if (Core::isTry("layout")) { //! delete a layout if (!empty($layout['delete'])) { $this->layout->delete(); } else { unset($layout['delete']); //! renamed? if ($this->layout->id != $layout['id']) { DS::exec("UPDATE " . Views::$_table . " SET id=? WHERE id=?", [$layout['id'], $this->layout->id]); Core::log('A', sprintf("Layout %s renamed to %s by %s", $this->layout->id, $layout['id'], Core::$user->name), "cmsaudit"); } //! save new data foreach ($layout as $k => $v) { $this->layout->{$k} = $v; } $this->layout->save(); } Http::redirect("cms/layouts"); } } }
public function testRegistry() { if (!class_exists("PHPPE\\Registry")) { $this->markTestSkipped(); } //registry in files \PHPPE\DS::close(); \PHPPE\Registry::del("key"); $this->assertEquals("default", \PHPPE\Registry::get("key", "default"), "Registry default"); $this->assertTrue(\PHPPE\Registry::set("key", "value"), "Registry set"); $this->assertEquals("value", \PHPPE\Registry::get("key", "default"), "Registry get"); //registry in database $ds = new \PHPPE\DS("sqlite::memory:"); \PHPPE\Registry::del("key"); $this->assertEquals("default", \PHPPE\Registry::get("key", "default"), "Registry db default"); $this->assertTrue(\PHPPE\Registry::set("key", "value"), "Registry db set"); $this->assertEquals("value", \PHPPE\Registry::get("key", "default"), "Registry db get"); }
public function testHelpers() { \PHPPE\Core::$core->nocache = true; \PHPPE\Core::$core->meta["test"] = "testing"; \PHPPE\Core::$core->link["apple-touch-icon"] = "testing"; \PHPPE\View::init([]); $dir = dirname(__DIR__); \PHPPE\View::setPath($dir); \PHPPE\View::assign("dir", $dir); \PHPPE\View::css("test.css"); \PHPPE\View::css("test2.css"); \PHPPE\View::css(url("css", "test.css")); $this->assertNotEmpty(\PHPPE\View::css(), "CSS"); \PHPPE\View::jslib("test.js", "testjs();"); \PHPPE\View::jslib("test2.js", "testjs();"); \PHPPE\View::jslib(url("js", "test.js"), "testjs();"); $this->assertNotEmpty(\PHPPE\View::jslib(), "JSLib"); \PHPPE\View::js("some()", "thing();"); \PHPPE\View::js("some2()", "thing();", true); \PHPPE\View::menu("a", "b"); \PHPPE\View::menu("c", ["d" => "e"]); $this->assertNotEmpty(\PHPPE\View::menu(), "Menu"); $o = \PHPPE\Core::$core->output; \PHPPE\Core::$core->output = "ncurses"; $o = trim(\PHPPE\View::e('D', "message", "module")); $this->assertEquals("module-D: message" . chr(27) . "[0m", $o, "error string #1"); \PHPPE\Core::$core->output = "html"; $this->assertEquals("<span style='background:#F00000;color:#FEA0A0;padding:3px;'>E-module: ["message"]</span>", trim(\PHPPE\View::e('E', ["message"], "module")), "error string #2"); \PHPPE\Core::$core->output = $o; $this->assertEquals("aaa\n<!include test2>\nbbb\n", \PHPPE\View::get("test1"), "Raw template file"); \PHPPE\DS::close(); $ds = new \PHPPE\DS("sqlite::memory:"); \PHPPE\DS::exec("UPDATE views SET css='[\"a.css\"]' WHERE id='simple'"); $this->assertNotEmpty(\PHPPE\View::get("simple"), "Raw template db"); \PHPPE\DS::exec("UPDATE views SET css='' WHERE id='simple'"); }
public function testDiag() { \PHPPE\DS::close(); $ds = new \PHPPE\DS(); $this->assertNull($ds->diag(), "Diag no ds"); \PHPPE\DS::db("sqlite::memory:"); ob_start(); $ds->diag(); $this->assertEmpty(ob_get_clean(), "Diag no update"); if (file_put_contents("vendor/phppe/Developer/sql/upd_test.sql", "select 1;")) { ob_start(); $ds->diag(); $this->assertNotEmpty(ob_get_clean(), "Diag update"); $this->assertFileNotExists("vendor/phppe/Developer/sql/upd_test.sql", "Diag file"); } }
public function testDB() { if (!\PHPPE\ClassMap::has("PHPPE\\DB")) { $this->markTestSkipped(); } $this->assertEquals("%some%thing%", \PHPPE\DB::like("some thing"), "like"); $this->assertEquals("SELECT * FROM users", \PHPPE\DB::select("users"), "Simple select"); $this->assertEquals("SELECT id,name FROM users", \PHPPE\DB::select("users")->fields(["id", "name"]), "Select with fields"); $this->assertEquals("SELECT * FROM users WHERE id=?", \PHPPE\DB::select("users")->where("id=?"), "Select with where #1"); $this->assertEquals("SELECT * FROM users WHERE (id=? AND name=?)", \PHPPE\DB::select("users")->where(["id=?", "name=?"]), "Select with where #2"); $this->assertEquals("SELECT * FROM users WHERE (id = 'my id')", \PHPPE\DB::select("users")->where([["id", "=", "my id"]]), "Select with where #3"); $this->assertEquals("SELECT * FROM users WHERE (id LIKE '%my%id%')", \PHPPE\DB::select("users")->where([["id", "like", "my id"]]), "Select with where #4"); $this->assertEquals("SELECT * FROM users WHERE (id LIKE '%my%id%' OR name LIKE '%my%name%') AND 1=1", \PHPPE\DB::select("users")->where([["id", "like", "my id"], ["name", "like", "my name"]], "or")->where("1=1"), "Select with where #5"); $this->assertEquals("SELECT * FROM users u, user_posts p WHERE u.id=p.id", \PHPPE\DB::select("users", "u")->table("user_posts", "p")->where("u.id=p.id"), "Select with where #6"); $wasExc = false; try { \PHPPE\DB::update("users")->where("id=id", "NOT"); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "bad where exception"); $this->assertEquals("SELECT * FROM users HAVING id=?", \PHPPE\DB::select("users")->having("id=?"), "Select with having"); $this->assertEquals("SELECT * FROM users LIMIT 10", \PHPPE\DB::select("users")->limit(10), "Select with limit #1"); $wasExc = false; try { \PHPPE\DB::select("users")->offset(5)->sql(); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "Select with limit #2"); $this->assertEquals("SELECT * FROM users LIMIT 10 OFFSET 5", \PHPPE\DB::select("users")->limit(10)->offset(5), "Select with limit #3"); $this->assertEquals("SELECT * FROM users GROUP BY name", \PHPPE\DB::select("users")->groupBy("name"), "Select with group by #1"); $this->assertEquals("SELECT * FROM users GROUP BY name,id", \PHPPE\DB::select("users")->groupBy(["name", "id"]), "Select with group by #2"); $this->assertEquals("SELECT * FROM users ORDER BY id", \PHPPE\DB::select("users")->orderBy("id"), "Select with order by #1"); $this->assertEquals("SELECT * FROM users ORDER BY id", \PHPPE\DB::select("users")->orderBy(["id"]), "Select with order by #2"); $wasExc = false; try { \PHPPE\DB::update("users")->sql(); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "update no fields exception"); $this->assertNotFalse(strpos(\PHPPE\DB::update("users"), "No fields specified"), "update no field string"); $this->assertEquals("UPDATE users SET id=?,name=?", \PHPPE\DB::update("users")->fields(['id', 'name']), "update with fields"); $this->assertEquals("DELETE FROM users", \PHPPE\DB::delete("users"), "delete table"); $this->assertEquals("DELETE a FROM users a", \PHPPE\DB::delete("users", "a")->sql(), "delete alias"); $this->assertEquals("DELETE user_posts FROM user_posts LEFT JOIN users ON user_posts.userId=users.id WHERE (users.id IS NULL)", \PHPPE\DB::delete("user_posts")->join("LEFT", "users", "user_posts.userId=users.id")->where([["users.id", "IS NULL"]]), "delete where"); $this->assertEquals("INSERT INTO users (id,name) VALUES (?,?)", \PHPPE\DB::insert("users")->fields('id,name'), "insert"); $wasExc = false; try { \PHPPE\DB::select("users")->join("SIMPLE", "user_posts", "id=id"); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "bad join exception"); $this->assertEquals("REPLACE INTO users (id,name) VALUES (?,?) WHERE id=''", \PHPPE\DB::replace("users")->fields(['id', 'name'])->where("id=''"), "replace"); $this->assertEquals("TRUNCATE TABLE users", \PHPPE\DB::truncate("users"), "truncate"); $wasExc = false; try { \PHPPE\DB::select("users")->where([["1", "!="]]); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "bad where exception"); $wasExc = false; try { \PHPPE\DB::select("users")->where([["a", "similarto", "b"]]); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "bad where exception"); $wasExc = false; try { \PHPPE\DB::update("")->sql(); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "no table exception"); $wasExc = false; try { \PHPPE\DB::insert("users")->sql(); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "no where exception"); $wasExc = false; try { \PHPPE\DB::replace("users")->fields(["id"])->sql(); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "no where exception"); \PHPPE\DS::close(); $ds = new \PHPPE\DS("sqlite::memory:"); $this->assertNotEmpty(\PHPPE\DB::select("users")->execute(), "execute"); \PHPPE\DB::truncate("users")->execute(); $wasExc = false; try { \PHPPE\DB::insert("users")->with(''); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "no fields exception"); $this->assertEquals(1, \PHPPE\DB::insert("users")->with(['id' => 123, 'name' => 'newcomer', 'email' => '*****@*****.**']), "insert with with"); $wasExc = false; try { \PHPPE\DB::select("users")->where("id=?")->execute(); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "no argument exception"); $ds = new \PHPPE\DS("sqlite::memory:"); $this->assertNotEmpty(\PHPPE\DB::select("users")->execute([], 1), "execute on ds"); }
function load(&$app) { $app->versions = DS::query("a.*,b.name as moduser,c.name as pubuser, CURRENT_TIMESTAMP as ct", "pages a left join users b on a.modifyid=b.id left join users c on a.publishid=c.id", "a.id=? AND (a.lang='' OR a.lang=?)", "", "a.created DESC", 0, 0, [$_SESSION['cms_url'], Core::$client->lang]); }
/** * Action handler */ function action($item) { setlocale(LC_NUMERIC, "C"); $lib = Core::lib("ClusterSrv"); $nodes = DS::query("*", self::$_table, "", "", "type,load DESC,id"); $master = DS::field("id", self::$_table, "type='master' AND modifyd>CURRENT_TIMESTAMP-120"); //! check if executed from CLI if (Core::$client->ip != "CLI") { header("Content-type:application/json"); $loadavg = 0.0; $waspeek = 0; $minSync = ""; if (!empty($nodes)) { $minSync = reset($nodes)['syncd']; foreach ($nodes as $k => $node) { unset($nodes[$k]["cmd"]); $loadavg += floatval($node['load']); if ($node['load'] >= 0.5) { $waspeek = 1; } if ($node['load'] >= 0.75) { $waspeek = 2; } if ($node['syncd'] < $minSync) { $minSync = $node['syncd']; } } $loadavg /= count($nodes); } date_default_timezone_set('UTC'); $minSync = strtotime($minSync); $D = []; $d = $lib->_skeleton; if (substr($d, -1) != "/") { $d .= "/"; } foreach (['vendor/*', 'vendor/*/*', 'vendor/*/*/*', 'vendor/*/*/*/*', 'vendor/*/*/*/*/*'] as $v) { $D += array_fill_keys(@glob($d . $v, GLOB_NOSORT), 0); } $newfiles = 0; foreach ($D as $d => $v) { $t = filemtime($d); if ($t != 0 && $t > $minSync) { $newfiles = 1; break; } } die(json_encode(["status" => $loadavg < 0.1 ? "idle" : ($loadavg > 0.5 || $waspeek ? $loadavg > 0.75 || $waspeek == 2 ? "error" : "warn" : "ok"), "loadavg" => $loadavg, "peek" => $waspeek, "master" => $master, "newfiles" => $newfiles, "id" => Core::lib("ClusterSrv")->id, "nodes" => $nodes])); } else { echo chr(27) . "[96mThis node is: " . chr(27) . "[0m" . $lib->id . " " . chr(27) . "[" . (strtolower(trim($lib->id)) == strtolower(trim($master)) ? "91mMASTER" : "92mSLAVE") . chr(27) . "[0m\n" . chr(27) . "[96mCluster nodes:\n"; echo chr(27) . "[96m Id Type Load Last seen Last viewed Name\n -------------- --------- ----- ------------------- ------------------- -----------------------------" . chr(27) . "[0m\n"; foreach ($nodes as $node) { echo sprintf("%s%-16s%-8s%8s", strtolower(trim($node['id'])) == strtolower(trim($master)) ? chr(27) . "[93m*" : " ", $node['id'], $node['type'], $node['load']) . " " . (!empty($node['modifyd']) ? $node['modifyd'] : sprintf("%-19s", L("booting"))) . " " . (!empty($node['viewd']) ? $node['viewd'] : "????-??-?? ??:??:??") . " " . $node['name'] . chr(27) . "[0m\n"; } echo "\n"; if (Core::$core->action == "action") { $this->help(); } } }
public function testContent() { Core::$core->nocache = true; include_once __DIR__ . "/../libs/FailFilter.php"; DS::close(); DS::db("sqlite::memory:"); DS::exec("insert into pages (id,name,template,data,dds,filter) values ('test','Test','testview','{\"body\":\"testbody\"}','{\"testdds\":[\"1\",\"\",\"\"]}','fail');"); DS::exec("insert into views (id,ctrl) values ('testview', 'echo(\"OK\");');"); $url = Core::$core->url; $title = Core::$core->title; $contentApp = new Content(); //! no content Core::$core->title = "NONE"; $contentApp = new Content("no/such/content"); $this->assertEquals("NONE", Core::$core->title, "No content"); //! filter $contentApp = new Content("test/"); $this->assertEquals("403", Core::$core->template, "Filtered"); DS::exec("update pages set filter='' where id='test';"); //! is content $contentApp = new Content("test/"); $this->assertEquals("Test", Core::$core->title, "Content"); $contentApp->getDDS($contentApp); $this->assertEquals("testbody", $contentApp->body, "Body"); $this->assertNotEmpty($contentApp->testdds, "DDS"); $old = Core::$core->noctrl; Core::$core->noctrl = false; $contentApp->ctrl = "echo('OK');"; $this->assertEquals("OK", $contentApp->action(), "Content controller #1"); $old = Core::$core->noctrl; Core::$core->noctrl = true; $this->assertNull($contentApp->action(), "Content controller #2"); Core::$core->noctrl = $old; DS::exec("update pages set dds='{\"testdds2\":[\"nosuchcolumn\",\"\",\"\"]}' where id='test';"); $contentApp = new Content("test/"); $contentApp->getDDS($contentApp); $this->assertEmpty(@$contentApp->testdds2, "DDS failed"); Core::$core->title = $title; }
public function testEmail() { if (!\PHPPE\ClassMap::has("PHPPE\\Email")) { $this->markTestSkipped(); } \PHPPE\Core::$core->mailer = null; $email = new \PHPPE\Email(); $emailData = $email->get(); $email2 = new \PHPPE\Email($emailData); $this->assertNotEmpty($email2, "Empty Email dump"); $wasExc = false; try { $email3 = new \PHPPE\Email("something"); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "Email creating exception"); $wasExc = false; try { $email->send(); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "No backend exception"); $wasExc = false; try { $email->send("db"); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "No message exception"); $email->message("Something"); $wasExc = false; try { $email->send("db"); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "No subject exception"); $email->subject("Subject"); \PHPPE\DS::close(); $wasExc = false; try { $email->send("db"); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "No recipient exception"); $wasExc = false; try { $email->to("me"); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "Bad address exception #1"); $wasExc = false; try { $email->to("me@notld"); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "Bad address exception #2"); $email->to("me@localhost"); $email->replyTo("me2@localhost"); $email->cc("me3@localhost"); $email->bcc("me4@localhost"); $wasExc = false; try { $email->send("db"); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "No db exception"); $wasExc = false; try { $email->send("phpmailer"); } catch (\Exception $e) { $wasExc = true; } $this->assertTrue($wasExc, "No phpmailer exception"); $this->assertNotEquals(0, preg_match("/Message\\-ID/", $email->send("mime")), "Return mime message"); $email->attachFile("images/phppe.png"); $email->attachFile("images/phppe.png", "image/png"); $email2->attachData("something.txt", "text/plain", "something"); $mime = $email2->message("<html><body>html mail<img src='http://localhost/something.jpg'><img src='images/phppe.png'></body></html>")->subject("Subject")->to("me@localhost")->send("mime"); $this->assertTrue($email2->send("log"), "Log backend"); $email2->send("mail"); $email2->send("sendmail"); $email2->send("smtp://*****:*****@localhost")->subject("Subject")->message("message"); \PHPPE\DS::db("sqlite::memory:"); $wasExc = false; try { $email->send("db"); $email3->send("db"); } catch (\Exception $e) { $wasExc = true; echo $e; } $this->assertFalse($wasExc, "To db queue"); \PHPPE\Core::$core->realmailer = "log"; $email->cronMinute(""); \PHPPE\Core::$core->realmailer = "log"; $email->cronMinute(""); }
/** * default action */ function action($item) { //! check access rights if (!Core::$user->has("siteadm|webadm")) { Http::redirect("403"); } //! if we have to delete a page version if (isset($_REQUEST['pagedel'])) { if (!empty($_REQUEST['created'])) { Page::delete($item, $_REQUEST['created']); } Http::redirect($item); } //! revert to an old version of the page if (isset($_REQUEST['revert'])) { if (!empty($_REQUEST['created'])) { Core::log('A', sprintf("Page %s reverted to %s by %s", $item, $_REQUEST['created'], Core::$user->name), "cmsaudit"); DS::exec("UPDATE pages set created=CURRENT_TIMESTAMP,modifyd=CURRENT_TIMESTAMP,modifyid=? WHERE id=? AND (lang='' OR lang=?) AND created=?", [Core::$user->id, $item, Core::$client->lang, $_REQUEST['created']]); } Http::redirect($item); } //! get the latest public version's date if (empty($_REQUEST['created'])) { $_REQUEST['created'] = DS::field("created", "pages", "(id=? OR ? LIKE id||'/%') AND (lang='' OR lang=?) AND publishid!=0", "", "id DESC,created DESC", [$item, $item, Core::$client->lang]); if (empty($_REQUEST['created'])) { $_REQUEST['created'] = DS::field("created", "pages", "(id=? OR ? LIKE id||'/%') AND (lang='' OR lang=?)", "", "id DESC,created ASC", [$item, $item, Core::$client->lang]); } } //! load frame page for page parameters and dds $frame = DS::fetch("data,dds", "pages", "id='frame' AND (lang='' OR lang=?) AND created<=?", "", "", [Core::$client->lang, $_REQUEST['created']]); $frame['dss'] = @json_decode($frame['dds'], true); $frame['data'] = @json_decode($frame['data'], true); View::assign("frame", $frame['data']); //! load archive version //! normally you would use Model, but that would only return the latest version $page = DS::fetch("*", "pages", "(id=? OR ? LIKE id||'/%') AND (lang='' OR lang=?) AND created=?", "", "id DESC,created DESC", [$item, $item, Core::$client->lang, $_REQUEST['created']]); $this->title = $page['name']; $title = L("ARCHIVE") . " " . $page['name']; if (is_string($page['data'])) { $page['data'] = @json_decode($page['data'], true); } if (is_array($page['data'])) { foreach ($page['data'] as $k => $v) { $this->{$k} = $v; } } foreach (["id", "name", "lang", "filter", "template", "pubd", "expd", "dds", "ownerid", "created"] as $k) { $this->{$k} = $page[$k]; } $p = @array_merge($frame['dds'], @json_decode($page['dds'], true)); if (is_array($p)) { foreach ($p as $k => $c) { if ($k != "dds") { try { $this->{$k} = DS::query($c[0], $c[1], @$c[2], @$c[3], @$c[4], @$c[5], View::getval(@$c[6])); } catch (\Exception $e) { Core::log("E", $item . " " . $e->getMessage() . " " . implode(" ", $c), "dds"); } } } } $old = View::template($this->template); //! if we have to compare to an older (or the latest) version if (isset($_REQUEST['diff'])) { include_once "vendor/phppe/CMS/libs/simplediff.php"; //! load current version $frame = DS::fetch("data,dds", "pages", "id='frame' AND (lang='' OR lang=?) AND publishid!=0", "", "created DESC", [Core::$client->lang]); $frame['dss'] = @json_decode($frame['dds'], true); $frame['data'] = @json_decode($frame['data'], true); View::assign("frame", $frame['data']); $page = DS::fetch("*", "pages", "id=? OR ? LIKE id||'/%'", "", "id DESC,created DESC", [$item, $item]); if (is_string($page['data'])) { $page['data'] = @json_decode($page['data'], true); } if (is_array($page['data'])) { foreach ($page['data'] as $k => $v) { $this->{$k} = $v; } } foreach (["id", "name", "lang", "filter", "template", "pubd", "expd", "dds", "ownerid", "created"] as $k) { $this->{$k} = $page[$k]; } $p = @array_merge($frame['dds'], @json_decode($page['dds'], true)); if (is_array($p)) { foreach ($p as $k => $c) { if ($k != "dds") { try { $this->{$k} = DS::query($c[0], $c[1], @$c[2], @$c[3], @$c[4], @$c[5], View::getval(@$c[6])); } catch (\Exception $e) { Core::log("E", $item . " " . $e->getMessage() . " " . implode(" ", $c), "dds"); } } } } $this->title = $page['name']; $curr = View::template($this->template); //! make sure diff splits on tag end $this->result = htmlDiff(preg_replace("/>([^\\ \t\n])/m", "> \\1", $old), preg_replace("/>([^\\ \t\n])/m", "> \\1", $curr)); //! remove diff inside tags $this->result = preg_replace("/(<[^<>]+)<ins>.*?<\\/ins>([^<>]*>)/ims", "\\1\\2", $this->result); $this->result = preg_replace("/(<[^<>]+)<del>(.*?)<\\/del>([^<>]*>)/ims", "\\1\\2\\3", $this->result); } else { $this->result = $old; } $this->title = $title; }