Passed
Push — master ( 4ab488...bcfbc7 )
by Bálint
03:58
created

getRelatedResourceReference()   C

Complexity

Conditions 11
Paths 11

Size

Total Lines 54

Duplication

Lines 42
Ratio 77.78 %

Importance

Changes 0
Metric Value
dl 42
loc 54
rs 6.8569
c 0
b 0
f 0
cc 11
nc 11
nop 4

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
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
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;
0 ignored issues
show
Bug introduced by
The constant UID was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
46
            $connectionInfo['PWD'] = PWD;    		
0 ignored issues
show
Bug introduced by
The constant PWD was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
47
        }
48
49
        $this->_connectionHandle = sqlsrv_connect(SERVER, $connectionInfo);
50
        if ($this->_connectionHandle) {        	
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)
93
     */
94
    public function getResourceSet(ResourceSet $resourceSet, $filterOption = null, 
95
        $select = null, $orderby = null, $top = null, $skip = null
96
    ) {
97
        $resourceSetName = $resourceSet->getName();
98
        if ($resourceSetName !== 'Customers' 
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 null|string 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);
0 ignored issues
show
Bug introduced by
It seems like $this->_connectionHandle can also be of type boolean; however, parameter $conn of sqlsrv_query() does only seem to accept resource, 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

114
        $stmt = sqlsrv_query(/** @scrutinizer ignore-type */ $this->_connectionHandle, $query);
Loading history...
115
        if ($stmt === false) {
116
            $errorAsString = self::_getSQLSRVError();
117
            throw ODataException::createInternalServerError($errorAsString);
118
        }
119
        $returnResult = array();
120
        switch ($resourceSetName) {
121
            case 'Customers':
122
                $returnResult = $this->_serializeCustomers($stmt);
0 ignored issues
show
Bug introduced by
$stmt of type resource is incompatible with the type array expected by parameter $result of NorthWindQueryProvider::_serializeCustomers(). ( Ignorable by Annotation )

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

122
                $returnResult = $this->_serializeCustomers(/** @scrutinizer ignore-type */ $stmt);
Loading history...
123
                break;
124
            case 'Orders':
125
                $returnResult = $this->_serializeOrders($stmt);
0 ignored issues
show
Bug introduced by
$stmt of type resource is incompatible with the type array expected by parameter $result of NorthWindQueryProvider::_serializeOrders(). ( Ignorable by Annotation )

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

125
                $returnResult = $this->_serializeOrders(/** @scrutinizer ignore-type */ $stmt);
Loading history...
126
                break;
127
            case 'Order Details':
128
                $returnResult = $this->_serializeOrderDetails($stmt);
0 ignored issues
show
Bug introduced by
$stmt of type resource is incompatible with the type array expected by parameter $result of NorthWindQueryProvider::_serializeOrderDetails(). ( Ignorable by Annotation )

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

128
                $returnResult = $this->_serializeOrderDetails(/** @scrutinizer ignore-type */ $stmt);
Loading history...
129
                break;
130
            case 'Employees':
131
                $returnResult = $this->_serializeEmployees($stmt);
0 ignored issues
show
Bug introduced by
$stmt of type resource is incompatible with the type array expected by parameter $result of NorthWindQueryProvider::_serializeEmployees(). ( Ignorable by Annotation )

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

131
                $returnResult = $this->_serializeEmployees(/** @scrutinizer ignore-type */ $stmt);
Loading history...
132
                break;
133
        }
134
        sqlsrv_free_stmt($stmt);
135
        return $returnResult;
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
        if ($resourceSetName !== 'Customers' 
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
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

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);
0 ignored issues
show
Bug introduced by
It seems like $this->_connectionHandle can also be of type boolean; however, parameter $conn of sqlsrv_query() does only seem to accept resource, 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

172
        $stmt = sqlsrv_query(/** @scrutinizer ignore-type */ $this->_connectionHandle, $query);
Loading history...
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
            switch ($resourceSetName) {
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
            if ($navigationPropName === 'Orders') {                
236
                $query = "SELECT * FROM Orders WHERE CustomerID = '$sourceEntityInstance->CustomerID' and $key";
237
                $stmt = sqlsrv_query($this->_connectionHandle, $query);
0 ignored issues
show
Bug introduced by
It seems like $this->_connectionHandle can also be of type boolean; however, parameter $conn of sqlsrv_query() does only seem to accept resource, 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

237
                $stmt = sqlsrv_query(/** @scrutinizer ignore-type */ $this->_connectionHandle, $query);
Loading history...
238
                if ($stmt === false) {            
239
                    $errorAsString = self::_getSQLSRVError();
240
                    throw ODataException::createInternalServerError($errorAsString);
241
                }
242
243
                $result = $this->_serializeOrders($stmt);
0 ignored issues
show
Bug introduced by
$stmt of type resource is incompatible with the type array expected by parameter $result of NorthWindQueryProvider::_serializeOrders(). ( Ignorable by Annotation )

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

243
                $result = $this->_serializeOrders(/** @scrutinizer ignore-type */ $stmt);
Loading history...
244
            } else {
245
                die('Customer does not have navigation porperty with name: ' . $navigationPropName);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
246
            }            
247
        } else if ($srcClass === 'Order') {
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);
0 ignored issues
show
Bug introduced by
$stmt of type resource is incompatible with the type array expected by parameter $result of NorthWindQueryProvider::_serializeOrderDetails(). ( Ignorable by Annotation )

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

256
                $result = $this->_serializeOrderDetails(/** @scrutinizer ignore-type */ $stmt);
Loading history...
257
            } else {
258
                die('Order does not have navigation porperty with name: ' . $navigationPropName);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

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
            if ($navigationPropName === 'Orders') {                
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 null|string 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);
0 ignored issues
show
Bug introduced by
It seems like $this->_connectionHandle can also be of type boolean; however, parameter $conn of sqlsrv_query() does only seem to accept resource, 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

301
                $stmt = sqlsrv_query(/** @scrutinizer ignore-type */ $this->_connectionHandle, $query);
Loading history...
302
                if ($stmt === false) {
303
                    $errorAsString = self::_getSQLSRVError();
304
                    throw ODataException::createInternalServerError($errorAsString);
305
                }
306
307
                $result = $this->_serializeOrders($stmt);
0 ignored issues
show
Bug introduced by
$stmt of type resource is incompatible with the type array expected by parameter $result of NorthWindQueryProvider::_serializeOrders(). ( Ignorable by Annotation )

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

307
                $result = $this->_serializeOrders(/** @scrutinizer ignore-type */ $stmt);
Loading history...
308
            } else {
309
                die('Customer does not have navigation porperty with name: ' . $navigationPropName);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
310
            }            
311
        } else if ($srcClass === 'Order') {
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 null|string 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);
0 ignored issues
show
Bug introduced by
$stmt of type resource is incompatible with the type array expected by parameter $result of NorthWindQueryProvider::_serializeOrderDetails(). ( Ignorable by Annotation )

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

323
                $result = $this->_serializeOrderDetails(/** @scrutinizer ignore-type */ $stmt);
Loading history...
324
            } else {
325
                die('Order does not have navigation porperty with name: ' . $navigationPropName);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
326
            }
327
        }
328
329
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type Order[]|Order_Details[]|array which is incompatible with the return type mandated by POData\Providers\Query\I...getRelatedResourceSet() of POData\Providers\Query\QueryResult.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
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
            if ($navigationPropName === 'Customer') {
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);
0 ignored issues
show
Bug introduced by
It seems like $this->_connectionHandle can also be of type boolean; however, parameter $conn of sqlsrv_query() does only seem to accept resource, 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

358
                    $stmt = sqlsrv_query(/** @scrutinizer ignore-type */ $this->_connectionHandle, $query);
Loading history...
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
The assignment to $result is dead and can be removed.
Loading history...
366
                    }
367
368
                    $result = $this->_serializeCustomer(sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC));
0 ignored issues
show
Bug introduced by
It seems like sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) can also be of type false; however, parameter $record of NorthWindQueryProvider::_serializeCustomer() does only seem to accept array, 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

368
                    $result = $this->_serializeCustomer(/** @scrutinizer ignore-type */ sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC));
Loading history...
369
                }
370
            } else {
371
                die('Customer does not have navigation porperty with name: ' . $navigationPropName);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
372
            }            
373
        } else if ($srcClass === 'Order_Details') {
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;
387
                    }
388
                    
389
                    $result = $this->_serializeOrder(sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC));
0 ignored issues
show
Bug introduced by
It seems like sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) can also be of type false; however, parameter $record of NorthWindQueryProvider::_serializeOrder() does only seem to accept array, 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

389
                    $result = $this->_serializeOrder(/** @scrutinizer ignore-type */ sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC));
Loading history...
390
                }
391
            } else {
392
                die('Order_Details does not have navigation porperty with name: ' . $navigationPropName);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

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
403
     * 
404
     * @return array(Object)
405
     */
406
    private function _serializeCustomers($result)
407
    {
408
        $customers = array();
409
        while ($record = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {         
0 ignored issues
show
Bug introduced by
$result of type array is incompatible with the type resource|null expected by parameter $stmt of sqlsrv_fetch_array(). ( Ignorable by Annotation )

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

409
        while ($record = sqlsrv_fetch_array(/** @scrutinizer ignore-type */ $result, SQLSRV_FETCH_ASSOC)) {         
Loading history...
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 Customer
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);
454
        }
455
		
456
        return $customer;
457
    }
458
    
459
        /**
460
         * copy address
461
         * 
462
         * @param Object &$src    source
463
         * @param Object &$target target
464
         * @param integer $tag     tag
465
         * @param Address $target
466
         * 
467
         * @return void
468
         */
469
    private function _copyAddress(&$src, &$target, $tag)
470
    {
471
        $target->StreetName = $src->StreetName . $tag;
472
        $target->City = $src->City . $tag;
473
        $target->Region = $src->Region . $tag;
474
        $target->PostalCode = $src->PostalCode . $tag;
475
        $target->Country = $src->Country . $tag;
476
        
477
        $target->AltAddress = new Address();
478
        $target->AltAddress->StreetName = $target->AltAddress->StreetName . $tag;
479
        $target->AltAddress->City = $target->AltAddress->City . $tag;
480
        $target->AltAddress->Region = $target->AltAddress->Region . $tag;
481
        $target->AltAddress->PostalCode = $target->AltAddress->PostalCode . $tag;
482
        $target->AltAddress->Country = $target->AltAddress->Country . $tag;
483
    }
484
485
    /**
486
     * Serialize the sql result array into Order objects
487
     * 
488
     * @param array(array) $result result of the sql query
489
     * 
490
     * @return array(Object)
491
     */
492
    private function _serializeOrders($result)
493
    {
494
        $orders = array();
495
        while ($record = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {
0 ignored issues
show
Bug introduced by
$result of type array is incompatible with the type resource|null expected by parameter $stmt of sqlsrv_fetch_array(). ( Ignorable by Annotation )

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

495
        while ($record = sqlsrv_fetch_array(/** @scrutinizer ignore-type */ $result, SQLSRV_FETCH_ASSOC)) {
Loading history...
496
                $orders[] = $this->_serializeOrder($record);
497
        }
498
499
        return $orders;
500
    }
501
502
    /**
503
     * Serialize the sql row into Order object
504
     * 
505
     * @param array $record each row of customer
506
     * 
507
     * @return Order
508
     */
509
    private function _serializeOrder($record)
510
    {
511
        $order = new Order();
512
        $order->OrderID = $record['OrderID'];
513
        $order->CustomerID = $record['CustomerID'];
514
        $order->EmployeeID = $record['EmployeeID'];
515
        $order->OrderDate = !is_null($record['OrderDate']) ? $record['OrderDate']->format('Y-m-d\TH:i:s') : null;
516
        $order->RequiredDate = !is_null($record['RequiredDate']) ? $record['RequiredDate']->format('Y-m-d\TH:i:s') : null;
517
        $order->ShippedDate = !is_null($record['ShippedDate']) ? $record['ShippedDate']->format('Y-m-d\TH:i:s') : null;
518
        $order->ShipVia = $record['ShipVia'];
519
        $order->Freight = $record['Freight'];
520
        $order->ShipName = $record['ShipName'];
521
        $order->ShipAddress = $record['ShipAddress'];
522
        $order->ShipCity = $record['ShipCity'];
523
        $order->ShipRegion = $record['ShipRegion'];
524
        $order->ShipPostalCode = $record['ShipPostalCode'];
525
        $order->ShipCountry = $record['ShipCountry'];
526
        return $order;
527
    }
528
529
    /**
530
     * Serialize the sql result array into Employee objects
531
     * 
532
     * @param array(array) $result result of the sql query
533
     * 
534
     * @return array(Object)
535
     */
536
    private function _serializeEmployees($result)
537
    {
538
        $employees = array();
539
        while ($record = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {
0 ignored issues
show
Bug introduced by
$result of type array is incompatible with the type resource|null expected by parameter $stmt of sqlsrv_fetch_array(). ( Ignorable by Annotation )

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

539
        while ($record = sqlsrv_fetch_array(/** @scrutinizer ignore-type */ $result, SQLSRV_FETCH_ASSOC)) {
Loading history...
540
                $employees[] = $this->_serializeEmployee($record);
541
        }
542
543
        return $employees;
544
    }
545
546
    /**
547
     * Serialize the sql row into Employee object
548
     * 
549
     * @param array $record each row of employee
550
     * 
551
     * @return Employee
552
     */
553
    private function _serializeEmployee($record)
554
    {
555
        $employee = new Employee();
556
        $employee->EmployeeID = $record['EmployeeID'];
557
        $employee->FirstName = $record['FirstName'];
558
        $employee->LastName = $record['LastName'];
559
        $employee->Title = $record['Title'];
560
        $employee->TitleOfCourtesy = $record['TitleOfCourtesy'];
561
        $employee->BirthDate = !is_null($record['BirthDate']) ? $record['BirthDate']->format('Y-m-d\TH:i:s') : null;
562
        $employee->HireDate = !is_null($record['HireDate']) ? $record['HireDate']->format('Y-m-d\TH:i:s') : null;        
563
        $employee->Address = $record['Address'];
564
        $employee->City = $record['City'];
565
        $employee->Region = $record['Region'];
566
        $employee->PostalCode = $record['PostalCode'];
567
        $employee->Country = $record['Country'];
568
        $employee->HomePhone = $record['HomePhone'];
569
        $employee->Extension = $record['Extension'];
570
        $employee->Notes = $record['Notes'];
571
        $employee->ReportsTo = $record['ReportsTo'];
572
        //$employee->Photo = $record['Photo'];
573
        $employee->Emails = array($employee->FirstName . '@hotmail.com', $employee->FirstName . '@live.com');
574
        return $employee;
575
    }
576
577
    /**
578
     * Serialize the sql result array into Order_Details objects
579
     * 
580
     * @param array(array) $result result of the sql query
581
     * 
582
     * @return array(Object)
583
     */
584
    private function _serializeOrderDetails($result)
585
    {
586
        $order_details = array();
587
        while ($record = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {        
0 ignored issues
show
Bug introduced by
$result of type array is incompatible with the type resource|null expected by parameter $stmt of sqlsrv_fetch_array(). ( Ignorable by Annotation )

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

587
        while ($record = sqlsrv_fetch_array(/** @scrutinizer ignore-type */ $result, SQLSRV_FETCH_ASSOC)) {        
Loading history...
588
            $order_details[] = $this->_serializeOrderDetail($record);
589
        }
590
591
        return $order_details;
592
    }
593
594
    /**
595
     * Serialize the sql row into Order_Details object
596
     * 
597
     * @param array $record each row of order detail
598
     * 
599
     * @return Order_Details
600
     */
601
    private function _serializeOrderDetail($record)
602
    {
603
        $order_details = new Order_Details();
604
        $order_details->Discount = $record['Discount'];
605
        $order_details->OrderID = $record['OrderID'];
606
        $order_details->ProductID = $record['ProductID'];
607
        $order_details->Quantity = $record['Quantity'];
608
        $order_details->UnitPrice = $record['UnitPrice'];
609
        return $order_details; 
610
    }
611
612
    
613
    /**
614
     * Gets the last sql server error as a string.
615
     *
616
     * @return string
617
     */
618
    private static function _getSQLSRVError()
619
    {
620
        $result = null;
621
        $errors = sqlsrv_errors();
622
        self::_getSQLSRVError1($errors, $result);
623
        return $result;
624
    }
625
    
626
    /**
627
     * Rescursive function to get the sql server error as string.
628
     *
629
     * @param array/string $errors
0 ignored issues
show
Documentation Bug introduced by
The doc comment array/string at position 0 could not be parsed: Unknown type name 'array/string' at position 0 in array/string.
Loading history...
630
     * @param string $result
631
     */
632
    private static function _getSQLSRVError1($errors, &$result)
633
    {
634
        if (is_array($errors)) {
635
            foreach ($errors as $error) {
636
                self::_getSQLSRVError1($error, $result);
637
            }
638
        } else {
639
            $result .= $errors;
640
        }
641
    }
642
643
    /**
644
     * The destructor     
645
     */
646
    public function __destruct()
647
    {
648
        if ($this->_connectionHandle) {
649
            sqlsrv_close($this->_connectionHandle);
0 ignored issues
show
Bug introduced by
It seems like $this->_connectionHandle can also be of type true; however, parameter $conn of sqlsrv_close() does only seem to accept resource|null, 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

649
            sqlsrv_close(/** @scrutinizer ignore-type */ $this->_connectionHandle);
Loading history...
650
        }
651
    }
652
}