|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
|
|
4
|
|
|
/** |
|
5
|
|
|
* @description (see $this->description) |
|
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 EcommerceTaskDeleteAllOrders extends BuildTask |
|
13
|
|
|
{ |
|
14
|
|
|
private static $allowed_actions = array( |
|
15
|
|
|
'*' => 'ADMIN', |
|
16
|
|
|
); |
|
17
|
|
|
|
|
18
|
|
|
protected $title = 'Deletes all orders - CAREFUL!'; |
|
19
|
|
|
|
|
20
|
|
|
protected $description = 'Deletes all the orders and payments ever placed - CAREFULL!'; |
|
21
|
|
|
|
|
22
|
|
|
public $verbose = false; |
|
23
|
|
|
|
|
24
|
|
|
/** |
|
25
|
|
|
*key = table where OrderID is saved |
|
26
|
|
|
*value = table where LastEdited is saved. |
|
27
|
|
|
**/ |
|
28
|
|
|
private static $linked_objects_array = array( |
|
29
|
|
|
'OrderAttribute' => 'OrderAttribute', |
|
30
|
|
|
'BillingAddress' => 'OrderAddress', |
|
31
|
|
|
'ShippingAddress' => 'OrderAddress', |
|
32
|
|
|
'OrderStatusLog' => 'OrderStatusLog', |
|
33
|
|
|
'OrderEmailRecord' => 'OrderEmailRecord', |
|
34
|
|
|
'EcommercePayment' => 'EcommercePayment', |
|
35
|
|
|
); |
|
36
|
|
|
|
|
37
|
|
|
/** |
|
38
|
|
|
*key = table where OrderID is saved |
|
39
|
|
|
*value = table where LastEdited is saved. |
|
40
|
|
|
**/ |
|
41
|
|
|
private static $double_check_objects = array( |
|
42
|
|
|
'Order', |
|
43
|
|
|
'OrderItem', |
|
44
|
|
|
'OrderModifier', |
|
45
|
|
|
'EcommercePayment', |
|
46
|
|
|
); |
|
47
|
|
|
|
|
48
|
|
|
/******************************************************* |
|
49
|
|
|
* DELETE OLD SHOPPING CARTS |
|
50
|
|
|
*******************************************************/ |
|
51
|
|
|
|
|
52
|
|
|
/** |
|
53
|
|
|
*@return int - number of carts destroyed |
|
|
|
|
|
|
54
|
|
|
**/ |
|
55
|
|
|
public function run($request) |
|
56
|
|
|
{ |
|
57
|
|
|
if (!Director::isDev() || Director::isLive()) { |
|
58
|
|
|
DB::alteration_message('you can only run this in dev mode!'); |
|
59
|
|
|
} else { |
|
60
|
|
|
if (!isset($_REQUEST['i-am-sure'])) { |
|
61
|
|
|
$_REQUEST['i-am-sure'] = ''; |
|
62
|
|
|
} |
|
63
|
|
|
if ('yes' != $_REQUEST['i-am-sure']) { |
|
64
|
|
|
die("<h1>ARE YOU SURE?</h1><br /><br /><br /> please add the 'i-am-sure' get variable to your request and set it to 'yes' ... e.g. <br />http://www.mysite.com/dev/ecommerce/ecommercetaskdeleteallorders/?i-am-sure=yes"); |
|
65
|
|
|
} |
|
66
|
|
|
$oldCarts = Order::get(); |
|
67
|
|
|
$count = 0; |
|
68
|
|
|
if ($oldCarts->count()) { |
|
69
|
|
|
if ($this->verbose) { |
|
70
|
|
|
$totalToDeleteSQLObject = DB::query('SELECT COUNT(*) FROM "Order"'); |
|
71
|
|
|
$totalToDelete = $totalToDeleteSQLObject->value(); |
|
72
|
|
|
DB::alteration_message('<h2>Total number of orders: '.$totalToDelete.' .... now deleting: </h2>', 'deleted'); |
|
73
|
|
|
} |
|
74
|
|
|
foreach ($oldCarts as $oldCart) { |
|
75
|
|
|
++$count; |
|
76
|
|
|
if ($this->verbose) { |
|
77
|
|
|
DB::alteration_message("$count ... deleting abandonned order #".$oldCart->ID, 'deleted'); |
|
78
|
|
|
} |
|
79
|
|
|
$oldCart->delete(); |
|
80
|
|
|
$oldCart->destroy(); |
|
81
|
|
|
} |
|
82
|
|
|
} else { |
|
83
|
|
|
if ($this->verbose) { |
|
84
|
|
|
$count = DB::query('SELECT COUNT("ID") FROM "Order"')->value(); |
|
85
|
|
|
DB::alteration_message("There are no abandonned orders. There are $count 'live' Orders.", 'created'); |
|
86
|
|
|
} |
|
87
|
|
|
} |
|
88
|
|
|
$countCheck = DB::query('Select COUNT(ID) FROM "Order"')->value(); |
|
89
|
|
|
if ($countCheck) { |
|
90
|
|
|
DB::alteration_message('ERROR: in testing <i>Orders</i> it appears there are '.$countCheck.' records left.', 'deleted'); |
|
91
|
|
|
} else { |
|
92
|
|
|
DB::alteration_message('PASS: in testing <i>Orders</i> there seem to be no records left.', 'created'); |
|
93
|
|
|
} |
|
94
|
|
|
$this->cleanupUnlinkedOrderObjects(); |
|
95
|
|
|
$this->doubleCheckModifiersAndItems(); |
|
96
|
|
|
|
|
97
|
|
|
return $count; |
|
98
|
|
|
} |
|
99
|
|
|
} |
|
100
|
|
|
|
|
101
|
|
|
public function cleanupUnlinkedOrderObjects() |
|
102
|
|
|
{ |
|
103
|
|
|
$classNames = $this->Config()->get('linked_objects_array'); |
|
104
|
|
|
if (is_array($classNames) && count($classNames)) { |
|
105
|
|
|
foreach ($classNames as $classWithOrderID => $classWithLastEdited) { |
|
106
|
|
|
if ($this->verbose) { |
|
107
|
|
|
DB::alteration_message("looking for $classWithOrderID objects without link to order.", 'deleted'); |
|
108
|
|
|
} |
|
109
|
|
|
$where = '"Order"."ID" IS NULL '; |
|
110
|
|
|
$join = ' LEFT JOIN "Order" ON '; |
|
|
|
|
|
|
111
|
|
|
//the code below is a bit of a hack, but because of the one-to-one relationship we |
|
112
|
|
|
//want to check both sides.... |
|
113
|
|
|
$unlinkedObjects = $classWithLastEdited::get(); |
|
114
|
|
|
if ($classWithLastEdited != $classWithOrderID) { |
|
115
|
|
|
$unlinkedObjects = $unlinkedObjects |
|
116
|
|
|
->leftJoin($classWithOrderID, "\"OrderAddress\".\"ID\" = \"$classWithOrderID\".\"ID\""); |
|
117
|
|
|
} |
|
118
|
|
|
$unlinkedObjects = $unlinkedObjects |
|
119
|
|
|
->where($where) |
|
120
|
|
|
->leftJoin('Order', "\"Order\".\"ID\" = \"$classWithOrderID\".\"OrderID\""); |
|
121
|
|
|
|
|
122
|
|
|
if ($unlinkedObjects->count()) { |
|
123
|
|
|
foreach ($unlinkedObjects as $unlinkedObject) { |
|
124
|
|
|
if ($this->verbose) { |
|
125
|
|
|
DB::alteration_message('Deleting '.$unlinkedObject->ClassName.' with ID #'.$unlinkedObject->ID.' because it does not appear to link to an order.', 'deleted'); |
|
126
|
|
|
} |
|
127
|
|
|
//HACK FOR DELETING |
|
128
|
|
|
$this->deleteObject($unlinkedObject); |
|
129
|
|
|
} |
|
130
|
|
|
} |
|
131
|
|
|
$countCheck = DB::query("Select COUNT(ID) FROM \"$classWithLastEdited\"")->value(); |
|
132
|
|
|
if ($countCheck) { |
|
133
|
|
|
DB::alteration_message('ERROR: in testing <i>'.$classWithOrderID.'</i> it appears there are '.$countCheck.' records left.', 'deleted'); |
|
134
|
|
|
} else { |
|
135
|
|
|
DB::alteration_message('PASS: in testing <i>'.$classWithOrderID.'</i> there seem to be no records left.', 'created'); |
|
136
|
|
|
} |
|
137
|
|
|
} |
|
138
|
|
|
} |
|
139
|
|
|
} |
|
140
|
|
|
|
|
141
|
|
|
private function doubleCheckModifiersAndItems() |
|
142
|
|
|
{ |
|
143
|
|
|
DB::alteration_message('<hr />double-check:</hr />'); |
|
144
|
|
|
foreach ($this->config()->get('double_check_objects') as $table) { |
|
145
|
|
|
$countCheck = DB::query("Select COUNT(ID) FROM \"$table\"")->value(); |
|
146
|
|
|
if ($countCheck) { |
|
147
|
|
|
DB::alteration_message('ERROR: in testing <i>'.$table.'</i> it appears there are '.$countCheck.' records left.', 'deleted'); |
|
148
|
|
|
} else { |
|
149
|
|
|
DB::alteration_message('PASS: in testing <i>'.$table.'</i> there seem to be no records left.', 'created'); |
|
150
|
|
|
} |
|
151
|
|
|
} |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
private function deleteObject($unlinkedObject) |
|
155
|
|
|
{ |
|
156
|
|
|
if ($unlinkedObject) { |
|
157
|
|
|
if ($unlinkedObject->ClassName) { |
|
158
|
|
|
if (class_exists($unlinkedObject->ClassName) && $unlinkedObject instanceof DataObject) { |
|
159
|
|
|
$unlinkedObjectClassName = $unlinkedObject->ClassName; |
|
160
|
|
|
$objectToDelete = $unlinkedObjectClassName::get()->byID($unlinkedObject->ID); |
|
161
|
|
|
if ($objectToDelete) { |
|
162
|
|
|
$objectToDelete->delete(); |
|
163
|
|
|
$objectToDelete->destroy(); |
|
164
|
|
|
} elseif ($this->verbose) { |
|
165
|
|
|
DB::alteration_message('ERROR: could not find '.$unlinkedObject->ClassName.' with ID = '.$unlinkedObject->ID, 'deleted'); |
|
166
|
|
|
} |
|
167
|
|
|
} elseif ($this->verbose) { |
|
168
|
|
|
DB::alteration_message('ERROR: trying to delete an object that is not a dataobject: '.$unlinkedObject->ClassName, 'deleted'); |
|
169
|
|
|
} |
|
170
|
|
|
} elseif ($this->verbose) { |
|
171
|
|
|
DB::alteration_message('ERROR: trying to delete object without a class name', 'deleted'); |
|
172
|
|
|
} |
|
173
|
|
|
} elseif ($this->verbose) { |
|
174
|
|
|
DB::alteration_message('ERROR: trying to delete non-existing object.', 'deleted'); |
|
175
|
|
|
} |
|
176
|
|
|
} |
|
177
|
|
|
} |
|
178
|
|
|
|
This check compares the return type specified in the
@returnannotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.