├── .github └── FUNDING.yml ├── JSONtoMYSQL ├── class.AbstractMysqlTable.php ├── class.CreateMYSQLTable.php ├── class.ExistingMYSQLTable.php ├── class.JSONtoMYSQL.php └── lib │ ├── class.DatabaseException.php │ ├── class.HashTable.php │ ├── class.MySQLConn.php │ ├── class.MySQLResult.php │ └── class.Timer.php ├── LICENSE ├── README.md ├── config-sample.php ├── example.php └── include.classloader.php /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: adamwulf 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /JSONtoMYSQL/class.AbstractMysqlTable.php: -------------------------------------------------------------------------------- 1 | mysql = $mysql; 34 | $this->tablename = $tablename; 35 | $this->primary = $this->getColumnNameForKey($primary); 36 | $this->locked = JSONTOMYSQL_LOCKED; 37 | } 38 | 39 | public function isLocked(): bool 40 | { 41 | return $this->locked; 42 | } 43 | 44 | public function setLocked(bool $lock): void 45 | { 46 | $this->locked = $lock; 47 | } 48 | 49 | public function name(): string 50 | { 51 | return $this->tablename; 52 | } 53 | 54 | abstract public function primaryColumn(); 55 | 56 | /** 57 | * this method should be called to make sure that 58 | * the table exists and could operate on the input 59 | * data if needed 60 | * 61 | * this will create the table if needed, and will create 62 | * any columns necessary for existing tables 63 | * 64 | * $typeForColName($data, $value) can return a mysql data type 65 | * to override JSONtoMYSQL's auto type. 66 | */ 67 | abstract public function validateTableFor($json_data, Closure $typeForColName = null); 68 | 69 | /** 70 | * will insert or update the table for the input 71 | * json object. the row will update if the input 72 | * does match a value in the primary column, otherwise 73 | * will insert a new row 74 | */ 75 | abstract public function save($json_data) : MySQLResult; 76 | 77 | abstract public function update($json_data) : MySQLResult; 78 | 79 | abstract public function insert($json_data) : MySQLResult; 80 | 81 | abstract public function find(array $json_obj = array(), array $ops = null, array $orders = null) : MySQLResult; 82 | 83 | abstract public function delete($json_obj) : MySQLResult; 84 | 85 | abstract public function truncate() : MySQLResult; 86 | 87 | abstract public function addUniqueIndexTo(array $columns, string $name): void; 88 | 89 | abstract public function addIndexTo(array $columns, string $name) : void; 90 | 91 | /** 92 | * helper method to make a mysql safe column name 93 | * from any input string 94 | */ 95 | public function getColumnNameForKey(string $key) : string { 96 | return preg_replace('/[^a-zA-Z0-9_]/', '', $key); 97 | } 98 | 99 | /** 100 | * will determine a valid mysql column type from 101 | * the input variable value 102 | * @param mixed $val 103 | * @return string 104 | * @throws DatabaseException 105 | */ 106 | protected function getMysqlTypeForValue($val) : ?string { 107 | if(preg_match('/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', $val)){ 108 | return "DATETIME"; 109 | }else if(preg_match('/\d{4}-\d{2}-\d{2}/', $val)){ 110 | return "DATE"; 111 | }else if(is_string($val)){ 112 | return "TEXT"; 113 | }else if(is_bool($val)){ 114 | return "TINYINT"; 115 | }else if(is_int($val)){ 116 | return "BIGINT"; 117 | }else if(is_double($val) || is_float($val) || is_real($val)){ 118 | return "DOUBLE"; 119 | }else if(!is_null($val)){ 120 | throw new DatabaseException("unknown mysql type for: " . gettype($val)); 121 | } 122 | return null; 123 | } 124 | } 125 | 126 | 127 | -------------------------------------------------------------------------------- /JSONtoMYSQL/class.CreateMYSQLTable.php: -------------------------------------------------------------------------------- 1 | isLocked()){ 20 | throw new DatabaseException("JsonToMysql is locked. Cannot create new table " . $this->tablename); 21 | } 22 | 23 | $colstr = ""; 24 | 25 | foreach($data as $key => $value){ 26 | if(is_array($value)){ 27 | echo "need to handle array subdata\n"; 28 | }else if(is_object($value)){ 29 | echo "need to handle object subdata\n"; 30 | }else if($key != $this->primary){ 31 | $colname = $this->getColumnNameForKey($key); 32 | $type = $this->getMysqlTypeForValue($value); 33 | $nullable = false; 34 | 35 | if($typeForColName){ 36 | $typeInfo = $typeForColName($colname, $value, $type); 37 | if(is_array($typeInfo)){ 38 | $type = $typeInfo[0]; 39 | $nullable = $typeInfo[1]; 40 | }else{ 41 | $type = $typeInfo; 42 | } 43 | } 44 | 45 | if(!$type){ 46 | /** @noinspection ForgottenDebugOutputInspection */ 47 | error_log(" - unknown type for column " . $colname); 48 | } 49 | 50 | $nullability = $nullable ? " NULL " : " NOT NULL "; 51 | 52 | $colstr .= " `" . $colname . "` " . $type . $nullability . ","; 53 | } 54 | } 55 | 56 | 57 | $sql = "CREATE TABLE IF NOT EXISTS `" . addslashes($this->tablename) . "` (" 58 | . " `" . $this->primary . "` bigint(20) NOT NULL auto_increment," 59 | . $colstr 60 | . " PRIMARY KEY (`" . $this->primary . "`)" 61 | . ") ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;"; 62 | 63 | $this->mysql->query($sql); 64 | 65 | $issues = []; 66 | $issues[] = ["notice" => "created table"]; 67 | return $issues; 68 | } 69 | 70 | /** 71 | * returns a MysqlResult for a SELECT query 72 | * that tries to find all values in the table 73 | * that match the input json object 74 | * @throws DatabaseException 75 | */ 76 | public function find($json_obj = array(), $ops=false, $orders=false) : MySQLResult{ 77 | $sql = "SELECT 0 LIMIT 0"; 78 | return $this->mysql->query($sql); 79 | } 80 | 81 | /** 82 | * @param $json_obj 83 | * @return MySQLResult 84 | * @throws DatabaseException 85 | */ 86 | public function delete($json_obj) : MySQLResult{ 87 | $sql = "SELECT 0 LIMIT 0"; 88 | return $this->mysql->query($sql); 89 | } 90 | 91 | /** 92 | * @return MySQLResult 93 | * @throws DatabaseException 94 | */ 95 | public function truncate() : MySQLResult{ 96 | $sql = "SELECT 0 LIMIT 0"; 97 | return $this->mysql->query($sql); 98 | } 99 | 100 | 101 | public function addUniqueIndexTo(array $columns, string $name): void{ 102 | // noop 103 | } 104 | 105 | public function addIndexTo(array $columns, string $name) : void{ 106 | // noop 107 | } 108 | 109 | } 110 | 111 | -------------------------------------------------------------------------------- /JSONtoMYSQL/class.ExistingMYSQLTable.php: -------------------------------------------------------------------------------- 1 | fields = array(); 16 | } 17 | 18 | public function primaryColumn() : string { 19 | return $this->primary; 20 | } 21 | 22 | /** 23 | * make sure to cache our primary column name 24 | * to ease future operations 25 | * @throws DatabaseException 26 | */ 27 | public function validateTableFor($data, Closure $typeForColName = null, Closure $nullabilityForColName = null) : array { 28 | $issues = []; 29 | 30 | if(!count($this->fields)){ 31 | // pull the primary column from the database 32 | $sql = "show index from " . addslashes($this->tablename) . " where Key_name = 'PRIMARY' ;"; 33 | $result = $this->mysql->query($sql); 34 | $arr = $result->fetch_array(); 35 | $this->primary = $arr["Column_name"]; 36 | 37 | // fetch all columns and types 38 | $this->fields = array(); 39 | $sql = "SHOW FIELDS FROM `" . addslashes($this->tablename) . "`"; 40 | $result = $this->mysql->query($sql); 41 | while($row = $result->fetch_array()){ 42 | $field = array("name" => $row["Field"], "type" => $row["Type"], "nullable" => $row["Null"] == "YES"); 43 | $this->fields[] = $field; 44 | } 45 | } 46 | 47 | $missing = array(); 48 | foreach($data as $key => $value){ 49 | if(!is_array($value) && !is_object($value)){ 50 | $columnname = $this->getColumnNameForKey($key); 51 | $found = false; 52 | foreach($this->fields as $field){ 53 | if($field["name"] == $columnname){ 54 | $found = $field; 55 | break; 56 | } 57 | } 58 | $type = $this->getMysqlTypeForValue($value); 59 | $nullable = null; 60 | 61 | if($typeForColName){ 62 | $typeInfo = $typeForColName($columnname, $value, $type); 63 | if(is_array($typeInfo)){ 64 | $type = $typeInfo[0]; 65 | $nullable = $typeInfo[1]; 66 | }else{ 67 | $type = $typeInfo; 68 | } 69 | } 70 | 71 | if(!$type && !$found){ 72 | $issues[] = ["column" => $columnname, "error" => "unknown type"]; 73 | /** @noinspection ForgottenDebugOutputInspection */ 74 | error_log(" - unknown type for column " . $columnname . " when validating table " . $this->name()); 75 | } 76 | 77 | if(!$found){ 78 | $issues[] = ["column" => $columnname, "error" => "missing column " . $type . " null? " . $nullable]; 79 | $missing[] = array("name" => $columnname, "type" => $type, "nullable" => $nullable); 80 | }else{ 81 | $type = strtoupper($type); 82 | $foundType = strtoupper($found["type"]); 83 | if($type && $foundType && strpos($type, $foundType) !== 0 && strpos($foundType, $type) !== 0){ 84 | $issues[] = ["column" => $columnname, "error" => "invalid type: should be " . $type . ", but is " . $found["type"]]; 85 | } 86 | if($nullable && !$found["nullable"]){ 87 | $issues[] = ["column" => $columnname, "error" => "invalid nullability: should nullable, but isn't"]; 88 | }else if($nullable === false && $found["nullable"]){ 89 | $issues[] = ["column" => $columnname, "error" => "invalid nullability: shouldn't nullable, but is"]; 90 | } 91 | } 92 | } 93 | } 94 | 95 | if($this->isLocked() && count($missing)){ 96 | $colnames = array_map(function($field){ 97 | return $field["name"]; 98 | }, $missing); 99 | throw new DatabaseException("JsonToMysql is locked. Cannot create columns " . join(',', $colnames) . " in table " . $this->tablename); 100 | }else if(count($missing)){ 101 | foreach($missing as $field){ 102 | $nullability = $field["nullable"] ? " NULL " : " NOT NULL "; 103 | $sql = "ALTER TABLE `" . addslashes($this->tablename) . "` ADD `" . addslashes($field["name"]) . "` " . $field["type"] . $nullability . ";"; 104 | $this->mysql->query($sql); 105 | $this->fields[] = $field; 106 | } 107 | } 108 | 109 | return $issues; 110 | } 111 | 112 | 113 | /** 114 | * @param array $columns 115 | * @param string $name 116 | * @throws DatabaseException 117 | */ 118 | public function addUniqueIndexTo(array $columns, string $name) : void { 119 | $sql = "show index from " . addslashes($this->tablename) . " where Key_name = '" . addslashes($name) . "' ;"; 120 | $result = $this->mysql->query($sql); 121 | 122 | if(!$result->num_rows()){ 123 | 124 | $cols = ""; 125 | foreach($columns as $column){ 126 | if(strlen($cols)){ 127 | $cols .= ", "; 128 | } 129 | if(is_string($column)){ 130 | $cols .= "`" . addslashes($column) . "`"; 131 | }else if(is_array($column)){ 132 | $cols .= "`" . addslashes($column[0]) . "`(" . ((int)$column[1]) . ")"; 133 | } 134 | } 135 | 136 | $sql = "ALTER TABLE `" . addslashes($this->tablename) . "` ADD UNIQUE `" . addslashes($name) . "` (" . $cols . ");"; 137 | $this->mysql->query($sql); 138 | } 139 | } 140 | 141 | /** 142 | * @param array $columns 143 | * @param string $name 144 | * @throws DatabaseException 145 | */ 146 | public function addIndexTo(array $columns, string $name) : void { 147 | $sql = "show index from " . addslashes($this->tablename) . " where Key_name = '" . addslashes($name) . "' ;"; 148 | $result = $this->mysql->query($sql); 149 | 150 | if(!$result->num_rows()){ 151 | 152 | $cols = ""; 153 | foreach($columns as $column){ 154 | if(strlen($cols)){ 155 | $cols .= ", "; 156 | } 157 | if(is_string($column)){ 158 | $cols .= "`" . addslashes($column) . "`"; 159 | }else if(is_array($column)){ 160 | $cols .= "`" . addslashes($column[0]) . "`(" . ((int)$column[1]) . ")"; 161 | } 162 | } 163 | 164 | $sql = "ALTER TABLE `" . addslashes($this->tablename) . "` ADD INDEX `" . addslashes($name) . "` (" . $cols . ");"; 165 | $this->mysql->query($sql); 166 | } 167 | } 168 | 169 | 170 | /** 171 | * will save the input json object contains 172 | * a value for the primary column or will 173 | * insert a new row 174 | * @throws DatabaseException 175 | */ 176 | public function save($json_obj) : MySQLResult{ 177 | $this->validateTableFor($json_obj); 178 | $primary = $this->primary; 179 | 180 | $primary_value = false; 181 | if(is_array($json_obj) && isset($json_obj[$primary])){ 182 | $primary_value = $json_obj[$primary]; 183 | }else if(is_object($json_obj) && isset($json_obj->$primary)){ 184 | $primary_value = $json_obj->$primary; 185 | } 186 | 187 | if($primary_value){ 188 | $res = $this->find(array($primary => $primary_value)); 189 | if($res->num_rows()){ 190 | // already exists with this primary key value, update it 191 | return $this->update($json_obj); 192 | }else{ 193 | // doesn't exist yet, insert 194 | return $this->insert($json_obj); 195 | } 196 | }else{ 197 | return $this->insert($json_obj); 198 | } 199 | } 200 | 201 | 202 | /** 203 | * returns a MysqlResult for a SELECT query 204 | * that tries to find all values in the table 205 | * that match the input json object 206 | * @throws DatabaseException 207 | */ 208 | public function find(array $json_obj = array(), array $ops = null, array $orders = null) : MySQLResult{ 209 | $this->validateTableFor($json_obj); 210 | $where = ""; 211 | foreach ($json_obj as $key => $value) { 212 | if (is_array($value)) { 213 | $colname = $this->getColumnNameForKey($key); 214 | if (strlen($where)) { 215 | $where .= " AND "; 216 | } 217 | $where .= "`" . $colname . "`"; 218 | $op = ($ops && $ops[$key]) ? addslashes($ops[$key]) : "IN"; 219 | $where .= " $op ("; 220 | $idx = 0; 221 | foreach ($value as $val) { 222 | $where .= ($idx ? "," : "") . "'" . addslashes($val) . "'"; 223 | $idx++; 224 | } 225 | $where .= ") "; 226 | } else if (is_object($value)) { 227 | /* echo "need to handle object subdata\n"; */ 228 | } else { 229 | $colname = $this->getColumnNameForKey($key); 230 | if (strlen($where)) { 231 | $where .= " AND "; 232 | } 233 | $where .= "`" . $colname . "`"; 234 | if ($this->getMysqlTypeForValue($value) == "TEXT") { 235 | $op = ($ops && $ops[$key]) ? addslashes($ops[$key]) : "LIKE"; 236 | $where .= " $op '" . addslashes($value) . "'"; 237 | } else { 238 | $op = ($ops && $ops[$key]) ? addslashes($ops[$key]) : "="; 239 | $where .= " $op '" . addslashes($value) . "'"; 240 | } 241 | } 242 | } 243 | $sql = "SELECT * FROM `" . addslashes($this->tablename); 244 | if ($where) { 245 | $sql .= "` WHERE " . $where; 246 | } else { 247 | $sql .= "`"; 248 | } 249 | 250 | if (is_array($orders) && count($orders)) { 251 | $sql .= " ORDER BY "; 252 | 253 | foreach ($orders as $i => $order) { 254 | $sql .= addslashes($order); 255 | if ($i < count($orders) - 1) { 256 | $sql .= ", "; 257 | } 258 | } 259 | } 260 | 261 | return $this->mysql->query($sql); 262 | } 263 | 264 | /** 265 | * finds the rows just like the find() method 266 | * and then deletes all of them 267 | * @throws DatabaseException 268 | */ 269 | public function delete($json_obj) : MySQLResult{ 270 | $where = ""; 271 | 272 | foreach($json_obj as $key => $value){ 273 | if(is_array($value)){ 274 | /* echo "need to handle array subdata\n"; */ 275 | }else if(is_object($value)){ 276 | /* echo "need to handle object subdata\n"; */ 277 | }else{ 278 | $colname = $this->getColumnNameForKey($key); 279 | if(strlen($where)){ 280 | $where .= " AND "; 281 | } 282 | $where .= "`" . $colname . "`"; 283 | if($this->getMysqlTypeForValue($value) == "TEXT"){ 284 | $where .= " LIKE '" . addslashes($value) . "'"; 285 | }else{ 286 | $where .= " = '" . addslashes($value) . "'"; 287 | } 288 | } 289 | } 290 | if(strlen($where)){ 291 | $sql = "DELETE FROM `" . addslashes($this->tablename) . "` WHERE " . $where; 292 | 293 | return $this->mysql->query($sql); 294 | }else{ 295 | $sql = "SELECT 0 LIMIT 0"; 296 | return $this->mysql->query($sql); 297 | } 298 | } 299 | 300 | /** 301 | * finds the rows just like the find() method 302 | * and then deletes all of them 303 | * @throws DatabaseException 304 | */ 305 | public function truncate() : MySQLResult{ 306 | $sql = "TRUNCATE `" . addslashes($this->tablename) . "`"; 307 | return $this->mysql->query($sql); 308 | } 309 | 310 | /** 311 | * will update a row in the database for 312 | * the input object by comparing its value 313 | * for the primary column name 314 | * @throws DatabaseException 315 | */ 316 | public function update($json_obj) : MySQLResult{ 317 | $this->validateTableFor($json_obj); 318 | $set = ""; 319 | 320 | $primary_val = 0; 321 | 322 | foreach($json_obj as $key => $value){ 323 | if($key == $this->primary){ 324 | $primary_val = $value; 325 | continue; 326 | } 327 | if(is_array($value)){ 328 | /* echo "need to handle array subdata\n"; */ 329 | }else if(is_object($value)){ 330 | /* echo "need to handle object subdata\n"; */ 331 | }else{ 332 | $colname = $this->getColumnNameForKey($key); 333 | if(strlen($set)){ 334 | $set .= ", "; 335 | } 336 | $set .= "`" . $colname . "`"; 337 | 338 | if(is_bool($value)){ 339 | $value = (int)$value; 340 | } 341 | 342 | if(is_null($value)){ 343 | $set .= " = NULL"; 344 | }else{ 345 | $set .= " = '" . addslashes($value) . "'"; 346 | } 347 | } 348 | } 349 | if(strlen($set)){ 350 | $sql = "UPDATE `" . addslashes($this->tablename) . "` SET " 351 | . $set . " WHERE `" . $this->primary . "`='" . addslashes($primary_val) . "';"; 352 | 353 | return $this->mysql->query($sql); 354 | }else{ 355 | $sql = "SELECT 0 LIMIT 0"; 356 | return $this->mysql->query($sql); 357 | } 358 | } 359 | 360 | /** 361 | * this method will attempt to add a new row 362 | * to the table with all of the values 363 | * of the input json object 364 | * @throws DatabaseException 365 | */ 366 | public function insert($json_obj) : MySQLResult{ 367 | $this->validateTableFor($json_obj); 368 | $fields = ""; 369 | $values = ""; 370 | 371 | foreach($json_obj as $key => $value){ 372 | if(is_array($value)){ 373 | /* echo "need to handle array subdata\n"; */ 374 | }else if(is_object($value)){ 375 | /* echo "need to handle object subdata\n"; */ 376 | }else{ 377 | $colname = $this->getColumnNameForKey($key); 378 | if(strlen($fields)){ 379 | $fields .= ","; 380 | $values .= ","; 381 | } 382 | $fields .= "`" . $colname . "`"; 383 | 384 | if(is_bool($value)){ 385 | $value = (int)$value; 386 | } 387 | 388 | if(is_null($value)){ 389 | $values .= "NULL"; 390 | }else{ 391 | $values .= "'" . addslashes($value) . "'"; 392 | } 393 | } 394 | } 395 | 396 | if(strlen($fields)){ 397 | $sql = "INSERT INTO `" . addslashes($this->tablename) . "` " 398 | . "(" . $fields . ") VALUES (" . $values . ")"; 399 | 400 | return $this->mysql->query($sql); 401 | }else{ 402 | $sql = "SELECT 0 LIMIT 0"; 403 | return $this->mysql->query($sql); 404 | } 405 | } 406 | 407 | /** 408 | * returns true if the input column name already exists 409 | * in the table, or false otherwise 410 | * @throws DatabaseException 411 | */ 412 | protected function columnExistsInTableHuh($columnname) : bool { 413 | if(count($this->fields)){ 414 | foreach($this->fields as $field){ 415 | if($field["name"] == $columnname){ 416 | return true; 417 | } 418 | } 419 | return false; 420 | } 421 | $sql = "SHOW COLUMNS FROM `" . addslashes($this->tablename) . "` LIKE '" . addslashes($columnname) . "'"; 422 | $result = $this->mysql->query($sql); 423 | return $result->num_rows() > 0; 424 | } 425 | 426 | 427 | 428 | } 429 | 430 | -------------------------------------------------------------------------------- /JSONtoMYSQL/class.JSONtoMYSQL.php: -------------------------------------------------------------------------------- 1 | mysql = $mysql; 17 | $this->table_cache = []; 18 | } 19 | 20 | 21 | /** 22 | * will return the modifications needed 23 | * to the scheme to support inserting 24 | * the input json object 25 | * 26 | * returns an array of modifications 27 | * including: 28 | * creating tables 29 | * adding columns 30 | * modifying existing columns 31 | * adding foreign keys / foreign tables 32 | * flattening sub object into columns 33 | * @throws DatabaseException 34 | */ 35 | public function save($json_obj, $tablename): MySQLResult 36 | { 37 | $table = $this->table($tablename); 38 | $table->validateTableFor($json_obj); 39 | return $table->save($json_obj); 40 | } 41 | 42 | /** 43 | * create or return a table for the input 44 | * tablename 45 | * @throws DatabaseException 46 | */ 47 | public function table($tablename){ 48 | if($this->tableExistsHuh($tablename)){ 49 | return new ExistingMYSQLTable($this->mysql, $tablename); 50 | }else if(isset($this->table_cache[$tablename])){ 51 | return $this->table_cache[$tablename]; 52 | } else { 53 | $this->table_cache[$tablename] = new CreateMYSQLTable($this->mysql, $tablename); 54 | return $this->table_cache[$tablename]; 55 | } 56 | } 57 | 58 | /** 59 | * helper method to determine if a table 60 | * already exists 61 | * @throws DatabaseException 62 | */ 63 | protected function tableExistsHuh($tablename): bool 64 | { 65 | $sql = "SHOW TABLES LIKE '" . addslashes($tablename) . "'"; 66 | $result = $this->mysql->query($sql); 67 | return $result->num_rows() > 0; 68 | } 69 | 70 | public function mysql() : MySQLConn{ 71 | return $this->mysql; 72 | } 73 | } 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /JSONtoMYSQL/lib/class.DatabaseException.php: -------------------------------------------------------------------------------- 1 | code}]: {$this->message}\n"; 9 | } 10 | } -------------------------------------------------------------------------------- /JSONtoMYSQL/lib/class.HashTable.php: -------------------------------------------------------------------------------- 1 | table = array(); 11 | } 12 | 13 | function put($key, $obj): void 14 | { 15 | $this->table[$key] = $obj; 16 | } 17 | 18 | function get($key){ 19 | if(isset($this->table[$key])){ 20 | return $this->table[$key]; 21 | }else{ 22 | return false; 23 | } 24 | } 25 | 26 | function clear($key): void 27 | { 28 | if(isset($this->table[$key])){ 29 | unset($this->table[$key]); 30 | } 31 | } 32 | 33 | function reset(): void 34 | { 35 | $this->table = array(); 36 | } 37 | 38 | 39 | function enum(): array 40 | { 41 | $ret = []; 42 | foreach($this->table as $key => $item){ 43 | $ret[] = $item; 44 | } 45 | return $ret; 46 | } 47 | 48 | } 49 | 50 | -------------------------------------------------------------------------------- /JSONtoMYSQL/lib/class.MySQLConn.php: -------------------------------------------------------------------------------- 1 | host = $h; 30 | $this->database = $db; 31 | $this->user = $u; 32 | $this->pass = $p; 33 | $this->_query_count = 0; 34 | $this->_mysqli_link = false; 35 | $this->_query_cache = new HashTable(); 36 | $this->logger = $log; 37 | } 38 | 39 | /** 40 | * queries mysql and caches the result if appropriate 41 | * @param $sql 42 | * @param bool $verbose 43 | * @return MySQLResult 44 | * @throws DatabaseException 45 | */ 46 | function query($sql, $verbose=false) : MySQLResult{ 47 | $sql = trim($sql); 48 | if($this->_mysqli_link === false){ 49 | $this->_mysqli_link = mysqli_connect($this->host, $this->user, $this->pass, $this->database); 50 | mysqli_set_charset($this->_mysqli_link, "utf8"); 51 | } 52 | if($this->_mysqli_link === false){ 53 | throw new DatabaseException("could not connect to MySQL"); 54 | } 55 | 56 | if($this->_query_cache->get($sql)){ 57 | if($verbose)echo "found in cache
"; 58 | $result = $this->_query_cache->get($sql); 59 | if(mysqli_num_rows($result)){ 60 | if($verbose) echo ": seeking to 0"; 61 | mysqli_data_seek($result, 0); 62 | } 63 | $ret = new MySQLResult($this->_mysqli_link, $result); 64 | if($verbose) echo "
"; 65 | }else{ 66 | if($verbose) echo "not in cache"; 67 | $this->_query_count++; 68 | /** 69 | * this following line should be run once per connection to mysql 70 | * 71 | * i'm running it before every query. I can probably optimize this 72 | * to run once per connection, but I need to do some thorough testing... 73 | * 74 | * http://dev.mysql.com/doc/refman/5.6/en/charset-connection.html 75 | */ 76 | if(is_object($this->logger)){ 77 | $this->logger->log($this, ALogger::$LOW, $sql); 78 | } 79 | 80 | mysqli_set_charset($this->_mysqli_link, "utf8"); 81 | $timer = new Timer(); 82 | $timer->start(); 83 | $result = mysqli_query($this->_mysqli_link, $sql); 84 | $ret = new MySQLResult($this->_mysqli_link, $result); 85 | $timer->stop(); 86 | $time = $timer->read(); 87 | 88 | /** 89 | * the query is too long! oh noes! 90 | */ 91 | if($time > .1){ 92 | /** 93 | * save the query to the DB, so I can look at it later 94 | */ 95 | error_log("long query: " . $sql); 96 | if(is_object($this->logger)){ 97 | $this->logger->longQuery($time, $sql); 98 | } 99 | } 100 | 101 | if(mysqli_error($this->_mysqli_link)){ 102 | if($verbose) echo "mysqli_error: " . mysqli_error($this->_mysqli_link) . "
"; 103 | error_log("sql error: " . $sql); 104 | throw new DatabaseException(mysqli_error($this->_mysqli_link)); 105 | } 106 | if(strpos($sql, "SELECT") === 0){ 107 | if($verbose) echo ": select: $sql

"; 108 | $this->_query_cache->put($sql, $result); 109 | }else{ 110 | if($verbose) echo ": not select: $sql
"; 111 | if($verbose) echo "clearing cache
"; 112 | $this->_query_cache->reset(); 113 | } 114 | 115 | } 116 | return $ret; 117 | } 118 | 119 | function reset() : void{ 120 | $this->_query_count = 0; 121 | $this->_query_cache->reset(); 122 | } 123 | 124 | function getQueryCount() : int{ 125 | return $this->_query_count; 126 | } 127 | 128 | function close() : bool{ 129 | if(!is_bool($this->_mysqli_link)){ 130 | return @mysqli_close($this->_mysqli_link); 131 | }else{ 132 | return false; 133 | } 134 | } 135 | 136 | } 137 | 138 | 139 | -------------------------------------------------------------------------------- /JSONtoMYSQL/lib/class.MySQLResult.php: -------------------------------------------------------------------------------- 1 | result = $result; 15 | $this->insert_id = @mysqli_insert_id($link); 16 | $this->affected_rows = @mysqli_affected_rows($link); 17 | $this->offset = 0; 18 | } 19 | 20 | 21 | function num_rows() : int { 22 | return mysqli_num_rows($this->result); 23 | } 24 | 25 | function fetch_array() : ?array { 26 | if($this->offset < $this->num_rows()){ 27 | $this->offset += 1; 28 | return mysqli_fetch_array($this->result, MYSQLI_ASSOC); 29 | } 30 | return null; 31 | } 32 | 33 | function peek_array() : ?array { 34 | $offset = $this->offset; 35 | $ret = $this->fetch_array(); 36 | 37 | if($this->offset != $offset){ 38 | // restore pointer to previous record 39 | mysqli_data_seek($this->result, $offset); 40 | $this->offset = $offset; 41 | } 42 | 43 | return $ret; 44 | } 45 | 46 | function insert_id() : int { 47 | return $this->insert_id; 48 | } 49 | 50 | function affected_rows() : int { 51 | return $this->affected_rows; 52 | } 53 | 54 | function has_next() : bool { 55 | if($this->offset < $this->num_rows()){ 56 | return true; 57 | }else{ 58 | return false; 59 | } 60 | } 61 | 62 | function rewind() : bool { 63 | if($this->num_rows() > 0){ 64 | $this->offset = 0; 65 | return mysqli_data_seek($this->result, 0); 66 | } 67 | return false; 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /JSONtoMYSQL/lib/class.Timer.php: -------------------------------------------------------------------------------- 1 | start = false; 13 | $this->stop = false; 14 | } 15 | 16 | function start(): void 17 | { 18 | $this->start = (float)microtime(true); 19 | $this->stop = false; 20 | } 21 | 22 | function stop(): void 23 | { 24 | $this->stop = (float)microtime(true); 25 | } 26 | 27 | function read() : float{ 28 | if(is_numeric($this->stop) && 29 | is_numeric($this->start) && 30 | ($this->stop > $this->start)){ 31 | return ($this->stop - $this->start); 32 | }else 33 | if(is_numeric($this->start)){ 34 | return (microtime(true) - $this->start); 35 | }else{ 36 | return 0; 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | Attribution 3.0 Unported 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR 10 | DAMAGES RESULTING FROM ITS USE. 11 | 12 | License 13 | 14 | THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE 15 | COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY 16 | COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS 17 | AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. 18 | 19 | BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE 20 | TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY 21 | BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS 22 | CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND 23 | CONDITIONS. 24 | 25 | 1. Definitions 26 | 27 | a. "Adaptation" means a work based upon the Work, or upon the Work and 28 | other pre-existing works, such as a translation, adaptation, 29 | derivative work, arrangement of music or other alterations of a 30 | literary or artistic work, or phonogram or performance and includes 31 | cinematographic adaptations or any other form in which the Work may be 32 | recast, transformed, or adapted including in any form recognizably 33 | derived from the original, except that a work that constitutes a 34 | Collection will not be considered an Adaptation for the purpose of 35 | this License. For the avoidance of doubt, where the Work is a musical 36 | work, performance or phonogram, the synchronization of the Work in 37 | timed-relation with a moving image ("synching") will be considered an 38 | Adaptation for the purpose of this License. 39 | b. "Collection" means a collection of literary or artistic works, such as 40 | encyclopedias and anthologies, or performances, phonograms or 41 | broadcasts, or other works or subject matter other than works listed 42 | in Section 1(f) below, which, by reason of the selection and 43 | arrangement of their contents, constitute intellectual creations, in 44 | which the Work is included in its entirety in unmodified form along 45 | with one or more other contributions, each constituting separate and 46 | independent works in themselves, which together are assembled into a 47 | collective whole. A work that constitutes a Collection will not be 48 | considered an Adaptation (as defined above) for the purposes of this 49 | License. 50 | c. "Distribute" means to make available to the public the original and 51 | copies of the Work or Adaptation, as appropriate, through sale or 52 | other transfer of ownership. 53 | d. "Licensor" means the individual, individuals, entity or entities that 54 | offer(s) the Work under the terms of this License. 55 | e. "Original Author" means, in the case of a literary or artistic work, 56 | the individual, individuals, entity or entities who created the Work 57 | or if no individual or entity can be identified, the publisher; and in 58 | addition (i) in the case of a performance the actors, singers, 59 | musicians, dancers, and other persons who act, sing, deliver, declaim, 60 | play in, interpret or otherwise perform literary or artistic works or 61 | expressions of folklore; (ii) in the case of a phonogram the producer 62 | being the person or legal entity who first fixes the sounds of a 63 | performance or other sounds; and, (iii) in the case of broadcasts, the 64 | organization that transmits the broadcast. 65 | f. "Work" means the literary and/or artistic work offered under the terms 66 | of this License including without limitation any production in the 67 | literary, scientific and artistic domain, whatever may be the mode or 68 | form of its expression including digital form, such as a book, 69 | pamphlet and other writing; a lecture, address, sermon or other work 70 | of the same nature; a dramatic or dramatico-musical work; a 71 | choreographic work or entertainment in dumb show; a musical 72 | composition with or without words; a cinematographic work to which are 73 | assimilated works expressed by a process analogous to cinematography; 74 | a work of drawing, painting, architecture, sculpture, engraving or 75 | lithography; a photographic work to which are assimilated works 76 | expressed by a process analogous to photography; a work of applied 77 | art; an illustration, map, plan, sketch or three-dimensional work 78 | relative to geography, topography, architecture or science; a 79 | performance; a broadcast; a phonogram; a compilation of data to the 80 | extent it is protected as a copyrightable work; or a work performed by 81 | a variety or circus performer to the extent it is not otherwise 82 | considered a literary or artistic work. 83 | g. "You" means an individual or entity exercising rights under this 84 | License who has not previously violated the terms of this License with 85 | respect to the Work, or who has received express permission from the 86 | Licensor to exercise rights under this License despite a previous 87 | violation. 88 | h. "Publicly Perform" means to perform public recitations of the Work and 89 | to communicate to the public those public recitations, by any means or 90 | process, including by wire or wireless means or public digital 91 | performances; to make available to the public Works in such a way that 92 | members of the public may access these Works from a place and at a 93 | place individually chosen by them; to perform the Work to the public 94 | by any means or process and the communication to the public of the 95 | performances of the Work, including by public digital performance; to 96 | broadcast and rebroadcast the Work by any means including signs, 97 | sounds or images. 98 | i. "Reproduce" means to make copies of the Work by any means including 99 | without limitation by sound or visual recordings and the right of 100 | fixation and reproducing fixations of the Work, including storage of a 101 | protected performance or phonogram in digital form or other electronic 102 | medium. 103 | 104 | 2. Fair Dealing Rights. Nothing in this License is intended to reduce, 105 | limit, or restrict any uses free from copyright or rights arising from 106 | limitations or exceptions that are provided for in connection with the 107 | copyright protection under copyright law or other applicable laws. 108 | 109 | 3. License Grant. Subject to the terms and conditions of this License, 110 | Licensor hereby grants You a worldwide, royalty-free, non-exclusive, 111 | perpetual (for the duration of the applicable copyright) license to 112 | exercise the rights in the Work as stated below: 113 | 114 | a. to Reproduce the Work, to incorporate the Work into one or more 115 | Collections, and to Reproduce the Work as incorporated in the 116 | Collections; 117 | b. to create and Reproduce Adaptations provided that any such Adaptation, 118 | including any translation in any medium, takes reasonable steps to 119 | clearly label, demarcate or otherwise identify that changes were made 120 | to the original Work. For example, a translation could be marked "The 121 | original work was translated from English to Spanish," or a 122 | modification could indicate "The original work has been modified."; 123 | c. to Distribute and Publicly Perform the Work including as incorporated 124 | in Collections; and, 125 | d. to Distribute and Publicly Perform Adaptations. 126 | e. For the avoidance of doubt: 127 | 128 | i. Non-waivable Compulsory License Schemes. In those jurisdictions in 129 | which the right to collect royalties through any statutory or 130 | compulsory licensing scheme cannot be waived, the Licensor 131 | reserves the exclusive right to collect such royalties for any 132 | exercise by You of the rights granted under this License; 133 | ii. Waivable Compulsory License Schemes. In those jurisdictions in 134 | which the right to collect royalties through any statutory or 135 | compulsory licensing scheme can be waived, the Licensor waives the 136 | exclusive right to collect such royalties for any exercise by You 137 | of the rights granted under this License; and, 138 | iii. Voluntary License Schemes. The Licensor waives the right to 139 | collect royalties, whether individually or, in the event that the 140 | Licensor is a member of a collecting society that administers 141 | voluntary licensing schemes, via that society, from any exercise 142 | by You of the rights granted under this License. 143 | 144 | The above rights may be exercised in all media and formats whether now 145 | known or hereafter devised. The above rights include the right to make 146 | such modifications as are technically necessary to exercise the rights in 147 | other media and formats. Subject to Section 8(f), all rights not expressly 148 | granted by Licensor are hereby reserved. 149 | 150 | 4. Restrictions. The license granted in Section 3 above is expressly made 151 | subject to and limited by the following restrictions: 152 | 153 | a. You may Distribute or Publicly Perform the Work only under the terms 154 | of this License. You must include a copy of, or the Uniform Resource 155 | Identifier (URI) for, this License with every copy of the Work You 156 | Distribute or Publicly Perform. You may not offer or impose any terms 157 | on the Work that restrict the terms of this License or the ability of 158 | the recipient of the Work to exercise the rights granted to that 159 | recipient under the terms of the License. You may not sublicense the 160 | Work. You must keep intact all notices that refer to this License and 161 | to the disclaimer of warranties with every copy of the Work You 162 | Distribute or Publicly Perform. When You Distribute or Publicly 163 | Perform the Work, You may not impose any effective technological 164 | measures on the Work that restrict the ability of a recipient of the 165 | Work from You to exercise the rights granted to that recipient under 166 | the terms of the License. This Section 4(a) applies to the Work as 167 | incorporated in a Collection, but this does not require the Collection 168 | apart from the Work itself to be made subject to the terms of this 169 | License. If You create a Collection, upon notice from any Licensor You 170 | must, to the extent practicable, remove from the Collection any credit 171 | as required by Section 4(b), as requested. If You create an 172 | Adaptation, upon notice from any Licensor You must, to the extent 173 | practicable, remove from the Adaptation any credit as required by 174 | Section 4(b), as requested. 175 | b. If You Distribute, or Publicly Perform the Work or any Adaptations or 176 | Collections, You must, unless a request has been made pursuant to 177 | Section 4(a), keep intact all copyright notices for the Work and 178 | provide, reasonable to the medium or means You are utilizing: (i) the 179 | name of the Original Author (or pseudonym, if applicable) if supplied, 180 | and/or if the Original Author and/or Licensor designate another party 181 | or parties (e.g., a sponsor institute, publishing entity, journal) for 182 | attribution ("Attribution Parties") in Licensor's copyright notice, 183 | terms of service or by other reasonable means, the name of such party 184 | or parties; (ii) the title of the Work if supplied; (iii) to the 185 | extent reasonably practicable, the URI, if any, that Licensor 186 | specifies to be associated with the Work, unless such URI does not 187 | refer to the copyright notice or licensing information for the Work; 188 | and (iv) , consistent with Section 3(b), in the case of an Adaptation, 189 | a credit identifying the use of the Work in the Adaptation (e.g., 190 | "French translation of the Work by Original Author," or "Screenplay 191 | based on original Work by Original Author"). The credit required by 192 | this Section 4 (b) may be implemented in any reasonable manner; 193 | provided, however, that in the case of a Adaptation or Collection, at 194 | a minimum such credit will appear, if a credit for all contributing 195 | authors of the Adaptation or Collection appears, then as part of these 196 | credits and in a manner at least as prominent as the credits for the 197 | other contributing authors. For the avoidance of doubt, You may only 198 | use the credit required by this Section for the purpose of attribution 199 | in the manner set out above and, by exercising Your rights under this 200 | License, You may not implicitly or explicitly assert or imply any 201 | connection with, sponsorship or endorsement by the Original Author, 202 | Licensor and/or Attribution Parties, as appropriate, of You or Your 203 | use of the Work, without the separate, express prior written 204 | permission of the Original Author, Licensor and/or Attribution 205 | Parties. 206 | c. Except as otherwise agreed in writing by the Licensor or as may be 207 | otherwise permitted by applicable law, if You Reproduce, Distribute or 208 | Publicly Perform the Work either by itself or as part of any 209 | Adaptations or Collections, You must not distort, mutilate, modify or 210 | take other derogatory action in relation to the Work which would be 211 | prejudicial to the Original Author's honor or reputation. Licensor 212 | agrees that in those jurisdictions (e.g. Japan), in which any exercise 213 | of the right granted in Section 3(b) of this License (the right to 214 | make Adaptations) would be deemed to be a distortion, mutilation, 215 | modification or other derogatory action prejudicial to the Original 216 | Author's honor and reputation, the Licensor will waive or not assert, 217 | as appropriate, this Section, to the fullest extent permitted by the 218 | applicable national law, to enable You to reasonably exercise Your 219 | right under Section 3(b) of this License (right to make Adaptations) 220 | but not otherwise. 221 | 222 | 5. Representations, Warranties and Disclaimer 223 | 224 | UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR 225 | OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY 226 | KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, 227 | INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, 228 | FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF 229 | LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, 230 | WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION 231 | OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. 232 | 233 | 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE 234 | LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR 235 | ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES 236 | ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS 237 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 238 | 239 | 7. Termination 240 | 241 | a. This License and the rights granted hereunder will terminate 242 | automatically upon any breach by You of the terms of this License. 243 | Individuals or entities who have received Adaptations or Collections 244 | from You under this License, however, will not have their licenses 245 | terminated provided such individuals or entities remain in full 246 | compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will 247 | survive any termination of this License. 248 | b. Subject to the above terms and conditions, the license granted here is 249 | perpetual (for the duration of the applicable copyright in the Work). 250 | Notwithstanding the above, Licensor reserves the right to release the 251 | Work under different license terms or to stop distributing the Work at 252 | any time; provided, however that any such election will not serve to 253 | withdraw this License (or any other license that has been, or is 254 | required to be, granted under the terms of this License), and this 255 | License will continue in full force and effect unless terminated as 256 | stated above. 257 | 258 | 8. Miscellaneous 259 | 260 | a. Each time You Distribute or Publicly Perform the Work or a Collection, 261 | the Licensor offers to the recipient a license to the Work on the same 262 | terms and conditions as the license granted to You under this License. 263 | b. Each time You Distribute or Publicly Perform an Adaptation, Licensor 264 | offers to the recipient a license to the original Work on the same 265 | terms and conditions as the license granted to You under this License. 266 | c. If any provision of this License is invalid or unenforceable under 267 | applicable law, it shall not affect the validity or enforceability of 268 | the remainder of the terms of this License, and without further action 269 | by the parties to this agreement, such provision shall be reformed to 270 | the minimum extent necessary to make such provision valid and 271 | enforceable. 272 | d. No term or provision of this License shall be deemed waived and no 273 | breach consented to unless such waiver or consent shall be in writing 274 | and signed by the party to be charged with such waiver or consent. 275 | e. This License constitutes the entire agreement between the parties with 276 | respect to the Work licensed here. There are no understandings, 277 | agreements or representations with respect to the Work not specified 278 | here. Licensor shall not be bound by any additional provisions that 279 | may appear in any communication from You. This License may not be 280 | modified without the mutual written agreement of the Licensor and You. 281 | f. The rights granted under, and the subject matter referenced, in this 282 | License were drafted utilizing the terminology of the Berne Convention 283 | for the Protection of Literary and Artistic Works (as amended on 284 | September 28, 1979), the Rome Convention of 1961, the WIPO Copyright 285 | Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 286 | and the Universal Copyright Convention (as revised on July 24, 1971). 287 | These rights and subject matter take effect in the relevant 288 | jurisdiction in which the License terms are sought to be enforced 289 | according to the corresponding provisions of the implementation of 290 | those treaty provisions in the applicable national law. If the 291 | standard suite of rights granted under applicable copyright law 292 | includes additional rights not granted under this License, such 293 | additional rights are deemed to be included in the License; this 294 | License is not intended to restrict the license of any rights under 295 | applicable law. 296 | 297 | 298 | Creative Commons Notice 299 | 300 | Creative Commons is not a party to this License, and makes no warranty 301 | whatsoever in connection with the Work. Creative Commons will not be 302 | liable to You or any party on any legal theory for any damages 303 | whatsoever, including without limitation any general, special, 304 | incidental or consequential damages arising in connection to this 305 | license. Notwithstanding the foregoing two (2) sentences, if Creative 306 | Commons has expressly identified itself as the Licensor hereunder, it 307 | shall have all rights and obligations of Licensor. 308 | 309 | Except for the limited purpose of indicating to the public that the 310 | Work is licensed under the CCPL, Creative Commons does not authorize 311 | the use by either party of the trademark "Creative Commons" or any 312 | related trademark or logo of Creative Commons without the prior 313 | written consent of Creative Commons. Any permitted use will be in 314 | compliance with Creative Commons' then-current trademark usage 315 | guidelines, as may be published on its website or otherwise made 316 | available upon request from time to time. For the avoidance of doubt, 317 | this trademark restriction does not form part of this License. 318 | 319 | Creative Commons may be contacted at http://creativecommons.org/. 320 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | json-to-mysql 2 | ============= 3 | 4 | Easily take any JSON object and create+insert it into a mysql table built from its structure. Also search, update, index, and validate tables with JSON. 5 | 6 | ``` 7 | 8 | include("config.php"); 9 | include("include.classloader.php"); 10 | 11 | $classLoader->addToClasspath(ROOT); 12 | 13 | 14 | $mysql = new MySQLConn(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASS); 15 | 16 | $db = new JSONtoMYSQL($mysql); 17 | 18 | // create some json 19 | $obj = json_decode('{"id":4,"name" : "asfd"}'); 20 | 21 | // save it to a table 22 | $db->save($obj, "brandnewtable"); 23 | 24 | // SELECT * from brandnewtable WHERE id = 4 25 | 26 | $obj = $db->table("brandnewtable")->find(["id" => 4]); 27 | 28 | print_r($obj); 29 | 30 | // SELECT * FROM brandnewtable WHERE id > 4 ORDER BY name DESC 31 | 32 | $obj = $db->table("brandnewtable")->find(["id" => 4], ["id" => ">"], ["name DESC"]); 33 | 34 | print_r($obj); 35 | 36 | // SELECT * FROM brandnewtable WHERE id IN (4, 5, 6, 7) 37 | 38 | $obj = $db->table("brandnewtable")->find(["id" => [4, 5, 6, 7]]); 39 | 40 | print_r($obj); 41 | 42 | 43 | ``` 44 | 45 | ## Support the project 46 | 47 | Has json-to-mysql saved you some time? Become a [Github Sponsor](https://github.com/sponsors/adamwulf) and buy me a coffee ☕️ 😄 48 | 49 | -------------------------------------------------------------------------------- /config-sample.php: -------------------------------------------------------------------------------- 1 | addToClasspath(ROOT); 11 | 12 | 13 | $mysql = new MySQLConn(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASS); 14 | 15 | $db = new JSONtoMYSQL($mysql); 16 | 17 | // create some json 18 | $obj = json_decode('{"id":4,"asdf" : "asfd"}'); 19 | 20 | // save it to a table 21 | $db->save($obj, "brandnewtable"); 22 | 23 | 24 | -------------------------------------------------------------------------------- /include.classloader.php: -------------------------------------------------------------------------------- 1 | classpath = array(); 12 | } 13 | 14 | /** 15 | * @param $dir 16 | * @throws Exception 17 | */ 18 | public function addToClasspath($dir) : void{ 19 | if(is_dir($dir)){ 20 | $this->classpath[] = $dir; 21 | }else{ 22 | throw new Exception("cannot find directory: $dir"); 23 | } 24 | } 25 | 26 | /** 27 | * @param $classname 28 | * @return bool 29 | */ 30 | public function load($classname) : bool{ 31 | $ok = false; 32 | foreach ($this->classpath as $path) { 33 | /* echo "load recur \"" . $path . "\";//
\n"; */ 34 | $ok = $ok || $this->load_recursive($path, $classname); 35 | } 36 | return $ok; 37 | } 38 | 39 | protected function load_recursive($classpath, $classname) : bool{ 40 | $ret = false; 41 | if ($handle = opendir($classpath)) { 42 | while (false != ($file = readdir($handle))) { 43 | if ($file != "." && $file != "..") { 44 | if(is_dir($classpath . $file)){ 45 | $ret = $ret || $this->load_recursive($classpath . $file . "/", $classname); 46 | }else{ 47 | if($file == "class.$classname.php"){ 48 | include_once $classpath . $file; 49 | $ret = true; 50 | /* echo "include_once \"" . $classpath . $file . "\";//
\n"; */ 51 | }else 52 | if($file == "class.Boolean.$classname.php"){ 53 | include_once $classpath . $file; 54 | $ret = true; 55 | /* echo "include_once \"" . $classpath . $file . "\";//
\n"; */ 56 | }else 57 | if($file == "interface.$classname.php"){ 58 | include_once $classpath . $file; 59 | $ret = true; 60 | /* echo "include_once \"" . $classpath . $file . "\";//
\n"; */ 61 | }else 62 | if($file == "abstract.$classname.php"){ 63 | include_once $classpath . $file; 64 | $ret = true; 65 | /* echo "include_once \"" . $classpath . $file . "\";//
\n"; */ 66 | } 67 | } 68 | } 69 | } 70 | closedir($handle); 71 | unset($handle); 72 | } 73 | return $ret; 74 | } 75 | } 76 | 77 | class ClassLoaderToString extends ClassLoader{ 78 | 79 | protected function load_recursive($classpath, $classname) : bool{ 80 | $ret = false; 81 | if ($handle = opendir($classpath)) { 82 | while (false != ($file = readdir($handle))) { 83 | if ($file != "." && $file != "..") { 84 | if(is_dir($classpath . $file)){ 85 | $this->load_recursive($classpath . $file . "/", $classname); 86 | }else{ 87 | if($file == "class.$classname.php"){ 88 | include_once $classpath . $file; 89 | $this->printClass($classpath, $file); 90 | $ret = true; 91 | }else 92 | if($file == "class.Boolean.$classname.php"){ 93 | include_once $classpath . $file; 94 | $this->printClass($classpath, $file); 95 | $ret = true; 96 | }else 97 | if($file == "interface.$classname.php"){ 98 | include_once $classpath . $file; 99 | $this->printClass($classpath, $file); 100 | $ret = true; 101 | } 102 | } 103 | } 104 | } 105 | closedir($handle); 106 | unset($handle); 107 | } 108 | return $ret; 109 | } 110 | 111 | protected function printClass($classpath, $file) : void{ 112 | if(strpos($classpath, ROOT) === 0){ 113 | $classpath = substr($classpath, strlen(ROOT)); 114 | echo "include_once(ROOT . \"" . $classpath . $file . "\");\n"; 115 | }else{ 116 | echo "include_once(\"" . $classpath . $file . "\");\n"; 117 | } 118 | } 119 | } 120 | 121 | 122 | function milestone_autoload($classname){ 123 | global $classLoader; 124 | // global $control; 125 | // $str = "classname: "; 126 | // $str .= $classname; 127 | // $str .= "\n"; 128 | // if(is_object($control) && !is_int(stripos($classname, "mysql"))){ 129 | // $control->getModel()->getLogger()->log($control->getModel(), ALogger::$HIGH, $str); 130 | // } 131 | try{ 132 | $classLoader->load($classname); 133 | // $str .= ":" . $ok; 134 | // if(is_object($control) && !is_int(stripos($classname, "mysql"))){ 135 | // $control->getModel()->getLogger()->log($control->getModel(), ALogger::$HIGH, $str); 136 | // } 137 | }catch(Exception $e){ 138 | /** @noinspection ForgottenDebugOutputInspection */ 139 | error_log($e->getMessage()); 140 | // $model->getLogger()->log($model, ALogger::$HIGH, print_r($e, true)); 141 | } 142 | } 143 | 144 | spl_autoload_register('milestone_autoload'); 145 | 146 | $classLoader = new ClassLoader(); 147 | --------------------------------------------------------------------------------