Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
9 / 9
CRAP
100.00% covered (success)
100.00%
46 / 46
StateMachineProcessor
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
9 / 9
22
100.00% covered (success)
100.00%
46 / 46
 __construct
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 setPrefix
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 processGraph
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
4 / 4
 processNodeAttrs
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
15 / 15
 processEdgeAttrs
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
7 / 7
 runGraphProcessor
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
5 / 5
 runNodeProcessor
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
5 / 5
 runEdgeProcessor
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
5 / 5
 getExtraSvgElements
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
<?php declare(strict_types = 1);
/*
 * Copyright (c) 2019, Josef Kufner  <josef@kufner.cz>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
namespace Smalldb\StateMachine\Definition\Renderer;
use Smalldb\StateMachine\Definition\ExtensibleDefinition;
use Smalldb\StateMachine\Definition\StateMachineGraph\StateMachineEdge;
use Smalldb\StateMachine\Definition\StateMachineGraph\StateMachineGraph;
use Smalldb\StateMachine\Definition\StateMachineGraph\StateMachineNode;
use Smalldb\Graph\Edge;
use Smalldb\Graph\Grafovatko\ProcessorInterface;
use Smalldb\Graph\Graph;
use Smalldb\Graph\NestedGraph;
use Smalldb\Graph\Node;
class StateMachineProcessor implements ProcessorInterface
{
    private string $prefix;
    private bool $horizontalLayout;
    public function __construct(bool $horizontalLayout = false)
    {
        $this->horizontalLayout = $horizontalLayout;
    }
    public function setPrefix(string $prefix): void
    {
        $this->prefix = $prefix;
    }
    /**
     * Returns modified $exportedGraph which become the graph's attributes.
     *
     * @param NestedGraph $graph
     * @param array $exportedGraph
     * @return array
     */
    public function processGraph(NestedGraph $graph, array $exportedGraph): array
    {
        if ($graph instanceof StateMachineGraph) {
            $exportedGraph['layoutOptions']['rankdir'] = $this->horizontalLayout ? 'LR' : 'TB';
            $this->runGraphProcessor($graph->getStateMachine(), $graph, $exportedGraph);
        }
        return $exportedGraph;
    }
    /**
     * Returns modified $exportedNode which become the node's attributes.
     */
    public function processNodeAttrs(Node $node, array $exportedNode): array
    {
        if ($node instanceof StateMachineNode) {
            $state = $node->getState();
            $stateName = $state->getName();
            $exportedNode['label'] = $stateName;
            $exportedNode['fill'] = "#eee";
            if ($stateName === '') {
                if ($node->isSourceNode()) {
                    $exportedNode['shape'] = 'uml.initial_state';
                } else if (empty($node->getConnectedEdges())) {
                    $exportedNode['shape'] = 'none';
                } else {
                    $exportedNode['shape'] = 'uml.final_state';
                }
            } else {
                $exportedNode['shape'] = 'uml.state';
            }
            $this->runNodeProcessor($node->getStateMachine(), $node, $exportedNode);
            $this->runNodeProcessor($state, $node, $exportedNode);
            // TODO: Highlight unreachable and undefined states
        }
        return $exportedNode;
    }
    /**
     * Returns modified $exportedEdge which become the edge's attributes.
     */
    public function processEdgeAttrs(Edge $edge, array $exportedEdge): array
    {
        if ($edge instanceof StateMachineEdge) {
            $transition = $edge->getTransition();
            $exportedEdge['label'] = $transition->getName();
            $exportedEdge['color'] = "#000";
            $this->runEdgeProcessor($transition, $edge, $exportedEdge);
            $this->runEdgeProcessor($edge->getStateMachine(), $edge, $exportedEdge);
        }
        return $exportedEdge;
    }
    private function runGraphProcessor(ExtensibleDefinition $definition, StateMachineGraph $graph, array &$exportedGraph)
    {
        foreach ($definition->getExtensionClassNames() as $extName) {
            $ext = $definition->getExtension($extName);
            if ($ext instanceof StateMachineGraphProcessor) {
                $ext->processGraphAttrs($graph, $exportedGraph);
            }
        }
    }
    private function runNodeProcessor(ExtensibleDefinition $definition, StateMachineNode $node, array &$exportedNode)
    {
        foreach ($definition->getExtensionClassNames() as $extName) {
            $ext = $definition->getExtension($extName);
            if ($ext instanceof StateMachineNodeProcessor) {
                $ext->processNodeAttrs($node, $exportedNode);
            }
        }
    }
    private function runEdgeProcessor(ExtensibleDefinition $definition, StateMachineEdge $edge, array &$exportedEdge)
    {
        foreach ($definition->getExtensionClassNames() as $extName) {
            $ext = $definition->getExtension($extName);
            if ($ext instanceof StateMachineEdgeProcessor) {
                $ext->processEdgeAttrs($edge, $exportedEdge);
            }
        }
    }
    /**
     * Returns Htag-style array of additional SVG elements which will be appended to the rendered SVG image.
     */
    public function getExtraSvgElements(Graph $graph): array
    {
        return [];
    }
}