Passed
Push — master ( 71e346...ca9e15 )
by Brian
02:28
created

Validate   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 9
eloc 32
c 1
b 0
f 0
dl 0
loc 94
ccs 0
cts 33
cp 0
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A validate() 0 26 3
A getElement() 0 7 1
A handle() 0 19 4
A getMessage() 0 5 1
1
<?php
2
3
namespace Bmatovu\Ussd\Commands;
4
5
use Illuminate\Console\Command;
6
7
class Validate extends Command
8
{
9
    /**
10
     * The name and signature of the console command.
11
     *
12
     * @var string
13
     */
14
    protected $signature = 'ussd:validate
15
                                {--f|file=menus.xml : Main menu file.}
16
                                {--s|schema=menus.xsd : XSD to validate against.}';
17
18
    /**
19
     * The console command description.
20
     *
21
     * @var string
22
     */
23
    protected $description = 'Validate ussd menus.';
24
25
    /**
26
     * Execute the console command.
27
     */
28
    public function handle(): void
29
    {
30
        $xml = menus_path($this->option('file'));
31
        $xsd = menus_path($this->option('schema'));
32
33
        if(! file_exists($xsd)) {
34
            $xsd = __DIR__.'/../../menus/menus.xsd';
35
        }
36
37
        $errors = $this->validate($xml, $xsd);
38
39
        if(! $errors) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $errors of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
introduced by
$errors is an empty array, thus ! $errors is always true.
Loading history...
40
            $this->info('Cheers, you have valid menus.');
41
            return;
42
        }
43
44
        foreach($errors as $file => $messages) {
45
            $this->error('File: '.$file);
46
            $this->table(['Line', 'Element', 'Message'], $messages);
47
        }
48
    }
49
50
    /**
51
     * @see https://www.php.net/manual/en/class.simplexmlelement.php#107869
52
     */
53
    public function validate(string $xmlFile, string $xsdFile, int $flags = 0): array
54
    {
55
        libxml_use_internal_errors(true);
56
57
        $domDocument = new \DOMDocument();
58
59
        $domDocument->load($xmlFile);
60
61
        $errors = [];
62
63
        if ($domDocument->schemaValidate($xsdFile, $flags)) {
64
            return $errors;
65
        }
66
67
        foreach (libxml_get_errors() as $error) {
68
            // level, code, column, message, file, line
69
            $errors[$error->file][] = [
70
                $error->line,
71
                $this->getElement($error->message),
72
                $this->getMessage($error->message),
73
            ];
74
        }
75
76
        libxml_clear_errors();
77
78
        return $errors;
79
    }
80
81
    /**
82
     * Get element from message.
83
     */
84
    protected function getElement(string $message): ?string
85
    {
86
        $matches = [];
87
88
        preg_match("/'([-_\\w]+)'/", $message, $matches);
89
90
        return array_pop($matches);
91
    }
92
93
    /**
94
     * Get refined message.
95
     */
96
    protected function getMessage(string $message): string
97
    {
98
        $parts = explode(':', $message);
99
100
        return trim(array_pop($parts));
101
    }
102
}
103