There is one table test that you can query. That table has the following fields:
- id which is an auto incrementing value.
- name which is an ascii field.
- lasttime which is an automatic time stamp.
You can do things like: select * from test, or insert into test (name) value ('something') or delete from test where id=10
You can add only 20 records and then the earliest records are deleted.
worker.main.php
<?php // Demonstrates the use of a worker using AJAX calls (worker.ajax.php). // This is the main program it uses worker.worker.js and worker.ajax.php // See worker.ajax.php for a description of the 'test' table in the database 'test'. // Load info from mysitemap.json for my framework SiteClass into $_site. // Check SiteClass out at https://github.com/bartonlp/site-class. // It has some documentation at that site. // The worker.ajax.php uses the 'test' user and database while this program uses what is in // mysitemap.json (which is usualy user=barton, database=barton). //exit("<h1>Not Authorized</h1>"); $_site = require_once(getenv("SITELOADNAME")); $S = new SiteClass($_site); // $S gives access to my framework. // escapeltgt() is a little utility that change < and > to < > from helper-functions.php. // These three, $main, $worker, $ajax are displayed when id 'showfiles' is clicked. $main = escapeltgt(file_get_contents("worker.main.php")); $worker = escapeltgt(file_get_contents("worker.worker.js")); $ajax = escapeltgt(file_get_contents("worker.ajax.php")); $S->title = "Workers"; $S->banner = "<h1>Worker Demo</h1>"; $S->h_script =<<<EOF <script src="https://bartonphillips.net/js/syntaxhighlighter.js"></script> <link rel='stylesheet' href="https://bartonphillips.net/css/theme.css"> <script> jQuery(document).ready(function($) { var w1 = new Worker("worker.worker.js"); // Listen from messages frrom worker.worker.js w1.addEventListener("message", function(evt) { console.log("data: ", evt.data); if(Object.keys(evt.data)[0] == "ERROR" || Object.keys(evt.data)[0] == "DONE") { $("pre").html(Object.values(evt.data)[0]); } else { //let string = String.fromCharCode.apply(null, evt.data) let string = new TextDecoder("utf-8").decode(evt.data); console.log("Main string: ", string); $("pre").html(string); } }); // now transfer array buffer const send = function(txt) { // use a map to create ascii to int. //bufView = Uint8Array.from(txt, x => x.charCodeAt()); let bufView = new TextEncoder("utf-8").encode(txt); console.log("Main bufView: ", bufView); w1.postMessage(bufView, [bufView.buffer]); } $("#click").on("click", function() { var sql = $("input").val(); send(sql); return false; }); $("#clear").on("click", function() { $("pre").html(""); return false; }); $("#showfiles").on("click", function() { $("#files").show(); $(this).hide(); return false; }); }); </script> EOF; $S->css =<<<EOF input { width: 100%; font-size: 1rem; } button { cursor: pointer; font-size: 1rem; } #files { display: none; } EOF; // Use my framework to get the $top of the page which includes the <head> section // the <body> tag and my banner which is in <header>. [$top, $footer] = $S->getPageTopBottom(); // Render the page echo <<<EOF $top <p>There is one table <b>test</b> that you can query. That table has the following fields:</p> <ul> <li><i>id</i> which is an auto incrementing value.</li> <li><i>name</i> which is an ascii field.</li> <li><i>lasttime</i> which is an automatic time stamp.</li> </ul> <p>You can do things like: <i>select * from test</i>, or <i>insert into test (name) value ('something')</i> or <i>delete from test where id=10</i></p> <p>You can add only 20 records and then the earliest records are deleted.</p> <form> Enter a SQL statement: <input type="text" autofocus ><br> <button id="click">Click Me</button> <button id="clear">Clear</button> </form> <pre> </pre> <hr> <button id="showfiles">View the file <b>worker.main.php</b>,<b>worker.worker.js</b> and <b>worker.ajax.php</b></button> <div id="files"> <p>worker.main.php</p> <pre class='brush: php'> $main </pre> <p>worker.worker.js</p> <pre class='brush: js'> $worker </pre> <p>worker.ajax.php</p> <pre class='brush: php'> $ajax </pre> </div> $footer EOF;
worker.worker.js
// worker.worker.js This is javascript. // This is the worker side of worker.main.php and it calls // worker.ajax.php for the info from the 'test' table. // See worker.ajax.php for description of the 'test' table in database // 'test'. // Add an event listener for 'message'. The data is in evt.data and we // make it into a string and then pass the string to sendText() addEventListener("message", function(evt) { var string = new TextDecoder("utf-8").decode(evt.data); console.log("Worker string: ", string); sendText(string); }); // SendText() does the usual XMLHttpRequest() stuff to post to // worker.ajax.php. function sendText(txt) { // Use fetch() to send and receive the data. console.log(txt); let ret = fetch("worker.ajax.php", { body: "&page=start&sql=" +txt, // This is just plain sql method: "POST", headers: { 'content-type': 'application/x-www-form-urlencoded' } }).then(res => res.text()); ret.then(newtxt => { newtxt = newtxt.toString(); $reg = /(\[?{.*}\]?).*/ms; newtxt = newtxt.replace($reg, '$1'); console.log("Worker response" + newtxt); newtxt = JSON.parse(newtxt); if(Object.keys(newtxt) == "ERROR" || Object.keys(newtxt) == "DONE") { postMessage(newtxt); } else { // Take the items out of newtxt which is an array. var rows = ''; for(item of newtxt) { // Now the stuff in the array is an object so get the key and // value and put them into the rows variable. for([key, value] of Object.entries(item)) { rows += key + ": " + value + "\n"; } rows += "\n"; } // Now we do the same thing we did above to make the Transfer // buffer bufView = Uint8Array.from(rows, x => x.charCodeAt()); console.log("Worker bufView: ", bufView); postMessage(bufView, [bufView.buffer]); } }); };
worker.ajax.php
<?php // This is part of the worker group. // This is the AJAX server that is called from worker.worker.js // The trio is worker.main.php, worker.worker.js and worker.ajax.php /* CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(254) DEFAULT NULL, `lasttime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; This table is in database "test" on bartonphillips.com. The database allows only 'select, update, insert and delete' and the code below maintains a max of 20 entries. The standard mysitemap.json has my normal database stuff. We change it here to ues the 'test' user and the 'test' database which has the 'test' table. */ //exit("<h1>Not Authorized</h1>"); $_site = require_once(getenv("SITELOADNAME")); //ErrorClass::setNoEmail(false); ErrorClass::setErrlast(true); $_site->dbinfo->user = "barton"; // use test user $_site->dbinfo->database = "test"; // and test database $_site->noTrack = true; // needed because user is test not barton. $S = new Database($_site); // Database does not do any counting and sets noTrack true by default. //error_log("POST: ".print_r($_POST, true)); if($_POST['page'] != 'start') { echo "ERROR: This program should not be run directly. Run 'worker.main.php' instead.<br>"; error_log("worker.ajax.php, ERROR: This program should not be run directly. Run 'worker.main.php' instead. $S->ip, $S->self, $S->agent"); exit(); } if(empty($sql = $_POST['sql'])) {; echo json_encode(["ERROR"=>"No sql statment"]); exit(); } // We are using fetch() in worker.worker.js so we need to get the data from 'php://input' //$sql = file_get_contents("php://input"); //error_log("worker.ajax.php, php://input=$sql"); //exit(); // We could be passed something that will not work try { if(preg_match("/insert/i", $sql)) { // We want to restrict the size of this table so check the TABLE_ROWS $S->sql("select count(*) from test"); $cnt = $S->fetchrow('num')[0]; $nn = $cnt - 19; // This is the number to delete if($cnt > 20) { $n = $S->sql("delete from test order by lasttime asc limit $nn"); // leave most resent 20 $del = "Deleted $n items"; } } $n = $S->sql($sql); if(preg_match("/update|insert|delete/", $sql)) { echo json_encode(["DONE"=>"$del Rows Affected: $n"]); exit(); } $rows = []; while($row = $S->fetchrow('assoc')) { $rows[] = $row; } if(!count($rows)) { echo json_encode(["ERROR"=>"NO DATA"]); exit(); } echo json_encode($rows); // encode the data and send it. exit(); } catch(Exception $e) { $tmp = json_encode(["ERROR"=> $e->getMessage()]); echo $tmp; throw(new Exception($e)); }