GithubHelp home page GithubHelp logo

domin's Introduction

Domin Build Status Scrutinizer Code Quality

domin ( domain model interface ) is an administration interface for abstract Domain Models using the Command Object pattern.

For an example of how to use use, check out the sample application.

Model

Every ability of a system is represented by an Action which specifies how to execute it and what Parameters it requires. Therefore domin can take care of getting missing parameters from the user using Fields. Actions may return values which are presented using Renderers.

Installation

To use domin in your project, require it with Composer

composer require rtens/domin

If you would like to develop on domin, download it with Composer and execute the specification with scrut

composer create-project -sdev rtens/domin
cd domin
vendor/bin/scrut spec

Quick Start

To run domin as a web application with curir as delivery system, paste the following code into index.php

use rtens\domin\delivery\web\adapters\curir\root\IndexResource;
use rtens\domin\delivery\web\WebApplication;
use watoki\curir\WebDelivery;

WebDelivery::quickResponse(IndexResource::class,
    WebDelivery::init(null,
        WebApplication::init(function (WebApplication $app) {
            // Set-up $app here (e.g. $app->actions->add('foo', ...))
        })));

To run domin with silex, past this code into index.php

use rtens\domin\delivery\web\adapters\silex\SilexControllerProvider;
use rtens\domin\delivery\web\WebApplication;
use Silex\Application;

require_once __DIR__ . '/vendor/autoload.php';

$app = new Application();
$app->mount('/', new SilexControllerProvider(
    WebApplication::init(function (WebApplication $app) {
        // Set-up $app here (e.g. $app->actions->add('foo', ...))
    })));
$app->run();

And then start a development server to access the application on localhost:8000

$ php -S localhost:8000 index.php

To get the CLI application running, paste this code into cli.php

use rtens\domin\delivery\cli\CliApplication;

CliApplication::run(CliApplication::init(function (CliApplication $app) {
    // Set-up $app here (e.g. $app->actions->add('foo', ...))
}));

and run it with

$ php cli.php

Action!

Actions decide what Parameters they need, how to fill() them with default values and, most importantly, how to execute() them. The way domin knows what actions there are is through the ActionRegistry, so all actions need to be added to it.

There are several ways to create actions:

Implementing Action

The most straight-forward although probably not most convenient way is to create an implementation of Action for every ability of the system.

class MyAction implements Action {

    public function caption() {
        return 'Some Action';
    }

    public function description() {
        return 'Some Description';
    }

    public function parameters() {
        return [
            new Parameter('foo', new StringType()),
            new Parameter('bar', new ClassType(\DateTime::class))
        ];
    }

    public function fill(array $parameters) {
        $parameters['foo'] = 'default value of foo';
        return $parameters;
    }

    public function execute(array $parameters) {
        return "Make it so! " . json_encode($parameters);
    }
}

$actionRegistry->add('my', new MyAction());

Extending ObjectAction

If you represent abilities with DTOs, you can extend you actions from the ObjectAction to infer Parameters from the properties of these classes using reflection. This sub-class can then be made generic for example by using a Command Bus.

class MyAction extends ObjectAction {
    
    public function __construct($class, TypeFactory $types, CommandBus $bus) {
        parent::__construct($class, $types);
        $this->bus = $bus;
    }

    protected function executeWith($object) {
        $this->bus->handle($object);
    }
}

$actionRegistry->add('my', new MyAction(MyCommand::class, $types, $bus));
$actionRegistry->add('your', new MyAction(YourCommand::class, $types, $bus));
$actionRegistry->add('their', new MyAction(TheirCommand::class, $types, $bus));

Generating ObjectActions

With a generic way to execute actions, you can use the ObjectActionGenerator to generate and register actions from all classes in a folder automatically.

(new ObjectActionGenerator($actionRegistry, $typeFactory))->fromFolder('model/commands', function ($object) {
    $bus->handle($object);
});

Using MethodAction

If you don't feel like creating a class for every command, you can use the MethodAction to infer parameters from a method signature.

$actionRegistry->add('my', new MethodAction($handler, 'handleMyCommand', $typeFactory));
$actionRegistry->add('your', new MethodAction($handler, 'handleYourCommand', $typeFactory));
$actionRegistry->add('their', new MethodAction($handler, 'handleTheirCommand', $typeFactory));

Generating MethodActions

There is also a MethodActionGenerator to register all methods of an object.

(new MethodActionGenerator($actionRegistry, $typeFactory))->fromObject($handler);

License

domin is released under the MIT License

domin's People

Contributors

rtens avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

jonfm muktitcc

domin's Issues

Revise breadcrumbs

They shouldn't be per-session (ie cookie) but instead per-window, meaning that it needs to be stored in the page itself. Also, it shouldn't reset when the user visits the action list.

Decouple field from property

It should be possible to use a certain field for a property, regardless of it's actual type. Converting will be necessary and probably has to be done by hand.

For example "string" could yield a StringField, a TextField or an HtmlField.

Required HTML

Required HTML field should show warning if empty on submit

Protect against CSRF

To protect against cross-site request forging, requests should be verified using synchronized tokens. This could also be used in links to enable execution if modifying actions through GET requests.

Action list as action

The action list itself should be an action that is by default registered under a specific identifier like "index" which is set as default action. It should be able to change the default action as well as set a new action with the "index" identifier.

The action returns an ActionList object that has its own renderer.

The routing will have to be changed for each web adapter.

Separate domain from ui

At the moment, you have to use domin types to change the controls. There should be a way to configure actions. For example by mapping the parameters both ways.

CLI output to file

Add an option in the interactive mode to write the output to a file instead of printing it

$ php foo.php ! --out my_file.txt

Output written to [my_file.txt]

Application programming interface

There should be a way to execute action through an API. Input and output is structured data which can be represented in any way (JSON, XML, ...). The application requires its own set of fields and renderers and should also generate documentation (which could be acessed with the OPTIONS method)

Modularize action form

Instead of having the form template hard-coded, it should be rendered by a replaceable object, like a form renderer. ObjectField actually already does most of what's needed.

Handle GET and POST requests separately

Currently it doesn't matter if an action is executed with GET or POST. The idea would be to mark actions as "modifying" and only allow non-modifying actions to be exectued with GET. If a modifying action is accessed with GET, the form is displayed but the action not executed, even if no fields are missing.

The form could then even contain an "execution token" that verifies the request.

Access control

A simple module that would decide for each execution of an action if the execution is permitted. There should also be a way to define how the user can acquire the permission. For example by providing a URL to be redirected to.

The access control should have no notion of "logged-in", only of "permission denied/granted"

Proper URL serialization

At the moment, URLs are serialized manually at a couple of places without support for array parameters. Instead, there should be a URL builder like on curir.

CLI field for string or file

A new Field that allows the input to either be a string or, if prefixed by '@', the input is read from a file.

Log errors

Exceptions during action execution should be logged besides or instead showing them to the user.

The default logger implementation could print the error to stderr but a monolog implementation should be available.

Project name

Make app have a project name which appears in menu and page titles

Range field

Support number ranges with slider controls

Move options to charts

The options of each chart are currently stored in the ChartRenderer but instead it should be part of the Chart itself so it can be overridden without creating a new renderer.

Default action

Instead of showing the action index, it should be possible to configure domin to execute a certain action by default.

Quotes in values

If a value contains double quotes ("), they need to be escaped when the field is rendered.

More space in CLI

In the interactive CLI, put a space between parameter and value and a new line before the output.

Make domin delivery-system independent

At the moment, domin is highly coupled with curir as a delivery system. Instead, it should be independent of such system and adapters should allow to use almost any and exchange them easily.

Group actions

Actions should be put into collapsed groups on the index page.

Required List

A required list should show a warning if empty on submit

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.