<?php
/**
    * @file func.site_tree.php
    * @brief Функции для работы с деревом сайта: получение, сохранение и обработка структуры, а также получение списка папок
*/

/**
    * @brief Получает структуру дерева сайта из XML-файла для текущего языка
    * @param array $params Не используется, но требуется для совместимости
    * @return array Массив с элементами дерева сайта, включая дочерние элементы и атрибуты
    * @throws Exception Если не удалось прочитать или разобрать XML-файл, или структура не сгенерирована
*/
function getSiteTree($params) {
    global $path, $_SESSION;

    $file = $path . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'filepath.' . $_SESSION['lng'] . '.php';
    $content = file_get_contents($file);
    $xml = simplexml_load_string($content);
    if (!$xml) {
        throw new Exception("Problem with file", -32004);
    }

    function generateArray($xml, $urlParts = []) {
        $result = [];
        $anyOpen = false;

        foreach ($xml->children() as $child) {
            $item = [
                'name' => (string) $child->attributes()->name,
                'tag' => $child->getName(),
                'children' => generateArray($child, $urlParts),
                'isOpen' => false,

                'url' => (string) $child->attributes()->url,
                'title' => (string) $child->attributes()->title,
                'template' => (string) $child->attributes()->template,
                'PageMenu' => (string) $child->attributes()->PageMenu,
                'users' => (string) $child->attributes()->users,
                'group' => (string) $child->attributes()->group,
                'news' => (string) $child->attributes()->news,
                'plugins' => (string) $child->attributes()->plugins,

                'content' => (string)$child
            ];

            if (!empty($urlParts) && $urlParts[0] == $item['tag']) {
                array_shift($urlParts);
                if (empty($urlParts)) {
                    if ($item['tag'] !== 'index') {
                        $item['isOpen'] = true;
                        $anyOpen = true;
                    }
                }
            }

            foreach ($item['children'] as $childItem) {
                if (!empty($childItem['isOpen'])) {
                    $item['isOpen'] = true;
                    $anyOpen = true;
                    break;
                }
            }

            $result[] = $item;
        }

        if (!$anyOpen) {
            foreach ($result as &$item) {
                if ($item['tag'] === 'index') {
                    $item['isOpen'] = true;
                    break;
                }
            }
        } else {
            foreach ($result as &$item) {
                if ($item['tag'] === 'index') {
                    $item['isOpen'] = false;
                }
            }
        }

        return $result;
    }

    $url = $_SERVER['REQUEST_URI'];
    $urlParts = array_filter(explode('/', trim($url, '/')));
    $urlParts = array_map(function($part) {
        return pathinfo($part, PATHINFO_FILENAME);
    }, $urlParts);

    $result = generateArray($xml, $urlParts);
    if (!is_array($result)) {
        throw new Exception("Failed to generate structure", -32003);
    }

    return $result;
}

/**
    * @brief Сохраняет структуру дерева сайта в XML-файл для текущего языка
    * @param array $params Массив с ключом 'data', содержащий структуру сайта
    * @return string "true" при успешном сохранении
    * @throws Exception Если не удалось сохранить файл или файл пустой
*/
function saveSiteTree($params) {
	global $path, $_SESSION;

	$file = $path . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'filepath.' . $_SESSION['lng'] . '.php';

	$treeData = isset($params['data']) ? $params['data'] : [];
	$siteName = isset($treeData['sitename']) ? htmlspecialchars($treeData['sitename'], ENT_XML1 | ENT_QUOTES, 'UTF-8') : '';
	$slogan = isset($treeData['slogan']) ? htmlspecialchars($treeData['slogan'], ENT_XML1 | ENT_QUOTES, 'UTF-8') : '';

	$xmlContent = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".
	"<site>\n".
	"    <sitename>$siteName</sitename>\n".
	"    <slogan>$slogan</slogan>\n".
	buildSiteTreeXml($treeData['children']).
	"</site>\n";

	$ok = file_put_contents($file, $xmlContent);

	if ($ok === false || !is_file($file) || !filesize($file)) {
		throw new Exception("Failed to save file", -32004);
	}

	return 'true';
}

/**
    * @brief Рекурсивно строит XML для структуры сайта
    * @param array $data Массив с элементами дерева сайта
    * @param int $level Уровень вложенности для отступов
    * @return string Строка XML, представляющая элементы дерева
*/
function buildSiteTreeXml($data, $level = 1) {
    $xml = "";
    foreach ($data as $item) {
        if (!isset($item['name']) || empty($item['name'])) continue;

        $tag = htmlspecialchars(trim(explode(' ', $item['name'])[0]), ENT_XML1 | ENT_QUOTES, 'UTF-8');
        $nameAttr = htmlspecialchars(trim($tag), ENT_XML1 | ENT_QUOTES, 'UTF-8');

        $attributes = [
            'url'      => isset($item['url'])      ? htmlspecialchars($item['url'],      ENT_XML1 | ENT_QUOTES, 'UTF-8') : '',
            'title'    => isset($item['title'])    ? htmlspecialchars($item['title'],    ENT_XML1 | ENT_QUOTES, 'UTF-8') : '',
            'name'     => $nameAttr,
            'template' => isset($item['template']) ? htmlspecialchars($item['template'], ENT_XML1 | ENT_QUOTES, 'UTF-8') : '',
            'PageMenu' => isset($item['PageMenu']) ? htmlspecialchars($item['PageMenu'], ENT_XML1 | ENT_QUOTES, 'UTF-8') : '',
            'users'    => isset($item['users'])    ? htmlspecialchars($item['users'],    ENT_XML1 | ENT_QUOTES, 'UTF-8') : '',
            'group'    => isset($item['group'])    ? htmlspecialchars($item['group'],    ENT_XML1 | ENT_QUOTES, 'UTF-8') : '',
            'news'     => isset($item['news'])     ? htmlspecialchars($item['news'],     ENT_XML1 | ENT_QUOTES, 'UTF-8') : '',
            'plugins'     => isset($item['plugins'])     ? htmlspecialchars($item['plugins'],     ENT_XML1 | ENT_QUOTES, 'UTF-8') : ''
        ];

        $attrString = "";
        foreach ($attributes as $key => $value) {
            $attrString .= " $key='$value'";
        }

        $xml .= str_repeat("    ", $level) . "<$tag$attrString>\n";
        if (!empty($item['children'])) {
            $xml .= buildSiteTreeXml($item['children'], $level + 1);
        }
        $xml .= str_repeat("    ", $level) . "</$tag>\n";
    }
    return $xml;
}

/**
    * @brief Получает список папок внутри указанной директории
    * @param array $params Массив с ключом 'folder', указывающим путь к директории
    * @return array Массив с именами папок
    * @throws Exception Если директория недействительна или невозможно прочитать содержимое
*/
function getFolders($params) {
	global $path;
	$folder = $path . DIRECTORY_SEPARATOR . $params['folder'];
	$folders = [];
	$ok = true;

	if (!is_dir($folder)) {
		$ok = false;
	} else {
		$files = scandir($folder);
		if ($files === false) {
			$ok = false;
		} else {
			foreach ($files as $file) {
				if ($file != '.' && $file != '..' && is_dir($folder . DIRECTORY_SEPARATOR . $file)) {
					$folders[] = $file;
				}
			}
		}
	}

	if (!$ok) {
		throw new Exception("Failed to read folder list", -32004);
	}
	return $folders;
}

?>
