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.
 
 
 
 
 
 

316 lines
8.6 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$
/**
* TransitionLib
*
*/
class TransitionLib
{
private $transitionType;
/**
* @param $transitionType
*/
public function __construct($transitionType)
{
$this->transitionType = $transitionType;
}
/**
* @param $object
* @param null $type
* @return array
*/
public function getAvailableTransitions($object, $type = null)
{
$states = $this->getCurrentStates($object, $type);
$transitions = $this->getTransitionsFromStates($states);
$transitions = Perms::filter(
['type' => 'transition'],
'object',
$transitions,
['object' => 'transitionId'],
'trigger_transition'
);
foreach ($transitions as & $tr) {
$object = new Tiki_Transition($tr['from'], $tr['to']);
$object->setStates($states);
foreach ($tr['guards'] as $guard) {
call_user_func_array([$object, 'addGuard' ], $guard);
}
$tr['enabled'] = $object->isReady();
$tr['explain'] = $object->explain();
}
return $transitions;
}
/**
* @param $state
* @param $object
* @param null $type
* @return array
*/
public function getAvailableTransitionsFromState($state, $object, $type = null)
{
$transitions = $this->getAvailableTransitions($object, $type);
$out = [];
foreach ($transitions as $tr) {
if ($tr['from'] == $state) {
$out[$tr['transitionId']] = $tr['name'];
}
}
return $out;
}
/**
* @param $transitionId
* @param $object
* @param null $type
* @return bool
*/
public function triggerTransition($transitionId, $object, $type = null)
{
// Make sure the transition exists
if (! $transition = $this->getTransition($transitionId)) {
return false;
}
// Make sure the user can use it
$perms = Perms::get(['type' => 'transition', 'object' => $transitionId]);
if (! $perms->trigger_transition) {
return false;
}
// Verify that the states are consistent
$states = $this->getCurrentStates($object, $type);
$tr = new Tiki_Transition($transition['from'], $transition['to']);
$tr->setStates($states);
foreach ($transition['guards'] as $guard) {
call_user_func_array([$tr, 'addGuard'], $guard);
}
if (! $tr->isReady()) {
return false;
}
$this->addState($transition['to'], $object, $type);
if (! $transition['preserve']) {
$this->removeState($transition['from'], $object, $type);
}
return true;
}
/**
* @param $states
* @return array
*/
public function listTransitions($states)
{
$db = TikiDb::get();
if (empty($states)) {
return [];
}
$bindvars = [$this->transitionType];
$query = "SELECT `transitionId`, `preserve`, `name`, `from`, `to`, `guards` FROM `tiki_transitions` WHERE `type` = ? AND ( " .
$db->in('from', $states, $bindvars) .
' OR ' . $db->in('to', $states, $bindvars) . ')';
$result = $db->fetchAll($query, $bindvars);
return array_map([$this, 'expandGuards'], $result);
}
// Database interaction
/**
* @param $from
* @param $to
* @param $name
* @param bool $preserve
* @param array $guards
* @return mixed
*/
public function addTransition($from, $to, $name, $preserve = false, array $guards = [])
{
$db = TikiDb::get();
$db->query(
"INSERT INTO `tiki_transitions` ( `type`, `from`, `to`, `name`, `preserve`, `guards`) VALUES( ?, ?, ?, ?, ?, ? )",
[$this->transitionType, $from, $to, $name, (int) $preserve, json_encode($guards)]
);
return $db->getOne('SELECT MAX(`transitionId`) FROM `tiki_transitions`');
}
/**
* @param $transitionId
* @param $from
* @param $to
* @param $label
* @param $preserve
*/
public function updateTransition($transitionId, $from, $to, $label, $preserve)
{
$db = TikiDb::get();
$db->query(
'UPDATE `tiki_transitions` SET `name` = ?, `from` = ?, `to` = ?, `preserve` = ? WHERE `transitionId` = ?',
[$label, $from, $to, (int) $preserve, (int) $transitionId]
);
}
/**
* @param $transitionId
* @param array $guards
*/
public function updateGuards($transitionId, array $guards)
{
$db = TikiDb::get();
$db->query(
'UPDATE `tiki_transitions` SET `guards` = ? WHERE `transitionId` = ?',
[json_encode($guards), (int) $transitionId]
);
}
/**
* @param $transitionId
*/
public function removeTransition($transitionId)
{
$db = TikiDb::get();
$db->query('DELETE FROM `tiki_transitions` WHERE `transitionId` = ?', [$transitionId]);
}
/**
* @param $states
* @return array
*/
private function getTransitionsFromStates($states)
{
$db = TikiDb::get();
if (empty($states)) {
return [];
}
$bindvars = [$this->transitionType];
$query = "SELECT `transitionId`, `preserve`, `name`, `from`, `to`, `guards` FROM `tiki_transitions` WHERE `type` = ? AND " .
$db->in('from', $states, $bindvars) . ' AND NOT (' .
$db->in('to', $states, $bindvars) . ')';
$result = $db->fetchAll($query, $bindvars);
return array_map([$this, 'expandGuards'], $result);
}
/**
* @param $transitionId
* @return mixed
*/
public function getTransition($transitionId)
{
$db = TikiDb::get();
$bindvars = [$this->transitionType, $transitionId];
$query = "SELECT `transitionId`, `preserve`, `name`, `from`, `to`, `guards` FROM" .
" `tiki_transitions` WHERE `type` = ? AND `transitionId` = ?";
$result = $db->fetchAll($query, $bindvars);
return $this->expandGuards(reset($result));
}
/**
* @param $transition
* @return mixed
*/
private function expandGuards($transition)
{
$transition['guards'] = json_decode($transition['guards'], true);
if (! $transition['guards']) {
$transition['guards'] = [];
}
return $transition;
}
// The following functions vary depending on the transition type
/**
* @param $object
* @param $type
* @return array
*/
private function getCurrentStates($object, $type)
{
switch ($this->transitionType) {
case 'group':
$userlib = TikiLib::lib('user');
return $userlib->get_user_groups($object);
case 'category':
$categlib = TikiLib::lib('categ');
return $categlib->get_object_categories($type, $object);
}
}
/**
* @param $state
* @param $object
* @param $type
*/
private function addState($state, $object, $type)
{
global $prefs;
switch ($this->transitionType) {
case 'group':
$userlib = TikiLib::lib('user');
$userlib->assign_user_to_group($object, $state);
if ($prefs['default_group_transitions'] === 'y') {
$userlib->set_default_group($object, $state);
}
return;
case 'category':
$categlib = TikiLib::lib('categ');
$categlib->categorize_any($type, $object, $state);
return;
}
}
/**
* @param $state
* @param $object
* @param $type
*/
private function removeState($state, $object, $type)
{
switch ($this->transitionType) {
case 'group':
$userlib = TikiLib::lib('user');
$userlib->remove_user_from_group($object, $state);
return;
case 'category':
$categlib = TikiLib::lib('categ');
if ($catobj = $categlib->is_categorized($type, $object)) {
$categlib->uncategorize($catobj, $state);
}
return;
}
}
}