NorthWindQueryProvider::getRelatedResourceSet()   C
last analyzed

Complexity

Conditions 9
Paths 11

Size

Total Lines 46
Code Lines 34

Duplication

Lines 32
Ratio 69.57 %

Importance

Changes 0
Metric Value
dl 32
loc 46
rs 5.0942
c 0
b 0
f 0
cc 9
eloc 34
nc 11
nop 9

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 11 and the first side effect is on line 8.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
use POData\UriProcessor\ResourcePathProcessor\SegmentParser\KeyDescriptor;
4
use POData\Providers\Metadata\ResourceSet;
5
use POData\Providers\Metadata\ResourceProperty;
6
use POData\Providers\Query\IQueryProvider;
7
use POData\Common\ODataException;
8
require_once "NorthWindMetadata.php";
9
require_once "POData\Providers\Query\IDataServiceQueryProvider2.php";
10
require_once 'NorthWindDSExpressionProvider.php';
11
define('DATABASE', 'Northwind');
12
// Note: The instance name of your sql server [How to find instance name]
13
// Start ->All progrmas->Microsoft SQL Server 2008 -> Configuration Tools -> SQL Server Configuration Manager
14
// In Configuration Manager -> SQL Server 2008 Services -> double click the SQL Service -> click the Service Tab.
15
define('SERVER', '.\SQLEXPRESS');
16
// Note: If your database access require credentials then un-comment 
17
// the following two lines [definition of UID and PWD] and provide db user name 
18
// as value for UID and password as value for PWD.
19
// define('UID',  '');
20
// define('PWD',  '');
21
22
23
class NorthWindQueryProvider implements IQueryProvider
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
24
{
25
    /**
26
     * Handle to connection to Database     
27
     */
28
    private $_connectionHandle = null;
29
30
    /**
31
     * Reference to the custom expression provider
32
     * 
33
     * @var NorthWindDSExpressionProvider
34
     */
35
    private $_northWindSQLSRVExpressionProvider;
36
37
    /**
38
     * Constructs a new instance of NorthWindQueryProvider
39
     * 
40
     */
41
    public function __construct()
42
    {
43
    	$connectionInfo = array("Database" => DATABASE);
44
        if (defined('UID')) {
45
        	$connectionInfo['UID'] = UID;
46
        	$connectionInfo['PWD'] = PWD;    		
47
    	}
48
49
        $this->_connectionHandle = sqlsrv_connect(SERVER, $connectionInfo);
50
        if ( $this->_connectionHandle ) {        	
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies 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 if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

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

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
51
        } else {
52
            $errorAsString = self::_getSQLSRVError();
53
        	throw ODataException::createInternalServerError($errorAsString);
54
        }
55
56
        $this->_northWindSQLSRVExpressionProvider = null;
57
    }
58
59
    /**
60
     * (non-PHPdoc)
61
     * @see POData\Providers\Query.IQueryProvider::canApplyQueryOptions()
62
     */
63
    public function handlesOrderedPaging()
64
    {
65
        return true;
66
    }
67
68
    /**
69
     * (non-PHPdoc)
70
     * @see POData\Providers\Query.IQueryProvider::getExpressionProvider()
71
     */
72
    public function getExpressionProvider()
73
    {
74
    	if (is_null($this->_northWindSQLSRVExpressionProvider)) {
75
    		$this->_northWindSQLSRVExpressionProvider = new NorthWindDSExpressionProvider();
76
    	}
77
78
    	return $this->_northWindSQLSRVExpressionProvider;
79
    }
80
81
    /**
82
     * Gets collection of entities belongs to an entity set
83
     * 
84
     * @param ResourceSet $resourceSet        The entity set whose entities 
85
     *                                        needs to be fetched.
86
     * @param string           $filterOption  Contains the filter condition
87
     * @param string           $select        For future purpose,no need to pass it
88
     * @param string           $orderby       For future purpose,no need to pass it
89
     * @param string           $top           For future purpose,no need to pass it
90
     * @param string           $skip          For future purpose,no need to pass it
91
     * 
92
     * @return array(Object)
0 ignored issues
show
Documentation introduced by
The doc-type array(Object) could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
93
     */
94
    public function getResourceSet(ResourceSet $resourceSet, $filterOption = null, 
95
        $select=null, $orderby=null, $top=null, $skip=null
96
    ) {
97
        $resourceSetName =  $resourceSet->getName();
98 View Code Duplication
        if ($resourceSetName !== 'Customers' 
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
99
            && $resourceSetName !== 'Orders' 
100
            && $resourceSetName !== 'Order_Details'
101
            && $resourceSetName !== 'Employees'
102
        ) {
103
        	throw ODataException::createInternalServerError('(NorthWindQueryProvider) Unknown resource set ' . $resourceSetName . '! Contact service provider');
104
        }
105
106
        if ($resourceSetName === 'Order_Details') {
107
            $resourceSetName = 'Order Details';
108
        }
109
110
        $query = "SELECT * FROM [$resourceSetName]";
111
        if ($filterOption != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $filterOption of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
112
            $query .= ' WHERE ' . $filterOption;
113
        }
114
        $stmt = sqlsrv_query($this->_connectionHandle, $query);
115
        if ($stmt === false) {
116
            $errorAsString = self::_getSQLSRVError();
117
        	throw ODataException::createInternalServerError($errorAsString);
118
        }
119
        $returnResult = array();
120 View Code Duplication
        switch ($resourceSetName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
121
        case 'Customers':
122
            $returnResult = $this->_serializeCustomers($stmt);
123
            break;
124
        case 'Orders':
125
            $returnResult = $this->_serializeOrders($stmt);
126
            break;
127
        case 'Order Details':
128
            $returnResult = $this->_serializeOrderDetails($stmt);
129
            break;
130
        case 'Employees':
131
            $returnResult = $this->_serializeEmployees($stmt);
132
            break;
133
        }
134
        sqlsrv_free_stmt($stmt);
135
        return $returnResult;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $returnResult; (array) is incompatible with the return type declared by the interface POData\Providers\Query\I...rovider::getResourceSet of type POData\Providers\Query\QueryResult.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
136
    }
137
138
    /**
139
     * Gets an entity instance from an entity set identifed by a key
140
     * 
141
     * @param ResourceSet   $resourceSet   The entity set from which 
142
     *                                     an entity needs to be fetched
143
     * @param KeyDescriptor $keyDescriptor The key to identify the entity to be fetched
144
     * 
145
     * @return object|null Returns entity instance if found else null
146
     */
147
    public function getResourceFromResourceSet(ResourceSet $resourceSet, KeyDescriptor $keyDescriptor)
148
    {   
149
        $resourceSetName =  $resourceSet->getName();
150 View Code Duplication
        if ($resourceSetName !== 'Customers' 
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
151
            && $resourceSetName !== 'Orders' 
152
            && $resourceSetName !== 'Order_Details' 
153
            && $resourceSetName !== 'Products' 
154
            && $resourceSetName !== 'Employees'
155
        ) {
156
            die('(NorthWindQueryProvider) Unknown resource set ' . $resourceSetName);    
0 ignored issues
show
Coding Style Compatibility introduced by
The method getResourceFromResourceSet() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
157
        }
158
159
        if ($resourceSetName === 'Order_Details') {
160
            $resourceSetName = 'Order Details';
161
        }
162
163
        $namedKeyValues = $keyDescriptor->getValidatedNamedValues();
164
        $condition = null;
165
        foreach ($namedKeyValues as $key => $value) {
166
            $condition .= $key . ' = ' . $value[0] . ' and ';
167
        }
168
169
        $len = strlen($condition);
170
        $condition = substr($condition, 0, $len - 5); 
171
        $query = "SELECT * FROM [$resourceSetName] WHERE $condition";
172
        $stmt = sqlsrv_query($this->_connectionHandle, $query);
173
        if ($stmt === false) {
174
            $errorAsString = self::_getSQLSRVError();
175
        	throw ODataException::createInternalServerError($errorAsString);
176
        }
177
178
        //If resource not found return null to the library
179
        if (!sqlsrv_has_rows($stmt)) {
180
            return null;
181
        }
182
183
        $result = null;
184
        while ( $record = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
185 View Code Duplication
            switch ($resourceSetName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
186
            case 'Customers':
187
                $result = $this->_serializeCustomer($record);
188
                break;
189
            case 'Orders':                    
190
                $result = $this->_serializeOrder($record);
191
                break;
192
            case 'Order Details':                    
193
                $result = $this->_serializeOrderDetail($record);
194
                break;
195
            case 'Employees':
196
                $result = $this->_serializeEmployee($record);
197
                break;
198
            }
199
        }
200
        sqlsrv_free_stmt($stmt);
201
        return $result;
202
    }
203
    
204
    /**
205
     * Gets a related entity instance from an entity set identifed by a key
206
     * 
207
     * @param ResourceSet      $sourceResourceSet    The entity set related to
208
     *                                               the entity to be fetched.
209
     * @param object           $sourceEntityInstance The related entity instance.
210
     * @param ResourceSet      $targetResourceSet    The entity set from which
211
     *                                               entity needs to be fetched.
212
     * @param ResourceProperty $targetProperty       The metadata of the target 
213
     *                                               property.
214
     * @param KeyDescriptor    $keyDescriptor        The key to identify the entity 
215
     *                                               to be fetched.
216
     * 
217
     * @return object|null Returns entity instance if found else null
218
     */
219
    public function  getResourceFromRelatedResourceSet(ResourceSet $sourceResourceSet, 
220
        $sourceEntityInstance, 
221
        ResourceSet $targetResourceSet,
222
        ResourceProperty $targetProperty,
223
        KeyDescriptor $keyDescriptor
224
    ) {
225
        $result = array();
226
        $srcClass = get_class($sourceEntityInstance);
227
        $navigationPropName = $targetProperty->getName();
228
        $key = null;
229
        foreach ($keyDescriptor->getValidatedNamedValues() as $keyName => $valueDescription) {
230
            $key = $key . $keyName . '=' . $valueDescription[0] . ' and ';
231
        }
232
233
        $key = rtrim($key, ' and ');
234
        if ($srcClass === 'Customer') {
235 View Code Duplication
            if ($navigationPropName === 'Orders') {                
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
236
                $query = "SELECT * FROM Orders WHERE CustomerID = '$sourceEntityInstance->CustomerID' and $key";
237
                $stmt = sqlsrv_query($this->_connectionHandle, $query);
238
                if ($stmt === false) {            
239
                    $errorAsString = self::_getSQLSRVError();
240
        	        throw ODataException::createInternalServerError($errorAsString);
241
                }
242
243
                $result = $this->_serializeOrders($stmt);
244
            } else {
245
                die('Customer does not have navigation porperty with name: ' . $navigationPropName);
0 ignored issues
show
Coding Style Compatibility introduced by
The method getResourceFromRelatedResourceSet() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
246
            }            
247 View Code Duplication
        } else if ($srcClass === 'Order') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
248
            if ($navigationPropName === 'Order_Details') {
249
                $query = "SELECT * FROM [Order Details] WHERE OrderID = $sourceEntityInstance->OrderID";
250
                $stmt = sqlsrv_query($this->_connectionHandle, $query);
251
                if ($stmt === false) {            
252
                    $errorAsString = self::_getSQLSRVError();
253
        	        throw ODataException::createInternalServerError($errorAsString);
254
                }
255
256
                $result = $this->_serializeOrderDetails($stmt);
257
            } else {
258
                die('Order does not have navigation porperty with name: ' . $navigationPropName);
0 ignored issues
show
Coding Style Compatibility introduced by
The method getResourceFromRelatedResourceSet() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
259
            }
260
        } 
261
262
        return empty($result) ? null : $result[0];
263
        
264
    }
265
266
    /**
267
     * Get related resource set for a resource
268
     * 
269
     * @param ResourceSet      $sourceResourceSet    The source resource set
270
     * @param mixed            $sourceEntityInstance The resource
271
     * @param ResourceSet      $targetResourceSet    The resource set of 
272
     *                                               the navigation property
273
     * @param ResourceProperty $targetProperty       The navigation property to be 
274
     *                                               retrieved
275
     * @param string           $filterOption         Contains the filter condition 
276
     *                                               to append with query.
277
     * @param string           $select               For future purpose,no need to pass it
278
     * @param string           $orderby              For future purpose,no need to pass it
279
     * @param string           $top                  For future purpose,no need to pass it
280
     * @param string           $skip                 For future purpose,no need to pass it
281
     *                                                
282
     * @return object[] Array of related resource if exists, if no 
283
     *                                related resources found returns empty array
284
     */
285
    public function  getRelatedResourceSet(ResourceSet $sourceResourceSet, 
286
        $sourceEntityInstance, 
287
        ResourceSet $targetResourceSet,
288
        ResourceProperty $targetProperty, 
289
        $filterOption = null,
290
        $select=null, $orderby=null, $top=null, $skip=null
291
    ) {    
292
        $result = array();
293
        $srcClass = get_class($sourceEntityInstance);
294
        $navigationPropName = $targetProperty->getName();
295
        if ($srcClass === 'Customer') {
296 View Code Duplication
            if ($navigationPropName === 'Orders') {                
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
297
                $query = "SELECT * FROM Orders WHERE CustomerID = '$sourceEntityInstance->CustomerID'";
298
                if ($filterOption != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $filterOption of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
299
                    $query .= ' AND ' . $filterOption;
300
                }
301
                $stmt = sqlsrv_query($this->_connectionHandle, $query);
302
                if ($stmt === false) {
303
                    $errorAsString = self::_getSQLSRVError();
304
        	        throw ODataException::createInternalServerError($errorAsString);
305
                }
306
307
                $result = $this->_serializeOrders($stmt);
308
            } else {
309
                die('Customer does not have navigation porperty with name: ' . $navigationPropName);
0 ignored issues
show
Coding Style Compatibility introduced by
The method getRelatedResourceSet() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
310
            }            
311 View Code Duplication
        } else if ($srcClass === 'Order') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
312
            if ($navigationPropName === 'Order_Details') {
313
                $query = "SELECT * FROM [Order Details] WHERE OrderID = $sourceEntityInstance->OrderID";
314
                if ($filterOption != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $filterOption of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
315
                    $query .= ' AND ' . $filterOption;
316
                }
317
                $stmt = sqlsrv_query($this->_connectionHandle, $query);
318
                if ($stmt === false) {            
319
                    $errorAsString = self::_getSQLSRVError();
320
        	        throw ODataException::createInternalServerError($errorAsString);
321
                }
322
323
                $result = $this->_serializeOrderDetails($stmt);
324
            } else {
325
                die('Order does not have navigation porperty with name: ' . $navigationPropName);
0 ignored issues
show
Coding Style Compatibility introduced by
The method getRelatedResourceSet() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
326
            }
327
        }
328
329
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $result; (array) is incompatible with the return type declared by the interface POData\Providers\Query\I...::getRelatedResourceSet of type POData\Providers\Query\QueryResult.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
330
    }
331
332
    /**
333
     * Get related resource for a resource
334
     * 
335
     * @param ResourceSet      $sourceResourceSet    The source resource set
336
     * @param mixed            $sourceEntityInstance The source resource
337
     * @param ResourceSet      $targetResourceSet    The resource set of 
338
     *                                               the navigation property
339
     * @param ResourceProperty $targetProperty       The navigation property to be 
340
     *                                               retrieved
341
     * 
342
     * @return object|null The related resource if exists else null
343
     */
344
    public function getRelatedResourceReference(ResourceSet $sourceResourceSet, 
345
        $sourceEntityInstance, 
346
        ResourceSet $targetResourceSet,
347
        ResourceProperty $targetProperty
348
    ) {
349
        $result = null;
350
        $srcClass = get_class($sourceEntityInstance);
351
        $navigationPropName = $targetProperty->getName();
352
        if ($srcClass === 'Order') {
353 View Code Duplication
            if ($navigationPropName === 'Customer') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
354
                if (empty($sourceEntityInstance->CustomerID)) {
355
                    $result = null;
356
                } else {                    
357
                    $query = "SELECT * FROM Customers WHERE CustomerID = '$sourceEntityInstance->CustomerID'";                
358
                    $stmt = sqlsrv_query($this->_connectionHandle, $query);
359
                    if ($stmt === false) {
360
                        $errorAsString = self::_getSQLSRVError();
361
        	            throw ODataException::createInternalServerError($errorAsString);
362
                    }
363
364
                    if (!sqlsrv_has_rows($stmt)) {
365
                        $result =  null;
0 ignored issues
show
Unused Code introduced by
$result 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...
366
                    }
367
368
                    $result = $this->_serializeCustomer(sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC));
369
                }
370
            } else {
371
                die('Customer does not have navigation porperty with name: ' . $navigationPropName);
0 ignored issues
show
Coding Style Compatibility introduced by
The method getRelatedResourceReference() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
372
            }            
373 View Code Duplication
        } else if ($srcClass === 'Order_Details') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
374
            if ($navigationPropName === 'Order') {
375
                if (empty($sourceEntityInstance->OrderID)) {
376
                    $result = null;
377
                } else {
378
                    $query = "SELECT * FROM Orders WHERE OrderID = $sourceEntityInstance->OrderID";
379
                    $stmt = sqlsrv_query($this->_connectionHandle, $query);
380
                    if ($stmt === false) {
381
                        $errorAsString = self::_getSQLSRVError();
382
        	            throw ODataException::createInternalServerError($errorAsString);
383
                    }
384
                    
385
                    if (!sqlsrv_has_rows($stmt)) {
386
                        $result =  null;
0 ignored issues
show
Unused Code introduced by
$result 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...
387
                    }
388
                    
389
                    $result = $this->_serializeOrder(sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC));
390
                }
391
            } else {
392
                die('Order_Details does not have navigation porperty with name: ' . $navigationPropName);
0 ignored issues
show
Coding Style Compatibility introduced by
The method getRelatedResourceReference() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
393
            }
394
        } 
395
396
        return $result;
397
    }
398
399
    /**
400
     * Serialize the sql result array into Customer objects
401
     * 
402
     * @param array(array) $result result of the sql query
0 ignored issues
show
Documentation introduced by
The doc-type array(array) could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
403
     * 
404
     * @return array(Object)
0 ignored issues
show
Documentation introduced by
The doc-type array(Object) could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
405
     */
406
    private function _serializeCustomers($result)
407
    {
408
        $customers = array();
409
        while ($record = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {         
410
             $customers[] = $this->_serializeCustomer($record);
411
        }
412
413
        return $customers;
414
    }
415
416
    /**
417
     * Serialize the sql row into Customer object
418
     * 
419
     * @param array $record each row of customer
420
     * 
421
     * @return object
422
     */
423
    private function _serializeCustomer($record)
424
    {
425
        $customer = new Customer();
426
        $customer->CustomerID = $record['CustomerID'];
427
        $customer->CompanyName = $record['CompanyName'];
428
        $customer->ContactName = $record['ContactName'];
429
        $customer->ContactTitle = $record['ContactTitle'];
430
        $customer->Phone = $record['Phone'];
431
        $customer->Fax = $record['Fax'];        
432
        $customer->Address = new Address();
433
        $customer->Address->StreetName = ($record['Address']);
434
        $customer->Address->City = $record['City'];
435
        $customer->Address->Region = $record['Region'];
436
        $customer->Address->PostalCode = $record['PostalCode'];
437
        $customer->Address->Country = $record['Country'];
438
        //Set alternate address
439
        $customer->Address->AltAddress = new Address();
440
        $customer->Address->AltAddress->StreetName = 'ALT_' . $customer->Address->StreetName;
441
        $customer->Address->AltAddress->City = 'ALT_' . $customer->Address->City;
442
        $customer->Address->AltAddress->Region = 'ALT_' . $customer->Address->Region;
443
        $customer->Address->AltAddress->PostalCode = 'ALT_' . $customer->Address->PostalCode;
444
        $customer->Address->AltAddress->Country = 'ALT_' . $customer->Address->Country;
445
        $customer->EmailAddresses = array();
446
        for ($i = 1; $i < 4; $i++) {
447
            $customer->EmailAddresses[] = $customer->CustomerID . $i . '@live.com'; 
448
        }
449
450
        $customer->OtherAddresses = array();
451
        for ($i = 0; $i < 2; $i++) {
452
            $customer->OtherAddresses[$i] = new Address();
453
            $this->_copyAddress($customer->Address, $customer->OtherAddresses[$i], $i + 1);
0 ignored issues
show
Documentation introduced by
$i + 1 is of type integer, but the function expects a object.

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...
454
        }
455
		
456
        return $customer;
457
    }
458
    
459
     /**
460
     * copy address
461
     * 
462
     * @param Object &$src    source
463
     * @param Object &$target target
464
     * @param Object $tag     tag
465
     * 
466
     * @return void
467
     */
468
    private function _copyAddress(&$src, &$target, $tag)
469
    {
470
        $target->StreetName = $src->StreetName . $tag;
471
        $target->City = $src->City . $tag;
472
        $target->Region = $src->Region . $tag;
473
        $target->PostalCode = $src->PostalCode . $tag;
474
        $target->Country = $src->Country . $tag;
475
        
476
        $target->AltAddress = new Address();
477
        $target->AltAddress->StreetName = $target->AltAddress->StreetName . $tag;
478
        $target->AltAddress->City = $target->AltAddress->City . $tag;
479
        $target->AltAddress->Region = $target->AltAddress->Region . $tag;
480
        $target->AltAddress->PostalCode = $target->AltAddress->PostalCode . $tag;
481
        $target->AltAddress->Country = $target->AltAddress->Country . $tag;
482
    }
483
484
    /**
485
     * Serialize the sql result array into Order objects
486
     * 
487
     * @param array(array) $result result of the sql query
0 ignored issues
show
Documentation introduced by
The doc-type array(array) could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
488
     * 
489
     * @return array(Object)
0 ignored issues
show
Documentation introduced by
The doc-type array(Object) could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
490
     */
491
    private function _serializeOrders($result)
492
    {
493
        $orders = array();
494
        while ( $record = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {
495
             $orders[] = $this->_serializeOrder($record);
496
        }
497
498
        return $orders;
499
    }
500
501
    /**
502
     * Serialize the sql row into Order object
503
     * 
504
     * @param array $record each row of customer
505
     * 
506
     * @return object
507
     */
508
    private function _serializeOrder($record)
509
    {
510
        $order = new Order();
511
        $order->OrderID = $record['OrderID'];
512
        $order->CustomerID = $record['CustomerID'];
513
        $order->EmployeeID = $record['EmployeeID'];
514
        $order->OrderDate = !is_null($record['OrderDate']) ? $record['OrderDate']->format('Y-m-d\TH:i:s'): null;
515
        $order->RequiredDate = !is_null($record['RequiredDate']) ? $record['RequiredDate']->format('Y-m-d\TH:i:s'): null;
516
        $order->ShippedDate = !is_null($record['ShippedDate']) ? $record['ShippedDate']->format('Y-m-d\TH:i:s'): null;
517
        $order->ShipVia = $record['ShipVia'];
518
        $order->Freight = $record['Freight'];
519
        $order->ShipName = $record['ShipName'];
520
        $order->ShipAddress = $record['ShipAddress'];
521
        $order->ShipCity = $record['ShipCity'];
522
        $order->ShipRegion = $record['ShipRegion'];
523
        $order->ShipPostalCode = $record['ShipPostalCode'];
524
        $order->ShipCountry = $record['ShipCountry'];
525
        return $order;
526
    }
527
528
    /**
529
     * Serialize the sql result array into Employee objects
530
     * 
531
     * @param array(array) $result result of the sql query
0 ignored issues
show
Documentation introduced by
The doc-type array(array) could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
532
     * 
533
     * @return array(Object)
0 ignored issues
show
Documentation introduced by
The doc-type array(Object) could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
534
     */
535
    private function _serializeEmployees($result)
536
    {
537
        $employees = array();
538
        while ($record = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {
539
             $employees[] = $this->_serializeEmployee($record);
540
        }
541
542
        return $employees;
543
    }
544
545
    /**
546
     * Serialize the sql row into Employee object
547
     * 
548
     * @param array $record each row of employee
549
     * 
550
     * @return object
551
     */
552
    private function _serializeEmployee($record)
553
    {
554
        $employee = new Employee();
555
        $employee->EmployeeID = $record['EmployeeID'];
556
        $employee->FirstName = $record['FirstName'];
557
        $employee->LastName = $record['LastName'];
558
        $employee->Title = $record['Title'];
559
        $employee->TitleOfCourtesy = $record['TitleOfCourtesy'];
560
        $employee->BirthDate = !is_null($record['BirthDate']) ? $record['BirthDate']->format('Y-m-d\TH:i:s'): null;
561
        $employee->HireDate = !is_null($record['HireDate']) ? $record['HireDate']->format('Y-m-d\TH:i:s'): null;        
562
        $employee->Address = $record['Address'];
563
        $employee->City = $record['City'];
564
        $employee->Region = $record['Region'];
565
        $employee->PostalCode = $record['PostalCode'];
566
        $employee->Country = $record['Country'];
567
        $employee->HomePhone = $record['HomePhone'];
568
        $employee->Extension = $record['Extension'];
569
        $employee->Notes = $record['Notes'];
570
        $employee->ReportsTo = $record['ReportsTo'];
571
        //$employee->Photo = $record['Photo'];
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...
572
        $employee->Emails = array ($employee->FirstName . '@hotmail.com', $employee->FirstName . '@live.com');
573
        return $employee;
574
    }
575
576
    /**
577
     * Serialize the sql result array into Order_Details objects
578
     * 
579
     * @param array(array) $result result of the sql query
0 ignored issues
show
Documentation introduced by
The doc-type array(array) could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
580
     * 
581
     * @return array(Object)
0 ignored issues
show
Documentation introduced by
The doc-type array(Object) could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
582
     */
583
    private function _serializeOrderDetails($result)
584
    {
585
        $order_details = array();
586
        while ($record = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {        
587
            $order_details[] = $this->_serializeOrderDetail($record);
588
        }
589
590
        return $order_details;
591
    }
592
593
    /**
594
     * Serialize the sql row into Order_Details object
595
     * 
596
     * @param array $record each row of order detail
597
     * 
598
     * @return object
599
     */
600
    private function _serializeOrderDetail($record)
601
    {
602
        $order_details = new Order_Details();
603
        $order_details->Discount = $record['Discount'];
604
        $order_details->OrderID = $record['OrderID'];
605
        $order_details->ProductID = $record['ProductID'];
606
        $order_details->Quantity = $record['Quantity'];
607
        $order_details->UnitPrice = $record['UnitPrice'];
608
        return $order_details; 
609
    }
610
611
    
612
    /**
613
     * Gets the last sql server error as a string.
614
     *
615
     * @return string
616
     */
617
    private static function _getSQLSRVError()
618
    {
619
    	$result = null;
620
    	$errors = sqlsrv_errors();
621
    	self::_getSQLSRVError1($errors, $result);
622
    	return $result;
623
    }
624
    
625
    /**
626
     * Rescursive function to get the sql server error as string.
627
     *
628
     * @param array/string $errors
0 ignored issues
show
Documentation introduced by
The doc-type array/string could not be parsed: Unknown type name "array/string" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
629
     * @param string $result
630
     */
631
    private static function _getSQLSRVError1($errors, &$result)
632
    {
633
    	if (is_array($errors)) {
634
    		foreach ($errors as $error) {
635
    			self::_getSQLSRVError1($error, $result);
636
    		}
637
    	} else {
638
    		$result .= $errors;
639
    	}
640
    }
641
642
    /**
643
     * The destructor     
644
     */
645
    public function __destruct()
646
    {
647
        if ($this->_connectionHandle) {
648
            sqlsrv_close($this->_connectionHandle);
649
        }
650
    }
651
}