You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

117 lines
2.9 KiB

<?php
// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
//
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id$
class Tiki_Transition
{
private $from;
private $to;
private $states = [];
private $guards = [];
private $blockers;
public function __construct($from, $to)
{
$this->from = $from;
$this->to = $to;
}
public function setStates(array $states)
{
$this->states = $states;
$this->blockers = null;
}
public function addGuard($type, $boundary, $set)
{
if (method_exists($this, '_' . $type)) {
$this->guards[] = [$type, $boundary, $set];
} else {
$this->guards[] = ['unknown', 1, [$type]];
}
}
public function isReady()
{
return count($this->explain()) == 0;
}
public function explain()
{
$this->blockers = [];
$this->_exactly(1, [$this->from]);
$this->_exactly(0, [$this->to]);
$this->applyGuards();
return $this->blockers;
}
private function applyGuards()
{
foreach ($this->guards as $guard) {
$method = '_' . array_shift($guard);
call_user_func_array([$this, $method], $guard);
}
}
private function addBlocker($type, $amount, $set)
{
$this->blockers[] = ['class' => $type, 'count' => $amount, 'set' => array_values($set)];
}
private function _exactly($amount, $list)
{
if (count($list) < $amount) {
$this->addBlocker('invalid', $amount, $list);
return;
}
$intersect = array_intersect($this->states, $list);
$count = count($intersect);
if ($count > $amount) {
$this->addBlocker('extra', $count - $amount, $intersect);
} elseif ($count < $amount) {
$set = array_diff($list, $intersect);
$this->addBlocker('missing', $amount - $count, $set);
}
}
private function _atMost($amount, $list)
{
$intersect = array_intersect($this->states, $list);
$count = count($intersect);
if ($count > $amount) {
$this->addBlocker('extra', $count - $amount, $intersect);
}
}
private function _atLeast($amount, $list)
{
if (count($list) < $amount) {
$this->addBlocker('invalid', $amount, $list);
return;
}
$intersect = array_intersect($this->states, $list);
$count = count($intersect);
if ($count < $amount) {
$set = array_diff($list, $intersect);
$this->addBlocker('missing', $amount - $count, $set);
}
}
private function _unknown($amount, $list)
{
$this->addBlocker('unknown', 1, $list);
}
}