Completed
Branch develop (e9fd73)
by Benjamin
03:23
created

RulesLoaderCommand::execute()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 11
nc 3
nop 2
dl 0
loc 16
rs 9.9
c 2
b 0
f 0
1
<?php
2
3
namespace Obblm\Core\Command;
4
5
use Obblm\Core\Entity\Rule;
6
use Doctrine\ORM\EntityManagerInterface;
7
use Obblm\Core\Helper\CoreTranslation;
8
use Obblm\Core\Helper\Rule\Config\ConfigResolver;
9
use Obblm\Core\Helper\Rule\Config\RuleConfigResolver;
10
use Symfony\Component\Console\Command\Command;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Output\OutputInterface;
13
use Symfony\Component\Console\Style\SymfonyStyle;
14
use Symfony\Component\Finder\Finder;
15
use Symfony\Component\Finder\SplFileInfo;
16
use Symfony\Component\OptionsResolver\Exception\InvalidArgumentException;
17
use Symfony\Component\Yaml\Yaml;
18
19
class RulesLoaderCommand extends Command
20
{
21
    /** @var string */
22
    protected static $defaultName = 'obblm:rules:load';
23
    /** @var string */
24
    protected $rulesDirectory = 'datas/rules';
25
    /** @var EntityManagerInterface */
26
    private $em;
27
    /** @var SymfonyStyle */
28
    private $io;
29
30
    public function __construct(EntityManagerInterface $em)
31
    {
32
        $this->em = $em;
33
        $this->rulesDirectory = dirname(__DIR__).'/Resources/datas/rules';
34
        parent::__construct();
35
    }
36
37
    protected function configure():void
38
    {
39
        $this->setDescription('Loads Blood Bowl core rules.')
40
            ->setHelp('This command will add core Blood Bowl rules to the database.');
41
    }
42
43
    protected function execute(InputInterface $input, OutputInterface $output)
44
    {
45
        $this->io = new SymfonyStyle($input, $output);
46
        $finder = new Finder();
47
        $this->io->title("Importing pre fetched rules from " . $this->rulesDirectory);
48
        $finder->directories()->ignoreDotFiles(true)->depth(0)->in($this->rulesDirectory);
49
        if ($finder->hasResults()) {
50
            foreach ($finder as $ruleDirectory) {
51
                $this->parseRule($ruleDirectory);
52
            }
53
            $this->em->flush();
54
            $this->io->success('All rules have been created or updated.');
55
            return 0;
56
        }
57
58
        return 1;
59
    }
60
61
    protected function parseRule(SplFileInfo $ruleDirectory):void
62
    {
63
        $rules = [];
64
        $key = $ruleDirectory->getFilename();
65
        $this->io->block("Importing {$key} rules form {$ruleDirectory->getPathname()}");
66
        $finder = new Finder();
67
        $finder->files()->ignoreDotFiles(true)->name(['*.yaml', '*.yml'])->in($ruleDirectory->getPathname());
68
        if ($finder->hasResults()) {
69
            $this->io->progressStart($finder->count());
70
            foreach ($finder as $file) {
71
                $content = Yaml::parseFile($file->getPathname());
72
                $rules = array_merge_recursive($rules, $content);
73
                $this->io->progressAdvance(1);
74
            }
75
            if (!isset($rules['rules'][$key])) {
76
                $this->io->error("The rules.{$key} rule does not exist in {$ruleDirectory->getPathname()} directory.");
77
            }
78
            $ruleArray = $rules['rules'][$key];
79
80
            try {
81
                $treeResolver = new ConfigResolver(new RuleConfigResolver());
82
                $ruleArray = $treeResolver->resolve($ruleArray);
83
84
                /** @var Rule|null $rule */
85
                $rule = $this->em->getRepository(Rule::class)->findOneBy(['ruleKey' => $key]);
86
                if (!$rule) {
87
                    $rule = (new Rule())
88
                        ->setRuleKey($key)
89
                        ->setReadOnly(true);
90
                }
91
                ksort($ruleArray['rosters']);
92
                $rule->setName(CoreTranslation::getRuleTitle($key))
93
                    ->setPostBb2020($ruleArray['post_bb_2020'] ?? false)
94
                    ->setTemplate($ruleArray['template'] ?? 'base')
95
                    ->setRule($ruleArray);
96
                $this->em->persist($rule);
97
                $this->io->progressFinish();
98
            } catch (InvalidArgumentException $e) {
99
                $this->io->progressFinish();
100
                $this->io->error("The rule.{$key} is not valid, resolver said :\n{$e->getMessage()}");
101
            }
102
            return;
103
        }
104
        $this->io->warning("There is no rule files in {$ruleDirectory->getPathname()} directory.");
105
        return;
106
    }
107
}
108