getPaymentMethod()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
ccs 0
cts 6
cp 0
crap 2
1
<?php
2
/**
3
 * ShopServer version 0.4.0
4
 * Class named with version XXYY from version numbering XX.YY.ZZ
5
 *
6
 * @todo we need to move kernel out of Product.
7
 * @todo we need to move kernel out of DBQuery.
8
 * @todo we need to find out what to do with hasIntranetAccess and stock
9
 * @todo we need to work out with getPictures() and Kernel->useModule
10
 *
11
 * @category XMLRPC_Server
12
 * @package  Intraface_XMLRPC_Shop
13
 * @author   Lars Olesen <[email protected]>
14
 * @version  @package-version@
15
 */
16
class Intraface_XMLRPC_Shop_Server0004 extends Intraface_XMLRPC_Server
17
{
18
    private $webshop;
19
    private $basket;
0 ignored issues
show
Unused Code introduced by
The property $basket is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
20
    private $product;
0 ignored issues
show
Unused Code introduced by
The property $product is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
21
    private $bucket;
22
23
    /**
24
     * Constructor
25
     * @param $encoding the encoding used for the XML_RPC2 backend
26
     * @return unknown_type
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
27
     */
28
    public function __construct($bucket, $encoding = 'utf-8')
29
    {
30
        $this->bucket = $bucket;
31
        parent::__construct($encoding);
32
    }
33
34
    /**
35
     * Gets a list with products
36
     *
37
     * @param struct $credentials Credentials to use the server
38
     * @param integer $shop_id    Id for the shop
39
     * @param array  $search      Optional search array
40
     *
41
     * @return array
42
     */
43 View Code Duplication
    public function getProducts($credentials, $shop_id, $search = array())
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
44
    {
45
        $this->checkCredentials($credentials);
46
47
        $offset = 0;
0 ignored issues
show
Unused Code introduced by
$offset 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...
48
49
        $search = $this->processRequestData($search);
50
51
        $mixed = array();
52
        if (!empty($search)) {
53
            $mixed = $search;
54
        }
55
56
        $search = '';
0 ignored issues
show
Unused Code introduced by
$search 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...
57
58
        $this->_factoryWebshop($shop_id);
59
60
        $products = array();
0 ignored issues
show
Unused Code introduced by
$products 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...
61
62
        $area = '';
63
64
        if (!empty($mixed['area'])) {
65
            $area = $mixed['area'];
66
        }
67
68
        $product = new Intraface_modules_product_Gateway($this->webshop->kernel);
69
70
        if (!isset($mixed['use_paging']) || $mixed['use_paging'] == 'true') {
71
            $product->getDBQuery()->usePaging('paging');
72
        }
73
74
        // sublevel has to be used so other searches are not overwritten
75
        $product->getDBQuery()->storeResult('use_stored', 'webshop_' . $area . '_' .  md5($this->credentials['session_id']), 'sublevel');
76
        $debug2 = serialize($mixed);
77
        if (isset($mixed['offset']) and is_numeric($mixed['offset']) and $mixed['offset'] > 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
78
            $product->getDBQuery()->useStored(true);
79
            $product->getDBQuery()->setPagingOffset((int)$mixed['offset']);
80
            $debug2 .= 'offset ' . $mixed['offset'];
81
        } elseif (isset($mixed['use_stored']) and array_key_exists('use_stored', $mixed) and $mixed['use_stored'] == 'true') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
82
            $product->getDBQuery()->useStored(true);
83
            $debug2 .= 'use_stored true';
84
        } else {
85
            if (array_key_exists('search', $mixed) and !empty($mixed['search'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
86
                $product->getDBQuery()->setFilter('search', $mixed['search']);
87
                $debug2 .= 'search ' . $mixed['search'];
88
            }
89
90
            if (array_key_exists('keywords', $mixed) and !empty($mixed['keywords'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
91
                $product->getDBQuery()->setFilter('keywords', $mixed['keywords']);
92
                $debug2 .= 'keyword ' . $mixed['keywords'];
93
            }
94
95
            if (array_key_exists('category', $mixed) and !empty($mixed['category'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
96
                $product->getDBQuery()->setFilter('shop_id', $shop_id);
97
                $product->getDBQuery()->setFilter('category', $mixed['category']);
98
                $debug2 .= 'category ' . $mixed['category'];
99
            }
100
101
            if (isset($mixed['ids']) and array_key_exists('ids', $mixed) and is_array($mixed['ids'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
102
                $product->getDBQuery()->setFilter('ids', $mixed['ids']);
103
                $debug2 .= 'ids ' . implode(', ', $mixed['ids']);
104
            }
105
106
            if (array_key_exists('sorting', $mixed) and !empty($mixed['sorting'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
107
                $product->getDBQuery()->setFilter('sorting', $mixed['sorting']);
108
                $debug2 .= 'sorting ' . $mixed['sorting'];
109
            }
110
        }
111
112
        if (false !== ($currency_gateway = $this->getCurrencyGateway())) {
113
            $currencies = $currency_gateway->findAllWithExchangeRate();
114
        } else {
115
            $currencies = false;
116
        }
117
118
        return $this->prepareResponseData(array(
119
            'parameter' => $mixed,
120
            //'debug2' => $debug2,
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% 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...
121
            'products' => $this->cleanUpProductList($product->getAllProducts('webshop', $currencies)),
122
            'paging' => $product->getDBQuery()->getPaging(),
123
            'search' => array(),
124
        ));
125
    }
126
127
    /**
128
     * Gets a list with products in given category
129
     *
130
     * @param struct $credentials Credentials to use the server
131
     * @param integer $shop_id    Id for the shop
132
     * @param integer $category_id Id of category
133
     * @param integer $results_per_page Optional returned products per page
134
     * @param integer $pagging_offset Otional offset for pagging.
135
     *
136
     * @return array
137
     */
138 View Code Duplication
    public function getProductsInCategoryId($credentials, $shop_id, $category_id, $results_per_page = 0, $pagging_offset = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
139
    {
140
        $search = array();
141
        $search['area'] = 'category_'.$category_id;
142
        if ($results_per_page > 0) {
143
            $search['use_paging'] = 'true';
144
        } else {
145
            $search['use_paging'] = 'false';
146
        }
147
148
        $search['category'] = $category_id;
149
        $search['offset'] = $pagging_offset;
150
151
        return $this->getProducts($credentials, $shop_id, $search);
152
    }
153
154
    /**
155
     * Gets a list with products with a given keyword or with given keywords
156
     *
157
     * @param struct $credentials Credentials to use the server
158
     * @param integer $shop_id    Id for the shop
159
     * @param mixed  $keyword      Integer with keyword id or array with keyword ids.
160
     * @param integer $results_per_page optional returned products per page
161
     * @param integer $pagging_offset optional offset for pagging.
162
     *
163
     * @return array
164
     */
165 View Code Duplication
    public function getProductsWithKeywordId($credentials, $shop_id, $keyword, $results_per_page = 0, $pagging_offset = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
166
    {
167
168
        $search = array();
169
        if (is_array($keyword)) {
170
            $search['area'] = 'keyword_'.implode('-', $keyword);
171
        } else {
172
            $search['area'] = 'keyword_'.$keyword;
173
        }
174
        if ($results_per_page > 0) {
175
            $search['use_paging'] = 'true';
176
        } else {
177
            $search['use_paging'] = 'false';
178
        }
179
        $search['keywords'] = $keyword;
180
        $search['offset'] = $pagging_offset;
181
182
        return $this->getProducts($credentials, $shop_id, $search);
183
    }
184
185
    /**
186
     * Returns product ids with keyword id
187
     *
188
     * @param struct $credentials Credentials to use the server
189
     * @param integer $shop_id Id for the shop
190
     * @param mixed $keyword Integer with keyword id or array with keyword ids.
191
     * @return array
192
     */
193 View Code Duplication
    public function getProductIdsWithKeywordId($credentials, $shop_id, $keyword)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
194
    {
195
        $this->checkCredentials($credentials);
196
        $this->_factoryWebshop($shop_id);
197
198
        $gateway = new Intraface_modules_product_Gateway($this->webshop->kernel);
199
200
        return $this->prepareResponseData(
201
            $gateway->getProductIdsWithKeywordForShop($this->processRequestData($keyword))
202
        );
203
    }
204
205
    /**
206
     * Gets a list with products with a given keyword or with given keywords
207
     *
208
     * @param struct $credentials Credentials to use the server
209
     * @param integer $shop_id    Id for the shop
210
     * @param integer $variation_id      Integer with variation id.
211
     * @param integer $attribute_id Integer with attribute id.
212
     * @param integer $results_per_page optional returned products per page
213
     * @param integer $pagging_offset optional offset for pagging.
214
     *
215
     * @return array
216
     */
217
    public function getProductsInWithVariationAttribute($credentials, $shop_id, $variation_id, $attribute_id, $results_per_page = 0, $pagging_offset = 0)
0 ignored issues
show
Unused Code introduced by
The parameter $credentials is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $shop_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $variation_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $attribute_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $results_per_page is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $pagging_offset is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
218
    {
219
    }
220
221
    /**
222
     * Make sure we only include necessary data. Several things more might
223
     * be left out. Mostly we remove description.
224
     *
225
     * @param array products
226
     * @return array cleaned up products
227
     */
228 View Code Duplication
    private function cleanUpProductList($products)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
229
    {
230
        $return = array();
231
        foreach ($products as $key => $p) {
232
            $return[$key]['id'] = $p['id'];
233
            $return[$key]['number'] = $p['number'];
234
            $return[$key]['name'] = $p['name'];
235
            $return[$key]['price'] = $p['price'];
236
            $return[$key]['unit'] = $p['unit'];
237
            $return[$key]['vat'] = $p['vat'];
238
            $return[$key]['weight'] = $p['weight'];
239
            $return[$key]['detail_id'] = $p['detail_id'];
240
            $return[$key]['vat_percent'] = $p['vat_percent'];
241
            $return[$key]['price_incl_vat'] = $p['price_incl_vat'];
242
            $return[$key]['stock'] = $p['stock'];
243
            $return[$key]['has_variation'] = $p['has_variation'];
244
            $return[$key]['stock_status'] = $p['stock_status'];
245
246
            foreach ($p['currency'] as $k => $c) {
247
                $return[$key]['currency'][$k]['price'] = $c['price']->getAsIso(2);
248
                $return[$key]['currency'][$k]['price_incl_vat'] = $c['price_incl_vat']->getAsIso(2);
249
                $return[$key]['currency'][$k]['before_price'] = $c['before_price']->getAsIso(2);
250
                $return[$key]['currency'][$k]['before_price_incl_vat'] = $c['before_price_incl_vat']->getAsIso(2);
251
            }
252
253
            if (isset($p['pictures'])) {
254
                $return[$key]['pictures'] = $p['pictures'];
255
            }
256
        }
257
258
        return $return;
259
    }
260
261
    /**
262
     * Gets one product
263
     *
264
     * @param struct  $credentials Credentials to use the server
265
     * @param integer $shop_id    Id for the shop
266
     * @param integer $id          Product id
267
     *
268
     * @return array
269
     */
270 View Code Duplication
    public function getProduct($credentials, $shop_id, $id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
271
    {
272
        $this->checkCredentials($credentials);
273
274
        $this->_factoryWebshop($shop_id);
275
276
        if (!is_numeric($id)) {
277
            require_once 'XML/RPC2/Exception.php';
278
            throw new XML_RPC2_FaultException('product id must be an integer', -5);
279
        }
280
281
        $id = $this->processRequestData(intval($id));
282
283
        $return = array();
284
285
        $product = new Product($this->kernel, $id);
286
        if ($product->get('id') == 0 || $product->get('do_show') == 0 || $product->get('active') == 0) {
287
            return array('product' => array('id' => 0));
288
        }
289
290
        $product->getPictures();
291
        $return['product'] = $product->get();
292
        $return['product']['currency']['DKK']['price'] = $product->getDetails()->getPrice()->getAsIso(2);
293
        $return['product']['currency']['DKK']['price_incl_vat'] = $product->getDetails()->getPriceIncludingVat()->getAsIso(2);
294
        $return['product']['currency']['DKK']['before_price'] = $product->getDetails()->getBeforePrice()->getAsIso(2);
295
        $return['product']['currency']['DKK']['before_price_incl_vat'] = $product->getDetails()->getBeforePriceIncludingVat()->getAsIso(2);
296
297
        if (false !== ($currency_gateway = $this->getCurrencyGateway())) {
298
            foreach ($currency_gateway->findAllWithExchangeRate() as $currency) {
299
                $return['product']['currency'][$currency->getType()->getIsoCode()]['price'] = $product->getDetails()->getPriceInCurrency($currency)->getAsIso(2);
300
                $return['product']['currency'][$currency->getType()->getIsoCode()]['price_incl_vat'] = $product->getDetails()->getPriceIncludingVatInCurrency($currency)->getAsIso(2);
301
                $return['product']['currency'][$currency->getType()->getIsoCode()]['before_price'] = $product->getDetails()->getBeforePriceInCurrency($currency)->getAsIso(2);
302
                $return['product']['currency'][$currency->getType()->getIsoCode()]['before_price_incl_vat'] = $product->getDetails()->getBeforePriceIncludingVatInCurrency($currency)->getAsIso(2);
303
            }
304
        }
305
306
        if (!$product->hasVariation() && $product->get('stock')) {
307
            $return['stock'] = $product->getStock()->get();
308
        }
309
310
        if ($product->get('has_variation')) {
311
            $variations = $product->getVariations();
312
            foreach ($variations as $variation) {
313
                if ($product->get('stock')) {
314
                    $stock = $variation->getStock($product)->get();
315
                } else {
316
                    $stock = false;
317
                }
318
319
                $detail = $variation->getDetail();
320
                $attribute_string = '';
321
                $attributes_array = $variation->getAttributesAsArray();
322
323
                foreach ($attributes_array as $attribute) {
324
                    if ($attribute_string != '') {
325
                        $attribute_string .= '-';
326
                    }
327
                    $attribute_string .= $attribute['id'];
328
329
                    // We calculate all products which is on stock with this attribute to be able to mark unused attributes in list.
330
                    if (!isset($attribute_for_sale[$attribute['id']])) {
331
                        $attribute_for_sale[$attribute['id']] = 0;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$attribute_for_sale was never initialized. Although not strictly required by PHP, it is generally a good practice to add $attribute_for_sale = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
332
                    }
333
                    if ($stock !== false) {
334
                        // If for_sale is less than zero we add zero.
335
                        $attribute_for_sale[$attribute['id']] += (($stock['for_sale'] < 0) ? 0 : $stock['for_sale']);
0 ignored issues
show
Bug introduced by
The variable $attribute_for_sale does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
336
                    } else {
337
                        // If product does not use stock, then we calculate one up, as the attribute is always in use.
338
                        $attribute_for_sale[$attribute['id']] += 1;
339
                    }
340
                }
341
342
                $variation_currency['DKK']['price'] = $detail->getPrice($product)->getAsIso(2);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$variation_currency was never initialized. Although not strictly required by PHP, it is generally a good practice to add $variation_currency = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
343
                $variation_currency['DKK']['price_incl_vat'] = $detail->getPriceIncludingVat($product)->getAsIso(2);
0 ignored issues
show
Bug introduced by
The variable $variation_currency does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
344
345
                if (isset($currency_gateway) && is_object($currency_gateway)) {
346
                    foreach ($currency_gateway->findAllWithExchangeRate() as $currency) {
347
                        $variation_currency[$currency->getType()->getIsoCode()]['price'] = $detail->getPriceInCurrency($currency, 0, $product)->getAsIso(2);
348
                        $variation_currency[$currency->getType()->getIsoCode()]['price_incl_vat'] = $detail->getPriceIncludingVatInCurrency($currency, 0, $product)->getAsIso(2);
349
                    }
350
                }
351
352
                $return['variations'][] = array(
353
                    'variation' => array(
354
                        'id' => $variation->getId(),
355
                        'detail_id' => $detail->getId(),
356
                        'number' => $variation->getNumber(),
357
                        'name' => $variation->getName(),
358
                        'attributes' => $attributes_array,
359
                        'identifier' => $attribute_string,
360
                        'price_incl_vat' => $detail->getPriceIncludingVat($product)->getAsIso(2),
361
                        'weight' => $product->get('weight') + $detail->getWeightDifference(2),
362
                        'currency' => $variation_currency
363
                    ),
364
                    'stock' => $stock
365
                );
366
            }
367
368
            // We should make a Doctrine Product_X_AttributeGroup class and get all the groups i one sql
369
            $groups = $product->getAttributeGroups();
370
            $group_gateway = new Intraface_modules_product_Attribute_Group_Gateway;
371
            foreach ($groups as $key => $group) {
372
                // Make sure we only include necessary data
373
                $return['attribute_groups'][$key]['id'] = $group['id'];
374
                $return['attribute_groups'][$key]['name'] = $group['name'];
375
                $attributes = $group_gateway->findById($group['id'])->getAttributesUsedByProduct($product);
376
                foreach ($attributes as $attribute) {
377
                    // No products has attribute on stock we remove it from the list.
378
                    if (isset($attribute_for_sale[$attribute->getId()]) && $attribute_for_sale[$attribute->getId()] == 0) {
379
                        $is_used = 0;
380
                    } else {
381
                        $is_used = 1;
382
                    }
383
384
                    $return['attribute_groups'][$key]['attributes'][] = array(
385
                        'id' => $attribute->getId(),
386
                        'name' => $attribute->getName(),
387
                        'is_used' => $is_used
388
                    );
389
                }
390
            }
391
        }
392
393
        return $this->prepareResponseData($return);
394
    }
395
396
    /**
397
     * Gets related products
398
     *
399
     * @param struct  $credentials Credentials to use the server
400
     * @param integer $shop_id    Id for the shop
401
     * @param integer $id          Product id
0 ignored issues
show
Bug introduced by
There is no parameter named $id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
402
     *
403
     * @return array
404
     */
405 View Code Duplication
    public function getRelatedProducts($credentials, $shop_id, $product_id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
406
    {
407
        $this->checkCredentials($credentials);
408
409
        $this->_factoryWebshop($shop_id);
410
411
        if (!is_numeric($product_id)) {
412
            require_once 'XML/RPC2/Exception.php';
413
            throw new XML_RPC2_FaultException('product id must be an integer', -5);
414
        }
415
416
        $product_id = $this->processRequestData(intval($product_id));
417
418
        if (false !== ($currency_gateway = $this->getCurrencyGateway())) {
419
            $currencies = $currency_gateway->findAllWithExchangeRate();
420
        } else {
421
            $currencies = false;
422
        }
423
424
        $product = new Product($this->kernel, $product_id);
425
        return $this->prepareResponseData($this->cleanUpProductList($product->getRelatedProducts($currencies, 'webshop')));
0 ignored issues
show
Bug introduced by
It seems like $currencies defined by $currency_gateway->findAllWithExchangeRate() on line 419 can also be of type object; however, Product::getRelatedProducts() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
426
    }
427
428
   /**
429
     * Gets featured products
430
     *
431
     * Method is experimental and only used by discimport.dk. If you need to use it
432
     * as well, please contact [email protected].
433
     *
434
     * @param struct  $credentials Credentials to use the server
435
     * @param integer $shop_id    Id for the shop
436
     *
437
     * @return array
438
     */
439 View Code Duplication
    public function getFeaturedProducts($credentials, $shop_id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
440
    {
441
        $related_products = array();
0 ignored issues
show
Unused Code introduced by
$related_products 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...
442
443
        $this->checkCredentials($credentials);
444
445
        $this->_factoryWebshop($shop_id);
446
447
        $db = MDB2::singleton(DB_DSN);
448
449
        if (PEAR::isError($db)) {
450
            require_once 'XML/RPC2/Exception.php';
451
            throw new XML_RPC2_FaultException($db->getMessage() . $db->getUserInfo(), -1);
452
        }
453
454
        $featured = new Intraface_modules_shop_FeaturedProducts($this->kernel->intranet, $this->webshop->getShop(), $db);
455
        $all = $featured->getAll();
456
457
        if (false !== ($currency_gateway = $this->getCurrencyGateway())) {
458
            $currencies = $currency_gateway->findAllWithExchangeRate();
459
        } else {
460
            $currencies = false;
461
        }
462
463
        $related_products = array();
464
465
        foreach ($all as $row) {
466
            $product_gateway = new Intraface_modules_product_Gateway($this->kernel);
467
            $product_gateway->getDBQuery()->setFilter('keywords', array($row['keyword_id']));
468
469
            $related_products[] = array(
470
                'title' => $row['headline'],
471
                'products' => $this->cleanUpProductList($product_gateway->getAllProducts('webshop', $currencies))
472
            );
473
        }
474
475
        return $this->prepareResponseData($related_products);
476
    }
477
478
   /**
479
     * Gets product keywords which can be used to sort ones webshop
480
     *
481
     *
482
     * @param struct  $credentials Credentials to use the server
483
     * @param integer $shop_id    Id for the shop
484
     *
485
     * @return array with id and keywords
486
     */
487 View Code Duplication
    function getProductKeywords($credentials, $shop_id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
488
    {
489
        $this->checkCredentials($credentials);
490
        $this->_factoryWebshop($shop_id);
491
492
        $product = new Product($this->kernel);
493
        $keywords = $product->getKeywordAppender();
494
        return $this->prepareResponseData($keywords->getUsedKeywords());
495
    }
496
497
    /**
498
     * Returns the categories for the shop
499
     *
500
     * @param struct  $credentials Credentials to use the server
501
     * @param integer $shop_id    Id for the shop
502
     *
503
     * @return array with categories
504
     *
505
     */
506 View Code Duplication
    public function getProductCategories($credentials, $shop_id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
507
    {
508
        if (is_object($return = $this->checkCredentials($credentials))) {
509
            return $return;
510
        }
511
512
        $this->_factoryWebshop($shop_id);
513
        $category = new Intraface_Category(
514
            $this->kernel,
515
            MDB2::singleton(DB_DSN),
516
            new Intraface_Category_Type('shop', $shop_id)
517
        );
518
519
        return $this->prepareResponseData($category->getAllCategories());
520
    }
521
522
    /**
523
     * Returns the pictures for the product categories for the shop
524
     *
525
     * @param struct  $credentials Credentials to use the server
526
     * @param integer $shop_id     Id for the shop
527
     * @param integer $category_id Categori id
528
     *
529
     * @return array with pictures for categories
530
     */
531 View Code Duplication
    public function getProductCategoryPicture($credentials, $shop_id, $category_id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
532
    {
533
        if (is_object($return = $this->checkCredentials($credentials))) {
534
            return $return;
535
        }
536
537
        $this->_factoryWebshop($shop_id);
538
539
        $module = $this->kernel->useModule('filemanager');
0 ignored issues
show
Unused Code introduced by
$module 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...
540
        require_once 'Intraface/modules/filemanager/AppendFile.php';
541
542
        $pictures = array();
543
544
            $append_file = new AppendFile($this->kernel, 'category', $category_id);
545
            $appendix_list = $append_file->getList();
546
        foreach ($appendix_list as $key => $appendix) {
547
            $tmp_filehandler = new FileHandler($this->kernel, $appendix['file_handler_id']);
548
            $pictures[$key]['id']                   = $appendix['file_handler_id'];
549
            $pictures[$key]['original']['icon_uri'] = $tmp_filehandler->get('icon_uri');
550
            $pictures[$key]['original']['name']     = $tmp_filehandler->get('file_name');
551
            $pictures[$key]['original']['width']    = $tmp_filehandler->get('width');
552
            $pictures[$key]['original']['height']   = $tmp_filehandler->get('height');
553
            $pictures[$key]['original']['file_uri'] = $tmp_filehandler->get('file_uri');
554
            $pictures[$key]['appended_file_id']     = $appendix['id'];
555
556
            if ($tmp_filehandler->get('is_image')) {
557
                $tmp_filehandler->createInstance();
558
                $instances = $tmp_filehandler->instance->getList('include_hidden');
559
                foreach ($instances as $instance) {
560
                    $pictures[$key][$instance['name']]['file_uri'] = $instance['file_uri'];
561
                    $pictures[$key][$instance['name']]['name']     = $instance['name'];
562
                    $pictures[$key][$instance['name']]['width']    = $instance['width'];
563
                    $pictures[$key][$instance['name']]['height']   = $instance['height'];
564
                }
565
            }
566
            $tmp_filehandler->__destruct();
567
            unset($tmp_filehandler);
568
        }
569
570
        return $this->prepareResponseData($pictures);
571
    }
572
573
    /**
574
     * Add product to basket
575
     *
576
     * @param struct  $credentials       Credentials to use the server
577
     * @param integer $shop_id    Id for the shop
578
     * @param integer $produt_id         Product id to add
0 ignored issues
show
Documentation introduced by
There is no parameter named $produt_id. Did you maybe mean $product_id?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
579
     * @param integer $product_variation_id Product variation id to change
580
     * @param integer $quantity          Optional quantity
581
     * @param string  $text              Extra text to the itemline
582
     * @param integer $product_detail_id Product detail id
583
     *
584
     * @return boolean
585
     */
586 View Code Duplication
    public function addProductToBasket($credentials, $shop_id, $product_id, $product_variation_id, $quantity = 1, $text = '', $product_detail_id = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
587
    {
588
        if (is_object($return = $this->checkCredentials($credentials))) {
589
            return $return;
590
        }
591
592
        $this->_factoryWebshop($shop_id);
593
594
        if (!is_numeric($product_id)) {
595
            require_once 'XML/RPC2/Exception.php';
596
            throw new XML_RPC2_FaultException('product id must be an integer', -5);
597
        }
598
599
        $product_id = $this->processRequestData(intval($product_id));
600
        $product_variation_id = $this->processRequestData(intval($product_variation_id));
601
        $quantity = $this->processRequestData(intval($quantity));
602
        $text = $this->processRequestData($text);
603
        $product_detail_id = $this->processRequestData(intval($product_detail_id));
604
605
        return $this->prepareResponseData(
606
            $this->webshop->getBasket()->add($product_id, $product_variation_id, $quantity, $text, $product_detail_id)
607
        );
608
    }
609
610
    /**
611
     * Change the quantity of one product in basket
612
     *
613
     * @param struct  $credentials       Credentials to use the server
614
     * @param integer $shop_id    Id for the shop
615
     * @param integer $product_id        Product id to change
616
     * @param integer $product_variation_id Product_variation_id to change
617
     * @param integer $quantity          New quantity
618
     * @param string  $text              Extra text to the itemline
619
     * @param integer $product_detail_id Product detail id
620
     *
621
     * @return mixed
622
     */
623 View Code Duplication
    public function changeProductInBasket($credentials, $shop_id, $product_id, $product_variation_id, $quantity, $text = '', $product_detail_id = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
624
    {
625
        $this->checkCredentials($credentials);
626
627
        $this->_factoryWebshop($shop_id);
628
629
        if (!is_numeric($product_id) and !is_numeric($quantity)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
630
            require_once 'XML/RPC2/Exception.php';
631
            throw new XML_RPC2_FaultException('product id and quantity must be integers', -5);
632
        }
633
634
        $product_id = $this->processRequestData(intval($product_id));
635
        $product_variation_id = $this->processRequestData(intval($product_variation_id));
636
        $quantity = $this->processRequestData(intval($quantity));
637
        $text = $this->processRequestData($text);
638
        $product_detail_id = $this->processRequestData(intval($product_detail_id));
639
640
        if (!$this->webshop->getBasket()->change($product_id, $product_variation_id, $quantity, $text, $product_detail_id)) {
641
            return false;
642
        }
643
644
        return true;
645
    }
646
647
    /**
648
     * Gets an array with the current basket
649
     *
650
     * @param struct $credentials Credentials to use the server
651
     * @param integer $shop_id    Id for the shop
652
     * @param struct $customer customer values
653
     *
654
     * @return array
655
     */
656 View Code Duplication
    public function getBasket($credentials, $shop_id, $customer = array())
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
657
    {
658
        $this->checkCredentials($credentials);
659
660
        $this->_factoryWebshop($shop_id);
661
662
        $customer = $this->processRequestData($customer);
663
664
665
        // we put the possibility for BasketEvaluation not to be run.
666
        if (is_string($customer) && $customer == 'no_evaluation') {
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...
667
            // nothing happens
668
        } elseif (is_array($customer)) {
669
            $basketevaluation = new Intraface_modules_shop_BasketEvaluation(MDB2::singleton(DB_DSN), $this->webshop->kernel->intranet, $this->webshop->shop);
670
            if (!$basketevaluation->run($this->webshop->getBasket(), $customer)) {
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...
671
                // We should see to return the result in some way.
672
            }
673
        }
674
675
        if (false !== ($currency_gateway = $this->getCurrencyGateway())) {
676
            $currencies = $currency_gateway->findAllWithExchangeRate();
677
        } else {
678
            $currencies = false;
679
        }
680
681
        return $this->prepareResponseData(array(
682
            'items' => $this->webshop->getBasket()->getItems($currencies),
683
            'total_price' => $this->webshop->getBasket()->getTotalPriceInCurrencies($currencies),
684
            'weight' => $this->webshop->getBasket()->getTotalWeight()
685
        ));
686
    }
687
688
    /**
689
     * Places an order in Intraface based on the current basket
690
     *
691
     * @param struct $credentials Credentials to use the server
692
     * @param integer $shop_id    Id for the shop
693
     * @param struct $values      Values to save
694
     *
695
     * @return integer $order_id
696
     */
697 View Code Duplication
    public function placeOrder($credentials, $shop_id, $values)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
698
    {
699
        $this->checkCredentials($credentials);
700
701
        $this->_factoryWebshop($shop_id);
702
703
        $values = $this->processRequestData($values);
704
705
        if (!is_array($this->webshop->getBasket()->getItems()) or count($this->webshop->getBasket()->getItems()) <= 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
706
            require_once 'XML/RPC2/Exception.php';
707
            throw new XML_RPC2_FaultException('order could not be sent - cart is empty', -4);
708
        }
709
710
        if (empty($values['description'])) {
711
            $values['description'] = $this->webshop->getShop()->getName();
712
        }
713
714
        if (!$order_id = $this->webshop->placeOrder($values)) {
715
            require_once 'XML/RPC2/Exception.php';
716
            throw new XML_RPC2_FaultException('order could not be placed. It returned the following error: ' . strtolower(implode(', ', $this->webshop->error->getMessage())), -4);
717
        }
718
719
        return $this->prepareResponseData($this->webshop->getOrderIdentifierKey());
720
    }
721
722
    /**
723
     * Saves buyer details
724
     *
725
     * @param struct $credentials Credentials to use the server
726
     * @param integer $shop_id    Id for the shop
727
     * @param struct $values      Values to save
728
     *
729
     * @return boolean true or false
730
     */
731 View Code Duplication
    public function saveAddress($credentials, $shop_id, $values)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
732
    {
733
        $this->checkCredentials($credentials);
734
735
        $this->_factoryWebshop($shop_id);
736
737
        if (!is_array($values)) {
738
            require_once 'XML/RPC2/Exception.php';
739
            throw new XML_RPC2_FaultException('details could not be saved - nothing to save', -4);
740
        }
741
742
        $values = $this->processRequestData($values);
743
744
        if (!$this->webshop->getBasket()->saveAddress($values)) {
745
            require_once 'XML/RPC2/Exception.php';
746
            throw new XML_RPC2_FaultException('datails could not be saved ' . strtolower(implode(', ', $this->webshop->error->getMessage())), -4);
747
        }
748
749
        return $this->prepareResponseData(true);
750
    }
751
752
    /**
753
     * Get buyer details
754
     *
755
     * @param struct  $credentials Credentials to use the server
756
     * @param integer $shop_id    Id for the shop
757
     *
758
     * @return array
759
     */
760
    public function getAddress($credentials, $shop_id)
761
    {
762
        $this->checkCredentials($credentials);
763
764
        $this->_factoryWebshop($shop_id);
765
766
        return $this->prepareResponseData($this->webshop->getBasket()->getAddress());
767
    }
768
769
    /**
770
     * Saves customer coupon
771
     *
772
     * @param struct $credentials     Credentials to use the server
773
     * @param integer $shop_id    Id for the shop
774
     * @param string $customer_coupon Customer coupon to save
775
     *
776
     * @return boolean true or false
777
     */
778 View Code Duplication
    public function saveCustomerCoupon($credentials, $shop_id, $customer_coupon)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
779
    {
780
        $this->checkCredentials($credentials);
781
782
        $this->_factoryWebshop($shop_id);
783
784
        $customer_coupon = $this->processRequestData($customer_coupon);
785
        if (!$this->webshop->getBasket()->saveCustomerCoupon($customer_coupon)) {
786
            require_once 'XML/RPC2/Exception.php';
787
            throw new XML_RPC2_FaultException('datails could not be saved ' . strtolower(implode(', ', $this->webshop->error->getMessage())), -4);
788
        }
789
790
        return $this->prepareResponseData(true);
791
    }
792
793
794
    /**
795
     * Get customer coupon
796
     *
797
     * @param struct $credentials Credentials to use the server
798
     * @param integer $shop_id    Id for the shop
799
     *
800
     * @return array
801
     */
802
    public function getCustomerCoupon($credentials, $shop_id)
803
    {
804
        $this->checkCredentials($credentials);
805
806
        $this->_factoryWebshop($shop_id);
807
        return $this->prepareResponseData($this->webshop->getBasket()->getCustomerCoupon());
808
    }
809
810
    /**
811
     * Saves customer EAN location number
812
     *
813
     * @param struct $credentials     Credentials to use the server
814
     * @param integer $shop_id    Id for the shop
815
     * @param string $customer_ean Customer EAN to save
816
     *
817
     * @return boolean true or false
818
     */
819 View Code Duplication
    public function saveCustomerEan($credentials, $shop_id, $customer_ean)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
820
    {
821
        $this->checkCredentials($credentials);
822
823
        $this->_factoryWebshop($shop_id);
824
825
        $customer_ean = $this->processRequestData($customer_ean);
826
        if (!$this->webshop->getBasket()->saveCustomerEan($customer_ean)) {
827
            require_once 'XML/RPC2/Exception.php';
828
            throw new XML_RPC2_FaultException('ean could not be saved ' . strtolower(implode(', ', $this->webshop->error->getMessage())), -4);
829
        }
830
831
        return $this->prepareResponseData(true);
832
    }
833
834
835
    /**
836
     * Get customer EAN location number
837
     *
838
     * @param struct $credentials Credentials to use the server
839
     * @param integer $shop_id    Id for the shop
840
     *
841
     * @return array
842
     */
843
    public function getCustomerEan($credentials, $shop_id)
844
    {
845
        $this->checkCredentials($credentials);
846
847
        $this->_factoryWebshop($shop_id);
848
849
        return $this->prepareResponseData($this->webshop->getBasket()->getCustomerEan());
850
    }
851
852
    /**
853
     * Saves customer comment
854
     *
855
     * @param struct $credentials     Credentials to use the server
856
     * @param integer $shop_id    Id for the shop
857
     * @param string $customer_comment Customer coupon to save
858
     *
859
     * @return boolean true or false
860
     */
861 View Code Duplication
    public function saveCustomerComment($credentials, $shop_id, $customer_comment)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
862
    {
863
        $this->checkCredentials($credentials);
864
865
        $this->_factoryWebshop($shop_id);
866
867
        $customer_comment = $this->processRequestData($customer_comment);
868
        if (!$this->webshop->getBasket()->saveCustomerComment($customer_comment)) {
869
            require_once 'XML/RPC2/Exception.php';
870
            throw new XML_RPC2_FaultException('datails could not be saved ' . strtolower(implode(', ', $this->webshop->error->getMessage())), -4);
871
        }
872
873
        return $this->prepareResponseData(true);
874
    }
875
876
877
    /**
878
     * Get customer comment
879
     *
880
     * @param struct $credentials Credentials to use the server
881
     * @param integer $shop_id    Id for the shop
882
     *
883
     * @return array
884
     */
885
    public function getCustomerComment($credentials, $shop_id)
886
    {
887
        $this->checkCredentials($credentials);
888
889
        $this->_factoryWebshop($shop_id);
890
891
        return $this->prepareResponseData($this->webshop->getBasket()->getCustomerComment());
892
    }
893
894
    /**
895
     * Get possible payment methods
896
     *
897
     * @param struct $credentials Credentials to use the server
898
     * @param integer $shop_id    Id for the shop
899
     *
900
     * @return array
901
     */
902
    public function getPaymentMethods($credentials, $shop_id)
903
    {
904
        $this->checkCredentials($credentials);
905
906
        $this->_factoryWebshop($shop_id);
907
908
        return $this->prepareResponseData($this->webshop->getPaymentMethods());
909
    }
910
911
    /**
912
     * Saves payment method
913
     *
914
     * @param struct $credentials     Credentials to use the server
915
     * @param integer $shop_id    Id for the shop
916
     * @param string $payment_method Payment method to save
917
     *
918
     * @return boolean true or false
919
     */
920 View Code Duplication
    public function savePaymentMethod($credentials, $shop_id, $payment_method)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
921
    {
922
        $this->checkCredentials($credentials);
923
924
        $this->_factoryWebshop($shop_id);
925
926
        $payment_method = $this->processRequestData($payment_method);
927
        if (!$this->webshop->getBasket()->savePaymentMethod($payment_method)) {
928
            require_once 'XML/RPC2/Exception.php';
929
            throw new XML_RPC2_FaultException('datails could not be saved ' . strtolower(implode(', ', $this->webshop->error->getMessage())), -4);
930
        }
931
932
        return $this->prepareResponseData(true);
933
    }
934
935
    /**
936
     * Returns selected payment method
937
     *
938
     * @param struct $credentials Credentials to use the server
939
     * @param integer $shop_id    Id for the shop
940
     *
941
     * @return array
942
     */
943
    public function getPaymentMethod($credentials, $shop_id)
944
    {
945
        $this->checkCredentials($credentials);
946
947
        $this->_factoryWebshop($shop_id);
948
949
        return $this->prepareResponseData($this->webshop->getBasket()->getPaymentMethod());
950
    }
951
952
    /**
953
     * Get receipt text
954
     *
955
     * @param struct $credentials Credentials to use the server
956
     * @param integer $shop_id    Id for the shop
957
     *
958
     * @return array
959
     */
960
    public function getReceiptText($credentials, $shop_id)
961
    {
962
        $this->checkCredentials($credentials);
963
964
        $this->_factoryWebshop($shop_id);
965
966
        return $this->prepareResponseData($this->webshop->getReceiptText());
967
    }
968
969
    /**
970
     * Get url for terms of trade
971
     *
972
     * @param struct  $credentials Credentials to use the server
973
     * @param integer $shop_id     Id for the shop
974
     *
975
     * @return string
976
     */
977
    public function getTermsOfTradeUrl($credentials, $shop_id)
978
    {
979
        $this->checkCredentials($credentials);
980
981
        $this->_factoryWebshop($shop_id);
982
983
        return $this->prepareResponseData($this->webshop->getShop()->getTermsOfTradeUrl());
984
    }
985
986
    /**
987
     * Get default currency.
988
     *
989
     * @param struct  $credentials Credentials to use the server
990
     * @param integer $shop_id     Id for the shop
991
     *
992
     * @return string
993
     */
994
    public function getCurrency($credentials, $shop_id)
995
    {
996
        $this->checkCredentials($credentials);
997
998
        $this->_factoryWebshop($shop_id);
999
1000
        return $this->prepareResponseData($this->getCurrencyArray());
1001
    }
1002
1003
    /**
1004
     * Returns currency gateway if there is access to it
1005
     */
1006 View Code Duplication
    private function getCurrencyGateway()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1007
    {
1008
        if ($this->webshop->kernel->intranet->hasModuleAccess('currency')) {
1009
            $this->webshop->kernel->useModule('currency', true); // true: ignore intranet access
1010
            return new Intraface_modules_currency_Currency_Gateway(Doctrine_Manager::connection(DB_DSN));
1011
        }
1012
        return false;
1013
    }
1014
1015
    /**
1016
     * Returns an array with currency information.
1017
     *
1018
     * @return array default currency and valid currencies
1019
     */
1020 View Code Duplication
    private function getCurrencyArray()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1021
    {
1022
        $currency['default'] = 'DKK';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$currency was never initialized. Although not strictly required by PHP, it is generally a good practice to add $currency = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1023
        $currency['currencies']['DKK'] = 'Danish Krone';
1024
1025
        if (false !== ($currency_gateway = $this->getCurrencyGateway())) {
1026
            foreach ($currency_gateway->findAllWithExchangeRate() as $c) {
1027
                $currency['currencies'][$c->getType()->getIsoCode()] = $c->getType()->getDescription();
1028
            }
1029
        }
1030
1031
        if (false !== ($default_currency = $this->webshop->getShop()->getDefaultCurrency($currency_gateway))) {
1032
            $currency['default'] = $default_currency->getType()->getIsoCode();
1033
        }
1034
1035
        return $currency;
1036
    }
1037
1038
    /**
1039
     * Get identifier
1040
     *
1041
     * @param struct  $credentials Credentials to use the server
1042
     * @param integer $shop_id     Id for the shop
1043
     *
1044
     * @return string
1045
     */
1046
    public function getIdentifier($credentials, $shop_id)
1047
    {
1048
        $this->checkCredentials($credentials);
1049
1050
        $this->_factoryWebshop($shop_id);
1051
1052
        return $this->prepareResponseData($this->webshop->getShop()->getIdentifier());
1053
    }
1054
1055
    /**
1056
     * Gets information about the company
1057
     *
1058
     * @param struct $credentials Credentials to use the server
1059
     *
1060
     * @return array
1061
     */
1062 View Code Duplication
    public function getCompanyInformation($credentials)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1063
    {
1064
        $this->checkCredentials($credentials);
1065
        $address = array();
1066
        $address['name'] = $this->kernel->getIntranet()->getAddress()->get('name');
1067
        $address['address'] = $this->kernel->getIntranet()->getAddress()->get('address');
1068
        $address['postcode'] = $this->kernel->getIntranet()->getAddress()->get('postcode');
1069
        $address['city'] = $this->kernel->getIntranet()->getAddress()->get('city');
1070
        $address['cvr'] = $this->kernel->getIntranet()->getAddress()->get('cvr');
1071
        return  $this->prepareResponseData($address);
1072
    }
1073
1074
    /**
1075
     * Initialize the webshop
1076
     *
1077
     * @return void
1078
     */
1079 View Code Duplication
    private function _factoryWebshop($shop_id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1080
    {
1081
        if (!$this->kernel->intranet->hasModuleAccess('shop')) {
1082
            require_once 'XML/RPC2/Exception.php';
1083
            throw new XML_RPC2_FaultException('The intranet does not have access to the module webshop', -2);
1084
        }
1085
        $this->kernel->module('shop');
1086
1087
        $doctrine = $this->bucket->get('Doctrine_Connection_Common');
1088
        $gateway = new Intraface_modules_shop_ShopGateway($doctrine);
1089
        $shop = $gateway->findById($shop_id);
1090
        if ($shop === false) {
1091
            throw new XML_RPC2_FaultException('Could not find shop', 1);
1092
        }
1093
        $this->webshop = new Intraface_modules_shop_Coordinator($this->kernel, $shop, $this->credentials['session_id']);
1094
    }
1095
}
1096