├── README.md └── json-db-check.php /README.md: -------------------------------------------------------------------------------- 1 | # Joomla JSON Database Check 2 | 3 | Checks Joomla 'params', 'rules' and 'attribs' fields for invalid JSON data. 4 | 5 | ## Why? 6 | 7 | Joomla 3.6.3 improved validation of JSON data stored in the database (Usually as params for extensions). Unfortunately, this means that after updating, sites with invalid data can can become inaccessible. 8 | 9 | The usual error message shown is: 10 | 11 | > 0 - Error decoding JSON data: Syntax error 12 | 13 | ## How To Use 14 | 15 | 1. Take a backup of your sites database. You use this file at your own risk! 16 | 2. Upload json-db-check.php to the root of your site. 17 | 3. Browse to the file in any browser. 18 | 4. The script will first check for any invalid empty fields and correct them. 19 | 5. Check your site to see if the error has gone. 20 | 6. If the site still has errors, select the columns you want to check by checking the checkboxes and click on the 'Check For All Invalid Values' button to check each field. 21 | 7. Check each error warning in a JSON validator and either manually fix it or contact the relevant extensions developer. 22 | 8. Delete this script from your hosting account. 23 | 24 | More detail and some screenshots can be seen in this [blog post](https://robertwent.com/blog/fixing-json-data-errors-after-updating-to-joomla-3-6-3/) 25 | 26 | ## False Positives 27 | 28 | The script has been updated to use the same check that Joomla does to see if the data should be decoded from JSON. 29 | 30 | It should only show issues that will cause Joomla to show an error. 31 | 32 | If you see an error in the script output but Joomla is working without any problems, please report it in [issues](https://github.com/robwent/joomla-json-db-check/issues). 33 | -------------------------------------------------------------------------------- /json-db-check.php: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | Joomla json Check 11 | 40 | 41 | 42 | input; 69 | $fullcheck = $jinput->get('fullcheck', 0, 'INT'); 70 | $columns = $jinput->get('columns', array(), 'array'); 71 | 72 | function is_trying_to_be_json($data) 73 | { 74 | $data = trim($data); 75 | 76 | return ((substr($data, 0, 1) === '{') || (substr($data, -1, 1) === '}')) ? true : false; 77 | } 78 | 79 | function is_json() 80 | { 81 | call_user_func_array('json_decode', func_get_args()); 82 | 83 | return (json_last_error() === JSON_ERROR_NONE); 84 | } 85 | 86 | //The columns to check 87 | $column_string = 'COLUMN_NAME = \'params\' OR COLUMN_NAME = \'rules\' OR COLUMN_NAME = \'attribs\''; 88 | if(count($columns) > 0) 89 | { 90 | $column_string = ''; 91 | $first = 1; 92 | 93 | if(in_array('params', $columns)) 94 | { 95 | $column_string .= 'COLUMN_NAME = \'params\''; 96 | $first = 0; 97 | } 98 | 99 | if(in_array('rules', $columns)) 100 | { 101 | $column_string .= $first ? 'COLUMN_NAME = \'rules\'' : ' OR COLUMN_NAME = \'rules\''; 102 | $first = 0; 103 | } 104 | 105 | if(in_array('attribs', $columns)) 106 | { 107 | $column_string .= $first ? 'COLUMN_NAME = \'attribs\'' : ' OR COLUMN_NAME = \'attribs\''; 108 | } 109 | } 110 | 111 | //We use this for both checks 112 | $query = $db->getQuery(true) 113 | ->select('TABLE_NAME,COLUMN_NAME') 114 | ->from('INFORMATION_SCHEMA.COLUMNS') 115 | ->where($column_string) 116 | ->andWhere('TABLE_SCHEMA = \'' . $config->get('db') . '\''); 117 | 118 | $db->setQuery($query); 119 | $results = $db->loadObjectList(); 120 | ?> 121 | 122 |

Checking for Invalid Empty Parameters

123 | TABLE_NAME}, column {$result->COLUMN_NAME}
"; 129 | $query = $db->getQuery(true) 130 | ->update($result->TABLE_NAME) 131 | ->set($result->COLUMN_NAME . ' = "{}"') 132 | ->where($result->COLUMN_NAME . ' = "" OR ' . $result->COLUMN_NAME . ' = \'{\"\"}\' OR ' . $result->COLUMN_NAME . ' = \'{\\\\\"\\\\\"}\' '); 133 | 134 | $db->setQuery($query); 135 | $results = $db->execute(); 136 | $changes = $db->getAffectedRows(); 137 | 138 | if ($changes != 0) 139 | { 140 | echo $changes . " rows modified.
"; 141 | } 142 | } 143 | } 144 | ?> 145 |

Finished checking empty parameters

146 |
147 | 148 | Columns to check: 149 | 153 | 157 | 161 |
162 |

163 |

(This will not replace any values, you will need to manaully fix them)

164 | 0) 166 | { 167 | ?> 168 |

Checking '' Entries for Invalid Syntax

169 | Checking table: {$result->TABLE_NAME}, column {$result->COLUMN_NAME}

"; 176 | $query = $db->getQuery(true) 177 | ->select('*') 178 | ->from($result->TABLE_NAME) 179 | ->where($result->COLUMN_NAME . ' != "{}"'); 180 | 181 | $db->setQuery($query); 182 | 183 | $results = $db->loadAssocList(); 184 | 185 | if ($results) 186 | { 187 | foreach ($results as $row) 188 | { 189 | if (!is_json($row[$result->COLUMN_NAME]) && is_trying_to_be_json($row[$result->COLUMN_NAME])) 190 | { 191 | $error = json_last_error_msg(); 192 | reset($row); 193 | $first_key = key($row); 194 | echo "Row {$row[$first_key]} is not valid JSON. Error: ($error)
"; 195 | echo "Content: {$row[$result->COLUMN_NAME]}

"; 196 | } 197 | } 198 | } 199 | } 200 | }?> 201 | 202 |

Finished checking invalid parameters

203 |

Check invalid rules at jsonlint.com

204 | 208 |

You need to select at least one column to check!

209 | 210 | 211 |
212 | 213 | Columns to check: 214 | 218 | 222 | 226 |
227 | 228 | 229 | 230 | 231 | --------------------------------------------------------------------------------