1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
<?php
namespace Studip\Cli\Commands\Fix;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/**
* For example
*
* php cli/studip fix:biest-7789 extern_config config
* php cli/studip fix:biest-7789 aux_lock_rules attributes
* php cli/studip fix:biest-7789 aux_lock_rules sorting
* php cli/studip fix:biest-7789 user_config value "field = 'MY_COURSES_ADMIN_VIEW_FILTER_ARGS'"
* php cli/studip fix:biest-7789 mail_queue_entries mail
*/
class Biest7789 extends Command
{
protected static $defaultName = 'fix:biest-7789';
protected function configure(): void
{
$this->setDescription('Fix Biest #7789');
$this->addArgument('table', InputArgument::REQUIRED, 'database table');
$this->addArgument('column', InputArgument::REQUIRED, 'table column');
$this->addArgument('where', InputArgument::OPTIONAL, 'where clause');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
ini_set('default_charset', 'utf-8');
$io = new SymfonyStyle($input, $output);
$table = $input->getArgument('table');
$column = $input->getArgument('column');
$where = $input->getArgument('where');
$db = \DBManager::get();
$io->title($table);
// get primary keys
$result = $db->query("SHOW KEYS FROM $table WHERE Key_name = 'PRIMARY'");
$keys = [];
while ($data = $result->fetch(\PDO::FETCH_ASSOC)) {
$keys[] = $data['Column_name'];
}
// retrieve and convert data
$result = $db->query(
'SELECT `' . implode('`,`', $keys) . "`, `$column` FROM `$table` WHERE " . ($where ?: '1')
);
while ($data = $result->fetch(\PDO::FETCH_ASSOC)) {
$content = unserialize(\legacy_studip_utf8decode($data[$column]));
if ($content === false) {
// try to fix string length denotations
$fixed = preg_replace_callback(
'/s:([0-9]+):\"(.*?)\";/s',
function ($matches) {
return 's:' . strlen($matches[2]) . ':"' . $matches[2] . '";';
},
$data[$column]
);
$content = unserialize(\legacy_studip_utf8decode($fixed));
}
if ($content !== false) {
// encode all data
$json = json_encode($this->legacy_studip_utf8encode($content), true);
$query = "UPDATE `$table` SET `$column` = " . $db->quote($json) . "\n WHERE ";
$where_query = [];
foreach ($keys as $key) {
$where_query[] = "`$key` = " . $db->quote($data[$key]);
}
$q = $query . implode(' AND ', $where_query);
$db->exec($q);
$io->writeln("<info>$q</info>");
} else {
$io->writeln(sprintf('<error>Could not convert: %s</error>', print_r($data, 1)));
}
}
return Command::SUCCESS;
}
private function legacy_studip_utf8encode($data)
{
if (is_array($data)) {
$new_data = [];
foreach ($data as $key => $value) {
$key = $this->legacy_studip_utf8encode($key);
$new_data[$key] = $this->legacy_studip_utf8encode($value);
}
return $new_data;
}
if (!\preg_match('/[\200-\377]/', $data) && !\preg_match("'&#[0-9]+;'", $data)) {
return $data;
} else {
return \mb_decode_numericentity(
\mb_convert_encoding($data, 'UTF-8', 'WINDOWS-1252'),
[0x100, 0xffff, 0, 0xffff],
'UTF-8'
);
}
}
}
|