raw = mysqli_connect(getenv('MYSQL_HOST'), getenv('MYSQL_USER'), getenv('MYSQL_PASSWORD'), getenv('MYSQL_DATABASE')); } else { $this->raw = mysqli_connect($db_params['MYSQL_HOST'], $db_params['MYSQL_USER'], $db_params['MYSQL_PASSWORD'], $db_params['MYSQL_DATABASE']); } $this->data_directory = 'raw'; if (!$this->raw) { echo 'Connection failed
'; echo 'Error number: ' . mysqli_connect_errno() . '
'; echo 'Error message: ' . mysqli_connect_error() . '
'; die(); } } function _exec($qery, $argtypes, ...$args) { $stmt = $this->raw->prepare($qery); $stmt->bind_param($argtypes, ...$args); $stmt->execute(); return $stmt->get_result(); } function _prepare_post_data($post_data) { if($post_data == null) { return [ "found" => false ]; } $post_data["found"] = true; $post_data["post_basename"] = basename($post_data["post_path"]); $post_meta = json_decode($post_data["post_metadata"], true) ?? []; $post_meta["title"] ??= basename($post_data["post_path"]); if(!isset($post_meta['type'])) { $type = null; $ext = pathinfo($post_data['post_basename'], PATHINFO_EXTENSION); if($ext == '') { $type = 'directory'; } elseif($ext == 'md') { $type = 'text/markdown'; } $post_meta['type'] = $type; } $post_data["post_content"] ??= ''; $post_data["post_file_dir"] = '/' . $this->data_directory . $post_data["post_path"]; $post_data['post_metadata'] = $post_meta; return $post_data; } function _fill_post_descriptors($post_data) { switch(($post_data['post_metadata']['type'] ?? '')) { case 'directory': $readme = $this->get_post_by_path($post_data['post_path'] . '/README.md', false); $post_data['readme'] = $readme; if($readme['found']) { $post_data['post_metadata']['title'] = $readme['post_metadata']['title']; } break; case 'file': $post_data['descriptor'] = $this->get_post_by_path($post_data['post_path'] . '.md', false); break; } return $post_data; } function ensure_directory($directory) { $data_directory = $this->data_directory . $directory; is_dir($data_directory) || mkdir($data_directory, 0777, true); $insert_statement = " INSERT INTO posts (post_path, post_path_depth, post_metadata, post_content) VALUES (?, ?, ?, '') AS new ON DUPLICATE KEY UPDATE post_path=new.post_path "; $json_metadata = json_encode(["type" => 'directory']); while(strlen($directory) > 1) { try { echo "Inserting dir " . $directory . "\n"; $this->_exec($insert_statement, "sis", $directory, substr_count($directory, '/'), $json_metadata); } catch(Exception $e) { } $directory = dirname($directory); } } function ensure_post_placeholder($post_path, $post_metadata) { $post_path = chop($post_path, '/'); $path_depth = substr_count($post_path, "/"); $this->ensure_directory(dirname($post_path)); echo "Bumping post placeholder " . $post_path . "\n"; $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 create_post_entry($post_path, $post_metadata, $post_content) { $post_path = chop($post_path, '/'); $path_depth = substr_count($post_path, "/"); $this->ensure_directory(dirname($post_path)); echo "Creating post entry " . $post_path . "\n"; $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 save_markdown_post($post_path, $post_data) { $frontmatter_post = YamlFrontMatter::parse($post_data); $post_path = chop($post_path, '/'); $post_content = $frontmatter_post->body(); $post_metadata = $frontmatter_post->matter(); if(basename($post_path) == "README.md") { $readme_metadata = $frontmatter_post->matter(); $readme_metadata['type'] = $post_metadata['readme_type'] ?? 'directory'; $this->create_post_entry(dirname($post_path), $readme_metadata, ''); $post_metadata['type'] = 'text/markdown'; } $post_metadata['type'] ??= 'text/markdown'; $this->create_post_entry($post_path, $post_metadata, $post_content); file_put_contents($this->data_directory . $post_path, $post_data); } function save_file($post_path, $file_path) { $post_metadata = ["type" => 'file']; $post_path = chop($post_path, '/'); $this->ensure_post_placeholder($post_path, $post_metadata, ''); copy($file_path, $this->data_directory . $post_path); } function handle_upload($post_path, $file_path) { $ext = pathinfo($post_path, PATHINFO_EXTENSION); switch($ext) { case "md": $this->save_markdown_post($post_path, file_get_contents($file_path)); break; default: $this->save_file($post_path, $file_path); } } function get_post_by_path($post_path, $with_subposts = true) { $qry = "SELECT * FROM posts WHERE post_path = ?"; $post_path = chop($post_path, '/'); $post_data = $this->_exec($qry, "s", $post_path)->fetch_assoc(); $post_data = $this->_prepare_post_data($post_data); $post_data = $this->_fill_post_descriptors($post_data); if($with_subposts) { $post_data['subposts'] = $this->get_subposts_by_path($post_path); } return $post_data; } function get_subposts_by_path($path) { global $sql; $path = chop($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->_prepare_post_data($data); }; $post_data = array_map($fn, $post_data); return $post_data; } } ?>