Completed
Push — master ( d66c3c...7db86c )
by Alex
05:11
created

AtomODataReader::EnumerateObjects()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 23
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
c 0
b 0
f 0
rs 9.0856
cc 3
eloc 17
nc 3
nop 1
1
<?php
2
namespace POData\Readers\Atom;
3
use DOMXPath;
4
use DOMDocument;
5
use ReflectionClass;
6
use ReflectionProperty;
7
use POData\Readers\IODataReader;
8
9
class AtomODataReader
10
{
11
    protected $objectContext;
12
    protected $domDocument;
13
    protected static $namespaces = array(
14
                                    'default' => 'http://www.w3.org/2005/Atom',
15
                                    'd' => 'http://schemas.microsoft.com/ado/2007/08/dataservices',
16
                                    'm' => 'http://schemas.microsoft.com/ado/2007/08/dataservices/metadata'
17
                                 );
18
    protected static $QUERY_ROOT_FEED = '/default:feed';
19
    protected static $QUERY_ROOT_ENTRY = '/default:entry';
20
    protected static $QUERY_TITLE = 'default:title';
21
    protected static $QUERY_ENTRY = 'default:entry';
22
    protected static $QUERY_ENTRY_ID = '/default:entry/default:id';
23
    protected static $QUERY_ID = 'default:id';
24
    protected static $QUERY_ENTRY_EDIT_LINK = '/default:entry/default:link[@rel="edit"]';
25
    protected static $QUERY_EDIT_LINK = 'default:link[@rel="edit"]';
26
    protected static $QUERY_FEED_OR_ENTRY_LINKS = 'default:link[@type="application/atom+xml;type=entry" or @type="application/atom+xml;type=feed"]';
27
    protected static $QUERY_EDIT_MEDIA_LINK = 'default:link[@rel="edit-media"]';
28
    protected static $QUERY_INLINE_FEED = 'm:inline/default:feed';
29
    protected static $QUERY_INLINE_ENTRY = 'm:inline/default:entry';
30
    protected static $QUERY_ENTRY_PROPERTIES = '/default:entry/default:content/m:properties/d:*';
31
    protected static $QUERY_CONTENT = 'default:content';
32
    protected static $QUERY_PROPERTIES1 = 'default:content/m:properties/d:*';
33
    protected static $QUERY_PROPERTIES2 = 'm:properties/d:*';
34
    protected static $QUERY_PROPERTY1 = 'default:content/m:properties/d:';
35
    protected static $QUERY_PROPERTY2 = 'm:properties/d:';
36
    protected static $QUERY_ERROR_MESSAGE = '/default:error/default:message';
37
    protected static $QUERY_INNER_EXCEPTION = '/default:error/default:innererror/default:internalexception/default:message';
38
    protected static $QUERY_NEXTLINK = 'default:link[@rel="next"]';
39
    protected static $QUERY_INLINECOUNT = 'm:count';
40
    protected static $QUERY_TYPE = 'm:type';
41
    protected static $ERROR_TAG = "<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">";
42
    protected $_objectIDToNextLinkUri = array();
43
    protected $_inlineCount = -1;
44
45
    /**
46
     * @param string $xml
47
     * @param ObjectContext $objectContext
48
     */
49
    public function AtomParser($xml, $objectContext)
50
    {
51
        $this->domDocument = new DOMDocument();
52
        $this->domDocument->loadXML($xml);
53
        $this->objectContext = $objectContext;
54
    }
55
56
    /**
57
     * @param QueryOperationResponse $queryOperationResponse
58
     */
59
    public function EnumerateObjects(&$queryOperationResponse)
60
    {
61
        $result = array();
62
        $xPath = new DOMXPath($this->domDocument);
63
        self::ApplyNamespace($xPath);
64
        $feeds = $xPath->query(self::$QUERY_ROOT_FEED);
65
66
        if (!$feeds->length) {
67
            $entries = $xPath->query(self::$QUERY_ROOT_ENTRY);
68
            if (!$entries->length) {
69
                throw new InternalError(Resource::XMLWithoutFeedorEntry);
70
            }
71
            $entityType;
0 ignored issues
show
Bug introduced by
The variable $entityType seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
72
            $result[] = self::EnumerateEntry($entries->item(0), $entityType);
0 ignored issues
show
Documentation introduced by
$entries->item(0) is of type object<DOMNode>, but the function expects a object<POData\Readers\Atom\DOMNode>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
73
            $this->_objectIDToNextLinkUri[0] = null;
74
        } else {
75
            $result = self::EnumerateFeed($feeds->item(0), $feedType);
0 ignored issues
show
Documentation introduced by
$feeds->item(0) is of type object<DOMNode>, but the function expects a object<POData\Readers\Atom\DOMNode>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
76
        }
77
78
        $queryOperationResponse->ObjectIDToNextLinkUrl = $this->_objectIDToNextLinkUri;
79
        $queryOperationResponse->Result = $result;
80
        $queryOperationResponse->CountValue = $this->_inlineCount;
81
    }
82
83
    /**
84
     * @param DOMNode $feed
85
     */
86
    protected function EnumerateFeed($feed, &$feedType, $parentObject = null)
87
    {
88
        $entryCollection = array();
89
        $xPath = self::GetXPathForNode($feed);
90
91
        $titles = $xPath->query(self::$QUERY_TITLE);
92
        $feedType = $titles->item(0)->nodeValue;
93
        $nextLinks = $xPath->query(self::$QUERY_NEXTLINK);
94
        $nextLinkHref = null;
95
        foreach ($nextLinks as $nextLink) {
96
            $nextLinkHref = self::GetAttribute($nextLink, "href");
97
        }
98
99
100
        $entries = $xPath->query(self::$QUERY_ENTRY);
101
        foreach ($entries as $entry) {
102
            $entryCollection[] = $this->EnumerateEntry($entry, $entityType, $parentObject);
103
        }
104
105
        if ($parentObject == null) {
106
            $this->_objectIDToNextLinkUri[0] = $nextLinkHref;
107
            $inlineCount = $xPath->query(self::$QUERY_INLINECOUNT);
108
            if ($inlineCount->length) {
109
                $this->_inlineCount = $inlineCount->item(0)->nodeValue;
0 ignored issues
show
Documentation Bug introduced by
The property $_inlineCount was declared of type integer, but $inlineCount->item(0)->nodeValue is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
110
            }
111
        } else {
112
            if (isset($entryCollection[0])) {
113
                $this->_objectIDToNextLinkUri[$entryCollection[0]->getObjectID()] = $nextLinkHref;
114
            }
115
        }
116
117
        return $entryCollection;
118
    }
119
120
    /**
121
     * @param DOMNode $entry
122
     */
123
    protected function EnumerateEntry($entry, &$entityType, $parentObject = null)
124
    {
125
        $xPath = self::GetXPathForNode($entry);
126
127
        $ids = $xPath->query(self::$QUERY_ID);
128
        $uri = $ids->item(0)->nodeValue;
129
130
        //Try to get EntitySet From edit link
131
        $entitySet = null;
132
        $editLinks = $xPath->query(self::$QUERY_EDIT_LINK);
133
        if ($editLinks->length) {
134
            $href = $this->GetAttribute($editLinks->item(0), 'href');
0 ignored issues
show
Documentation introduced by
$editLinks->item(0) is of type object<DOMNode>, but the function expects a object<POData\Readers\Atom\DOMNode>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
135
            if ($href) {
136
                if (($pos = strpos($href, '(')) !== false) {
137
                    $entitySet = substr($href, 0, $pos);
138
                }
139
            }
140
        }
141
142
        //If failed to get entity set name, then get it from url
143
        if (!$entitySet) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $entitySet of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
144
            $entitySet = Utility::GetEntitySetFromUrl($uri);
145
        }
146
147
        $entityType = $this->objectContext->GetEntityTypeNameFromSet($entitySet);
148
149
        $atomEntry = new AtomEntry();
150
        $atomEntry->Identity = $uri;
151
        $atomEntry->EntityETag = $this->GetAttribute($entry, 'm:etag');
152
153
        self::CheckAndProcessMediaLinkEntryData($xPath, $atomEntry);
154
155
        $object = $this->objectContext->AddToObjectToResource($entityType, $atomEntry);
156
157
        if ($parentObject != null) {
158
            $this->objectContext->AddToBindings($parentObject, $entitySet, $object);
159
        }
160
161
        $links = $xPath->query(self::$QUERY_FEED_OR_ENTRY_LINKS);
162
        foreach ($links as $link) {
163
            self::EnumerateFeedorEntryLink($link, $object);
164
        }
165
166
        $relLinks = self::GetRelatedLinks($links);
0 ignored issues
show
Documentation introduced by
$links is of type object<DOMNodeList>, but the function expects a object<POData\Readers\Atom\DOMNodeList>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
167
        $class = new ReflectionClass(get_class($object));
168
        $method = $class->getMethod('setRelatedLinks');
169
        $method->invoke($object, $relLinks);
170
171
172
173
        $queryProperties = self::$QUERY_PROPERTIES1;
0 ignored issues
show
Unused Code introduced by
$queryProperties is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
174
        $queryProperty = self::$QUERY_PROPERTY1;
175
        if ($atomEntry->MediaLinkEntry) {
176
            $queryProperties = self::$QUERY_PROPERTIES2;
0 ignored issues
show
Unused Code introduced by
$queryProperties is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
177
            $queryProperty = self::$QUERY_PROPERTY2;
178
        }
179
180
        $clientType = ClientType::Create($entityType);
181
        self::HandleProperties($xPath, $queryProperty, $clientType, $object);
182
        return $object;
183
    }
184
185
    protected function EnumerateFeedorEntryLink($link, $object)
186
    {
187
        $xPath = self::GetXPathForNode($link);
188
        $feeds = $xPath->query(self::$QUERY_INLINE_FEED);
189
190
        foreach ($feeds as $feed) {
191
            $entryCollection = $this->EnumerateFeed($feed, $feedType, $object);
192
            $property = new ReflectionProperty($object, $feedType);
193
            $property->setValue($object, $entryCollection);
194
        }
195
196
        $entries = $xPath->query(self::$QUERY_INLINE_ENTRY);
197
        if ($entries->length) {
198
            $entry = $this->EnumerateEntry($entries->item(0), $entryType, $object);
0 ignored issues
show
Documentation introduced by
$entries->item(0) is of type object<DOMNode>, but the function expects a object<POData\Readers\Atom\DOMNode>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
199
            $entry = array($entry);
200
            $property = new ReflectionProperty($object, $entryType);
201
            $property->setValue($object, $entry);
202
        }
203
    }
204
205
    /**
206
     * @param DOMNodeList $links
207
     */
208
    protected function GetRelatedLinks($links)
209
    {
210
        $relLinks = array();
211
        foreach ($links as $link) {
212
            $feedNode = $link->getElementsByTagNameNS(self::$namespaces['default'], 'feed');
213
            if ($feedNode->item(0) === null) {
214
                $relUri = self::GetAttribute($link, "href");
215
                $index = Utility::reverseFind($relUri, '/');
216
                $entityName = substr($relUri, $index + 1, strlen($relUri) - $index);
217
                $relLinks[$entityName] = $relUri;
218
            }
219
        }
220
        return $relLinks;
221
    }
222
223
    /**
224
     * @param DOMXPath $xPath
225
     * @param AtomEntry $atomEntry
226
     */
227
    protected static function CheckAndProcessMediaLinkEntryData($xPath, &$atomEntry)
228
    {
229
        $edit_media_links = $xPath->query(self::$QUERY_EDIT_MEDIA_LINK);
230
        if ($edit_media_links->length) {
231
            $edit_media_link = $edit_media_links->item(0);
232
            $atomEntry->EditMediaLink = self::GetAttribute($edit_media_link, 'href');
0 ignored issues
show
Documentation introduced by
$edit_media_link is of type object<DOMNode>, but the function expects a object<POData\Readers\Atom\DOMNode>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
233
            if ($atomEntry->EditMediaLink == null) {
234
                throw new InternalError(Resource::MissingEditMediaLinkInResponseBody);
235
            }
236
            $atomEntry->StreamETag = self::GetAttribute($edit_media_link, 'm:etag');
0 ignored issues
show
Documentation introduced by
$edit_media_link is of type object<DOMNode>, but the function expects a object<POData\Readers\Atom\DOMNode>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
237
        }
238
239
        $contents = $xPath->query(self::$QUERY_CONTENT);
240
        if ($contents->length) {
241
            $content = $contents->item(0);
242
            $streamUri = null;
0 ignored issues
show
Unused Code introduced by
$streamUri is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
243
            $streamUri = self::GetAttribute($content, 'src');
0 ignored issues
show
Documentation introduced by
$content is of type object<DOMNode>, but the function expects a object<POData\Readers\Atom\DOMNode>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
244
            if ($streamUri != null) {
245
                if ($content->nodeValue != null) {
246
                    throw new InternalError(Resource::ExpectedEmptyMediaLinkEntryContent);
247
                }
248
                $atomEntry->MediaLinkEntry = true;
249
                $atomEntry->MediaContentUri = $streamUri;
250
            }
251
        }
252
    }
253
254
    protected static function SetObjectProperty($object, $property)
255
    {
256
        $prefix = $property->prefix;
257
        $name = $property->nodeName;
258
259
        if ($prefix != "default") {
260
            $prefix = $prefix . ":";
261
            $pos = (($index = strpos($name, $prefix)) === false) ? 0 : $index + strlen($prefix);
262
            $name = substr($name, $pos);
263
        }
264
265
        $value = $property->nodeValue;
266
        try {
267
            $property = new ReflectionProperty($object, $name);
268
269
            //Do Atom format to PHP format conversion if required for property value ex:
270
            //if (strpos($property->getDocComment(), 'Edm.DateTime') == TRUE)
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
271
            //{
272
            //    $value = AtomDateToPHPDate()
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
273
            //}
274
275
            $property->setValue($object, $value);
276
        } catch (ReflectionException $ex) {
0 ignored issues
show
Bug introduced by
The class POData\Readers\Atom\ReflectionException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
277
            // Ignore the error at the moment. TBD later.
278
        }
279
    }
280
281
    protected function GetXPathForNode($node)
282
    {
283
        $domDocument = self::GetDomDocumentFromNode($node);
284
        $xPath = new DOMXPath($domDocument);
285
        self::ApplyNamespace($xPath);
286
        return $xPath;
287
    }
288
289
    protected function GetDomDocumentFromNode($node)
290
    {
291
        $domDocument_From_Node = new DomDocument();
292
        $domNode = $domDocument_From_Node->importNode($node, true);
293
        $domDocument_From_Node->appendChild($domNode);
294
        return $domDocument_From_Node;
295
    }
296
297
    /**
298
     * @param DOMNode $node
299
     * @param string $attributeName
300
     */
301
    protected static function GetAttribute($node, $attributeName)
302
    {
303
        $attributes = $node->attributes;
304
        foreach ($attributes as $attribute) {
305
            if ($attribute->nodeName == $attributeName) {
306
                return $attribute->value;
307
            }
308
        }
309
        //return "";
310
        return null;
311
    }
312
313
    /**
314
     * @param DOMXPath $xPath
315
     * @param string $propertyQuery
316
     */
317
    protected function HandleProperties($xPath, $propertyQuery, $clientType, $object)
318
    {
319
320
        if ($clientType->hasEPM()) {
321
            $epmProperties = $clientType->getRawEPMProperties();
322
            foreach ($epmProperties as $epmProperty) {
323
                $propertyName = $epmProperty->getName();
324
                $attributes = $epmProperty->getAttributes();
325
326
                $targetQuery = null;
0 ignored issues
show
Unused Code introduced by
$targetQuery is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
327
                $synd = false;
328
                if ($epmProperty->hasEPM($synd)) {
329
                    if ($synd) {
330
                        $targetQuery = SyndicationItemProperty::GetSyndicationItemPathwithNS($attributes['FC_TargetPath']);
331
                    } else {
332
                        $targetQuery = $attributes['FC_TargetPathNS'];
333
                        $xPath->registerNamespace($attributes['FC_NsPrefix'], $attributes['FC_NsUri']);
334
                    }
335
336
                    $nodes = $xPath->Query($targetQuery);
337
338
                    if ($nodes->length) {
339
                        $value = null;
0 ignored issues
show
Unused Code introduced by
$value is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
340
                        if (isset($attributes['NodeAttribute'])) {
341
                            $attribute = $attributes['FC_NsPrefix'] . ":" . $attributes['NodeAttribute'];
342
                            $value = self::GetAttribute($nodes->item(0), $attribute);
0 ignored issues
show
Documentation introduced by
$nodes->item(0) is of type object<DOMNode>, but the function expects a object<POData\Readers\Atom\DOMNode>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
343
                            if ((is_null($value) &&
344
                                (isset($attributes['EdmType']) &&
345
                                 ($attributes['EdmType'] == 'Edm.Int16' ||
346
                                  $attributes['EdmType'] == 'Edm.Int32' ||
347
                                  $attributes['EdmType'] == 'Edm.Int64')))) {
348
                                   $value = '0';
349
                            }
350
                        } else {
351
                            $value = null;
0 ignored issues
show
Unused Code introduced by
$value is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
352
                            if ($nodes->item(0)->hasChildNodes()) {
353
                                $value = $nodes->item(0)->firstChild->textContent;
354
                            } else {
355
                                $value = $nodes->item(0)->nodeValue;
356
                            }
357
358
                            if (empty($value)) {
359
                                $query1 = $propertyQuery . $propertyName;
360
                                $nodes1 = $xPath->Query($query1);
361
                                if ($nodes1->length) {
362
                                    $value1 = self::GetAttribute($nodes1->item(0), "m:null");
0 ignored issues
show
Documentation introduced by
$nodes1->item(0) is of type object<DOMNode>, but the function expects a object<POData\Readers\Atom\DOMNode>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
363
                                    if ($value1 == 'true') {
364
                                        $value = null;
365
                                    }
366
                                }
367
                            }
368
                        }
369
370
                        $property = new ReflectionProperty($object, $propertyName);
371
                        $property->setValue($object, $value);
372
                    } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
373
                        //NOTE: Atom Entry not contains $targetQuery node its
374
                        //an error, becase in the case of projection also
375
                        //custmerizable feeds will be there.
376
                        //
377
                    }
378
                }
379
            }
380
        }
381
382
        $nonEpmProperties = $clientType->getRawNonEPMProperties(true);
383
        foreach ($nonEpmProperties as $nonEpmProperty) {
384
            $propertyName = $nonEpmProperty->getName();
385
            $propertyAttributes = $nonEpmProperty->getAttributes();
386
387
            //Now check for complex type. If type not start with 'Edm.'
388
            //it can be a complex type.
389
            if (isset($propertyAttributes['EdmType']) &&
390
               strpos($propertyAttributes['EdmType'], 'Edm.') !== 0) {
391
                $complexPropertyObject = null;
392
                $complexPropertyName = '';
393
                if ($this->CheckAndProcessComplexType($xPath, $propertyQuery, $propertyName, $complexPropertyName, $complexPropertyObject)) {
394
                    $property = new ReflectionProperty($object, $complexPropertyName);
395
                    $property->setValue($object, $complexPropertyObject);
396
                    continue;
397
                }
398
            }
399
400
            $query = $propertyQuery . $propertyName;
401
            $nodes = $xPath->Query($query);
402
            if ($nodes->length) {
403
                $value = $nodes->item(0)->nodeValue;
404
                $property = new ReflectionProperty($object, $propertyName);
405
                $property->setValue($object, $value);
406
            } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
407
                //NOTE: Atom Entry not contains the required property
408
                //not a bug projection can lead to this case
409
            }
410
        }
411
    }
412
413
    /**
414
     * Check whether the in $xPath (which represents an entity), the
415
     * $propertyQuery.$propertyName represents a complex, if so
416
     * create an object of that type, polpulate it and return it.
417
     * @param DOMXPath $xPath
418
     * @param string $propertyQuery
419
     * @param string $propertyName
420
     * @param type [out] $complexPropertyName
421
     * @param type [out] $complexPropertyObject
422
     * @param string $complexPropertyName
423
     * @return bool
424
     */
425
    protected function CheckAndProcessComplexType($xPath, $propertyQuery, $propertyName, &$complexPropertyName, &$complexPropertyObject)
426
    {
427
        //Check and Process Complex Type
428
        //
429
        //make query string ex: "/m:properties/d:BoxArt"
430
        $query = $propertyQuery . $propertyName;
431
        $nodes = $xPath->Query($query);
432
        if (!$nodes->length) {
433
            return false;
434
        }
435
436
        //<d:BoxArt m:type="NetflixCatalog.BoxArt">
437
        //<d:MediumUrl>..</d:MediumUrl>
438
        //<d:SmallUrl>..</d:SmallUrl>
439
        //<d:LargeUrl>..</d:LargeUrl>
440
        //<d:HighDefinitionUrl m:null="true" />
441
        //</d:BoxArt>
442
        $type = $this->GetAttribute($nodes->item(0), 'm:type');
443
444
        if (!$type) {
445
            return false;
446
        }
447
448
        $complexType = '';
0 ignored issues
show
Unused Code introduced by
$complexType is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
449
450
        //got NetflixCatalog.BoxArt
451
        $pisces = explode('.', $type);
452
        if (count($pisces) == 1) {
453
            $complexType = $pisces[0];
454
        } else {
455
            $complexType = $pisces[1];
456
        }
457
458
        try {
459
            $complexClientType = ClientType::Create($complexType);
460
            //here if complex def found
461
            $xPathComplex = self::GetXPathForNode($nodes->item(0));
462
            $class = new ReflectionClass($complexType);
463
            $complexPropertyObject = $class->newInstance();
464
            $complexPropertyName = $propertyName;
465
            $this->HandleProperties($xPathComplex, 'd:', $complexClientType, $complexPropertyObject);
466
        } catch (ReflectionException $exception) {
0 ignored issues
show
Bug introduced by
The class POData\Readers\Atom\ReflectionException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
467
            //if no class definition is there in proxy, just continue
468
            //for raw copy
469
            return false;
470
        }
471
472
        return true;
473
    }
474
475
    /**
476
     * @param DOMXPath $xPath
477
     */
478
    protected static function ApplyNamespace($xPath)
479
    {
480
        foreach (self::$namespaces as $prefix => $namespaceURI) {
481
            $xPath->registerNamespace($prefix, $namespaceURI);
482
        }
483
    }
484
485
    /**
486
     * @param string $atomXML
487
     */
488
    public static function PopulateObject($atomXML, $object, &$uri, &$atomEntry)
489
    {
490
        $domDocument = new DomDocument();
491
        $domDocument->loadXML($atomXML);
492
        $xPath = new DOMXPath($domDocument);
493
        self::ApplyNamespace($xPath);
494
        $ids = $xPath->query(self::$QUERY_ENTRY_ID);
495
        $uri = $ids->item(0)->nodeValue;
496
497
        $properties = $xPath->query(self::$QUERY_ENTRY_PROPERTIES);
498
        foreach ($properties as $property) {
499
            self::SetObjectProperty($object, $property);
500
        }
501
502
        $atomEntry = new AtomEntry();
503
        ;
504
        self::CheckAndProcessMediaLinkEntryData($xPath, $atomEntry);
505
    }
506
507
    /**
508
     * @param string $atomXML
509
     */
510
    public static function PopulateMediaEntryKeyFields($atomXML, $object)
511
    {
512
        $domDocument = new DomDocument();
513
        $domDocument->loadXML($atomXML);
514
        $xPath = new DOMXPath($domDocument);
515
        self::ApplyNamespace($xPath);
516
517
        $type = ClientType::Create(get_class($object));
518
        $keyPropertyNames = $type->geyKeyProperties();
519
        foreach ($keyPropertyNames as $keyPropertyName) {
520
            $properties = $xPath->query(self::$QUERY_PROPERTY2 . $keyPropertyName);
521
            if ($properties->length) {
522
                $value = $properties->item(0)->nodeValue;
523
                $refProp = new ReflectionProperty($object, $keyPropertyName);
524
                $refProp->setValue($object, $value);
525
            }
526
        }
527
    }
528
529
    /**
530
     * @param string $atomXML
531
     */
532
    public static function GetEntityEtag($atomXML)
533
    {
534
        $domDocument = new DomDocument();
535
        $domDocument->loadXML($atomXML);
536
        $xPath = new DOMXPath($domDocument);
537
        self::ApplyNamespace($xPath);
538
        $entries = $xPath->query(self::$QUERY_ROOT_ENTRY);
539
        if ($entries->length) {
540
            return self::GetAttribute($entries->item(0), 'm:etag');
541
        }
542
543
        return null;
544
    }
545
546
    /**
547
     * @param string $errorXML
548
     */
549
    public static function GetErrorDetails($errorXML, &$outerError, &$innnerError)
550
    {
551
        if (strstr($errorXML, self::$ERROR_TAG) === false) {
552
            $innerError = "";
0 ignored issues
show
Unused Code introduced by
$innerError is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
553
            $outerError = $errorXML;
554
        } else {
555
            $errorXML = str_replace("innererror xmlns=\"xmlns\"", "innererror", $errorXML);
556
            $domDocument = new DOMDocument();
557
            $domDocument->loadXML($errorXML);
558
559
            $xPath = new DOMXPath($domDocument);
560
            $xPath->registerNamespace('default', self::$namespaces['m']);
561
562
            $outerErrors = $xPath->query(self::$QUERY_ERROR_MESSAGE);
563
            if ($outerErrors->length) {
564
                $outerError = $outerErrors->item(0)->nodeValue;
565
            }
566
567
            $innerErrors = $xPath->query(self::$QUERY_INNER_EXCEPTION);
568
            if ($innerErrors->length) {
569
                $innnerError = $innerErrors->item(0)->nodeValue;
570
            }
571
        }
572
    }
573
}
574