This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | |||
4 | class DataIntegrityTest extends BuildTask |
||
5 | { |
||
6 | |||
7 | |||
8 | /** |
||
9 | * standard SS variable |
||
10 | * @var String |
||
11 | */ |
||
12 | protected $title = "Check Database Integrity"; |
||
13 | |||
14 | /** |
||
15 | * standard SS variable |
||
16 | * @var String |
||
17 | */ |
||
18 | protected $description = "Go through all fields in the database and work out what fields are superfluous."; |
||
19 | |||
20 | private static $warning = "are you sure - this step is irreversible! - MAKE SURE TO MAKE A BACKUP OF YOUR DATABASE BEFORE YOU CONFIRM THIS!"; |
||
21 | |||
22 | private static $test_array = array( |
||
23 | "In SiteTree_Live but not in SiteTree" => |
||
24 | "SELECT SiteTree.ID, SiteTree.Title FROM SiteTree_Live RIGHT JOIN SiteTree ON SiteTree_Live.ID = SiteTree.ID WHERE SiteTree.ID IS NULL;", |
||
25 | "ParentID does not exist in SiteTree" => |
||
26 | "SELECT SiteTree.ID, SiteTree.Title FROM SiteTree RIGHT JOIN SiteTree Parent ON SiteTree.ParentID = Parent.ID Where SiteTree.ID IS NULL and SiteTree.ParentID <> 0;", |
||
27 | "ParentID does not exists in SiteTree_Live" => |
||
28 | "SELECT SiteTree_Live.ID, SiteTree_Live.Title FROM SiteTree_Live RIGHT JOIN SiteTree_Live Parent ON SiteTree_Live.ParentID = Parent.ID Where SiteTree_Live.ID IS NULL and SiteTree_Live.ParentID <> 0;", |
||
29 | ); |
||
30 | |||
31 | private static $global_exceptions = array( |
||
32 | "EditableFormField" => "Version", |
||
33 | "EditableOption" => "Version", |
||
34 | "OrderItem" => "Version" |
||
35 | ); |
||
36 | |||
37 | /** |
||
38 | *@param array = should be provided as follows: array("Member.UselessField1", "Member.UselessField2", "SiteTree.UselessField3") |
||
39 | */ |
||
40 | private static $fields_to_delete = array(); |
||
41 | |||
42 | private static $allowed_actions = array( |
||
43 | "obsoletefields" => "ADMIN", |
||
44 | "deleteonefield" => "ADMIN", |
||
45 | "deletemarkedfields" => "ADMIN", |
||
46 | "deleteobsoletetables" => "ADMIN", |
||
47 | "deleteallversions" => "ADMIN", |
||
48 | "cleanupdb" => "ADMIN" |
||
49 | ); |
||
50 | |||
51 | |||
52 | public function init() |
||
53 | { |
||
54 | //this checks security |
||
55 | parent::init(); |
||
0 ignored issues
–
show
|
|||
56 | } |
||
57 | |||
58 | public function run($request) |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
59 | { |
||
60 | ini_set('max_execution_time', 3000); |
||
61 | if ($action = $request->getVar("do")) { |
||
62 | $methodArray = explode("/", $action); |
||
63 | $method = $methodArray[0]; |
||
64 | $allowedActions = Config::inst()->get("DataIntegrityTest", "allowed_actions"); |
||
65 | if (isset($allowedActions[$method])) { |
||
66 | if ($method == "obsoletefields") { |
||
67 | $deletesafeones = $fixbrokendataobjects = $deleteall = false; |
||
68 | if (isset($_GET["deletesafeones"]) && $_GET["deletesafeones"]) { |
||
69 | $deletesafeones = true; |
||
70 | } |
||
71 | if (isset($_GET["fixbrokendataobjects"]) && $_GET["fixbrokendataobjects"]) { |
||
72 | $fixbrokendataobjects = true; |
||
73 | } |
||
74 | if (isset($_GET["deleteall"]) && $_GET["deleteall"]) { |
||
75 | $deleteall = true; |
||
76 | } |
||
77 | return $this->$method($deletesafeones, $fixbrokendataobjects, $deleteall); |
||
78 | } else { |
||
79 | return $this->$method(); |
||
80 | } |
||
81 | } else { |
||
82 | user_error("could not find method: $method"); |
||
83 | } |
||
84 | } |
||
85 | $warning = Config::inst()->get("DataIntegrityTest", "warning"); |
||
86 | echo "<h2>Database Administration Helpers</h2>"; |
||
87 | echo "<p><a href=\"".$this->Link()."?do=obsoletefields\">Prepare a list of obsolete fields.</a></p>"; |
||
88 | echo "<p><a href=\"".$this->Link()."?do=obsoletefields&deletesafeones=1\" onclick=\"return confirm('".$warning."');\">Prepare a list of obsolete fields and DELETE! obsolete fields without any data.</a></p>"; |
||
89 | echo "<p><a href=\"".$this->Link()."?do=obsoletefields&fixbrokendataobjects=1\" onclick=\"return confirm('".$warning."');\">Fix broken dataobjects.</a></p>"; |
||
90 | echo "<p><a href=\"".$this->Link()."?do=obsoletefields&deleteall=1\" onclick=\"return confirm('".$warning."');\">Delete all obsolete fields now!</a></p>"; |
||
91 | echo "<hr />"; |
||
92 | echo "<p><a href=\"".$this->Link()."?do=deletemarkedfields\" onclick=\"return confirm('".$warning."');\">Delete fields listed in _config.</a></p>"; |
||
93 | echo "<hr />"; |
||
94 | echo "<p><a href=\"".$this->Link()."?do=deleteobsoletetables\" onclick=\"return confirm('".$warning."');\">Delete all tables that are marked as obsolete</a></p>"; |
||
95 | echo "<hr />"; |
||
96 | echo "<p><a href=\"".$this->Link()."?do=deleteallversions\" onclick=\"return confirm('".$warning."');\">Delete all versioned data</a></p>"; |
||
97 | echo "<hr />"; |
||
98 | echo "<p><a href=\"".$this->Link()."?do=cleanupdb\" onclick=\"return confirm('".$warning."');\">Clean up Database (remove obsolete records)</a></p>"; |
||
99 | echo "<hr />"; |
||
100 | echo "<p><a href=\"/dev/tasks/DataIntegrityTestInnoDB/\" onclick=\"return confirm('".$warning."');\">Set all tables to innoDB</a></p>"; |
||
101 | echo "<p><a href=\"/dev/tasks/DataIntegrityTestUTF8/\" onclick=\"return confirm('".$warning."');\">Set all tables to utf-8</a></p>"; |
||
102 | } |
||
103 | |||
104 | protected function Link() |
||
105 | { |
||
106 | return "/dev/tasks/DataIntegrityTest/"; |
||
107 | } |
||
108 | |||
109 | protected function obsoletefields($deleteSafeOnes = false, $fixBrokenDataObject = false, $deleteAll = false) |
||
110 | { |
||
111 | increase_time_limit_to(600); |
||
112 | $dataClasses = ClassInfo::subclassesFor('DataObject'); |
||
113 | $notCheckedArray = array(); |
||
114 | $canBeSafelyDeleted = array(); |
||
115 | //remove dataobject |
||
116 | array_shift($dataClasses); |
||
117 | $rows = DB::query("SHOW TABLES;"); |
||
118 | $actualTables = array(); |
||
119 | if ($rows) { |
||
120 | foreach ($rows as $key => $item) { |
||
121 | foreach ($item as $table) { |
||
122 | $actualTables[$table] = $table; |
||
123 | } |
||
124 | } |
||
125 | } |
||
126 | echo "<h1>Report of fields that may not be required.</h1>"; |
||
127 | echo "<p>NOTE: it may contain fields that are actually required (e.g. versioning or many-many relationships) and it may also leave out some obsolete fields. Use as a guide only.</p>"; |
||
128 | foreach ($dataClasses as $dataClass) { |
||
129 | // Check if class exists before trying to instantiate - this sidesteps any manifest weirdness |
||
130 | if (class_exists($dataClass)) { |
||
131 | $dataObject = $dataClass::create(); |
||
132 | if (!($dataObject instanceof TestOnly)) { |
||
133 | $requiredFields = $this->swapArray(DataObject::database_fields($dataObject->ClassName)); |
||
134 | if (count($requiredFields)) { |
||
135 | foreach ($requiredFields as $field) { |
||
136 | if (!$dataObject->hasOwnTableDatabaseField($field)) { |
||
137 | DB::alteration_message(" **** $dataClass.$field DOES NOT EXIST BUT IT SHOULD BE THERE!", "deleted"); |
||
138 | } |
||
139 | } |
||
140 | $actualFields = $this->swapArray(DB::fieldList($dataClass)); |
||
0 ignored issues
–
show
The method
DB::fieldList() has been deprecated with message: since version 4.0 Use DB::field_list instead
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
141 | if ($actualFields) { |
||
0 ignored issues
–
show
The expression
$actualFields of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
142 | foreach ($actualFields as $actualField) { |
||
143 | if ($deleteAll) { |
||
144 | $link = " !!!!!!!!!!! DELETED !!!!!!!!!"; |
||
145 | } else { |
||
146 | $warning = Config::inst()->get("DataIntegrityTest", "warning"); |
||
147 | $link = "<a href=\"".Director::absoluteBaseURL()."dev/tasks/DataIntegrityTest/?do=deleteonefield/".$dataClass."/".$actualField."/\" onclick=\"return confirm('".$warning."');\">delete field</a>"; |
||
148 | } |
||
149 | if (!in_array($actualField, array("ID", "Version"))) { |
||
150 | if (!in_array($actualField, $requiredFields)) { |
||
151 | $distinctCount = DB::query("SELECT COUNT(DISTINCT \"$actualField\") FROM \"$dataClass\" WHERE \"$actualField\" IS NOT NULL AND \"$actualField\" <> '' AND \"$actualField\" <> '0';")->value(); |
||
152 | DB::alteration_message("<br /><br />\n\n$dataClass.$actualField $link - unique entries: $distinctCount", "deleted"); |
||
153 | if ($distinctCount) { |
||
154 | $rows = DB::query(" |
||
155 | SELECT \"$actualField\" as N, COUNT(\"$actualField\") as C |
||
156 | FROM \"$dataClass\" |
||
157 | GROUP BY \"$actualField\" |
||
158 | ORDER BY C DESC |
||
159 | LIMIT 7"); |
||
160 | if ($rows) { |
||
161 | foreach ($rows as $row) { |
||
162 | DB::alteration_message(" ".$row["C"].": ".$row["N"]); |
||
163 | } |
||
164 | } |
||
165 | } else { |
||
166 | if (!isset($canBeSafelyDeleted[$dataClass])) { |
||
167 | $canBeSafelyDeleted[$dataClass] = array(); |
||
168 | } |
||
169 | $canBeSafelyDeleted[$dataClass][$actualField] = "$dataClass.$actualField"; |
||
170 | } |
||
171 | if ($deleteAll || ($deleteSafeOnes && $distinctCount == 0)) { |
||
172 | $this->deleteField($dataClass, $actualField); |
||
173 | } |
||
174 | } |
||
175 | } |
||
176 | if ($actualField == "Version" && !in_array($actualField, $requiredFields)) { |
||
177 | $versioningPresent = $dataObject->hasVersioning(); |
||
178 | if (!$versioningPresent) { |
||
179 | DB::alteration_message("$dataClass.$actualField $link", "deleted"); |
||
180 | if ($deleteAll) { |
||
181 | $this->deleteField($dataClass, $actualField); |
||
182 | } |
||
183 | } |
||
184 | } |
||
185 | } |
||
186 | } |
||
187 | $rawCount = DB::query("SELECT COUNT(\"ID\") FROM \"$dataClass\"")->value(); |
||
188 | Versioned::set_reading_mode("Stage.Stage"); |
||
189 | $realCount = 0; |
||
190 | $allSubClasses = array_unique(array($dataClass)+ClassInfo::subclassesFor($dataClass)); |
||
191 | $objects = $dataClass::get()->filter(array("ClassName" => $allSubClasses)); |
||
192 | if ($objects->count()) { |
||
193 | $realCount = $objects->count(); |
||
194 | } |
||
195 | if ($rawCount != $realCount) { |
||
196 | echo "<hr />"; |
||
197 | $sign = " > "; |
||
198 | if ($rawCount < $realCount) { |
||
199 | $sign = " < "; |
||
200 | } |
||
201 | DB::alteration_message("The DB Table Row Count does not seem to match the DataObject Count for <strong>$dataClass ($rawCount $sign $realCount)</strong>. This could indicate an error as generally these numbers should match.", "deleted"); |
||
202 | if ($fixBrokenDataObject) { |
||
203 | $objects = $dataClass::get()->where("LinkedTable.ID IS NULL")->leftJoin($dataClass, "$dataClass.ID = LinkedTable.ID", "LinkedTable"); |
||
204 | if ($objects->count() > 500) { |
||
205 | DB::alteration_message("It is recommended that you manually fix the difference in real vs object count in $dataClass. There are more than 500 records so it would take too long to do it now.", "deleted"); |
||
206 | } else { |
||
207 | DB::alteration_message("Now trying to recreate missing items... COUNT = ".$objects->count(), "created"); |
||
208 | foreach ($objects as $object) { |
||
209 | if (DB::query("SELECT COUNT(\"ID\") FROM \"$dataClass\" WHERE \"ID\" = ".$object->ID.";")->value() != 1) { |
||
210 | Config::inst()->update('DataObject', 'validation_enabled', false); |
||
211 | $object->write(true, false, true, false); |
||
212 | Config::inst()->update('DataObject', 'validation_enabled', true); |
||
213 | } |
||
214 | } |
||
215 | $objectCount = $dataClass::get()->count(); |
||
216 | DB::alteration_message("Consider deleting superfluous records from table $dataClass .... COUNT =".($rawCount - $objectCount)); |
||
217 | $ancestors = ClassInfo::ancestry($dataClass, true); |
||
218 | if ($ancestors && is_array($ancestors) && count($ancestors)) { |
||
0 ignored issues
–
show
The expression
$ancestors of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
219 | foreach ($ancestors as $ancestor) { |
||
220 | if ($ancestor != $dataClass) { |
||
221 | echo "DELETE `$dataClass`.* FROM `$dataClass` LEFT JOIN `$ancestor` ON `$dataClass`.`ID` = `$ancestor`.`ID` WHERE `$ancestor`.`ID` IS NULL;"; |
||
222 | DB::query("DELETE `$dataClass`.* FROM `$dataClass` LEFT JOIN `$ancestor` ON `$dataClass`.`ID` = `$ancestor`.`ID` WHERE `$ancestor`.`ID` IS NULL;"); |
||
223 | } |
||
224 | } |
||
225 | } |
||
226 | } |
||
227 | } |
||
228 | echo "<hr />"; |
||
229 | } |
||
230 | unset($actualTables[$dataClass]); |
||
231 | } else { |
||
232 | $db = DB::getConn(); |
||
0 ignored issues
–
show
The method
DB::getConn() has been deprecated with message: since version 4.0 Use DB::get_conn instead
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
233 | if ($db->hasTable($dataClass)) { |
||
0 ignored issues
–
show
The method
SS_Database::hasTable() has been deprecated with message: since version 4.0 Use DB::get_schema()->hasTable() instead
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
234 | DB::alteration_message(" **** The $dataClass table exists, but according to the data-scheme it should not be there ", "deleted"); |
||
235 | } else { |
||
236 | $notCheckedArray[] = $dataClass; |
||
237 | } |
||
238 | } |
||
239 | } |
||
240 | } |
||
241 | } |
||
242 | |||
243 | if (count($canBeSafelyDeleted)) { |
||
244 | DB::alteration_message("<h2>Can be safely deleted: </h2>"); |
||
245 | foreach ($canBeSafelyDeleted as $table => $fields) { |
||
246 | DB::alteration_message($table.": ".implode(", ", $fields)); |
||
247 | } |
||
248 | } |
||
249 | |||
250 | if (count($notCheckedArray)) { |
||
251 | echo "<h3>Did not check the following classes as no fields appear to be required and hence there is no database table.</h3>"; |
||
252 | foreach ($notCheckedArray as $table) { |
||
253 | View Code Duplication | if (DB::query("SHOW TABLES LIKE '".$table."'")->value()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
254 | DB::alteration_message($table ." - NOTE: a table exists for this Class, this is an unexpected result", "deleted"); |
||
255 | } else { |
||
256 | DB::alteration_message($table, "created"); |
||
257 | } |
||
258 | } |
||
259 | } |
||
260 | |||
261 | if (count($actualTables)) { |
||
262 | echo "<h3>Other Tables in Database not directly linked to a Silverstripe DataObject:</h3>"; |
||
263 | foreach ($actualTables as $table) { |
||
264 | $remove = true; |
||
265 | if (class_exists($table)) { |
||
266 | $classExistsMessage = " a PHP class with this name exists."; |
||
267 | $obj = singleton($table); |
||
268 | //not sure why we have this. |
||
269 | if ($obj instanceof DataExtension) { |
||
270 | $remove = false; |
||
271 | } elseif (class_exists("Versioned") && $obj->hasExtension("Versioned")) { |
||
272 | $remove = false; |
||
273 | } |
||
274 | } else { |
||
275 | $classExistsMessage = " NO PHP class with this name exists."; |
||
276 | if (substr($table, -5) == "_Live") { |
||
277 | $remove = false; |
||
278 | } |
||
279 | if (substr($table, -9) == "_versions") { |
||
280 | $remove = false; |
||
281 | } |
||
282 | //many 2 many tables... |
||
283 | if (strpos($table, "_")) { |
||
284 | $class = explode("_", $table); |
||
0 ignored issues
–
show
$class is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
285 | $manyManyClass = substr($table, 0, strrpos($table, '_')); |
||
286 | $manyManyExtension = substr($table, strrpos($table, '_') + 1 - strlen($table)); |
||
287 | if (class_exists($manyManyClass)) { |
||
288 | $manyManys = Config::inst()->get($manyManyClass, "many_many"); |
||
289 | if (isset($manyManys[$manyManyExtension])) { |
||
290 | $remove = false; |
||
291 | } |
||
292 | } |
||
293 | } |
||
294 | } |
||
295 | if ($remove) { |
||
296 | if (substr($table, 0, strlen("_obsolete_")) != "_obsolete_") { |
||
297 | $rowCount = DB::query("SELECT COUNT(*) FROM $table")->value(); |
||
298 | DB::alteration_message($table.", rows ".$rowCount); |
||
299 | $obsoleteTableName = "_obsolete_".$table; |
||
300 | if (!$this->tableExists($obsoleteTableName)) { |
||
301 | DB::alteration_message("We recommend deleting $table or making it obsolete by renaming it to ".$obsoleteTableName, "deleted"); |
||
302 | if ($deleteAll) { |
||
303 | DB::getConn()->renameTable($table, $obsoleteTableName); |
||
0 ignored issues
–
show
The method
DB::getConn() has been deprecated with message: since version 4.0 Use DB::get_conn instead
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() The method
SS_Database::renameTable() has been deprecated with message: since version 4.0 Use DB::get_schema()->renameTable() instead
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
304 | } else { |
||
305 | DB::alteration_message($table." - ".$classExistsMessage." It can be moved to _obsolete_".$table.".", "created"); |
||
306 | } |
||
307 | } else { |
||
308 | DB::alteration_message("I'd recommend to move <strong>$table</strong> to <strong>".$obsoleteTableName."</strong>, but that table already exists", "deleted"); |
||
309 | } |
||
310 | } |
||
311 | } |
||
312 | } |
||
313 | } |
||
314 | |||
315 | echo "<a href=\"".Director::absoluteURL("/dev/tasks/DataIntegrityTest/")."\">back to main menu.</a>"; |
||
316 | } |
||
317 | |||
318 | |||
319 | |||
320 | public function deletemarkedfields() |
||
321 | { |
||
322 | $fieldsToDelete = Config::inst()->get("DataIntegrityTest", "fields_to_delete"); |
||
323 | if (is_array($fieldsToDelete)) { |
||
324 | if (count($fieldsToDelete)) { |
||
325 | foreach ($fieldsToDelete as $key => $tableDotField) { |
||
326 | $tableFieldArray = explode(".", $tableDotField); |
||
327 | $this->deleteField($tableFieldArray[0], $tableFieldArray[1]); |
||
328 | } |
||
329 | } else { |
||
330 | DB::alteration_message("there are no fields to delete", "created"); |
||
331 | } |
||
332 | } else { |
||
333 | user_error("you need to select these fields to be deleted first (DataIntegrityTest.fields_to_delete)"); |
||
334 | } |
||
335 | echo "<a href=\"".Director::absoluteURL("/dev/tasks/DataIntegrityTest/")."\">back to main menu.</a>"; |
||
336 | } |
||
337 | |||
338 | public function deleteonefield() |
||
339 | { |
||
340 | $requestExploded = explode("/", $_GET["do"]); |
||
341 | if (!isset($requestExploded[1])) { |
||
342 | user_error("no table has been specified", E_USER_WARNING); |
||
343 | } |
||
344 | if (!isset($requestExploded[2])) { |
||
345 | user_error("no field has been specified", E_USER_WARNING); |
||
346 | } |
||
347 | $table = $requestExploded[1]; |
||
348 | $field = $requestExploded[2]; |
||
349 | if ($this->deleteField($table, $field)) { |
||
350 | DB::alteration_message("successfully deleted $field from $table now"); |
||
351 | } else { |
||
352 | DB::alteration_message("COULD NOT delete $field from $table now", "deleted"); |
||
353 | } |
||
354 | DB::alteration_message("<a href=\"".Director::absoluteURL("dev/tasks/DataIntegrityTest/?do=obsoletefields")."\">return to list of obsolete fields</a>", "created"); |
||
355 | echo "<a href=\"".Director::absoluteURL("/dev/tasks/DataIntegrityTest/")."\">back to main menu.</a>"; |
||
356 | } |
||
357 | |||
358 | private function cleanupdb() |
||
359 | { |
||
360 | $obj = new DatabaseAdmin(); |
||
361 | $obj->cleanup(); |
||
362 | DB::alteration_message("============= COMPLETED =================", ""); |
||
363 | echo "<a href=\"".Director::absoluteURL("/dev/tasks/DataIntegrityTest/")."\">back to main menu.</a>"; |
||
364 | } |
||
365 | |||
366 | private function deleteField($table, $field) |
||
367 | { |
||
368 | $fields = $this->swapArray(DB::fieldList($table)); |
||
0 ignored issues
–
show
The method
DB::fieldList() has been deprecated with message: since version 4.0 Use DB::field_list instead
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
369 | $globalExeceptions = Config::inst()->get("DataIntegrityTest", "global_exceptions"); |
||
370 | if (count($globalExeceptions)) { |
||
371 | foreach ($globalExeceptions as $exceptionTable => $exceptionField) { |
||
0 ignored issues
–
show
The expression
$globalExeceptions of type array|integer|double|string|boolean is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() |
|||
372 | if ($exceptionTable == $table && $exceptionField == $field) { |
||
373 | DB::alteration_message("tried to delete $table.$field but this is listed as a global exception and can not be deleted", "created"); |
||
374 | return false; |
||
375 | } |
||
376 | } |
||
377 | } |
||
378 | View Code Duplication | if (!DB::query("SHOW TABLES LIKE '".$table."'")->value()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
379 | DB::alteration_message("tried to delete $table.$field but TABLE does not exist", "deleted"); |
||
380 | return false; |
||
381 | } |
||
382 | if (!class_exists($table)) { |
||
383 | DB::alteration_message("tried to delete $table.$field but CLASS does not exist", "deleted"); |
||
384 | return false; |
||
385 | } |
||
386 | View Code Duplication | if (!in_array($field, $fields)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
387 | DB::alteration_message("tried to delete $table.$field but FIELD does not exist", "deleted"); |
||
388 | return false; |
||
389 | } else { |
||
390 | DB::alteration_message("Deleting $field in $table", "deleted"); |
||
391 | DB::query('ALTER TABLE "'.$table.'" DROP "'.$field.'";'); |
||
392 | $obj = singleton($table); |
||
393 | //to do: make this more reliable - checking for versioning rather than SiteTree |
||
394 | if ($obj instanceof SiteTree) { |
||
395 | DB::query('ALTER TABLE "'.$table.'_Live" DROP "'.$field.'";'); |
||
396 | DB::alteration_message("Deleted $field in {$table}_Live", "deleted"); |
||
397 | DB::query('ALTER TABLE "'.$table.'_versions" DROP "'.$field.'";'); |
||
398 | DB::alteration_message("Deleted $field in {$table}_versions", "deleted"); |
||
399 | } |
||
400 | return true; |
||
401 | } |
||
402 | } |
||
403 | |||
404 | private function swapArray($array) |
||
405 | { |
||
406 | $newArray = array(); |
||
407 | if (is_array($array)) { |
||
408 | foreach ($array as $key => $value) { |
||
409 | $newArray[] = $key; |
||
410 | } |
||
411 | } |
||
412 | return $newArray; |
||
413 | } |
||
414 | |||
415 | protected function hasVersioning($dataObject) |
||
416 | { |
||
417 | $versioningPresent = false; |
||
418 | $array = $dataObject->stat('extensions'); |
||
419 | if (is_array($array) && count($array)) { |
||
420 | if (in_array("Versioned('Stage', 'Live')", $array)) { |
||
421 | $versioningPresent = true; |
||
422 | } |
||
423 | } |
||
424 | if ($dataObject->stat('versioning')) { |
||
425 | $versioningPresent = true; |
||
426 | } |
||
427 | return $versioningPresent; |
||
428 | } |
||
429 | |||
430 | |||
431 | private function deleteobsoletetables() |
||
432 | { |
||
433 | $tables = DB::query('SHOW tables'); |
||
434 | $unique = array(); |
||
0 ignored issues
–
show
$unique is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
435 | foreach ($tables as $table) { |
||
436 | $table = array_pop($table); |
||
437 | if (substr($table, 0, 10) == "_obsolete_") { |
||
438 | DB::alteration_message("Removing table $table", "deleted"); |
||
439 | DB::query("DROP TABLE \"$table\" "); |
||
440 | } |
||
441 | } |
||
442 | echo "<a href=\"".Director::absoluteURL("/dev/tasks/DataIntegrityTest/")."\">back to main menu.</a>"; |
||
443 | } |
||
444 | |||
445 | private function deleteallversions() |
||
446 | { |
||
447 | $tables = DB::query('SHOW tables'); |
||
448 | $unique = array(); |
||
0 ignored issues
–
show
$unique is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
449 | foreach ($tables as $table) { |
||
450 | $table = array_pop($table); |
||
451 | $endOfTable = substr($table, -9); |
||
452 | if ($endOfTable == "_versions") { |
||
453 | $className = substr($table, 0, strlen($table) - 9); |
||
454 | if (class_exists($className)) { |
||
455 | $obj = DataObject::get_one($className); |
||
456 | if ($obj) { |
||
457 | if ($obj->hasExtension("Versioned")) { |
||
458 | DB::alteration_message("Removing all records from $table", "created"); |
||
459 | DB::query("DELETE FROM \"$table\" "); |
||
460 | } |
||
461 | } |
||
462 | } else { |
||
463 | DB::alteration_message("Could not find $className class... the $table may be obsolete", "deleted"); |
||
464 | } |
||
465 | } |
||
466 | } |
||
467 | echo "<a href=\"".Director::absoluteURL("/dev/tasks/DataIntegrityTest/")."\">back to main menu.</a>"; |
||
468 | } |
||
469 | |||
470 | private function tableExists($table) |
||
471 | { |
||
472 | $db = DB::getConn(); |
||
0 ignored issues
–
show
The method
DB::getConn() has been deprecated with message: since version 4.0 Use DB::get_conn instead
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
473 | return $db->hasTable($table); |
||
0 ignored issues
–
show
The method
SS_Database::hasTable() has been deprecated with message: since version 4.0 Use DB::get_schema()->hasTable() instead
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
474 | } |
||
475 | } |
||
476 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the parent class: