Completed
Push — master ( ec109c...5519ab )
by Lawrence
03:13
created

Product::getProducts()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
3
namespace ABM\Wasabi;
4
5
use Ratchet\MessageComponentInterface;
6
use Ratchet\ConnectionInterface;
7
use Analog\Analog;
8
9
class Product implements MessageComponentInterface
10
{
11
    protected $clients;
12
    protected $dbConn;
13
14
    public function __construct()
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...
15
    {
16
        $this->clients = new \SplObjectStorage();
17
        // Now connect to PS DB using Simplon on Composer
18
        $this->dbConn = new \Simplon\Mysql\Mysql(
19
    '127.0.0.1',
20
    _DB_USER_,
21
    _DB_PASSWD_,
22
    _DB_NAME_
23
        );
24
        $log_file = 'ws-prod.log';
25
        Analog::handler(\Analog\Handler\File::init($log_file));
0 ignored issues
show
Documentation introduced by
\Analog\Handler\File::init($log_file) is of type object<Closure>, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
26
    }
27
28
    public function onOpen(ConnectionInterface $conn)
29
    {
30
        // Store the new connection to send messages to later
31
        $this->clients->attach($conn);
32
33
        Analog::log("New connection: $conn->resourceId");
0 ignored issues
show
Bug introduced by
Accessing resourceId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
34
    }
35
36 View Code Duplication
    public function onMessage(ConnectionInterface $from, $msg)
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...
37
    {
38
        foreach ($this->clients as $client) {
39
            if ($from == $client) {
40
                $category = (int) substr($msg, 0, strpos($msg, ','));
41
                if ($category != 0) {
42
                    $products = $this->getProducts($category);
43
                } else {
44
                    $product = substr($msg, strpos($msg, ',') + 1);
45
                    $products = $this->getProducts($product);
46
                }
47
                Analog::log("Product variables: $msg");
48
            }
49
        }
50
51
            // Basic test - fire the correct product back via Websocket
52
            $client->send(json_encode($products));
0 ignored issues
show
Bug introduced by
The variable $client seems to be defined by a foreach iteration on line 38. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
Bug introduced by
The variable $products 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...
53
    }
54
55
    private function getProducts($category)
56
    {
57
        $product_ids = $this->getProductIDs($category);
58
        $products = $this->getProduct($product_ids);
59
60
        return $products;
61
    }
62
63
    private function getProductIDs($category)
64
    {
65
        $sql = 'SELECT DISTINCT p.id_product
66
                from '._DB_PREFIX_.'product as p
67
                LEFT JOIN '._DB_PREFIX_.'image AS i ON i.id_product = p.id_product 
68
                LEFT JOIN '._DB_PREFIX_.'product_lang as pl ON pl.id_product = p.id_product
69
                WHERE p.active = 1
70
                AND p.id_category_default = '.(int) $category.'
71
                GROUP BY p.id_product';
72
        $pcats = $this->dbConn->fetchRowMany($sql);
73
        $ids = '';
74
        if (is_array($pcats) && (!empty($pcats))) {
75
        foreach ($pcats as $row) {
76
            $ids .= $row['id_product'].',';
77
            }
78
        }
79
80
        $ids = rtrim($ids, ',');
81
82
        return $ids;
83
    }
84
85
    /**
86
     * @param string $ids
87
     */
88
    private function getProduct($ids)
89
    {
90
        $sql = 'SELECT p.id_product, p.id_supplier, p.ean13, p.upc, p.price, p.wholesale_price, p.on_sale, p.quantity, p.id_category_default, p.show_price, p.available_for_order, p.minimal_quantity, p.customizable,
91
                    p.out_of_stock, pl.link_rewrite, pl.name, i.id_image, il.legend,
92
                    cl.name AS category_default,  cl.id_category AS cat_id,
93
                    ps.price AS orderprice
94
                    FROM '._DB_PREFIX_.'product as p                 
95
                    LEFT JOIN '._DB_PREFIX_.'image AS i ON i.id_product = p.id_product 
96
                    LEFT JOIN '._DB_PREFIX_.'product_shop as ps ON ps.id_product = p.id_product
97
                    LEFT JOIN '._DB_PREFIX_.'product_lang as pl ON pl.id_product = p.id_product
98
                    LEFT JOIN '._DB_PREFIX_.'image_lang as il ON i.id_image = il.id_image
99
                    LEFT JOIN '._DB_PREFIX_.'category_lang cl ON p.id_category_default = cl.id_category
100
                    WHERE p.id_product IN ('.$ids.')
101
                    AND i.cover = 1
102
                    AND p.active = 1
103
                    GROUP BY p.id_product
104
                    ORDER BY p.price ASC';
105
106
        $result = $this->dbConn->fetchRowMany($sql);
107
108
        return $result;
109
    }
110
111
    public function onClose(ConnectionInterface $conn)
112
    {
113
        // The connection is closed, remove it, as we can no longer send it messages
114
        $this->clients->detach($conn);
115
        Analog::log('Connection '.$conn->resourceId.' has disconnected');
0 ignored issues
show
Bug introduced by
Accessing resourceId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
116
    }
117
118
    public function onError(ConnectionInterface $conn, \Exception $e)
119
    {
120
        echo "An error has occurred: {$e->getMessage()}\n";
121
        Analog::log('Error: '.$e->getMessage().'');
122
        $conn->close();
123
    }
124
}
125