Document toolboxDocument toolbox

Microbizz Script (technical)

This page describes the technical details in handling the script language that is built into Microbizz. See the End user documentation for details about the script syntax and functions.

Limitations

There is a functionality that has to be enabled by Ventu.

The supported object modcodes are listed in CustomField::$support_scripts[].

Classes

Parser

This class evaluates an expression and returns the result. The expression may return a numeric result, or a string, or something else.

Examples: "1+2+3", eller "toupper(this.customer.customername)".

The class is described in details here.

Record2Parser

This class is used to evaluated expressions in the context of a Record2 object. The class provides various functions for the Parser class, and creates a variable "this", which the expression/script can use to access the Record2 object. This variable is implemented by a Record2ParserObject object.

It can either use the Record2 field names, or the fields names in the corresponding ApiBridge class. Record2 field names are used when evaluating custom field expressions ("old syntax"), whereas ApiBridge field names are used when executing scripts (plugins, tabs and custom fields ("new syntax)).

Record2ParserObject

This class is used to describe a Record2 object (e.g. Todo) so that the Parser class can understand it. Record2ParserObject thus allows the parser to access fields in the Record2 object; it can either use the Record2 field names, or the fields names in the corresponding ApiBridge class.

Record2ParserObject is typically used to implement the variable "this".

There are derived classes for Todo, Customer, Tool etc., f.ex. Record2ParserTodo which provides additional funtionality like "this.customer" and "this.user".

Record2ParserObject::$supported_objects lists the Record2 objects that may be accessed. For each Record2 object there should be a Record2ParserXXXX class; only objects that are also supported by ApiBridge and CustomField should be included.

Record2Script

This stores scripts in the DB.

When attaching a script to a plugin event (or "hook"), the plugin entrypoint is saved with a URL of the format script://ID, the ID refers to the ID of a Record2Script.

Script

The Script class executes a script; it is closely tied to the Parser class.

Typical use without the additional complexity of Record2 objects:

$code = <<<EOF
a = 123
return a - 23
EOF;
$script = new Script();
$cfg = [ 'cb_variable' => "Script::parserVars", 'cb_variable_arg' => $script, 'isscript' => true];
$parser = new Parser($cfg);
$script->setParser($parser);
$script->loadString($code);
$script->run();
print_r($script->script_returnvalue);

ScriptEditor

The ScriptEditor class implements an editor for scripts. Currently this is based on codemirror.js. See also FScripteditor.

This should be used wherever you need to edit scripts. A Tab will be converted to two spaces.

Custom field

There are 3 types of custom fields that use the parser: expression fields (using Record2 field names), new syntax expression fields (using ApiBridge field names), and script fields.

Not all Record2 objects that support customfields also support script custom fields, or the new syntax expression custom fields. Those that support script custom fields are listed in CustomField::$support_scripts[], those that support the new syntax are listed in Record2ParserObject::$supported_objects[].

Plugin events

It is possible to run a script a plugin event occurs, see Making a Microbizz app for details about events. In this case the script engine will make different functions available to the script, compared to when the script is run as part of a custom field, as these situations have different requirements. F.ex. plugins need to be able to call other APIs, and custom fields need to be able to output simple HTML.

Plugin tab

It is possible to run a script in a tab. 

Using a script to update values

Assume that you want to use a script to update some values, f.ex. update question form answers before saving the answers.

// setup the values that you want to the script to be able to update 
$answers = ['3' => 'John', '4' => 7];
$answers = Parser::fromAssocArray($answers);
// load the script that you want to run, this is just a dummy example
$code = 'answers["3"] = "Paul"';
// setup the script and parser
$script = new Script();
$cfg = [ 'cb_variable' => "Script::parserVars", 'cb_variable_arg' => $script, 'isscript' => true];
$parser = new Parser($cfg);
$script->setParser($parser);
$script->loadString($code);
 // make the answers available from within the script
$script->registerVariable('answers', $answers);
 // prevent the stack from being cleared at the end, otherwise the variables would disappear
$script->run(['keep_stack' => true]);
// retrieve the updated answers 
$new_answers = $script->readVar('answers');


Extending the parser/script with new functions

Patches may be used to extend the functionality of the script / parser, to add functionality for a single customer.

The patch point is named "parserextension", see the class PatchHBP for an example. The patch point is called after the "this" object has been created.

Examples of what a patch  can do:

  • provide global objects, which may provide new functions (use $parser→registerGlobalObject())
  • extend existing global objects with new functions (use $parser→addPropertyToObject())
  • provide new functions (use $parser→registerFunction())
  • extend the prototype for strings, numbers, arrays and dicts (use $parser->addPropertyToPrototype())

See the class PatchHBP for an example.

Debugging

Set Record2Script::$DEBUG to true to enable a lot of logging to the screen.

See also

Udtryksevaluering tillægsfelt

End user documentation