php/netOld.php
<?php
require_once 'cloud.php';
Class Pipeline {
public static function cfgBase($src, $ignMiss) { # cleanup the base config $src and generatebase
$wlk = $rwk = $wNR = $fNR = [];
foreach ($src as &$s) {
for ($bx = 0; $bx < 4; $bx++)
$s[$bx] = trim($s[$bx] ?? '');
$s[4] = isset($s[4]) ? ($s[4] ? preg_split('/\s+/', $s[4], flags: PREG_SPLIT_NO_EMPTY) : []) : ($s[0] ? [$s[0]] : []);
if ($s[0])
isset($wlk[$s[0]]) ? err("duplicate wlk $s[0] in", $src) : $wlk[$s[0]] = $s;
if ($s[1]) {
$rwk[$s[1]][] = $s;
} else {
$wNR[$s[0]] = $s;
array_push($fNR, ...$s[4]);
}
}
$n = [$wlk, $rwk, $wNR, $fNR, $ignMiss, $src];
return $n;
}
/* add a cfg to $c with name $cfgN and keys $kys
indexes: walk => by wlk ix, rwk => $rwkys empty => empty row , flds => fields */
public static function cfg($c, $rwKys) {
$wlk = $c[2]; #walk indexes without row key
$empty = [];
$flds = $c[3]; #fileds without row key
foreach($rwKys as $k) {
if ( ! $aLi = $c[1][$k] ?? null) {
if (isset($c[4][$k]))
continue;
err("fieldName $k not in cfg", array_keys($c[1]));
}
$empty[$k] = null;
foreach($aLi as $a) {
if (isset($wlk[$a[0]]))
err("cfgAdd $a[0] already set in ele, keys", $kys);
$wlk[$a[0]] = $a;
array_push($flds, ...$a[4]);
}
}
return ['walk' => $wlk, 'row' => $rwKys, 'empty' => $empty, 'flds' => $flds];
}
public function __construct($cl, $cfg) {
$this->cloud = $cl;
$this->cfg = $cfg;
$this->errF = Net::ERRFILTER;
$this->out = null;
}
public function makeWalk($trg) {
if (str_starts_with($trg, 'meta')) {
$this->metaDo = 1;
$trg = substr($trg, 4);
}
$this->walk->rowWriter = $this->rowWriter = new $trg;
return $this;
}
public function constructOld($tr, $cfg, $pp) {
$this->cfg = $cfg;
# $trA = preg_split('/\s+/', $trg, flags: PREG_SPLIT_NO_EMPTY);
$pL = count($pp);
$pp[] = $this->target = $tr; # = array_shift($trA);
$mm = fn($ft) => match ($ft) {
'req-string' => new Net2Str,
'req-xmlRdr' => new Net2XMLReader,
'string-jsonObj' => new Json(false),
'string-jsonArr' => new Json(true),
'xmlRdr-rowOut' => new WalkXML($cfg, 'rowOut'),
'xmlRdr-rowTb' => new WalkXML($cfg, 'rowTb'),
'xmlRdr-rowArr' => new WalkXML($cfg, 'rowArr'),
'xmlRdr-rowCsv' => new WalkXML($cfg, 'rowCsv'),
default => null,
};
for ($px=0; $px < $pL; $px++) {
$st = $pp[$px];
$nxt = $pp[$px+1];
if ($this->$st = $mm("$st-$tr"))
break;
if (! ($this->$st = $mm("$st-$nxt")))
err("no pipe step $st -> $nxt");
}
}
public function request($uri, $ctx, $doBits=7){
$res = 0;
if ($doBits & 2) {
$res = $this->req->request($uri, $ctx);
# out("req got $res");
if (is_int($res))
return $res;
if (isset($this->httpChk) and $this->httpChk !== $this->req->httpRsp[0])
err("uri $uri bad status {$this->req->httpRsp[0]} expected $this->httpChk");
if (isset($this->json)) {
$res = json_decode($o=$res, $this->json);
if (('No error' !== $l = json_last_error_msg()) or ! $res)
err('json returns', gettype($res), ", err $l\njson", $res, "input $o");
}
}
if ( ! isset($this->walk))
return $res;
if ($doBits & 1) {
$this->walk->pathPre = $this->cloud->fPath ?? null;
if (isset($this->metaDo))
$this->rowWriter->single('meta', $this->meta);
}
return $doBits === 2 ? $this->walk->walk($res) : $this->walk->walkAll($res, doBits: $doBits);
}
} # end Class Pipeline
Class Net {
public const
OK = -1
, NOTFOUND = -2
, CD2TXT = [Net::OK => 'ok'
, Net::NOTFOUND => 'notFound'
]
, ERRFILTER = [ 'notFound' => ['notFound' => Net::NOTFOUND]]
, N2STR = -11
, N2JSONOBJ = -12
, N2JSONARR = -13
, N2XMLRDR = -14
;
public static $errFun, $errCode,$errRspH, $errXml, $errLast;
public static function errF($fun, $rspH = null) { # error filter: either fail with an error message or return an error result
Net::$errFun = $fun;
$r = Net::OK;
Net::$errCode = Net::$errXml = Net::$errLast = null;
if (Net::$errRspH = $rspH)
($rspH[0] === 'HTTP/1.1 404 Not Found') ? $r = Net::NOTFOUND : err("rspHdr $fun response $rspH[0]", $rspH);
if (Net::$errXml = libxml_get_last_error())
err("$fun xml", Net::$errXml, ', errors', libxml_get_errors());
if ((Net::$errLast = $e = error_get_last()) and $r === Net::OK)
str_ends_with($e['message'], 'Failed to open stream: No such file or directory') ? $r = Net::NOTFOUND : err("$fun", $e);
if ($r === Net::OK)
err("$fun failed, but no message found");
Net::errClear(true);
return Net::$errCode = $r;
}
public static function err($fun, $rspH = null) { # error filter: either fail with an error message or return an error result
err("$fun code " . ($c = Net::errF($fun, $rspH) . " " . Net::CD2TXT[$c]));
}
public static function errClear($silent=false) {
if ($e = error_get_last()) {
$silent or out("clearing error_get_last", $e);
error_clear_last();
}
if ($e = libxml_get_last_error()) {
$silent or out("clearing libxml_get_last_error", $e, ', errors', libxml_get_errors());
libxml_clear_errors();
}
libxml_use_internal_errors(true);
Net::$errFun = Net::$errCode = Net::$errRspH = Net::$errXml = Net::$errLast = null;
}
} #end Class Net
Class Net2Str extends Net {
public function request($uri, $ctx) {
Net::errClear();
if (! is_string($r = @ file_get_contents($uri, 0, $ctx)))
return Net::errF("get($uri)", $http_response_header);
$this->httpRsp = $http_response_header;
// echo "ff response\n" . print_r($http_response_header, true). "\n";
/* if ($r == '' or $http_response_header[0] != 'HTTP/1.1 207 Multi-Status')
err("$uri returned $http_response_header", $http_response_header);
echo "\nff result\n" . preg_replace_callback('=(<d:getlastmodified>)([^<>]*)(</d:getlastmodified>)='
, fn ($m) => $m[1] . $m[2] . ' => ' . toLocalTst($m[2]) . $m[3]
, xmlpp($r)) . "\n"; */
return $r;
}
}
Class Net2XMLReader extends Net {
public function request($uri, $ctx) {
Net::errClear();
# libxml_use_internal_errors(true); done in errClear
$ctx and libxml_set_streams_context($ctx);
$this->xr ??= new XMLReader;
if (!$this->xr->open($uri))
return Net::errF("open($uri)", $http_response_header);
$this->httpRsp = $http_response_header;
return $this->xr;
}
}
Class Req2SimpleXML {
public function webRequest($uri, $ctx, $cld) {
libxml_set_streams_context($ctx);
$xml = simplexml_load_file($uri,options: LIBXML_PEDANTIC);
var_dump($xml);
print_r($xml);
for ($xml->rewind(); $xml->valid(); $xml->next()) {
foreach($xml->getChildren() as $name => $data) {
echo "The $name is '$data' from the class " . get_class($data) . "\n";
}
}
foreach($xml->children() as $c) out("child $c", $c->getName());
out('getName', $xml->getName());
out('children', $xml->getChildren());
out('rsp getName', $xml->response[0]->getName());
out('rsp children', $xml->response->children());
return $xml;
$r = file_get_contents($uri, 0, $ctx);
// echo "ff response\n" . print_r($http_response_header, true). "\n";
if ($r == '' or $http_response_header[0] != 'HTTP/1.1 207 Multi-Status')
err("$uri returned $http_response_header", $http_response_header);
/* echo "\nff result\n" . preg_replace_callback('=(<d:getlastmodified>)([^<>]*)(</d:getlastmodified>)='
, fn ($m) => $m[1] . $m[2] . ' => ' . toLocalTst($m[2]) . $m[3]
, xmlpp($r)) . "\n"; */
return $r;
}
}
class RowOut {
private $rowC = 'rowC-construct';
public function begin ($id, $hdr = '') { # write header info for the following rows
$this->rowC = 0;
out("RowWriter $id begin", $hdr);
}
public function write($row) { # write one row
out("row $this->rowC", $row);
$this->rowC++;
}
public function end($id) { # end of the row sequence
out("RowWriter $id end, $this->rowC rows");
$this->rowC = 'rowC-end';
}
public function single ($id, $row) { # a sequence of a single row
out("RowWriter $id single", $row);
}
}
class RowTb {
private $rowC = 'rowC-construct';
public function begin ($id, $hdr = '') { # write header info for the following rows
$this->rowC = 0;
outH("tbh $id", __CLASS__);
outTb();
if ($hdr)
outTRH(...$hdr);
}
public function write($row) { # write one row
outTRD(...array_values($row));
$this->rowC++;
}
public function end($id) { # end of the row sequence
outTbEnd();
out("tbh $id end, $this->rowC rows", __CLASS__);
$this->rowC = 'rowC-end';
}
public function single ($id, $row) { # a sequence of a single row
$this->begin($id, array_keys($row));
$this->write($row);
$this->end($id);
}
}
class WalkTree extends Cloud /* implements Stringable */ {
public const SIBLING = 99;
/* build base config: trim $src,
indexes: 0 => by walk ix, 1 => by row key 2 => by wlkIx if rowkey='', 3 => default cloud fields, 4 => ignoreMiss, 5 src */
public $e2m, $allB, $allE, $rowH, $pathPre, $out;
public function __construct($cfg, $rw=null, $allB = false, $allE = false) {
if (is_object($cfg))
$cfg = ($this->ppl = $cfg)->cfg;
$this->e2m = $cfg['walk'];
$this->rowEmpty = $cfg['empty'];
$this->rowWriter = $rw;
$this->allB = $allB;
$this->allE = $allE;
}
function walkAll($src, $rw=null, $id=__CLASS__, $allB = null, $allE = null, $doBits=7) { # configure, begin the writer, walk and end the writer
if ($doBits & 1) {
$rw and $this->rowWriter = $rw;
$allB and $this->allB = $allB;
$allE and $this->allE = $allE;
$this->rowWriter->begin($id, array_keys($this->rowEmpty));
}
if ($doBits & 2)
$this->walk($src);
if ($doBits & 4)
return $this->rowWriter->end($id);
}
public function aText($mm, $tx) { $this->row[$mm[1]] = $tx; } # assign text unchanged into row
public function aTst($mm, $tx) { $this->row[$mm[1]] = toLocalTst($tx); } # assing timestamp converted to local timestamp
public function aDir($mm) { $this->row[$mm[1]] = CLOUD::DIR; } # assign directory constant
public function aType($mm, $tx) { $this->row[$mm[1]] = $this->typeMap[$tx] ?? $tx; } # assign the mapped mimeType
public function aPpl($mm, $tx) { # assing text to ppl
$k = $mm[0];
if (! is_object($this->ppl ?? null))
err("aPpl $k ppl missing or bad", $this->ppl ?? '') ;
elseif ($this->ppl->$k ?? false)
err("aPpl $k already set: {$this->ppl->$k}, new:", $tx) ;
else
$this->ppl->$k = $tx;
return self::SIBLING;
}
} # end class WalkTree
class WalkXML extends WalkTree {
public function __construct($cfg, $rowH=null, $allB = null, $allE = null) {
parent::__construct($cfg, $rowH, $allB, $allE);
}
public function __toString() {
$xr = $this->xr;
return '{' . __CLASS__ . "->xr $xr->nodeType: $xr->name}";
}
function walk($xr) { # walk the Tree by the XMLReader $xr
$this->nst = '';
($this->xr = $xr)->read() or $this->rChk();
$this->walkRec();
$xr->nodeType === XMLReader::NONE or err("not at end after walk $this");
}
public function rChk () {
static $fCnt = 0;
++$fCnt;
# out("rChk $fCnt $this, last", libxml_get_last_error(), ", errors", libxml_get_errors(), ', error_get_last', error_get_last());
if ($this->xr->nodeType !== XMLReader::NONE or libxml_get_last_error() or error_get_last())
Net::err("rChk");
($fCnt > 30) and Net::err("too many XML errs");
return false;
}
function walkRec() {
$nm = ($xr = $this->xr)->name;
$pn = $this->nst = "$this->nst/$nm";
$mm = $this->e2m[$nm] ?? null;
$r = $this->allB ? $this->{$this->allB}($mm) : (($mm[2] ?? false) ? $this->{$mm[2]}($mm) : null);
if ($xr->isEmptyElement)
return $xr->read() or $this->rChk();
elseif ($r === self::SIBLING)
return $xr->next();
$txt = '';
$xr->read() or $this->rChk();
while (XMLReader::END_ELEMENT !== $ty = $xr->nodeType) {
# out(" ty $this->nodeType name $this->name");
if ($ty === XMLReader::TEXT) {
$txt .= $xr->value;
$xr->read() or $this->rChk();
} elseif ($ty === XMLReader::ELEMENT) {
$this->walkRec();
$this->nst = $pn;
} else {
err("unsported xml node", $this);
}
}
$this->allE ? $this->{$this->allE}($mm, $txt) : (($mm[3] ?? false) ? $this->{$mm[3]}($mm, $txt) : null);
if ($nm === $xr->name)
return $xr->read() or $this->rChk();
err("end $pn expected but $this");
}
public function outB($mm) {
$xr = $this->xr;
out(($xr->isEmptyElement ? 'emp' : 'beg') ." $this->nst mm", $mm);
for($i=0; $xr->moveToNextAttribute();$i++)
out(" att $i: $xr->name => $xr->value");
if ($mm[2] ?? false) {
if (($r = $this->{$mm[2]}($mm)) === self::SIBLING and ! $xr->isEmptyElement)
out("nxt $this->nst skipping to next node");
return $r;
}
}
public function outE($mm, $txt) {
out("end $this->nst, txt=$txt");
if ($mm[3] ?? false)
return $this->{$mm[3]}($mm, $txt);
}
public function responseB($mm) {
$this->row = $this->rowEmpty;
$this->propC = $this->propS = -1;
}
public function responseE($mm) {
($this->propC === $this->propS) or err(__METHOD__ . "#prop $this->propC !== #status $this->propS");
$this->rowWriter->write($this->row);
unset($this->row, $this->propC);
}
public function hrefE($mm, $tx) {
$pa = rawurldecode($tx);
$this->row[$mm[1]] = ! str_starts_with($pa, $this->pathPre) ? "???$pa"
: (strlen($pa) > strlen($this->pathPre) ? substr($pa, strlen($this->pathPre)) : "./");
}
public function propB($mm) {
($this->propC === $this->propS) or err(__METHOD__ . " #prop $this->propC !== #status $this->propS");
$c = ++$this->propC;
return $c ? self::SIBLING : null;
}
public function statusE($mm, $tx) {
($this->propC !== $this->propS-1) or err(__METHOD__ . "#prop $this->propC !== -1 + #status $this->propS");
$c = ++$this->propS;
$c === 0 and $tx === 'HTTP/1.1 200 OK' or $c === 1 and $tx === 'HTTP/1.1 404 Not Found' or err("after $pn #$c bad status $tx");
}
} # end class WalkXML
class WalkJson extends WalkTree {
public function __construct($cfg, $rowH=null, $allB = null, $allE = null) {
parent::__construct($cfg, $rowH, $allB, $allE);
}
public function __toString() {
$xr = $this->xr;
return '{' . __CLASS__ . "->xr $xr->nodeType: $xr->name}";
}
function walk($js) { # walk the Tree of the json $js
$this->nst = '';
$this->walkRec($js);
}
function walkRec($js) {
$pa = $this->nst;
if (! is_array($js)) {
err("walkRec not an array at $pa, js", $js);
} elseif (array_is_list($js)) {
foreach ($js as $w => $c) {
$this->nst = "$pa/$w";
$this->walkRec($c);
}
} else {
$this->row = $this->rowEmpty;
foreach ($js as $w => $c) {
$mm = $this->e2m[$w] ?? null;
$this->nst = $pc = "$pa/$w";
$r = isset($this->allB) ? $this->{$this->allB}($mm, $c) : (($mm[2] ?? false) ? $this->{$mm[2]}($mm, $c) : 0);
if ($r !== self::SIBLING and is_array($c)) {
$this->nst = $pc;
$this->walkRec($c);
$this->nst = $pc;
$r = isset($this->allE) ? $this->{$this->allE}($mm, $c) : (($mm[3] ?? false) ? $this->{$mm[3]}($mm, $c) : 0);
}
}
$this->row and $this->rowWriter->write($this->row);
$this->row = false;
}
}
public function outB($mm, $js) {
is_array($js) ? out("beg $this->nst", $mm) : out("b-e $this->nst", $js, $mm);
if ($mm[2] ?? false)
return $this->{$mm[2]}($mm, $js);
}
public function outE($mm, $js) {
if ($mm[3] ?? false)
return $this->{$mm[3]}($mm, $js);
out("end $this->nst", $js);
}
public function parentB($mm, $js) {
$this->row[$mm[1]] = $js[0];
return self::SIBLING;
}
public function ownerB($mm, $js) {
$this->row[$mm[1]] = $js[0]['emailAddress'];
return self::SIBLING;
}
} # end class WalkJson
/* ------------------
require_once 'cloud.php';
if (0) {
$s = new Net2Str;
$o = (object) ['net' => $s, 'errFltr' => Net::ERRFILTER['notFound']];
out('txt', $s->request('../www/inf/php/aa.txt', opt: $o), 'hdr', $s->hdr, 'body', $s->body);
out('txt', $s->request('https://localhost/home/inf/php/aa.txt', opt: $o), "\nhdr", $s->hdr, "\nbody", $s->body);
} elseif (0) {
$x = new Net2XMLReader;
$o = (object) ['net' => $x, 'errFltr' => Net::ERRFILTER['notFound']];
out('txt', $r = $x->request('o.xml', opt: $o), 'hdr', $x->hdr); # '../www/inf/php/a.txt'
for ($i=0; ($r->read() or Net::errF('xml read')) and $i <10; $i++)
out("$i $r->nodeType $r->name depth $r->depth");
} elseif (0) {
out("notF", Net::NOTFOUND, Net::CD2TXT[Net::NOTFOUND]);
} else {
$f = new CloudFactory;
$cc = $f->make('wlklNC');
$o = (object) ['net' => new Net2XMLReader, 'errFltr' => Net::ERRFILTER['notFound']
, 'walk' => new WalkXML(WalkTree::$cfg['all'], 'outB', 'outE')];
out($cc->ffReq('nf', $o)); #new Req2Str);
outH('reuse xr');
out($cc->ffReq('Documents', $xr)); #new Req2Str);
#out('get', $cc->getHTTP('1OI9ebyLj9r6LsfFlEq9x8JdFWfEgT2Jq6ofUI4IW1PQ'));
}
exit(outEnd());
if (0) {
$x = new MyXml(MyXml::$cfg['all'], 'outB', 'outE');
$x->open('o.xml');
if (0) {
for ($i=0; $x->read() and $i <100; $i++)
out("$i $x $x->localName depth $x->depth, uri $x->baseURI");
exit();
}
$x->read();
$x->walk();
exit(outEnd());
}
$myXMLData =
"<?xml version='1.0' encoding='UTF-8'?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>";
$xml=simplexml_load_string($myXMLData) or die("Error: Cannot create object");
print_r($xml);
libxml_use_internal_errors(true);
$xml=simplexml_load_file('o.xml',options: LIBXML_PEDANTIC | LIBXML_NONET);
if (! $xml) {
err('xml error', libxml_get_errors());
} else {
print_r($xml);
out('---all', $xml);
out('title', $xml->title);
out('href', (string)$xml->{'d:response'}->{'d:href'});
}
exit();
$cc->ff('', fn ($n) => outTRD(...$n)
, fn($m) => [out(']]tbh meta'), outTb(), outTRH(...$m[0]), outTRD(...$m[1]), outTbEnd(), out(']]tbh ffid'), outTb(), outTRH(...$m[2])]);
outTbEnd();
out("$cc->ffFo folders, $cc->ffFi files, " . sprintf('%7.2e', $cc->ffSz) . ' Bytes (file) at ' . toLocalTst('now'));
$e = fopen('php://temp', 'w+');
$o = fn ($n) => fputcsv($e, $n);
$cc->ff('', $o
, fn($m) => [$o([']]tbh meta']), $o($m[0]), $o($m[1]), $o([']]tbh ffid']), $o($m[2])]);
out("$one $cc->ffFo folders, $cc->ffFi files, " . sprintf('%7.2e', $cc->ffSz) . ' Bytes (file) at ' . toLocalTst('now'));
$sz = ftell($e);
rewind($e);
out("$one writing $sz bytes to $one:ffid-$one.csv, at " . toLocalTst('now'));
$cc->upload("ffid-$one.csv" ,'text/csv', $sz < 1 ? '' : fread($e, $sz));
fclose($e);
outEnd();
exit();
------------ */