ShopMigrationTask   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 178
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 76
dl 0
loc 178
rs 10
c 0
b 0
f 0
wmc 28

11 Methods

Rating   Name   Duplication   Size   Complexity  
A migrateShippingTaxValues() 0 2 1
A migrateProductImages() 0 3 1
A migrate() 0 8 1
A migrateProductPrice() 0 9 3
A migrateStatuses() 0 9 3
A up() 0 6 1
A migrateShippingValues() 0 22 6
A migrateProductVariationsAttribues() 0 10 2
A migrateOrders() 0 14 3
A migrateOrderCalculation() 0 5 3
A migrateMemberFields() 0 18 4
1
<?php
2
3
namespace SilverShop\Tasks;
4
5
use SilverShop\Model\Modifiers\Shipping\Base;
6
use SilverShop\Model\Order;
7
use SilverStripe\Dev\MigrationTask;
8
use SilverStripe\ORM\DataObject;
9
use SilverStripe\ORM\DB;
10
11
/**
12
 * TODO: Implement for 2.x to 3.x
13
 * Updates database to work with latest version of the code.
14
 */
15
class ShopMigrationTask extends MigrationTask
16
{
17
    /**
18
     * Choose how many orders get processed at a time.
19
     */
20
    public static $batch_size = 250;
21
22
    protected $title = 'Migrate Shop';
23
24
    protected $description = 'Where dev/build is not enough, this task updates database to work with latest version of shop module.
25
You may want to run the CartCleanupTask before migrating if you want to discard past carts.';
26
27
    /**
28
     * Migrate upwards
29
     */
30
    public function up()
31
    {
32
        $this->migrateOrders();
33
        $this->migrateProductPrice();
34
        $this->migrateProductVariationsAttribues();
35
        $this->migrateProductImages();
36
        //TODO: migrate CheckoutPage->TermsPageID to ShopConfig
37
    }
38
39
    /**
40
     * batch process orders
41
     */
42
    public function migrateOrders()
43
    {
44
        $start = $count = 0;
45
        $batch = Order::get()->sort('Created', 'ASC')->limit($start, self::$batch_size);
46
        while ($batch->exists()) {
47
            foreach ($batch as $order) {
48
                $this->migrate($order);
49
                echo '. ';
50
                $count++;
51
            }
52
            $start += self::$batch_size;
53
            $batch = $batch->limit($start, self::$batch_size);
54
        };
55
        echo "$count orders updated.\n<br/>";
56
    }
57
58
    /**
59
     * Perform migration scripts on a single order.
60
     */
61
    public function migrate(Order $order)
62
    {
63
        //TODO: set a from / to version to preform a migration with
64
        $this->migrateStatuses($order);
65
        $this->migrateMemberFields($order);
66
        $this->migrateShippingValues($order);
67
        $this->migrateOrderCalculation($order);
68
        $order->write();
69
    }
70
71
    public function migrateProductPrice()
72
    {
73
        $db = DB::get_conn();
74
        //if BasePrice has no values, but Price does, then copy from Price
75
        if ($db->hasTable('Product') && !DataObject::get_one('Product', '"BasePrice" > 0')) {
0 ignored issues
show
Bug introduced by
The method hasTable() does not exist on SilverStripe\ORM\Connect\Database. ( Ignorable by Annotation )

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

75
        if ($db->/** @scrutinizer ignore-call */ hasTable('Product') && !DataObject::get_one('Product', '"BasePrice" > 0')) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
76
            //TODO: warn against lost data
77
            DB::query('UPDATE "Product" SET "BasePrice" = "Price";');
78
            DB::query('UPDATE "Product_Live" SET "BasePrice" = "Price";');
79
            DB::query('UPDATE "Product_versions" SET "BasePrice" = "Price";');
80
            //TODO: rename, if possible without breaking migraton task next time it runs
81
            //$db->renameField("Product","Price","Price_obselete");
82
            //$db->renameField("Product_Live","Price","Price_obselete");
83
        }
84
    }
85
86
    /**
87
     * Rename all Product_Image ClassNames to Image
88
     * Added in v1.0
89
     */
90
    public function migrateProductImages()
91
    {
92
        DB::query('UPDATE "File" SET "ClassName"=\'Image\' WHERE "ClassName" = \'Product_Image\'');
93
    }
94
95
    /**
96
     * Customer and shipping details have been added to Order,
97
     * so that memberless (guest) orders can be placed.
98
     */
99
    public function migrateMemberFields($order)
100
    {
101
        if ($member = $order->Member()) {
102
            $fieldstocopy = [
103
                'FirstName',
104
                'Surname',
105
                'Email',
106
                'Address',
107
                'AddressLine2',
108
                'City',
109
                'Country',
110
                'HomePhone',
111
                'MobilePhone',
112
                'Notes',
113
            ];
114
            foreach ($fieldstocopy as $field) {
115
                if (!$order->$field) {
116
                    $order->$field = $member->$field;
117
                }
118
            }
119
        }
120
    }
121
122
    /**
123
     * Migrate old statuses
124
     */
125
    public function migrateStatuses($order)
126
    {
127
        switch ($order->Status) {
128
            case "Cancelled": //Pre version 0.5
129
                $order->Status = 'AdminCancelled';
130
                break;
131
            case "":
132
                $order->Status = 'Cart';
133
                break;
134
        }
135
    }
136
137
    /**
138
     * Convert shipping and tax columns into modifiers
139
     *
140
     * Applies to pre 0.6 sites
141
     */
142
    public function migrateShippingValues($order)
143
    {
144
        //TODO: see if this actually works..it probably needs to be writeen to a SQL query
145
        if ($order->hasShippingCost && abs($order->Shipping)) {
146
            $modifier1 = Base::create();
147
            $modifier1->Amount = $order->Shipping < 0 ? abs($order->Shipping) : $order->Shipping;
148
            $modifier1->Type = 'Chargable';
149
            $modifier1->OrderID = $order->ID;
150
            $modifier1->ShippingChargeType = 'Default';
151
            $modifier1->write();
152
            $order->hasShippingCost = null;
153
            $order->Shipping = null;
154
        }
155
        if ($order->AddedTax) {
156
            $modifier2 = \SilverShop\Model\Modifiers\Tax\Base::create();
157
            $modifier2->Amount = $order->AddedTax < 0 ? abs($order->AddedTax) : $order->AddedTax;
158
            $modifier2->Type = 'Chargable';
159
            $modifier2->OrderID = $order->ID;
160
            //$modifier2->Name = 'Undefined After Ecommerce Upgrade';
161
            $modifier2->TaxType = 'Exclusive';
162
            $modifier2->write();
163
            $order->AddedTax = null;
164
        }
165
    }
166
167
    /**
168
     * Performs calculation function on un-calculated orders.
169
     */
170
    public function migrateOrderCalculation($order)
171
    {
172
        if (!is_numeric($order->Total) || $order->Total <= 0) {
173
            $order->calculate();
174
            $order->write();
175
        }
176
    }
177
178
    public function migrateProductVariationsAttribues()
179
    {
180
        $db = DB::get_conn();
181
        //TODO: delete Product_VariationAttribute, if it's empty
182
        if ($db->hasTable(
183
            'Product_VariationAttributes'
184
        )
185
        ) { //TODO: check if Product_VariationAttributeTypes table is empty
186
            DB::query('DROP TABLE "Product_VariationAttributeTypes"');
187
            $db->renameTable('Product_VariationAttributes', 'Product_VariationAttributeTypes');
0 ignored issues
show
Bug introduced by
The method renameTable() does not exist on SilverStripe\ORM\Connect\Database. ( Ignorable by Annotation )

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

187
            $db->/** @scrutinizer ignore-call */ 
188
                 renameTable('Product_VariationAttributes', 'Product_VariationAttributeTypes');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
188
        }
189
    }
190
191
    public function migrateShippingTaxValues()
192
    {
193
        //rename obselete columns
194
        //DB::query("ALTER TABLE \"Order\" CHANGE COLUMN \"hasShippingCost\" \"_obsolete_hasShippingCost\" tinyint(1)");
195
        //DB::query("ALTER TABLE \"Order\" CHANGE COLUMN \"Shipping\" \"_obsolete_Shipping\" decimal(9,2)");
196
        //DB::query("ALTER TABLE \"Order\" CHANGE COLUMN \"AddedTax\" \"_obsolete_AddedTax\" decimal(9,2)");
197
    }
198
}
199