EcommerceTaskLinkProductWithImages::run()   F
last analyzed

Complexity

Conditions 23
Paths 240

Size

Total Lines 67

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
dl 0
loc 67
rs 2.8333
c 0
b 0
f 0
nc 240
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Add any Image (or other file) to a product using the InternalItemID.
5
 *
6
 *
7
 * @authors: Nicolaas [at] Sunny Side Up .co.nz
8
 * @package: ecommerce
9
 * @sub-package: tasks
10
 * @inspiration: Silverstripe Ltd, Jeremy
11
 **/
12
class EcommerceTaskLinkProductWithImages extends BuildTask
13
{
14
    protected $title = 'Find product images';
15
16
    protected $description = '
17
        Finds product images (or other files) based on their name.
18
        That is, any image name [InteralItemID]_[two digits].[png/gif/jpg/pdf/(etc)] will automatically be linked to the product.
19
        For example SKUAAFF_1 or SKU_02.
20
        All files ending in a number from 00 to 99 will be added (e.g. 02, 5 or 55)
21
        Also SKUAAFF.jpg (without the standard ending with underscore and number) will be added to the product where InternalItemID equals SKUAAFF.
22
    ';
23
24
    /**
25
     * In the default e-commerce, each product only has one image.
26
     * Many e-commerce sites, however, like to have more than one image per product.
27
     *
28
     * @var string
29
     */
30
    protected $productManyManyField = 'AdditionalFiles';
31
32
    /**
33
     * Starting point for selecting products
34
     * Usually starts at zero and goes up to the total number of products.
35
     *
36
     * @var int
37
     */
38
    protected $start = 0;
39
40
    /**
41
     * The number of products selected per cycle.
42
     *
43
     * @var int
44
     */
45
    protected $limit = 100;
46
47
    /**
48
     * output messages?
49
     *
50
     * @var bool
51
     */
52
    public $verbose = true;
53
54
    protected $productID = 0;
55
56
    public function run($request)
57
    {
58
        if (isset($_REQUEST['start']) && intval($_REQUEST['start'])) {
59
            $this->start = intval($_REQUEST['start']);
60
        }
61
        if (isset($_REQUEST['productid']) && intval($_REQUEST['productid'])) {
62
            $this->productID = intval($_REQUEST['productid']);
63
        }
64
        if ($this->productManyManyField) {
65
            $products = Product::get()->limit($this->limit, $this->start);
66
            if ($this->productID) {
67
                $products = $products->filter(array('ID' => $this->productID));
68
            }
69
            if ($products->count()) {
70
                foreach ($products as $product) {
71
                    if ($product->InternalItemID) {
72
                        if ($product->hasMethod($this->productManyManyField)) {
73
                            $whereStringArray[] = $product->InternalItemID;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$whereStringArray was never initialized. Although not strictly required by PHP, it is generally a good practice to add $whereStringArray = 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...
74
                            for ($i = 0; $i < 10; ++$i) {
75
                                for ($j = 0; $j < 10; ++$j) {
76
                                    $number = strval($i).strval($j);
77
                                    $whereStringArray[] = $product->InternalItemID.'_'.$number;
0 ignored issues
show
Bug introduced by
The variable $whereStringArray 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...
78
                                }
79
                            }
80
                            $images = File::get()
81
                                ->filter(array('Name:PartialMatch' => $whereStringArray));
82
                            if ($images->count()) {
83
                                $method = $this->productManyManyField;
84
                                $collection = $product->$method();
85
                                foreach ($images as $image) {
86
                                    if (is_a($image, Object::getCustomClass('Image')) && $image->ClassName != Object::getCustomClass('Product_Image')) {
87
                                        $image = $image->newClassInstance('Product_Image');
88
                                        $image->write();
89
                                    }
90
                                    $collection->add($image);
91
                                    if ($this->verbose) {
92
                                        DB::alteration_message('Adding image '.$image->Name.' to '.$product->Title, 'created');
93
                                    }
94
                                }
95
                            } else {
96
                                if ($this->verbose) {
97
                                    DB::alteration_message('No images where found for product with Title <i>'.$product->Title.'</i>: no images could be added.');
98
                                }
99
                            }
100
                        } else {
101
                            if ($this->verbose) {
102
                                DB::alteration_message('The method <i>'.$this->productManyManyField.'</i> does not exist on <i>'.$product->Title.' ('.$product->ClassName.')</i>: no images could be added.');
103
                            }
104
                        }
105
                    } else {
106
                        if ($this->verbose) {
107
                            DB::alteration_message('No InternalItemID set for <i>'.$product->Title.'</i>: no images could be added.');
108
                        }
109
                    }
110
                }
111
                $productCount = Product::get()->count();
112
                if ($this->limit < $productCount) {
113
                    $controller = Controller::curr();
114
                    $controller->redirect($this->nextBatchLink());
115
                }
116
            }
117
        } else {
118
            if ($this->verbose) {
119
                DB::alteration_message('No product Many-2-Many method specified.  No further action taken.  ');
120
            }
121
        }
122
    }
123
124
    protected function nextBatchLink()
125
    {
126
        $link = Controller::join_links(
127
            Director::baseURL(),
128
            'dev/ecommerce/ecommercetasklinkproductwithimages/'
129
        ).
130
        '?start='.($this->start + $this->limit);
131
        if ($this->productID) {
132
            $link .= '&productid='.$this->productID;
133
        }
134
135
        return $link;
136
    }
137
138
    public function setProductID($id)
139
    {
140
        $this->productID = $id;
141
    }
142
143
    public function Link($action = null)
0 ignored issues
show
Unused Code introduced by
The parameter $action 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...
144
    {
145
        return Controller::join_links(
146
            Director::baseURL(),
147
            'dev/ecommerce/ecommercetasklinkproductwithimages/'
148
        );
149
    }
150
}
151