Completed
Push — master ( eef492...cef1d4 )
by Michael
04:41
created

Transformer::setXslDir()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
/**
3
 * Contains Transformer class.
4
 *
5
 * PHP version 5.5
6
 *
7
 * LICENSE:
8
 * This file is part of Yet Another Php Eve Api Library also know as Yapeal
9
 * which can be used to access the Eve Online API data and place it into a
10
 * database.
11
 * Copyright (C) 2015-2016 Michael Cummings
12
 *
13
 * This program is free software: you can redistribute it and/or modify it
14
 * under the terms of the GNU Lesser General Public License as published by the
15
 * Free Software Foundation, either version 3 of the License, or (at your
16
 * option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful, but WITHOUT
19
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
21
 * for more details.
22
 *
23
 * You should have received a copy of the GNU Lesser General Public License
24
 * along with this program. If not, see
25
 * <http://www.gnu.org/licenses/>.
26
 *
27
 * You should be able to find a copy of this license in the LICENSE.md file. A
28
 * copy of the GNU GPL should also be available in the GNU-GPL.md file.
29
 *
30
 * @copyright 2015-2016 Michael Cummings
31
 * @license   http://www.gnu.org/copyleft/lesser.html GNU LGPL
32
 * @author    Michael Cummings <[email protected]>
33
 */
34
namespace Yapeal\Xsl;
35
36
use DOMDocument;
37
use SimpleXMLElement;
38
use tidy;
39
use XSLTProcessor;
40
use Yapeal\Event\EveApiEventEmitterTrait;
41
use Yapeal\Event\EveApiEventInterface;
42
use Yapeal\Event\MediatorInterface;
43
use Yapeal\FileSystem\RelativeFileSearchTrait;
44
use Yapeal\Log\Logger;
45
use Yapeal\Xml\EveApiReadWriteInterface;
46
47
/**
48
 * Class Transformer
49
 */
50
class Transformer implements TransformerInterface
51
{
52
    use EveApiEventEmitterTrait, RelativeFileSearchTrait;
53
    /**
54
     * Transformer Constructor.
55
     *
56
     * @param string $dir Base directory where Eve API XSL files can be found.
57
     */
58
    public function __construct($dir = __DIR__)
59
    {
60
        $this->setRelativeBaseDir($dir . '/');
61
    }
62
    /**
63
     * @param EveApiEventInterface $event
64
     * @param string               $eventName
65
     * @param MediatorInterface    $yem
66
     *
67
     * @return EveApiEventInterface
68
     * @throws \DomainException
69
     * @throws \InvalidArgumentException
70
     * @throws \LogicException
71
     */
72
    public function transformEveApi(EveApiEventInterface $event, $eventName, MediatorInterface $yem)
73
    {
74
        $this->setYem($yem);
75
        $data = $event->getData();
76
        $this->getYem()
77
            ->triggerLogEvent(
78
                'Yapeal.Log.log',
79
                Logger::DEBUG,
80
                $this->getReceivedEventMessage($data, $eventName, __CLASS__)
81
            );
82
        $fileName = $this->findEveApiFile($data->getEveApiSectionName(), $data->getEveApiName(), 'xsl');
83
        if ('' === $fileName) {
84
            return $event;
85
        }
86
        $xml = $this->addYapealProcessingInstructionToXml($data)
87
            ->performTransform($fileName, $data);
88
        if (false === $xml) {
89
            $mess = 'Failed to transform xml during';
90
            $yem->triggerLogEvent(
91
                'Yapeal.Log.log',
92
                Logger::WARNING,
93
                $this->createEventMessage($mess, $data, $eventName)
94
            );
95
            return $event;
96
        }
97
        $xml = (new tidy())->repairString($xml, $this->tidyConfig, 'utf8');
98
        return $event->setData($data->setEveApiXml($xml))
99
            ->eventHandled();
100
    }
101
    /**
102
     * Adds Processing Instruction to XML containing json encoding of any post used during retrieve.
103
     *
104
     * NOTE: This use to be done directly in the network retriever but felt modifying the XML like that belonged in
105
     * transform instead.
106
     *
107
     * @param EveApiReadWriteInterface $data
108
     *
109
     * @return self Fluent interface.
110
     * @throws \InvalidArgumentException
111
     */
112
    protected function addYapealProcessingInstructionToXml(EveApiReadWriteInterface $data)
113
    {
114
        $xml = $data->getEveApiXml();
115
        if (false === $xml) {
116
            return $this;
117
        }
118
        $arguments = $data->getEveApiArguments();
119
        if (!empty($arguments['vCode'])) {
120
            $arguments['vCode'] = substr($arguments['vCode'], 0, 8) . '...';
121
        }
122
        unset($arguments['mask']);
123
        $json = json_encode($arguments);
124
        $xml = str_replace(
125
            ["encoding='UTF-8'?>\r\n<eveapi", "encoding='UTF-8'?>\n<eveapi"],
126
            [
127
                "encoding='UTF-8'?>\r\n<?yapeal.parameters.json " . $json . "?>\r\n<eveapi",
128
                "encoding='UTF-8'?>\n<?yapeal.parameters.json " . $json . "?>\n<eveapi"
129
            ],
130
            $xml
131
        );
132
        $data->setEveApiXml($xml);
133
        return $this;
134
    }
135
    /**
136
     * @param string                   $fileName
137
     * @param EveApiReadWriteInterface $data
138
     *
139
     * @return false|string
140
     * @throws \DomainException
141
     * @throws \InvalidArgumentException
142
     * @throws \LogicException
143
     */
144
    protected function performTransform($fileName, EveApiReadWriteInterface $data)
145
    {
146
        $xslt = new XSLTProcessor();
147
        $oldErrors = libxml_use_internal_errors(true);
148
        libxml_clear_errors();
149
        $dom = new DOMDocument();
150
        $dom->load($fileName);
151
        $xslt->importStylesheet($dom);
152
        $result = false;
153
        try {
154
            $result = $xslt->transformToXml(new SimpleXMLElement($data->getEveApiXml()));
155
        } catch (\Exception $exc) {
156
            $mess = 'XML cause SimpleXMLElement exception in';
157
            $this->getYem()
158
                ->triggerLogEvent(
159
                    'Yapeal.log.log',
160
                    Logger::WARNING,
161
                    $this->createEveApiMessage($mess, $data),
162
                    ['exception' => $exc]
163
                );
164
        }
165
        if (false === $result) {
166
            /**
167
             * @type array $errors
168
             */
169
            $errors = libxml_get_errors();
170
            if (0 !== count($errors)) {
171
                foreach ($errors as $error) {
172
                    $this->getYem()
173
                        ->triggerLogEvent('Yapeal.Log.log', Logger::NOTICE, $error->message);
174
                }
175
            }
176
        }
177
        libxml_clear_errors();
178
        libxml_use_internal_errors($oldErrors);
179
        return $result;
180
    }
181
    /**
182
     * Holds tidy config settings.
183
     *
184
     * @type array $tidyConfig
185
     */
186
    protected $tidyConfig = [
187
        'indent'        => true,
188
        'indent-spaces' => 4,
189
        'input-xml'     => true,
190
        'newline'       => 'LF',
191
        'output-xml'    => true,
192
        'wrap'          => '1000'
193
    ];
194
}
195