Passed
Push — master ( cc388a...80543a )
by Daniel
02:47
created

ConfiguredXmlToCsv::outputToCsvOneLine()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 9
rs 9.6666
c 1
b 0
f 0
cc 2
eloc 6
nc 2
nop 2
1
<?php
2
3
/*
4
 * The MIT License
5
 *
6
 * Copyright 2017 Daniel Popiniuc.
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated documentation files (the "Software"), to deal
10
 * in the Software without restriction, including without limitation the rights
11
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
 * copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
 * THE SOFTWARE.
25
 */
26
27
namespace danielgp\configured_xml2csv;
28
29
trait ConfiguredXmlToCsv
30
{
31
32
    protected $csvEolString;
33
    protected $csvFieldSeparator;
34
35
    private function cleanStringElement($initialString, $desiredCleaningTechniques)
36
    {
37
        $knownCleaningTechniques = $this->knownCleaningTechniques();
38
        $cleanedString           = $initialString;
39
        foreach ($desiredCleaningTechniques as $crtCleaningTechnique) {
40
            if (is_array($knownCleaningTechniques[$crtCleaningTechnique])) {
41
                $cleanedString = call_user_func_array($knownCleaningTechniques[$crtCleaningTechnique][0], [
42
                    $knownCleaningTechniques[$crtCleaningTechnique][1],
43
                    $knownCleaningTechniques[$crtCleaningTechnique][2],
44
                    $cleanedString,
45
                ]);
46
            } else {
47
                $cleanedString = call_user_func($knownCleaningTechniques[$crtCleaningTechnique], $cleanedString);
48
            }
49
        }
50
        return $cleanedString;
51
    }
52
53
    private function knownCleaningTechniques()
54
    {
55
        return [
56
            'html_entity_decode'         => 'html_entity_decode',
57
            'htmlspecialchars'           => 'htmlspecialchars',
58
            'str_replace__double_space'  => ['str_replace', '  ', ' '],
59
            'str_replace__nbsp__space'   => ['str_replace', '&nbsp;', ' '],
60
            'str_replace__tripple_space' => ['str_replace', '   ', ' '],
61
            'strip_tags'                 => 'strip_tags',
62
            'trim'                       => 'trim',
63
        ];
64
    }
65
66
    private function outputToCsvOneLine($lineCunter, $outputCsvArray)
67
    {
68
        $sReturn = [];
69
        if ($lineCunter == 0) {
70
            $sReturn[] = implode($this->csvFieldSeparator, array_keys($outputCsvArray[$lineCunter]));
71
        }
72
        $sReturn[] = implode($this->csvFieldSeparator, array_values($outputCsvArray[$lineCunter]));
73
        return implode($this->csvEolString, $sReturn);
74
    }
75
76
    private function processMultipleInstancesOfSameElement($config, $arr, $name)
77
    {
78
        $crncy     = $config['features'][$name]['multiple']['currency'];
79
        $optnl     = $config['features'][$name]['multiple']['discounter'];
80
        $minValues = [];
81
        foreach ($arr as $key => $value) {
82
            if ($key == $name) {
83
                foreach ($value->attributes() as $key2 => $val2) {
84
                    switch ($key2) {
85
                        case $crncy:
86
                            $minValues[] = (int) $val2;
87
                            break;
88
                        case $optnl:
89
                            $minValues[] = $value->attributes()[$crncy] - ($value->attributes()[$crncy] * $val2) / 100;
90
                            break;
91
                    }
92
                }
93
            }
94
        }
95
        return min($minValues);
96
    }
97
98
    protected function readConfiguration($filePath, $fileBaseName)
99
    {
100
        $jSonContent = $this->readFileContent($filePath, $fileBaseName);
101
        return json_decode($jSonContent, true);
102
    }
103
104
    protected function readFileContent($filePath, $fileBaseName)
105
    {
106
        $fName    = $filePath . DIRECTORY_SEPARATOR . $fileBaseName;
107
        $fFile    = fopen($fName, 'r');
108
        $fContent = fread($fFile, filesize($fName));
109
        fclose($fFile);
110
        return $fContent;
111
    }
112
113
    private function transformKnownElements($config, $xmlIterator, $name, $data)
114
    {
115
        $cleanedData = $data;
116
        switch ($config['features'][$name]['type']) {
117
            case 'integer':
118
                $cleanedData = (int) $data;
119
                break;
120
            case 'multiple':
121
                $arr         = $xmlIterator->current();
122
                $cleanedData = $this->processMultipleInstancesOfSameElement($config, $arr, $name);
123
                break;
124
            case 'string':
125
                $cleanedData = $data;
126
                if (array_key_exists('transformation', $config['features'][$name])) {
127
                    $tr          = $config['features'][$name]['transformation'];
128
                    $cleanedData = $this->cleanStringElement($cleanedData, $tr);
129
                }
130
                break;
131
        }
132
        return $cleanedData;
133
    }
134
135
    public function xmlToCSV($text)
136
    {
137
        $cnfg           = $this->readConfiguration(__DIR__, 'configuration.json');
138
        $xmlItrtr       = new \SimpleXMLIterator($text);
139
        $outputCsvArray = [];
140
        $lineCunter     = 0;
141
        $csvLine        = [];
142
        for ($xmlItrtr->rewind(); $xmlItrtr->valid(); $xmlItrtr->next()) {
143
            foreach ($xmlItrtr->getChildren() as $name => $data) {
144
                if (array_key_exists($name, $cnfg['features'])) {
145
                    $hdr                               = $cnfg['features'][$name]['header'];
146
                    $cleanedData                       = $this->transformKnownElements($cnfg, $xmlItrtr, $name, $data);
147
                    $outputCsvArray[$lineCunter][$hdr] = $cleanedData;
148
                }
149
            }
150
            $csvLine[] = $this->outputToCsvOneLine($lineCunter, $outputCsvArray);
151
            $lineCunter++;
152
        }
153
        return implode($this->csvEolString, $csvLine);
154
    }
155
}
156