GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Pull Request — master (#2843)
by Brendan
04:11
created

DynamicXMLDatasource::execute()   F

Complexity

Conditions 32
Paths 784

Size

Total Lines 186
Code Lines 103

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 32
eloc 103
c 0
b 0
f 0
nc 784
nop 1
dl 0
loc 186
rs 2.1166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * @package data-sources
5
 */
6
/**
7
 * The `DynamicXMLDatasource` allows a user to retrieve XML from an URL.
8
 * This datasource supports namespaces, partial results using XPath and
9
 * caching the result for a number of minutes.
10
 *
11
 * @since Symphony 2.3
12
 *
13
 * @deprecated As of Symphony 2.6.0 this class is deprecated. Please
14
 * use the Remote Datasource extensions since it provides more features and
15
 * is more robust. It should be completely removed in Symphony 3.
16
 *
17
 */
18
19
require_once TOOLKIT . '/class.gateway.php';
0 ignored issues
show
Bug introduced by
The constant TOOLKIT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
20
require_once TOOLKIT . '/class.xsltprocess.php';
21
require_once CORE . '/class.cacheable.php';
0 ignored issues
show
Bug introduced by
The constant CORE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
22
23
class DynamicXMLDatasource extends Datasource
24
{
25
    public function __construct($env = null, $process_params = true)
26
    {
27
        if (Symphony::Log()) {
28
            Symphony::Log()->pushDeprecateWarningToLog('new DynamicXMLDatasource()', 'new RemoteDatasource()', array(
29
                'alternative-format' => __('Please install the Remote Datasource extension and use `%s` instead.'),
30
            ));
31
        }
32
        parent::__construct($env, $process_params);
33
    }
34
35
    public function execute(array &$param_pool = null)
36
    {
37
        $result = new XMLElement($this->dsParamROOTELEMENT);
0 ignored issues
show
Bug Best Practice introduced by
The property dsParamROOTELEMENT does not exist on DynamicXMLDatasource. Did you maybe forget to declare it?
Loading history...
38
39
        $this->dsParamURL = $this->parseParamURL($this->dsParamURL);
0 ignored issues
show
Bug Best Practice introduced by
The property dsParamURL does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
40
41
        if (isset($this->dsParamXPATH)) {
42
            $this->dsParamXPATH = $this->__processParametersInString($this->dsParamXPATH, $this->_env);
0 ignored issues
show
Bug Best Practice introduced by
The property dsParamXPATH does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
43
        }
44
45
        $stylesheet = new XMLElement('xsl:stylesheet');
46
        $stylesheet->setAttributeArray(array('version' => '1.0', 'xmlns:xsl' => 'http://www.w3.org/1999/XSL/Transform'));
47
48
        $output = new XMLElement('xsl:output');
49
        $output->setAttributeArray(array('method' => 'xml', 'version' => '1.0', 'encoding' => 'utf-8', 'indent' => 'yes', 'omit-xml-declaration' => 'yes'));
50
        $stylesheet->appendChild($output);
51
52
        $template = new XMLElement('xsl:template');
53
        $template->setAttribute('match', '/');
54
55
        $instruction = new XMLElement('xsl:copy-of');
56
57
        // Namespaces
58
        if (isset($this->dsParamFILTERS) && is_array($this->dsParamFILTERS)) {
59
            foreach ($this->dsParamFILTERS as $name => $uri) {
60
                $instruction->setAttribute('xmlns' . ($name ? ":{$name}" : null), $uri);
61
            }
62
        }
63
64
        // XPath
65
        $instruction->setAttribute('select', $this->dsParamXPATH);
66
67
        $template->appendChild($instruction);
68
        $stylesheet->appendChild($template);
69
70
        $stylesheet->setIncludeHeader(true);
71
72
        $xsl = $stylesheet->generate(true);
73
74
        $cache_id = md5($this->dsParamURL . serialize($this->dsParamFILTERS) . $this->dsParamXPATH);
75
76
        $cache = new Cacheable(Symphony::Database());
0 ignored issues
show
Bug introduced by
Symphony::Database() of type MySQL is incompatible with the type iCache expected by parameter $cacheProvider of Cacheable::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

76
        $cache = new Cacheable(/** @scrutinizer ignore-type */ Symphony::Database());
Loading history...
77
78
        $cachedData = $cache->read($cache_id);
79
        $writeToCache = false;
80
        $valid = true;
81
        $creation = DateTimeObj::get('c');
82
        $timeout = (isset($this->dsParamTIMEOUT)) ? (int)max(1, $this->dsParamTIMEOUT) : 6;
0 ignored issues
show
Bug introduced by
The property dsParamTIMEOUT does not exist on DynamicXMLDatasource. Did you mean dsParamLIMIT?
Loading history...
83
84
        // Execute if the cache doesn't exist, or if it is old.
85
        if (
86
            (!is_array($cachedData) || empty($cachedData)) // There's no cache.
87
            || (time() - $cachedData['creation']) > ($this->dsParamCACHE * 60) // The cache is old.
0 ignored issues
show
Bug introduced by
The property dsParamCACHE does not exist on DynamicXMLDatasource. Did you mean dsParamXPATH?
Loading history...
88
        ) {
89
            if (Mutex::acquire($cache_id, $timeout, TMP)) {
0 ignored issues
show
Bug introduced by
The method acquire() does not exist on Mutex. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

89
            if (Mutex::/** @scrutinizer ignore-call */ acquire($cache_id, $timeout, TMP)) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The constant TMP was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
90
                $ch = new Gateway;
91
                $ch->init($this->dsParamURL);
92
                $ch->setopt('TIMEOUT', $timeout);
93
                $ch->setopt('HTTPHEADER', array('Accept: text/xml, */*'));
94
95
                $data = $ch->exec();
96
                $info = $ch->getInfoLast();
97
98
                Mutex::release($cache_id, TMP);
0 ignored issues
show
Bug introduced by
The method release() does not exist on Mutex. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

98
                Mutex::/** @scrutinizer ignore-call */ 
99
                       release($cache_id, TMP);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
99
100
                $data = trim($data);
101
                $writeToCache = true;
102
103
                // Handle any response that is not a 200, or the content type does not include XML, plain or text
104
                if ((int)$info['http_code'] !== 200 || !preg_match('/(xml|plain|text)/i', $info['content_type'])) {
105
                    $writeToCache = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $writeToCache is dead and can be removed.
Loading history...
106
107
                    $result->setAttribute('valid', 'false');
108
109
                    // 28 is CURLE_OPERATION_TIMEOUTED
110
                    if ($info['curl_error'] == 28) {
111
                        $result->appendChild(
112
                            new XMLElement('error',
113
                                sprintf('Request timed out. %d second limit reached.', $timeout)
114
                            )
115
                        );
116
                    } else {
117
                        $result->appendChild(
118
                            new XMLElement('error',
119
                                sprintf('Status code %d was returned. Content-type: %s', $info['http_code'], $info['content_type'])
120
                            )
121
                        );
122
                    }
123
124
                    return $result;
125
126
                    // Handle where there is `$data`
127
                } elseif (strlen($data) > 0) {
128
                    // If the XML doesn't validate..
129
                    if (!General::validateXML($data, $errors, false, new XsltProcess)) {
130
                        $writeToCache = false;
131
                    }
132
133
                    // If the `$data` is invalid, return a result explaining why
134
                    if ($writeToCache === false) {
135
                        $element = new XMLElement('errors');
136
137
                        $result->setAttribute('valid', 'false');
138
139
                        $result->appendChild(new XMLElement('error', __('Data returned is invalid.')));
140
141
                        foreach ($errors as $e) {
142
                            if (strlen(trim($e['message'])) == 0) {
143
                                continue;
144
                            }
145
146
                            $element->appendChild(new XMLElement('item', General::sanitize($e['message'])));
147
                        }
148
149
                        $result->appendChild($element);
150
151
                        return $result;
152
                    }
153
154
                    // If `$data` is empty, set the `force_empty_result` to true.
155
                } elseif (strlen($data) == 0) {
156
                    $this->_force_empty_result = true;
157
                }
158
159
                // Failed to acquire a lock
160
            } else {
161
                $result->appendChild(
162
                    new XMLElement('error', __('The %s class failed to acquire a lock, check that %s exists and is writable.', array(
163
                        '<code>Mutex</code>',
164
                        '<code>' . TMP . '</code>'
165
                    )))
166
                );
167
            }
168
169
            // The cache is good, use it!
170
        } else {
171
            $data = trim($cachedData['data']);
172
            $creation = DateTimeObj::get('c', $cachedData['creation']);
173
        }
174
175
        // If `$writeToCache` is set to false, invalidate the old cache if it existed.
176
        if (is_array($cachedData) && !empty($cachedData) && $writeToCache === false) {
177
            $data = trim($cachedData['data']);
178
            $valid = false;
179
            $creation = DateTimeObj::get('c', $cachedData['creation']);
180
181
            if (empty($data)) {
182
                $this->_force_empty_result = true;
183
            }
184
        }
185
186
        // If `force_empty_result` is false and `$result` is an instance of
187
        // XMLElement, build the `$result`.
188
        if (!$this->_force_empty_result && is_object($result)) {
189
            $proc = new XsltProcess;
190
            $ret = $proc->process($data, $xsl);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $data does not seem to be defined for all execution paths leading up to this point.
Loading history...
191
192
            if ($proc->isErrors()) {
193
                $result->setAttribute('valid', 'false');
194
                $error = new XMLElement('error', __('Transformed XML is invalid.'));
195
                $result->appendChild($error);
196
                $element = new XMLElement('errors');
197
198
                foreach ($proc->getError() as $e) {
199
                    if (strlen(trim($e['message'])) == 0) {
200
                        continue;
201
                    }
202
203
                    $element->appendChild(new XMLElement('item', General::sanitize($e['message'])));
204
                }
205
206
                $result->appendChild($element);
207
            } elseif (strlen(trim($ret)) == 0) {
0 ignored issues
show
Bug introduced by
It seems like $ret can also be of type false; however, parameter $str of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

207
            } elseif (strlen(trim(/** @scrutinizer ignore-type */ $ret)) == 0) {
Loading history...
208
                $this->_force_empty_result = true;
209
            } else {
210
                if ($writeToCache) {
211
                    $cache->write($cache_id, $data, $this->dsParamCACHE);
212
                }
213
214
                $result->setValue(PHP_EOL . str_repeat("\t", 2) . preg_replace('/([\r\n]+)/', "$1\t", $ret));
215
                $result->setAttribute('status', ($valid === true ? 'fresh' : 'stale'));
216
                $result->setAttribute('creation', $creation);
0 ignored issues
show
Bug introduced by
It seems like $creation can also be of type false; however, parameter $value of XMLElement::setAttribute() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

216
                $result->setAttribute('creation', /** @scrutinizer ignore-type */ $creation);
Loading history...
217
            }
218
        }
219
220
        return $result;
221
    }
222
}
223