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
@return
annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.