A Simple PHP Finite State Machine

Related tags

Architectural Finite
Overview

Finite, A Simple PHP Finite State Machine

Finite is a Simple State Machine, written in PHP. It can manage any Stateful object by defining states and transitions between these states.

Build Status Latest Stable Version Total Downloads License Scrutinizer Code Quality Code Coverage SensioLabsInsight Dependency Status Reference Status Gitter

Features

  • Managing State/Transition graph for an object
  • Defining and retrieving properties for states
  • Event Listenable transitions
  • Symfony2 integration
  • Custom state graph loaders
  • Twig Extension

Documentation

Documentation for master (1.1)

Getting started

Installation (via composer)

{
      "require": {
        "yohang/finite": "~1.1"
    }
}

Version note :

If your are using this library in a Symfony project, 1.1 version is only compatible with Symfony >=2.6. 1.0 is compatible with Symfony >=2.3, <2.6.

Define your Stateful Object

Your stateful object just need to implement the StatefulInterface Interface.

use Finite\StatefulInterface;

class Document implements StatefulInterface
{
        private $state;
        public function setFiniteState($state)
        {
                $this->state = $state;
        }

        public function getFiniteState()
        {
            return $this->state;
        }
}

Initializing a simple StateMachine

use Finite\StateMachine\StateMachine;
use Finite\State\State;
use Finite\State\StateInterface;

// $document = retrieve your stateful object

$sm = new StateMachine();

// Define states
$sm->addState(new State('s1', StateInterface::TYPE_INITIAL));
$sm->addState('s2');
$sm->addState('s3');
$sm->addState(new State('s4', StateInterface::TYPE_FINAL));

// Define transitions
$sm->addTransition('t12', 's1', 's2');
$sm->addTransition('t23', 's2', 's3');
$sm->addTransition('t34', 's3', 's4');
$sm->addTransition('t42', 's4', 's2');

// Initialize
$sm->setObject($document);
$sm->initialize();

// Retrieve current state
$sm->getCurrentState();

// Can we process a transition ?
$sm->can('t34');
Comments
  • Split standalone component and Symfony bundle

    Split standalone component and Symfony bundle

    First, really nice project, i love it !

    Is it possible to split Finite as standalone component without the symfony stack inside ? and add the symfony bundle on top ?

    Currently on non symfony project (like silex or cilex) it's a bit frustrating to see a bundle folder appear :D

    Is it plan ?

    opened by jjsaunier 18
  • Add a callback to cascade transitions

    Add a callback to cascade transitions

    Hi,

    This PR adds 2 useful things:

    1. The ability to pass arguments to callbacks. Currently, we are limited to the arguments $object and $transitionEvent. With this PR you can define arguments to pass to your callback directly from the graph configuration (via the args parameter).
    2. A simple callback that you can use (in combination with the callback arguments :) to cascade some transitions. I updated the callback.php example with an automatic transition from accepted to archived. This can be useful in many cases. The callback supports as well the cascade when dealing with the same object but different graph, and even with another object reachable from the main object via a PropertyAccessor (for example, when your shipment goes from ready to shipped, you may want to automatically update your order (reachable with shipment.order).

    Thanks,

    opened by winzou 13
  • fix for symfony/options-resolver 2.6+

    fix for symfony/options-resolver 2.6+

    We had an issue with Finite installing along symfony/options-resolver 2.6+ which caused E_DEPRECATED errors due to new syntax of setAllowedTypes method. This little fix removes the error, it is however optional, because you have 2.4.4 in your composer.lock file (which was somehow ignored in our system). You could add this to prevent problems with update to 2.6+/3.0 of options-resolver or simply ignore this, as manual specification of "symfony/options-resolver": "2.4.4" in our composer.json seemed to do the trick too.

    Cheers.

    Related to issue #84.

    opened by keiosweb 11
  • Event Params

    Event Params

    It would be useful to be able to pass params to transition events. See the doc for more details

    | Q | A | | --- | --- | | Test Pass? | y | | License | MIT |

    opened by Padam87 10
  • Support multiple states per object?

    Support multiple states per object?

    Hi Yohan, very nice project!

    We have been looking at it from over at https://github.com/Sylius/Sylius/issues/1037, but one problem we have that the use of the StatefulInterface limits each object to only one state. In Sylius we have an Order class which has several states, such as ShippingState, and PaymentState.

    Would it not be possible to get rid of the interface and instead rely on the PropertyAccess component to access whichever property represents the state?

    Another (more explicit) possibility would be to rely on a new StateExtractorInterface which would be used to extract a single state from an object..

    If you agree that this is a limitation that we should/could address, I would be happy to help with the implementation..

    opened by Richtermeister 9
  • [WIP] Adding a way to easily work with the State machine lifecycle

    [WIP] Adding a way to easily work with the State machine lifecycle

    TODO

    • [x] Add a callback handler
    • [x] Add Symfony EventDispatcher as an hard dependency
    • [x] Deprecate ListenableStateMachine and make the base State machine listenable
    • [x] Link ArrayLoader and the CallbackHandler to define callbacks from configuration
    • [ ] Update the Symfony Bundle
    • [x] Add docs and examples

    (Inspired by @tortuetorche work here : https://gist.github.com/tortuetorche/6365575)

    opened by yohang 8
  • Release a stable version

    Release a stable version

    Do you think you could tag a stable release? Would be great since more recent projects using Composer do only use stable releases by default. Also gives somewhat more confidence to use the project by other people.

    opened by mac-cain13 8
  • Finite don't work on Linux box

    Finite don't work on Linux box

    It does work on my windows development machine (php version 5.4.27) but it doesn't work on linux test or production server with php 5.4.33 The error I'm getting is: request.CRITICAL: Uncaught PHP Exception Symfony\Component\OptionsResolver\Exception\InvalidOptionsException: "The option "disabled" does not exist. Known options are: "exclude_from", "exclude_to", "from", "on", "to"" at /var/www/vhosts/xxxxxxx.local/httpdocs/vendor/symfony/symfony/src/Symfony/Component/OptionsResolver/OptionsResolver.php line 255 {"exception":"[object](Symfony\Component\OptionsResolver\Exception\InvalidOptionsException: The option "disabled" does not exist. Known options are: "exclude_from", "exclude_to", "from", "on", "to" at /var/www/vhosts/xxxxxxx.local/httpdocs/vendor/symfony/symfony/src/Symfony/Component/OptionsResolver/OptionsResolver.php:255)"

    state-machine.yml is

        callbacks:
          after:
            callback1:
              do:
                [@xxxxxxx_finite.transition_events, transitionEverytimeAfter]
    
    bug 
    opened by ppavlovic 7
  • [WIP] Refactor CallbackHandler

    [WIP] Refactor CallbackHandler

    Here is a draft of the refactoring of the CallbackHandler (#48).

    It introduces no BC, but it deprecates the previous usage of CallbackHandler::add* methods.

    Callbacks are now wrapped in a Callback, with a CallbackSpecification responsible of the execution, or not, of the callback on transition events.

    Callback defines an __invoke method, and instances are directly registered as event listeners.

    The Callback instantiation logic has been moved to a CallbackBuilder and to the ArrayLoader.

    I kept the options resolver, as it's pretty good at cleaning configuration arrays.

    opened by yohang 7
  • Warning and unexpected behaviour after rejecting a transaction

    Warning and unexpected behaviour after rejecting a transaction

    Only today I came across this library, after a few hours of study and running a few examples, I came across the following:

    • Warning if I do not pass a guard option when defining a transition: PHP Notice: Undefined index: guard in vendor/yohang/finite/src/Finite/Loader/ArrayLoader.php on line 109. I did not see any reference of this property in the examples.
    • I was expecting that by calling the method reject() on the TransitionEvent, this would abort the transition, but not the case, it seems it has no impact. The method apply() on StateMachine, after dispatching the pre events, call process() on the Transition, but that method has an empty body, it does not return any value, but still, we use that as the return value of the apply(). Is this by design, are we suppose to create/extend the Transition class and implement our logic in the process method()?
    opened by titomiguelcosta 6
  • Update for Symfony ~2.6

    Update for Symfony ~2.6

    We've been using your library (via kphoen/doctrine-state-machine-bundle) and as a push for getting ready for Symfony 2.8 / 3.0, we've been trying to eliminate all deprecated warnings in our code and the third party libraries that we use.

    This PR represents the changes that were required for preventing this library from causing the warnings. It represents a culmination of the code in #90, #85 and #79 (and maybe some extra too)

    In addition, I have made the following composer related changes:

    • I have also removed the composer.lock file, as it's generally superfluous in a library designed for consumption by others.
    • I have updated the composer.json requirements for Symfony versions to be ~2.6

    The required changes in symfony versions means that this PR has BC compatibility issues for people using it in projects with older versions of Symfony, so in the strictest semver terms, it would require a new major release.

    If you have any issues, please let me know. Would love to see the deprecation issues addressed.

    Thanks. :+1:

    opened by navitronic 5
  • Maintainer for this repo and the library

    Maintainer for this repo and the library

    Hey there @yohang ,

    this repo and the library does not get the love it deserves. There are multiple open issues and a LOT of PRs ready to be merged or at least tested. People invest in this repo an obviously the interest in this repo is big with over a million installs on Packagist and over 150 forks here on GitHub.

    Since you seem to be unable/unwilling to maintain this library for the community on your own, would you be willing to enable one of your contributers (if they are willing) to moderate and administer this library for or at least with you?

    @winzou @navitronic @RonRademaker @Padam87 @liuggio @tortuetorche @tompedals @pborreli @nidup @defrag @arikal @realshadow @K-Phoen @acorncom @dannykopping @ksn135 @reiz

    The other path would be to mark this project as abandoned, so people would stop installing it and then realize that there are (known) bugs, that are not fixed or missing functionality that is not merged, even when the work is done.

    This should neither be attacking nor judgemental. I know, it is hard to maintain open source and interact with a community if you already have a demanding life out there in the real world and a company whatsoever. But I also think, that it is unfair to the community to let them use software without a clear message that this library is not maintained actively.

    opened by func0der 2
  • Examples multiple-graphs-with-factory.php and multiple-graphs.php do not work

    Examples multiple-graphs-with-factory.php and multiple-graphs.php do not work

    I have tested the examples. Examples multiple-graphs-with-factory.php and multiple-graphs.php do not work. Here is what we get.

    php multiple-graphs-with-factory.php
    PHP Fatal error:  Class 'Pimple' not found in vendor/yohang/finite/examples/multiple-graphs-with-factory.php on line 77
    
    php multiple-graphs.php
    PHP Fatal error:  Uncaught exception 'Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException' with message 'Neither the property "finiteState" nor one of the methods "getFiniteState()", "finiteStat\
    e()", "isFiniteState()", "hasFiniteState()", "__get()" exist and have public access in class "Order".' in vendor/symfony/property-access/PropertyAccessor.php:516
    Stack trace:
    
    opened by kresimir71 0
  • Symfony Events require different event listener connection than normal

    Symfony Events require different event listener connection than normal

    I'm using Symfony 4.4. The documentation at https://finite.readthedocs.io/en/master/usage/symfony.html#using-callbacks say:

    Events dispatched with the EventDispatcher and works as the Symfony kernel events.

    This would seem to imply that one can simply follow the standard Symfony ways of registering an event listener. i.e. using services.yaml or Creating an Event Subscriber.

    However, neither of those work, because Finite creates its own event dispatcher! When a new StateMachine is created, it creates a new StateMachineDispatcher() which creates...a new Symfony\Component\EventDispatcher\EventDispatcher.

    So any Symfony event registered in the normal way will not listen to the event.

    Solution

    We have to connect our event listener to the StateMachine's dispatcher.

    $sm = new StateMachine();
    $dispatcher = $sm->getDispatcher();
    $dispatcher->addListener(FiniteEvents::POST_TRANSITION, [new MyPostTransitionListener(), 'onFinitePostTransition']);
    
    class MyPostTransitionListener
    {
        public function onFinitePostTransition(\Finite\Event\TransitionEvent $event)
        {
            // handle event here
        }
    }
    
    opened by BurningDog 1
  • Incompatibility of 1.2.* where symfony/contracts also exists

    Incompatibility of 1.2.* where symfony/contracts also exists

    If symfony/contracts is also used in the project, there versions 1.2.* have an issue:

    TypeError : Argument 2 passed to Symfony\Component\EventDispatcher\EventDispatcher::dispatch() must be an instance of Symfony\Component\EventDispatcher\Event or null, instance of Finite\Event\StateMachineEvent given
    

    This seems to occur when someone has both the Symfony\Contracts\EventDispatcher\Event and Symfony\Component\EventDispatcher\Event installed. This check in StateMachineEvent checks whether Symfony\Contracts\EventDispatcher\Event exists, and aliases it to Symfony\Component\EventDispatcher\Event if not.

    opened by irinikp 1
  • Upgrade to PHPUnit 8, Symfony 5, PHP 7.2

    Upgrade to PHPUnit 8, Symfony 5, PHP 7.2

    All automated tests pass, but I haven't tested all functionality in-depth. Probably want to merge this into a different branch to test further.

    This PR allows use of this repo with Laravel 7. Without these changes, composer hangs indefinitely trying to resolve dependencies that include Symfony 5.x.

    opened by Mattnmoore 0
A simple Monad library for PHP

MonadPHP This is a basic Monad library for PHP. Usage Values are "wrapped" in the monad via either the constructor: new MonadPHP\Identity($value) or t

Anthony Ferrara 283 Dec 29, 2022
sample code for several design patterns in PHP 8

DesignPatternsPHP Read the Docs of DesignPatternsPHP or Download as PDF/Epub This is a collection of known design patterns and some sample codes on ho

null 21k Jan 1, 2023
Primitives for functional programming in PHP

Functional PHP: Functional primitives for PHP NOTE: functional-php used to come with a C extension that implemented most of the functions natively. As

Lars Strojny 1.9k Jan 3, 2023
Option Type for PHP

PHP Option Type This package implements the Option type for PHP! Motivation The Option type is intended for cases where you sometimes might return a v

Johannes 2.4k Dec 26, 2022
Powerful implementation of the Specification pattern in PHP

RulerZ The central idea of Specification is to separate the statement of how to match a candidate, from the candidate object that it is matched agains

Kévin Gomez 865 Dec 22, 2022
A Finite State Machine System based on Chapter 3.1 of Game Programming Gems 1 by Eric Dybsand

A Finite State Machine System based on Chapter 3.1 of Game Programming Gems 1 by Eric Dybsand,Written by Roberto Cezar Bianchini, July 2010 ported to php by MrFerrys.

null 4 Apr 18, 2022
PHP Machine Learning Rain Forecaster is a simple machine learning experiment in predicting rain based on a few forecast indicators.

PHP Machine Learning Rain Forecaster is a simple machine learning experiment in predicting rain based on a few forecast indicators.: forecasted "HighT

null 4 Nov 3, 2021
A simple laravel state machine to handle model transitions, based on a pre-defined list of rules

A simple state machine that allows transitioning model states based on pre-defined rules. Installation You can install the package via composer: compo

Jack Mollart 18 Apr 2, 2022
XState - A State Machine for PHP

XState - A State Machine for PHP State machine library to play with any complex behavior of your PHP objects Installation You can install the package

Mouad Ziani 68 Dec 18, 2022
A simple PHP web backdoor allows you to retrieve directory/file contents and upload file(s) from the local machine or remote URL.

Simple PHP Web Backdoor A simple PHP web backdoor allows you to retrieve directory/file contents and upload file(s) from the local machine or remote U

Aqhmal Hafizi 15 Oct 7, 2022
PHPIDS (PHP-Intrusion Detection System) is a simple to use, well structured, fast and state-of-the-art security layer for your PHP based web application

PHPIDS PHPIDS (PHP-Intrusion Detection System) is a simple to use, well structured, fast and state-of-the-art security layer for your PHP based web ap

null 752 Jan 3, 2023
A simple class that provides access to country & state list.

GeoData A simple class that provides access to country & state list. Installation composer require ahmard/geodata Usage Fetch country list <?php use

Ahmad Mustapha 4 Jun 20, 2022
PHP Machine Learning library

PHP-ML - Machine Learning library for PHP Fresh approach to Machine Learning in PHP. Algorithms, Cross Validation, Neural Network, Preprocessing, Feat

Jorge Casas 204 Dec 27, 2022
A high-level machine learning and deep learning library for the PHP language.

Rubix ML A high-level machine learning and deep learning library for the PHP language. Developer-friendly API is delightful to use 40+ supervised and

Rubix 1.7k Jan 1, 2023
Rubix ML - A high-level machine learning and deep learning library for the PHP language.

A high-level machine learning and deep learning library for the PHP language. Developer-friendly API is delightful to use 40+ supervised and

Rubix 1.7k Jan 6, 2023
PHP Machine Learning with Naive Bayes to classify the right contraceptive based on your medical history

What is php-ml-bayes PHP-ML Bayes is a Machine Learning with Naive Bayes Algorithm to classify the right contraceptive based on your medical history.

Fikri Lazuardi 2 Jan 21, 2022
Tutorial for computer vision and machine learning in PHP 7/8 by opencv (installation + examples + documentation)

Examples detect face by cascade classifier detect face by pretrained caffe model res10_300x300_ssd by ddn module detect facemarks by LBF algorithm rec

null 409 Dec 25, 2022
A PHP package for MRZ (Machine Readable Zones) code parser for Passport, Visa & Travel Document (TD1 & TD2).

MRZ (Machine Readable Zones) Parser for PHP A PHP package for MRZ (Machine Readable Zones) code parser for Passport, Visa & Travel Document (TD1 & TD2

Md. Rakibul Islam 25 Aug 24, 2022
Show caffeine intake stats for our office coffee machine

Coffee brewing statistics for the Spatie office Over at Spatie we drink a lot of coffee. How much coffee? We had no idea until we created this dashboa

Spatie 1 Nov 16, 2021
Identifies objects in an image using Machine Learning.

laravel-object-detection This package identifies objects in an image using Machine Learning, TensorFlow and the coco-ssd model. Installation You can i

Fredrik 91 Oct 23, 2022