Файл: system/controllers/admin/actions/settings_check_nested.php
Строк: 113
<?php
class actionAdminSettingsCheckNested extends cmsAction {
public function run() {
$db_nested_tables = cmsEventsManager::hookAll('db_nested_tables');
$form = new cmsForm();
$successful = [];
$unsuccessful = [];
if($db_nested_tables){
foreach ($db_nested_tables as $name => $tables) {
$controller_title = string_lang('LANG_'.$name.'_CONTROLLER');
$fieldset_id = $form->addFieldset($controller_title);
foreach ($tables as $table_name => $title) {
$has_errors = $this->checkNestedSet($table_name);
if($has_errors){
$form->addField($fieldset_id,
new fieldCheckbox($table_name, array(
'title' => $title.' => '.$table_name,
'default' => 1
)
)
);
$unsuccessful[$table_name] = $table_name;
} else {
$successful[$table_name] = $controller_title.': '.$title;
}
}
}
}
if($unsuccessful && $this->request->has('submit')){
$repair_tables = $form->parse($this->request, true);
$errors = $form->validate($this, $repair_tables);
if (!$errors){
foreach ($repair_tables as $tname => $is_repair) {
if($is_repair && isset($unsuccessful[$tname])){
if($this->repairNestedSet($tname) !== false){
cmsUser::addSessionMessage(sprintf(LANG_CP_NS_FIX_SUCCESS, $tname), 'success');
} else {
cmsUser::addSessionMessage(sprintf(LANG_CP_NS_FIX_ERROR, $tname), 'error');
}
}
}
$this->redirectToAction('settings/check_nested');
}
if ($errors){
cmsUser::addSessionMessage(LANG_FORM_ERRORS, 'error');
}
}
return $this->cms_template->render('settings_check_nested', array(
'nested_tables_exists' => boolval($db_nested_tables),
'successful' => $successful,
'unsuccessful' => $unsuccessful,
'form' => $form
));
}
private function repairNestedSet($table, $i_value = 1, $k_parent = 0, $lvl = 0) {
$db = $this->model->db;
if (!is_numeric($k_parent) || !is_numeric($i_value)) {
return false;
}
$r = $db->query("SELECT `id` FROM {#}{$table} WHERE `parent_id` = '{$k_parent}' ORDER BY `ns_left` asc, `ordering` asc", false, true);
if (!$r) {
return false;
}
$o = 1;
while ($f = $db->fetchAssoc($r)) {
$k_item = $f['id'];
$i_right = $this->repairNestedSet($table, $i_value + 1, $k_item, $lvl + 1);
if ($i_right === false) {
return false;
}
if (!$db->query("UPDATE {#}{$table} SET `ns_left` = '{$i_value}', `ns_right` = '{$i_right}', `ordering` = '".$o++."', `ns_level` = '{$lvl}' where `id` = '{$k_item}'", false, true)) {
return false;
}
$i_value = $i_right + 1;
}
return $i_value;
}
private function checkNestedSet($table, $differ = '') {
$errors = [];
$db = $this->model->db;
$differ = $db->escape($differ);
// Шаг 1
$sql = "SELECT id FROM {#}{$table} WHERE `ns_left` >= `ns_right` AND `ns_differ` = '{$differ}'";
$result = $db->query($sql, false, true);
if ($result !== false) {
$errors[1] = $db->numRows($result) > 0;
} else {
$errors[1] = true;
}
// Шаг 2 и 3
$sql = "SELECT COUNT(`id`) as rows_count, MIN(`ns_left`) as min_left, MAX(`ns_right`) as max_right FROM {#}{$table} WHERE `ns_differ` = '{$differ}'";
$result = $db->query($sql);
if ($result !== false) {
$data = $db->fetchAssoc($result);
$errors[2] = $data['min_left'] != 1;
$errors[3] = $data['max_right'] != 2 * $data['rows_count'];
} else {
$errors[2] = true;
}
// Шаг 4
$sql = "SELECT `id`, `ns_right`, `ns_left`
FROM {#}{$table}
WHERE MOD((`ns_right`-`ns_left`), 2) = 0 AND `ns_differ` = '{$differ}'";
$result = $db->query($sql, false, true);
if ($result !== false) {
$errors[4] = $db->numRows($result) > 0;
} else {
$errors[4] = true;
}
// Шаг 5
$sql = "SELECT `id`
FROM {#}{$table}
WHERE MOD((`ns_left`-`ns_level`+2), 2) = 0 AND `ns_differ` = '$differ'";
$result = $db->query($sql, false, true);
if ($result !== false) {
$errors[5] = $db->numRows($result) > 0;
} else {
$errors[5] = true;
}
// Шаг 6
$sql = "SELECT t1.id,
COUNT(t1.id) AS rep,
MAX(t3.ns_right) AS max_right
FROM {#}{$table} AS t1, {#}{$table} AS t2, {#}{$table} AS t3
WHERE t1.ns_left <> t2.ns_left AND t1.ns_left <> t2.ns_right AND t1.ns_right <> t2.ns_left AND t1.ns_right <> t2.ns_right
AND t1.ns_differ = '{$differ}' AND t2.ns_differ = '{$differ}' AND t3.ns_differ = '{$differ}'
GROUP BY t1.id
HAVING max_right <> SQRT(4 * rep + 1) + 1";
$result = $db->query($sql, false, true);
if ($result !== false) {
$errors[6] = $db->numRows($result) > 0;
} else {
$errors[6] = true;
}
return in_array(true, $errors);
}
}