Intraface_XMLRPC_Shop_Server2::getPaymentMethods()   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
4
 *
5
 * @todo we need to move kernel out of Product.
6
 * @todo we need to move kernel out of DBQuery.
7
 * @todo we need to find out what to do with hasIntranetAccess and stock
8
 * @todo we need to work out with getPictures() and Kernel->useModule
9
 *
10
 * @category XMLRPC_Server
11
 * @package  Intraface_XMLRPC_Shop
12
 * @author   Lars Olesen <[email protected]>
13
 * @version  @package-version@
14
 */
15
class Intraface_XMLRPC_Shop_Server2 extends Intraface_XMLRPC_Server
16
{
17
    private $webshop;
18
    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...
19
    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...
20
21
    /**
22
     * Gets a list with products
23
     *
24
     * @param struct $credentials Credentials to use the server
25
     * @param integer $shop_id    Id for the shop
26
     * @param array  $search      Optional search array
27
     *
28
     * @return array
29
     */
30
    public function getProducts($credentials, $shop_id, $search = array())
31
    {
32
        $this->checkCredentials($credentials);
33
34
        $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...
35
36
        $search = $this->processRequestData($search);
37
38
        $mixed = array();
39
        if (!empty($search)) {
40
            $mixed = $search;
41
        }
42
43
        $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...
44
45
        $this->_factoryWebshop($shop_id);
46
47
        $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...
48
49
        $area = '';
50
51
        if (!empty($mixed['area'])) {
52
            $area = $mixed['area'];
53
        }
54
55
        $product = new Product($this->webshop->kernel);
56
57
        if (!isset($mixed['use_paging']) || $mixed['use_paging'] == 'true') {
58
            $product->getDBQuery()->usePaging('paging');
59
        }
60
61
62
        // sublevel has to be used so other searches are not overwritten
63
        $product->getDBQuery()->storeResult('use_stored', 'webshop_' . $area . '_' .  md5($this->credentials['session_id']), 'sublevel');
64
        $debug2 = serialize($mixed);
65
        if (isset($mixed['offset']) and array_key_exists('offset', $mixed) and is_numeric($mixed['offset'])) {
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...
66
            $product->getDBQuery()->useStored(true);
67
            $product->getDBQuery()->setPagingOffset((int)$mixed['offset']);
68
            $debug2 .= 'offset ' . $mixed['offset'];
69
        } 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...
70
            $product->getDBQuery()->useStored(true);
71
            $debug2 .= 'use_stored true';
72
        } else {
73
            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...
74
                $product->getDBQuery()->setFilter('search', $mixed['search']);
75
                $debug2 .= 'search ' . $mixed['search'];
76
            }
77
78
            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...
79
                $product->getDBQuery()->setFilter('keywords', $mixed['keywords']);
80
                $debug2 .= 'keyword ' . $mixed['keywords'];
81
            }
82
83
            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...
84
                $product->getDBQuery()->setFilter('shop_id', $shop_id);
85
                $product->getDBQuery()->setFilter('category', $mixed['category']);
86
                $debug2 .= 'category ' . $mixed['category'];
87
            }
88
89
            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...
90
                $product->getDBQuery()->setFilter('ids', $mixed['ids']);
91
                $debug2 .= 'ids ' . implode(', ', $mixed['ids']);
92
            }
93
94
            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...
95
                $product->getDBQuery()->setFilter('sorting', $mixed['sorting']);
96
                $debug2 .= 'sorting ' . $mixed['sorting'];
97
            }
98
        }
99
100
        $products = array();
101
        foreach ($product->getList('webshop') as $p) {
102
            // Make sure we only include necessary data. Several things more might be left out. Mostly we remove description.
103
            $products[] = array(
104
                'id' => $p['id'],
105
                'number' => $p['number'],
106
                'name' => $p['name'],
107
                'price' => $p['price'],
108
                'unit' => $p['unit'],
109
                'vat' => $p['vat'],
110
                'weight' => $p['weight'],
111
                'detail_id' => $p['detail_id'],
112
                'vat_percent' => $p['vat_percent'],
113
                'price_incl_vat' => $p['price_incl_vat'],
114
                'changed_date' => $p['changed_date'],
115
                'stock' => $p['stock'],
116
                'has_variation' => $p['has_variation'],
117
                'pictures' => $p['pictures'],
118
                'stock_status' => $p['stock_status']);
119
        }
120
121
        return $this->prepareResponseData(array(
122
            'parameter' => $mixed,
123
            //'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...
124
            'products' => $products,
125
            'paging' => $product->getDBQuery()->getPaging(),
126
            'search' => array(),
127
        ));
128
    }
129
130
131
    /**
132
     * Gets one product
133
     *
134
     * @param struct  $credentials Credentials to use the server
135
     * @param integer $shop_id    Id for the shop
136
     * @param integer $id          Product id
137
     *
138
     * @return array
139
     */
140
    public function getProduct($credentials, $shop_id, $id)
141
    {
142
        $this->checkCredentials($credentials);
143
144
        $this->_factoryWebshop($shop_id);
145
146
        if (!is_numeric($id)) {
147
            require_once 'XML/RPC2/Exception.php';
148
            throw new XML_RPC2_FaultException('product id must be an integer', -5);
149
        }
150
151
        $id = $this->processRequestData(intval($id));
152
153
        $return = array();
154
155
        $product = new Product($this->kernel, $id);
156
        $product->getPictures();
157
        $return['product'] = $product->get();
158
        if (!$product->get('has_variation') && $product->get('stock')) {
159
            $return['stock'] = $product->getStock()->get();
160
        }
161
162
        if ($product->get('has_variation')) {
163
            // We should make a Doctrine Product_X_AttributeGroup class and get all the groups i one sql
164
            $groups = $product->getAttributeGroups();
165
            $group_gateway = new Intraface_modules_product_Attribute_Group_Gateway;
166
            foreach ($groups as $key => $group) {
167
                // Make sure we only include necessary data
168
                $return['attribute_groups'][$key]['id'] = $group['id'];
169
                $return['attribute_groups'][$key]['name'] = $group['name'];
170
                $attributes = $group_gateway->findById($group['id'])->getAttributesUsedByProduct($product);
171
                foreach ($attributes as $attribute) {
172
                    $return['attribute_groups'][$key]['attributes'][] = array(
173
                        'id' => $attribute->getId(),
174
                        'name' => $attribute->getName()
175
                    );
176
                }
177
            }
178
179
            $variations = $product->getVariations();
180
            foreach ($variations as $variation) {
181
                $detail = $variation->getDetail();
182
                $attribute_string = '';
183
                $attributes_array = $variation->getAttributesAsArray();
184
                foreach ($attributes_array as $attribute) {
185
                    if ($attribute_string != '') {
186
                        $attribute_string .= '-';
187
                    }
188
                    $attribute_string .= $attribute['id'];
189
                }
190
191
                $return['variations'][] = array(
192
                    'variation' => array(
193
                        'id' => $variation->getId(),
194
                        'detail_id' => $detail->getId(),
195
                        'number' => $variation->getNumber(),
196
                        'name' => $variation->getName(),
197
                        'attributes' => $attributes_array,
198
                        'identifier' => $attribute_string,
199
                        'price_incl_vat' => round(($product->get('price') + $detail->getPriceDifference()) * (1 + $product->get('vat_percent')/100), 2),
200
                        'weight' => $product->get('weight') + $detail->getWeightDifference()
201
                    ),
202
                    'stock' => $variation->getStock($product)->get()
203
                );
204
            }
205
        }
206
207
        return $this->prepareResponseData($return);
208
    }
209
210
    /**
211
     * Gets related products
212
     *
213
     * @param struct  $credentials Credentials to use the server
214
     * @param integer $shop_id    Id for the shop
215
     * @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...
216
     *
217
     * @return array
218
     */
219 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...
220
    {
221
        $this->checkCredentials($credentials);
222
223
        $this->_factoryWebshop($shop_id);
224
225
        if (!is_numeric($product_id)) {
226
            require_once 'XML/RPC2/Exception.php';
227
            throw new XML_RPC2_FaultException('product id must be an integer', -5);
228
        }
229
230
        $product_id = $this->processRequestData(intval($product_id));
231
232
        $product = new Product($this->kernel, $product_id);
233
        return $this->prepareResponseData($product->getRelatedProducts());
234
    }
235
236
   /**
237
     * Gets featured products
238
     *
239
     * Method is experimental and only used by discimport.dk. If you need to use it
240
     * as well, please contact [email protected].
241
     *
242
     * @param struct  $credentials Credentials to use the server
243
     * @param integer $shop_id    Id for the shop
244
     *
245
     * @return array
246
     */
247
    public function getFeaturedProducts($credentials, $shop_id)
248
    {
249
        $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...
250
251
        $this->checkCredentials($credentials);
252
253
        $this->_factoryWebshop($shop_id);
254
255
        $db = MDB2::singleton(DB_DSN);
256
257
        if (PEAR::isError($db)) {
258
            require_once 'XML/RPC2/Exception.php';
259
            throw new XML_RPC2_FaultException($db->getMessage() . $db->getUserInfo(), -1);
260
        }
261
262
        $featured = new Intraface_modules_shop_FeaturedProducts($this->kernel->intranet, $this->webshop->getShop(), $db);
263
        $all = $featured->getAll();
264
265
        $related_products = array();
266
267
        foreach ($all as $row) {
268
            $product = new Product($this->kernel);
269
            $product->getDBQuery()->setFilter('keywords', array($row['keyword_id']));
270
271
            $related_products[] = array(
272
                'title' => $row['headline'],
273
                'products' => $product->getList()
274
            );
275
        }
276
277
        return $this->prepareResponseData($related_products);
278
    }
279
280
   /**
281
     * Gets product keywords which can be used to sort ones webshop
282
     *
283
     *
284
     * @param struct  $credentials Credentials to use the server
285
     * @param integer $shop_id    Id for the shop
286
     *
287
     * @return array with id and keywords
288
     */
289 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...
290
    {
291
        $this->checkCredentials($credentials);
292
        $this->_factoryWebshop($shop_id);
293
294
        $product = new Product($this->kernel);
295
        $keywords = $product->getKeywordAppender();
296
        return $this->prepareResponseData($keywords->getUsedKeywords());
297
    }
298
299
    /**
300
     * Returns the categories for the shop
301
     *
302
     * @param struct  $credentials Credentials to use the server
303
     * @param integer $shop_id    Id for the shop
304
     *
305
     * @return array with categories
306
     *
307
     */
308 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...
309
    {
310
        if (is_object($return = $this->checkCredentials($credentials))) {
311
            return $return;
312
        }
313
314
        $this->_factoryWebshop($shop_id);
315
        $category = new Intraface_Category(
316
            $this->kernel,
317
            MDB2::singleton(DB_DSN),
318
            new Intraface_Category_Type('shop', $shop_id)
319
        );
320
321
        return $this->prepareResponseData($category->getAllCategories());
322
    }
323
324
    /**
325
     * Add product to basket
326
     *
327
     * @param struct  $credentials       Credentials to use the server
328
     * @param integer $shop_id    Id for the shop
329
     * @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...
330
     * @param integer $product_variation_id Product variation id to change
331
     * @param integer $quantity          Optional quantity
332
     * @param string  $text              Extra text to the itemline
333
     * @param integer $product_detail_id Product detail id
334
     *
335
     * @return boolean
336
     */
337 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...
338
    {
339
        if (is_object($return = $this->checkCredentials($credentials))) {
340
            return $return;
341
        }
342
343
        $this->_factoryWebshop($shop_id);
344
345
        if (!is_numeric($product_id)) {
346
            require_once 'XML/RPC2/Exception.php';
347
            throw new XML_RPC2_FaultException('product id must be an integer', -5);
348
        }
349
350
        $product_id = $this->processRequestData(intval($product_id));
351
        $product_variation_id = $this->processRequestData(intval($product_variation_id));
352
        $quantity = $this->processRequestData(intval($quantity));
353
        $text = $this->processRequestData($text);
354
        $product_detail_id = $this->processRequestData(intval($product_detail_id));
355
356
        return $this->prepareResponseData(
357
            $this->webshop->getBasket()->add($product_id, $product_variation_id, $quantity, $text, $product_detail_id)
358
        );
359
    }
360
361
    /**
362
     * Change the quantity of one product in basket
363
     *
364
     * @param struct  $credentials       Credentials to use the server
365
     * @param integer $shop_id    Id for the shop
366
     * @param integer $product_id        Product id to change
367
     * @param integer $product_variation_id Product_variation_id to change
368
     * @param integer $quantity          New quantity
369
     * @param string  $text              Extra text to the itemline
370
     * @param integer $product_detail_id Product detail id
371
     *
372
     * @return mixed
373
     */
374 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...
375
    {
376
        $this->checkCredentials($credentials);
377
378
        $this->_factoryWebshop($shop_id);
379
380
        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...
381
            require_once 'XML/RPC2/Exception.php';
382
            throw new XML_RPC2_FaultException('product id and quantity must be integers', -5);
383
        }
384
385
        $product_id = $this->processRequestData(intval($product_id));
386
        $product_variation_id = $this->processRequestData(intval($product_variation_id));
387
        $quantity = $this->processRequestData(intval($quantity));
388
        $text = $this->processRequestData($text);
389
        $product_detail_id = $this->processRequestData(intval($product_detail_id));
390
391
        if (!$this->webshop->getBasket()->change($product_id, $product_variation_id, $quantity, $text, $product_detail_id)) {
392
            return false;
393
        }
394
395
        return true;
396
    }
397
398
    /**
399
     * Gets an array with the current basket
400
     *
401
     * @param struct $credentials Credentials to use the server
402
     * @param integer $shop_id    Id for the shop
403
     * @param struct $customer customer values
404
     *
405
     * @return array
406
     */
407
    public function getBasket($credentials, $shop_id, $customer = array())
408
    {
409
        $this->checkCredentials($credentials);
410
411
        $this->_factoryWebshop($shop_id);
412
413
        $customer = $this->processRequestData($customer);
414
415
        // we put the possibility for BasketEvaluation not to be run.
416
        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...
417
            // nothing happens
418
        } elseif (is_array($customer)) {
419
            $basketevaluation = new Intraface_modules_shop_BasketEvaluation(MDB2::singleton(DB_DSN), $this->webshop->kernel->intranet, $this->webshop->shop);
420
            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...
421
                // We should see to return the result in some way.
422
            }
423
        }
424
425
        return $this->prepareResponseData(array(
426
            'items' => $this->webshop->getBasket()->getItems(),
427
            'price_total' => $this->webshop->getBasket()->getTotalPrice(),
428
            'weight' => $this->webshop->getBasket()->getTotalWeight()
429
        ));
430
    }
431
432
    /**
433
     * Places an order in Intraface based on the current basket
434
     *
435
     * @param struct $credentials Credentials to use the server
436
     * @param integer $shop_id    Id for the shop
437
     * @param struct $values      Values to save
438
     *
439
     * @return integer $order_id
440
     */
441 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...
442
    {
443
        $this->checkCredentials($credentials);
444
445
        $this->_factoryWebshop($shop_id);
446
447
        $values = $this->processRequestData($values);
448
449
        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...
450
            require_once 'XML/RPC2/Exception.php';
451
            throw new XML_RPC2_FaultException('order could not be sent - cart is empty', -4);
452
        }
453
454
        if (empty($values['description'])) {
455
            $values['description'] = $this->webshop->getShop()->getName();
456
        }
457
458
        if (!$order_id = $this->webshop->placeOrder($values)) {
459
            require_once 'XML/RPC2/Exception.php';
460
            throw new XML_RPC2_FaultException('order could not be placed. It returned the following error: ' . strtolower(implode(', ', $this->webshop->error->getMessage())), -4);
461
        }
462
463
        return $this->prepareResponseData($this->webshop->getOrderIdentifierKey());
464
    }
465
466
    /**
467
     * Saves buyer details
468
     *
469
     * @param struct $credentials Credentials to use the server
470
     * @param integer $shop_id    Id for the shop
471
     * @param struct $values      Values to save
472
     *
473
     * @return boolean true or false
474
     */
475 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...
476
    {
477
        $this->checkCredentials($credentials);
478
479
        $this->_factoryWebshop($shop_id);
480
481
        if (!is_array($values)) {
482
            require_once 'XML/RPC2/Exception.php';
483
            throw new XML_RPC2_FaultException('details could not be saved - nothing to save', -4);
484
        }
485
486
        $values = $this->processRequestData($values);
487
488
        if (!$this->webshop->getBasket()->saveAddress($values)) {
489
            require_once 'XML/RPC2/Exception.php';
490
            throw new XML_RPC2_FaultException('datails could not be saved ' . strtolower(implode(', ', $this->webshop->error->getMessage())), -4);
491
        }
492
493
        return $this->prepareResponseData(true);
494
    }
495
496
    /**
497
     * Get buyer details
498
     *
499
     * @param struct  $credentials Credentials to use the server
500
     * @param integer $shop_id    Id for the shop
501
     *
502
     * @return array
503
     */
504
    public function getAddress($credentials, $shop_id)
505
    {
506
        $this->checkCredentials($credentials);
507
508
        $this->_factoryWebshop($shop_id);
509
510
        return $this->prepareResponseData($this->webshop->getBasket()->getAddress());
511
    }
512
513
    /**
514
     * Saves customer coupon
515
     *
516
     * @param struct $credentials     Credentials to use the server
517
     * @param integer $shop_id    Id for the shop
518
     * @param string $customer_coupon Customer coupon to save
519
     *
520
     * @return boolean true or false
521
     */
522 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...
523
    {
524
        $this->checkCredentials($credentials);
525
526
        $this->_factoryWebshop($shop_id);
527
528
        $customer_coupon = $this->processRequestData($customer_coupon);
529
        if (!$this->webshop->getBasket()->saveCustomerCoupon($customer_coupon)) {
530
            require_once 'XML/RPC2/Exception.php';
531
            throw new XML_RPC2_FaultException('datails could not be saved ' . strtolower(implode(', ', $this->webshop->error->getMessage())), -4);
532
        }
533
534
        return $this->prepareResponseData(true);
535
    }
536
537
538
    /**
539
     * Get customer coupon
540
     *
541
     * @param struct $credentials Credentials to use the server
542
     * @param integer $shop_id    Id for the shop
543
     *
544
     * @return array
545
     */
546
    public function getCustomerCoupon($credentials, $shop_id)
547
    {
548
        $this->checkCredentials($credentials);
549
550
        $this->_factoryWebshop($shop_id);
551
        return $this->prepareResponseData($this->webshop->getBasket()->getCustomerCoupon());
552
    }
553
554
    /**
555
     * Saves customer EAN location number
556
     *
557
     * @param struct $credentials     Credentials to use the server
558
     * @param integer $shop_id    Id for the shop
559
     * @param string $customer_ean Customer EAN to save
560
     *
561
     * @return boolean true or false
562
     */
563 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...
564
    {
565
        $this->checkCredentials($credentials);
566
567
        $this->_factoryWebshop($shop_id);
568
569
        $customer_ean = $this->processRequestData($customer_ean);
570
        if (!$this->webshop->getBasket()->saveCustomerEan($customer_ean)) {
571
            require_once 'XML/RPC2/Exception.php';
572
            throw new XML_RPC2_FaultException('ean could not be saved ' . strtolower(implode(', ', $this->webshop->error->getMessage())), -4);
573
        }
574
575
        return $this->prepareResponseData(true);
576
    }
577
578
579
    /**
580
     * Get customer EAN location number
581
     *
582
     * @param struct $credentials Credentials to use the server
583
     * @param integer $shop_id    Id for the shop
584
     *
585
     * @return array
586
     */
587
    public function getCustomerEan($credentials, $shop_id)
588
    {
589
        $this->checkCredentials($credentials);
590
591
        $this->_factoryWebshop($shop_id);
592
593
        return $this->prepareResponseData($this->webshop->getBasket()->getCustomerEan());
594
    }
595
596
    /**
597
     * Saves customer comment
598
     *
599
     * @param struct $credentials     Credentials to use the server
600
     * @param integer $shop_id    Id for the shop
601
     * @param string $customer_comment Customer coupon to save
602
     *
603
     * @return boolean true or false
604
     */
605 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...
606
    {
607
        $this->checkCredentials($credentials);
608
609
        $this->_factoryWebshop($shop_id);
610
611
        $customer_comment = $this->processRequestData($customer_comment);
612
        if (!$this->webshop->getBasket()->saveCustomerComment($customer_comment)) {
613
            require_once 'XML/RPC2/Exception.php';
614
            throw new XML_RPC2_FaultException('datails could not be saved ' . strtolower(implode(', ', $this->webshop->error->getMessage())), -4);
615
        }
616
617
        return $this->prepareResponseData(true);
618
    }
619
620
621
    /**
622
     * Get customer comment
623
     *
624
     * @param struct $credentials Credentials to use the server
625
     * @param integer $shop_id    Id for the shop
626
     *
627
     * @return array
628
     */
629
    public function getCustomerComment($credentials, $shop_id)
630
    {
631
        $this->checkCredentials($credentials);
632
633
        $this->_factoryWebshop($shop_id);
634
635
        return $this->prepareResponseData($this->webshop->getBasket()->getCustomerComment());
636
    }
637
638
    /**
639
     * Get possible payment methods
640
     *
641
     * @param struct $credentials Credentials to use the server
642
     * @param integer $shop_id    Id for the shop
643
     *
644
     * @return array
645
     */
646
    public function getPaymentMethods($credentials, $shop_id)
647
    {
648
        $this->checkCredentials($credentials);
649
650
        $this->_factoryWebshop($shop_id);
651
652
        return $this->prepareResponseData($this->webshop->getPaymentMethods());
653
    }
654
655
    /**
656
     * Saves payment method
657
     *
658
     * @param struct $credentials     Credentials to use the server
659
     * @param integer $shop_id    Id for the shop
660
     * @param string $payment_method Payment method to save
661
     *
662
     * @return boolean true or false
663
     */
664 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...
665
    {
666
        $this->checkCredentials($credentials);
667
668
        $this->_factoryWebshop($shop_id);
669
670
        $payment_method = $this->processRequestData($payment_method);
671
        if (!$this->webshop->getBasket()->savePaymentMethod($payment_method)) {
672
            require_once 'XML/RPC2/Exception.php';
673
            throw new XML_RPC2_FaultException('datails could not be saved ' . strtolower(implode(', ', $this->webshop->error->getMessage())), -4);
674
        }
675
676
        return $this->prepareResponseData(true);
677
    }
678
679
    /**
680
     * Returns selected payment method
681
     *
682
     * @param struct $credentials Credentials to use the server
683
     * @param integer $shop_id    Id for the shop
684
     *
685
     * @return array
686
     */
687
    public function getPaymentMethod($credentials, $shop_id)
688
    {
689
        $this->checkCredentials($credentials);
690
691
        $this->_factoryWebshop($shop_id);
692
693
        return $this->prepareResponseData($this->webshop->getBasket()->getPaymentMethod());
694
    }
695
696
    /**
697
     * Get receipt text
698
     *
699
     * @param struct $credentials Credentials to use the server
700
     * @param integer $shop_id    Id for the shop
701
     *
702
     * @return array
703
     */
704
    public function getReceiptText($credentials, $shop_id)
705
    {
706
        $this->checkCredentials($credentials);
707
708
        $this->_factoryWebshop($shop_id);
709
710
        return $this->prepareResponseData($this->webshop->getReceiptText());
711
    }
712
713
    /**
714
     * Get url for terms of trade
715
     *
716
     * @param struct  $credentials Credentials to use the server
717
     * @param integer $shop_id     Id for the shop
718
     *
719
     * @return string
720
     */
721
    public function getTermsOfTradeUrl($credentials, $shop_id)
722
    {
723
        $this->checkCredentials($credentials);
724
725
        $this->_factoryWebshop($shop_id);
726
727
        return $this->prepareResponseData($this->webshop->getShop()->getTermsOfTradeUrl());
728
    }
729
730
    /**
731
     * Get identifier
732
     *
733
     * @param struct  $credentials Credentials to use the server
734
     * @param integer $shop_id     Id for the shop
735
     *
736
     * @return string
737
     */
738
    public function getIdentifier($credentials, $shop_id)
739
    {
740
        $this->checkCredentials($credentials);
741
742
        $this->_factoryWebshop($shop_id);
743
744
        return $this->prepareResponseData($this->webshop->getShop()->getIdentifier());
745
    }
746
747
    /**
748
     * Checks credentials
749
     *
750
     * @param struct $credentials Credentials to use the server
751
     *
752
     * @return array
753
     */
754
    /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% 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...
755
    protected function checkCredentials($credentials)
756
    {
757
        $this->credentials = $credentials;
758
759
        if (count($credentials) != 2) { // -4
760
            require_once 'XML/RPC2/Exception.php';
761
            throw new XML_RPC2_FaultException('wrong argument count in $credentials - got ' . count($credentials) . ' arguments - need 2', -4);
762
        }
763
        if (empty($credentials['private_key'])) { // -5
764
            require_once 'XML/RPC2/Exception.php';
765
            throw new XML_RPC2_FaultException('supply a private_key', -5);
766
        }
767
        if (empty($credentials['session_id'])) { // -5
768
            require_once 'XML/RPC2/Exception.php';
769
            throw new XML_RPC2_FaultException('supply a session_id', -5);
770
        }
771
772
        $auth_adapter = new Intraface_Auth_PrivateKeyLogin(MDB2::singleton(DB_DSN), $credentials['session_id'], $credentials['private_key']);
773
        $weblogin = $auth_adapter->auth();
774
775
        if (!$weblogin) {
776
            require_once 'XML/RPC2/Exception.php';
777
            throw new XML_RPC2_FaultException('access to intranet denied', -2);
778
        }
779
780
        $this->kernel = new Intraface_Kernel($credentials['session_id']);
781
        $this->kernel->weblogin = $weblogin;
782
        $this->kernel->intranet = new Intraface_Intranet($weblogin->getActiveIntranetId());
783
        $this->kernel->setting = new Intraface_Setting($this->kernel->intranet->get('id'));
784
785
        return true;
786
    }
787
    */
788
789
    /**
790
     * Initialize the webshop
791
     *
792
     * @return void
793
     */
794
    private function _factoryWebshop($shop_id)
795
    {
796
        if (!$this->kernel->intranet->hasModuleAccess('shop')) {
797
            require_once 'XML/RPC2/Exception.php';
798
            throw new XML_RPC2_FaultException('The intranet does not have access to the module webshop', -2);
799
        }
800
        $this->kernel->module('shop');
801
802
        Doctrine_Manager::connection(DB_DSN);
803
        $shop = Doctrine::getTable('Intraface_modules_shop_Shop')->findOneById((int)$shop_id);
804
        if ($shop === false) {
805
            throw new XML_RPC2_FaultException('Could not find shop', 1);
806
        }
807
        $this->webshop = new Intraface_modules_shop_Coordinator($this->kernel, $shop, $this->credentials['session_id']);
808
    }
809
}
810