raw = mysqli_connect(getenv('MYSQL_HOST'),
getenv('MYSQL_USER'), getenv('MYSQL_PASSWORD'),
getenv('MYSQL_DATABASE'),
getenv('MYSQL_PORT'));
}
else {
$this->raw = mysqli_connect($db_params['MYSQL_HOST'],
$db_params['MYSQL_USER'], $db_params['MYSQL_PASSWORD'],
$db_params['MYSQL_DATABASE'],
$db_params['MYSQL_PORT']);
}
} catch (\Throwable $th) {
echo 'Connection failed
';
echo 'Error number: ' . mysqli_connect_errno() . '
';
echo 'Error message: ' . mysqli_connect_error() . '
';
die();
//throw $th;
}
}
function _sanitize_path($post_path) {
$post_path = chop($post_path, '/');
if($post_path == "") {
return "";
}
if(!preg_match('/^(?:\/[\w-]+)+(?:\.[\w-]+)*$/', $post_path)) {
echo "Post path match against " . $post_path . " failed!";
die();
}
return $post_path;
}
function _exec($qery, $argtypes, ...$args) {
$stmt = $this->raw->prepare($qery);
$stmt->bind_param($argtypes, ...$args);
$stmt->execute();
return $stmt->get_result();
}
function _normalize_post_data($post_data) {
if($post_data == null) {
return [
"found" => false
];
}
$post_data["found"] = true;
$post_data['post_metadata'] = json_decode($post_data["post_metadata"], true) ?? [];
$post_data["post_content"] ??= '';
return $post_data;
}
function bump_post($post_path, $post_metadata = [], $create_dirs = true) {
$post_path = $this->_sanitize_path($post_path);
$path_depth = substr_count($post_path, "/");
if($create_dirs) {
$this->make_post_directory(dirname($post_path));
}
$qry = "
INSERT INTO posts
(post_path, post_path_depth, post_metadata, post_content)
VALUES
( ?, ?, ?, ?) AS new
ON DUPLICATE KEY UPDATE post_path=new.post_path;";
$this->_exec($qry, "siss",
$post_path,
$path_depth,
json_encode($post_metadata),
'');
}
function make_post_directory($directory) {
$json_metadata = ["type" => 'directory'];
while(strlen($directory) > 1) {
try {
$this->bump_post($directory, $json_metadata, false);
}
catch(Exception $e) {
}
$directory = dirname($directory);
}
}
function log_post_access($post_path, $agent, $time) {
$qry = "
INSERT INTO path_access_counts
(post_path, agent,
path_access_count,
path_processing_time)
VALUES ( ?, ?, 1, ? ) AS new
ON DUPLICATE KEY
UPDATE path_access_count=path_access_counts.path_access_count+1,
path_processing_time=path_access_counts.path_processing_time+new.path_processing_time;
";
$this->_exec($qry, "ssd", $post_path, $agent, $time);
}
function get_post_access_counters() {
$qry = "
SELECT post_path, agent, path_access_count, path_processing_time
FROM path_access_counts
WHERE path_last_access_time > ( CURRENT_TIMESTAMP - INTERVAL 10 MINUTE );
";
$data = $this->_exec($qry, "")->fetch_all(MYSQLI_ASSOC);
$out_data = [];
foreach($data AS $post_data) {
$path = $post_data['post_path'];
$agent_data = ($out_data[$path] ?? []);
$agent_data[$post_data['agent']] = [
'count' => $post_data['path_access_count'],
'time' => round($post_data['path_processing_time'], 6)
];
$out_data[$path] = $agent_data;
}
return $out_data;
}
function update_or_create_post($post_path, $post_metadata, $post_content) {
$post_path = $this->_sanitize_path($post_path);
$path_depth = substr_count($post_path, "/");
$this->make_post_directory(dirname($post_path));
$qry = "
INSERT INTO posts
(post_path, post_path_depth, post_metadata, post_content)
VALUES
( ?, ?, ?, ?) AS new
ON DUPLICATE KEY UPDATE post_metadata=new.post_metadata, post_content=new.post_content;";
$this->_exec($qry, "siss",
$post_path,
$path_depth,
json_encode($post_metadata),
$post_content);
}
function get_settings_for_path($post_path) {
$post_path = $this->_sanitize_path($post_path);
$qry = "
WITH RECURSIVE settings_data (post_path, post_depth, json_settings) AS (
SELECT post_path, post_path_depth, post_metadata
FROM posts
WHERE post_path = ?
UNION ALL
SELECT posts.post_path, posts.post_path_depth, posts.post_metadata
FROM posts, settings_data
WHERE posts.post_path = SUBSTRING_INDEX(settings_data.post_path, '/', settings_data.post_depth)
AND posts.post_path_depth = settings_data.post_depth - 1
)
SELECT post_depth, json_settings
FROM settings_data
ORDER BY post_depth ASC;
";
$out_settings = [];
$settings_list = $this->_exec($qry, "s", $post_path)->fetch_all(MYSQLI_ASSOC);
foreach($settings_list AS $setting) {
$setting = json_decode($setting['json_settings'], true);
if(!isset($setting) || !isset($setting['settings'])) {
continue;
}
$out_settings = array_merge($out_settings, $setting['settings']);
}
return $out_settings;
}
function get_post_by_path($post_path,
$with_subposts = false, $with_settings = true) {
$qry = "SELECT * FROM posts WHERE post_path = ?";
$post_path = $this->_sanitize_path($post_path);
$post_data = $this->_exec($qry, "s", $post_path)->fetch_assoc();
$post_data = $this->_normalize_post_data($post_data);
$post_data['post_path'] = $post_path;
if(!$post_data['found']) {
return $post_data;
}
if($with_subposts) {
$post_data['subposts'] = $this->get_subposts_by_path($post_path);
}
if($with_settings) {
$post_data['settings'] = $this->get_settings_for_path($post_path);
}
return $post_data;
}
function get_subposts_by_path($path) {
global $sql;
$path = $this->_sanitize_path($path);
$path_depth = substr_count($path, "/");
$qry = "SELECT post_path, post_metadata, post_update_time
FROM posts
WHERE (post_path LIKE CONCAT(?,'/%'))
AND post_path_depth = ?
ORDER BY post_create_time DESC
LIMIT 10";
$post_data = $this->_exec($qry, "si", $path, $path_depth+1)->fetch_all(MYSQLI_ASSOC);
$fn = function($data) {
return $this->_normalize_post_data($data);
};
$post_data = array_map($fn, $post_data);
return $post_data;
}
}
?>