blackprint/engine

PHP Engine for Blackprint

0.9.0 2023-06-23 19:41 UTC

This package is auto-updated.

Last update: 2024-10-23 22:54:39 UTC


README

Blackprint

Blackprint Engine for PHP

Run exported Blackprint on PHP environment.

Documentation

Warning: This project haven't reach it stable version (semantic versioning at v1.0.0)
But please try to use it and help improve this project

This engine is designed to be similar with engine-js, some API and property will be similar.

Minimum PHP version >= 8.1

Defining Blackprint Node and Interface

Because PHP does support class-based programming and to make the node import more effective and easier, this engine will only support Node/Interface that declared with classes.

But before that, we need to create a folder to store our Node/Interface logic. For the example /BPNode.

Registering Namespace folder

require_once('../vendor/autoload.php');

// This can be called on different PHP libraries
\Blackprint\registerNamespace(__DIR__.'/BPNode');

// When registering with Namespace, the default root namespace is always "BPNode"
// Please name your nodes namespace along with your library name to avoid conflict with other library

Define Node and Interface

After the namespace folder ./BPNode has been registered, you can now create a folder with your library name. For the example: ./BPNode/Example.

// file: ./BPNode/Example/Hello.php
namespace \BPNode\Example;

// The class name must match with the file name
// This will be registered as Node definition
class Hello extends \Blackprint\Node {
    // Please remember to capitalize the port name
    // Set the output port structure for your node (Optional)
    static $output = [
        'Changed'=> Types::Trigger,
        // Callable: $this->output['Changed']()

        'Output'=> Types::Number,
        // $this->output['Value'] = 246
    ];

    // Set the input port structure for your node (Optional)
    static $input = [
        'Multiply'=> Types::Number,
        // $val = $this->output['Value']
    ]

    function __construct($instance){
        // Call the parent constructor first, passing the $instance (Blackprint\Engine)
        parent::__construct($instance);

        // Set the Interface, let it empty if you want
        // to use default empty interface "setInterface()"
        $iface = $this->setInterface('BPIC/Example/Hello');
        $iface->title = "Hello"; // Set the title for debugging
    }
}

Let's also define our custom interface, this is optional and needed only if you want to provide access for other developer. Just like an API (Application Programming Interface).

// same file: ./BPNode/Example/Hello.php
namespace \BPNode\Example;

// Your Interface namespace must use "BPIC" as the prefix
\Blackprint\registerInterface('BPIC/Example/Hello', HelloIFace::class);
class HelloIFace extends \Blackprint\Interfaces {
    function __construct($node){
        // Call the parent constructor first, passing the $node (Blackprint\Node)
        parent::__construct($node);
        // $this->node => Blackprint\Node

        // Define IFace's data (optional if you want to export/import data from JSON)
        // Because getter/setter feature only available on class, we will create from `class MyData`
        $this->data = new MyData($this);
        // $this->data->value === 123 (if the default value is not replaced when importing JSON)
    }

    function recalculate(){
        // Get value from input port
        $multiplyBy = $this->node->input['Multiply'];

        // Assign new value to output port
        $this->node->output['Output'] = $this->data->value * $multiplyBy;
    }
}

// Getter and setter should be changed with basic property accessor
class MyData {
    // Constructor promotion, $iface as private MyData property
    function __construct(private $iface){}

    // Draft: please design it like below after
    // this PR was merged to PHP https://github.com/php/php-src/pull/6873
    private $_value = 123;
    public $value {
        get { return $this->_value };
        set {
            $this->_value = $value;
            $this->iface->recalculate(); // Call recalculate() on HelloIFace
        };
    };

    // Current polyfill for property accessor (https://github.com/php/php-src/pull/6873)
    private $data = ["value"=> 123];
    function __get($key) {
        return $this->data[$key];
    }

    function __set($key, $val) {
        $this->data[$key] = &$val;

        if($key === 'value')
            $this->iface->recalculate($val); // Call recalculate() on HelloIFace
    }
}

Creating new Engine instance

// Create Blackprint Engine instance
$instance = new Blackprint\Engine();

// You can import nodes with JSON
// if the nodes haven't been registered, this will throw an error
$instance->importJSON(`{...}`);

// You can also create the node dynamically
$iface = $instance->createNode('Example/Hello', /* [..options..] */);

// ----

// Change the default data 'value' property
$iface->data->value = 123;

// Assign the 'Multiply' input port = 2
$iface->node->input['Multiply'] = 2;

// Get the value from 'Output' output port
echo $iface->node->output['Output']; // 246

Example

wKKLQb1Y0D

This repository provide an example with the JSON too, and you can try it with PHP CLI:

# Change your working directory into empty folder first
$ git clone --depth 1 https://github.com/Blackprint/engine-php .
$ composer install
$ php ./example/init.php