Initial status page
This commit is contained in:
parent
a3511b1bfc
commit
a1f35b97d3
17 changed files with 618 additions and 83 deletions
|
|
@ -1,17 +1,33 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* This script will list all the URIs that this system is aware of.
|
||||
* This works by listing all the default graph uris of all the adapters.
|
||||
*/
|
||||
|
||||
use Drupal\wisski_pathbuilder\Entity\WisskiPathEntity;
|
||||
|
||||
// load all the pathbuilders
|
||||
$pbs = \Drupal::entityTypeManager()->getStorage('wisski_pathbuilder')->loadMultiple();
|
||||
/** all_xml lists all pathbuilders, and returns the corresponding xml */
|
||||
function all_xml(): object {
|
||||
$all = \Drupal::entityTypeManager()->getStorage('wisski_pathbuilder')->loadMultiple();
|
||||
return (object)array_map("entity_to_xml", $all);
|
||||
}
|
||||
|
||||
// map over the pathbuilders
|
||||
$xmls = array_map(function($pb) {
|
||||
|
||||
/** all_list lists the ids of all pathbuilders */
|
||||
function all_list(): Array {
|
||||
return array_keys(\Drupal::entityQuery('wisski_pathbuilder')->execute());
|
||||
}
|
||||
|
||||
/** one_xml serializes a single pathbuilder as xml */
|
||||
function one_xml(string $id): string {
|
||||
$pb = \Drupal::entityTypeManager()->getStorage('wisski_pathbuilder')->load($id);
|
||||
if ($pb === NULL) {
|
||||
return "";
|
||||
}
|
||||
return entity_to_xml($pb);
|
||||
}
|
||||
|
||||
// =================================================================================
|
||||
// =================================================================================
|
||||
|
||||
|
||||
function entity_to_xml($pb) {
|
||||
$xml = new \SimpleXMLElement("<pathbuilderinterface></pathbuilderinterface>");
|
||||
|
||||
$paths = $pb->getAllPaths();
|
||||
|
|
@ -58,6 +74,4 @@ $xmls = array_map(function($pb) {
|
|||
$dom = dom_import_simplexml($xml)->ownerDocument;
|
||||
$dom->formatOutput = TRUE;
|
||||
return $dom->saveXML();
|
||||
}, $pbs);
|
||||
|
||||
echo json_encode($xmls);
|
||||
}
|
||||
|
|
@ -1,34 +1,45 @@
|
|||
package instances
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
_ "embed"
|
||||
|
||||
"github.com/tkw1536/goprogram/stream"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
var errPathbuildersExecFailed = errors.New("ExportPathbuilders: Failed to call export_pathbuilder")
|
||||
//go:embed php/export_pathbuilder.php
|
||||
var exportPathbuilderPHP string
|
||||
|
||||
// Pathbuilders returns the ids of all pathbuilders in consistent order.
|
||||
func (wisski *WissKI) Pathbuilders() (ids []string, err error) {
|
||||
err = wisski.ExecPHPScript(stream.FromNil(), &ids, exportPathbuilderPHP, "all_list")
|
||||
slices.Sort(ids)
|
||||
return
|
||||
}
|
||||
|
||||
// Pathbuilder returns a single pathbuilder as xml.
|
||||
// If it does not exist, it returns the empty string and nil error.
|
||||
func (wisski *WissKI) Pathbuilder(id string) (xml string, err error) {
|
||||
err = wisski.ExecPHPScript(stream.FromNil(), &xml, exportPathbuilderPHP, "one_xml", id)
|
||||
return
|
||||
}
|
||||
|
||||
// AllPathbuilders returns all pathbuilders serialized as xml
|
||||
func (wisski *WissKI) AllPathbuilders() (pathbuilders map[string]string, err error) {
|
||||
err = wisski.ExecPHPScript(stream.FromNil(), &pathbuilders, exportPathbuilderPHP, "all_xml")
|
||||
return
|
||||
}
|
||||
|
||||
// ExportPathbuilders writes pathbuilders into the directory dest
|
||||
func (wisski *WissKI) ExportPathbuilders(dest string) error {
|
||||
// export all the pathbuilders into the buffer
|
||||
var buffer bytes.Buffer
|
||||
wu := stream.NewIOStream(&buffer, nil, nil, 0)
|
||||
code, err := wisski.Barrel().Exec(wu, "barrel", "/bin/bash", "/user_shell.sh", "-c", "drush php:script /wisskiutils/export_pathbuilder.php")
|
||||
if err != nil || code != 0 {
|
||||
return errPathbuildersExecFailed
|
||||
}
|
||||
|
||||
// decode them as a json array
|
||||
var pathbuilders map[string]string
|
||||
if err := json.NewDecoder(&buffer).Decode(&pathbuilders); err != nil {
|
||||
pathbuilders, err := wisski.AllPathbuilders()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,11 +13,12 @@ var ErrExecInvalidCode = errors.New("invalid code to execute")
|
|||
var ErrExecNonZero = errors.New("script returned non-zero code")
|
||||
|
||||
// ExecPHPScript executes the PHP code as a script within the wisski instance.
|
||||
// The script should define a function "main", and may define additional functions.
|
||||
// The script should define a function called entrypoint, and may define additional functions.
|
||||
//
|
||||
// Code must start with "<?php" and may not contain a closing tag.
|
||||
// Code is expected not to mess with PHPs output buffer.
|
||||
// Code should not contain user input.
|
||||
// Code breaking these conventions may or may not result in an error.
|
||||
//
|
||||
// It's arguments are encoded as json using [json.Marshal] and decoded within php.
|
||||
//
|
||||
|
|
@ -25,10 +26,10 @@ var ErrExecNonZero = errors.New("script returned non-zero code")
|
|||
//
|
||||
// Standard input and output streams should not be used.
|
||||
// Standard error is redirected to io.
|
||||
func (wisski *WissKI) ExecPHPScript(io stream.IOStream, code string, args ...any) (any, error) {
|
||||
func (wisski *WissKI) ExecPHPScript(io stream.IOStream, result any, code string, entrypoint string, args ...any) error {
|
||||
// make sure the beginning is right
|
||||
if !strings.HasPrefix(code, "<?php") {
|
||||
return nil, ErrExecInvalidCode
|
||||
return ErrExecInvalidCode
|
||||
}
|
||||
|
||||
// make sure that args is not nil, but an array of length 0!
|
||||
|
|
@ -36,15 +37,20 @@ func (wisski *WissKI) ExecPHPScript(io stream.IOStream, code string, args ...any
|
|||
args = []any{}
|
||||
}
|
||||
|
||||
// encode code and args!
|
||||
// encode code, args and entrypoint!
|
||||
codeEscape, err := marshalPHP("?>" + code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
entrypointEscape, err := marshalPHP(entrypoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
argsEscape, err := marshalPHP(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// assemble the script
|
||||
|
|
@ -55,7 +61,7 @@ func (wisski *WissKI) ExecPHPScript(io stream.IOStream, code string, args ...any
|
|||
|
||||
call_user_func(function(){
|
||||
ob_start(null, 0, PHP_OUTPUT_HANDLER_CLEANABLE);
|
||||
$result = call_user_func_array("main", ` + argsEscape + `);
|
||||
$result = call_user_func_array(` + entrypointEscape + `, ` + argsEscape + `);
|
||||
ob_end_clean();
|
||||
echo json_encode($result);
|
||||
});
|
||||
|
|
@ -65,22 +71,19 @@ func (wisski *WissKI) ExecPHPScript(io stream.IOStream, code string, args ...any
|
|||
var output bytes.Buffer
|
||||
res, err := wisski.Shell(io.Streams(&output, nil, strings.NewReader(script), 0), "-c", "drush php:script -")
|
||||
if res != 0 {
|
||||
return nil, ErrExecNonZero
|
||||
return ErrExecNonZero
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// did not request to receive a result
|
||||
if result == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// decode the output
|
||||
var result any
|
||||
err = json.NewDecoder(&output).Decode(&result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// EvalPHP is similar to ExecPHPScript, except that it evaluates a single line of php.
|
||||
// A single parameter may be passed, which can be accessed using the name $arg inside the expression.
|
||||
func (wisski *WissKI) EvalPHP(expr string, arg any) (any, error) {
|
||||
return wisski.ExecPHPScript(stream.FromEnv(), "function main($arg){return "+expr+";}", arg)
|
||||
return json.NewDecoder(&output).Decode(result)
|
||||
}
|
||||
|
||||
const marshalRune = 'F' // press to pay respect
|
||||
|
|
|
|||
|
|
@ -8,25 +8,36 @@ import (
|
|||
// Info represents some info about this WissKI
|
||||
type Info struct {
|
||||
Slug string // The slug of the instance
|
||||
URL string // The public URL of this instance
|
||||
|
||||
Running bool // is the instance running?
|
||||
|
||||
DrupalVersion interface{} // version of drupal being used
|
||||
Running bool // is the instance running?
|
||||
Pathbuilders []string // list of pathbuilders
|
||||
}
|
||||
|
||||
// Info returns information about this WissKI instance.
|
||||
func (wisski *WissKI) Info() (info Info, err error) {
|
||||
func (wisski *WissKI) Info(quick bool) (info Info, err error) {
|
||||
// static properties
|
||||
info.Slug = wisski.Slug
|
||||
info.URL = wisski.URL().String()
|
||||
|
||||
// dynamic properties, TODO: Add more properties here!
|
||||
var group errgroup.Group
|
||||
|
||||
// quick check if this wisski is running
|
||||
group.Go(func() (err error) {
|
||||
info.Running, err = wisski.Alive()
|
||||
return
|
||||
})
|
||||
|
||||
// slower checks for extra properties.
|
||||
// these execute php code
|
||||
if !quick {
|
||||
group.Go(func() (err error) {
|
||||
info.Pathbuilders, err = wisski.Pathbuilders()
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
err = group.Wait()
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue