<commit_before><?php

namespace Tienvx\Bundle\MbtBundle\Graph\Dumper;

use Fhaculty\Graph\Edge\Directed;
use Fhaculty\Graph\Graph;
use Fhaculty\Graph\Vertex;

class PlantUmlDumper implements DumperInterface
{
    private const INITIAL = '<<initial>>';
    private const MARKED = '<<marked>>';

    const STATEMACHINE_TRANSITION = 'arrow';
    const DEFAULT_OPTIONS = array(
        'skinparams' => array(
            'titleBorderRoundCorner' => 15,
            'titleBorderThickness' => 2,
            'state' => array(
                'BackgroundColor'.self::INITIAL => '#87b741',
                'BackgroundColor'.self::MARKED => '#3887C6',
                'BorderColor' => '#3887C6',
                'BorderColor'.self::MARKED => 'Black',
                'FontColor'.self::MARKED => 'White',
            ),
        ),
    );

    public function dump(string $initialPlaces, Graph $graph, array $options = array()): string
    {
        $options = array_replace_recursive(self::DEFAULT_OPTIONS, $options);
        $code = $this->initialize($options);
        /** @var Vertex $vertex */
        foreach ($graph->getVertices() as $vertex) {
            $placeEscaped = $this->escape($vertex->getId());
            $code[] = "state $placeEscaped" . ($initialPlaces === $vertex->getId() ? ' '.self::INITIAL : '');
        }
        /** @var Directed $edge */
        foreach ($graph->getEdges() as $edge) {
            $fromEscaped = $this->escape($edge->getVertexStart()->getId());
            $toEscaped = $this->escape($edge->getVertexEnd()->getId());
            $transitionEscaped = $this->escape($edge->getAttribute('name'));
            $code[] = "$fromEscaped --> $toEscaped: $transitionEscaped";
        }

        return $this->startPuml($options).$this->getLines($code).$this->endPuml($options);
    }

    private function startPuml(array $options): string
    {
        $start = '@startuml'.PHP_EOL;
        $start .= 'allow_mixing'.PHP_EOL;

        return $start;
    }

    private function endPuml(array $options): string
    {
        return PHP_EOL.'@enduml';
    }

    private function getLines(array $code): string
    {
        return implode(PHP_EOL, $code);
    }

    private function initialize(array $options): array
    {
        $code = array();
        if (isset($options['title'])) {
            $code[] = "title {$options['title']}";
        }
        if (isset($options['name'])) {
            $code[] = "title {$options['name']}";
        }
        if (isset($options['skinparams']) && \is_array($options['skinparams'])) {
            foreach ($options['skinparams'] as $skinparamKey => $skinparamValue) {
                if (!\is_array($skinparamValue)) {
                    $code[] = "skinparam {$skinparamKey} $skinparamValue";
                    continue;
                }
                $code[] = "skinparam {$skinparamKey} {";
                foreach ($skinparamValue as $key => $value) {
                    $code[] = "    {$key} $value";
                }
                $code[] = '}';
            }
        }

        return $code;
    }

    private function escape(string $string): string
    {
        // It's not possible to escape property double quote, so let's remove it
        return '"'.str_replace('"', '', $string).'"';
    }
}
<commit_msg>Fix escaping characters<commit_after><?php

namespace Tienvx\Bundle\MbtBundle\Graph\Dumper;

use Fhaculty\Graph\Edge\Directed;
use Fhaculty\Graph\Graph;
use Fhaculty\Graph\Vertex;

class PlantUmlDumper implements DumperInterface
{
    private const INITIAL = '<<initial>>';
    private const MARKED = '<<marked>>';

    const STATEMACHINE_TRANSITION = 'arrow';
    const DEFAULT_OPTIONS = array(
        'skinparams' => array(
            'titleBorderRoundCorner' => 15,
            'titleBorderThickness' => 2,
            'state' => array(
                'BackgroundColor'.self::INITIAL => '#87b741',
                'BackgroundColor'.self::MARKED => '#3887C6',
                'BorderColor' => '#3887C6',
                'BorderColor'.self::MARKED => 'Black',
                'FontColor'.self::MARKED => 'White',
            ),
        ),
    );

    public function dump(string $initialPlaces, Graph $graph, array $options = array()): string
    {
        $options = array_replace_recursive(self::DEFAULT_OPTIONS, $options);
        $code = $this->initialize($options);
        /** @var Vertex $vertex */
        foreach ($graph->getVertices() as $vertex) {
            $placeEscaped = $this->escape(implode(',', json_decode($vertex->getId(), true)));
            $code[] = "state $placeEscaped" . ($initialPlaces === $vertex->getId() ? ' '.self::INITIAL : '');
        }
        /** @var Directed $edge */
        foreach ($graph->getEdges() as $edge) {
            $fromEscaped = $this->escape(implode(',', json_decode($edge->getVertexStart()->getId())));
            $toEscaped = $this->escape(implode(',', json_decode($edge->getVertexEnd()->getId())));
            $transitionEscaped = $this->escape($edge->getAttribute('name'));
            $code[] = "$fromEscaped --> $toEscaped: $transitionEscaped";
        }

        return $this->startPuml($options).$this->getLines($code).$this->endPuml($options);
    }

    private function startPuml(array $options): string
    {
        $start = '@startuml'.PHP_EOL;
        $start .= 'allow_mixing'.PHP_EOL;

        return $start;
    }

    private function endPuml(array $options): string
    {
        return PHP_EOL.'@enduml';
    }

    private function getLines(array $code): string
    {
        return implode(PHP_EOL, $code);
    }

    private function initialize(array $options): array
    {
        $code = array();
        if (isset($options['title'])) {
            $code[] = "title {$options['title']}";
        }
        if (isset($options['name'])) {
            $code[] = "title {$options['name']}";
        }
        if (isset($options['skinparams']) && \is_array($options['skinparams'])) {
            foreach ($options['skinparams'] as $skinparamKey => $skinparamValue) {
                if (!\is_array($skinparamValue)) {
                    $code[] = "skinparam {$skinparamKey} $skinparamValue";
                    continue;
                }
                $code[] = "skinparam {$skinparamKey} {";
                foreach ($skinparamValue as $key => $value) {
                    $code[] = "    {$key} $value";
                }
                $code[] = '}';
            }
        }

        return $code;
    }

    private function escape(string $string): string
    {
        // It's not possible to escape property double quote, so let's remove it
        return '"'.str_replace('"', '', $string).'"';
    }
}

{'fraction_non_alphanumeric': 0.16564600448095593, 'fraction_numerical': 0.005377147124719941, 'mean_word_length': 2.205361416945907, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3813357', 'n_tokens_mistral': 2019, 'n_tokens_neox': 1931, 'n_words': 378}