diff options
author | Freya Murphy <freya@freyacat.org> | 2024-05-24 09:05:42 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2024-05-24 09:05:42 -0400 |
commit | c5f39ea2cd7cf02246705ea8872d3b350526165c (patch) | |
tree | 2694f9fdc5d83b529a01f2997c1d89c271c86592 /src/web/helpers | |
download | website-c5f39ea2cd7cf02246705ea8872d3b350526165c.tar.gz website-c5f39ea2cd7cf02246705ea8872d3b350526165c.tar.bz2 website-c5f39ea2cd7cf02246705ea8872d3b350526165c.zip |
initial
Diffstat (limited to 'src/web/helpers')
-rw-r--r-- | src/web/helpers/aria.php | 16 | ||||
-rw-r--r-- | src/web/helpers/database.php | 282 | ||||
-rw-r--r-- | src/web/helpers/image.php | 94 | ||||
-rw-r--r-- | src/web/helpers/lang.php | 79 | ||||
-rw-r--r-- | src/web/helpers/markdown.php | 33 | ||||
-rw-r--r-- | src/web/helpers/sanitize.php | 8 |
6 files changed, 512 insertions, 0 deletions
diff --git a/src/web/helpers/aria.php b/src/web/helpers/aria.php new file mode 100644 index 0000000..8ebfcc5 --- /dev/null +++ b/src/web/helpers/aria.php @@ -0,0 +1,16 @@ +<?php /* Copyright (c) 2024 Freya Murphy */ + +function aria_section($id, $title = NULL): string { + $out = ''; + if ($title) { + $idh = $id . '_heading'; + $out .= sprintf('<div id="%s" class="section" role="region" aria-labelledby="%s">', + $id, $idh); + $out .= sprintf('<h2 class="heading" id="%s">%s</h2>', + $idh, $title); + } else { + $out .= sprintf('<div id="%s" class="section" role="region">', + $id); + } + return $out; +} diff --git a/src/web/helpers/database.php b/src/web/helpers/database.php new file mode 100644 index 0000000..25cb5ba --- /dev/null +++ b/src/web/helpers/database.php @@ -0,0 +1,282 @@ +<?php /* Copyright (c) 2024 Freya Murphy */ + +class DatabaseQuery { + + private $conn; + private $query; + + private $where; + private $set; + + private $param; + + function __construct($conn) { + $this->conn = $conn; + $this->query = ''; + + $this->set = FALSE; + $this->where = FALSE; + $this->param = array(); + } + + /// + /// ARBITRARY QUERY + /// + + public function query($query) { + $this->query .= $query; + return $this; + } + + /// + /// SELECT + /// + + public function select($select) { + $this->query .= "SELECT $select\n"; + return $this; + } + + public function from($from) { + $this->query .= "FROM $from\n"; + return $this; + } + + /// + /// INSERT + /// + + public function insert_into($insert, ...$columns) { + $this->query .= "INSERT INTO $insert\n ("; + foreach ($columns as $idx => $column) { + if ($idx !== 0) { + $this->query .= ","; + } + $this->query .= $column; + } + $this->query .= ")\n"; + return $this; + } + + public function values(...$values) { + $this->query .= "VALUES ("; + foreach ($values as $idx => $value) { + if ($idx !== 0) { + $this->query .= ","; + } + $this->query .= "?"; + array_push($this->param, $value); + } + $this->query .= ")\n"; + return $this; + } + + /// + /// WHERE + /// + + public function where($cond) { + if (!$this->where) { + $this->where = TRUE; + $this->query .= "WHERE "; + } else { + $this->query .= "AND "; + } + $this->query .= "$cond "; + return $this; + } + + public function where_in($column, $array) { + if (!$this->where) { + $this->where = TRUE; + $this->query .= "WHERE "; + } else { + $this->query .= "AND "; + } + if (empty($array)) { + $this->query .= "FALSE\n"; + return $this; + } + $in = $this->in($array); + $this->query .= "$column $in\n"; + return $this; + } + + private function in($array) { + $in = 'IN ('; + foreach ($array as $idx => $item) { + if ($idx != 0) { + $in .= ","; + } + $in .= "?"; + array_push($this->param, $item); + } + $in .= ")"; + return $in; + } + + /// + /// OPERATORS + /// + + public function like($item) { + $this->query .= "LIKE ?\n"; + array_push($this->param, $item); + return $this; + } + + public function eq($item) { + $this->query .= "= ?\n"; + array_push($this->param, $item); + return $this; + } + + public function ne($item) { + $this->query .= "<> ?\n"; + array_push($this->param, $item); + return $this; + } + + public function lt($item) { + $this->query .= "< ?\n"; + array_push($this->param, $item); + return $this; + } + + public function le($item) { + $this->query .= "<= ?\n"; + array_push($this->param, $item); + return $this; + } + + /// + /// JOINS + /// + + public function join($table, $on, $type = 'LEFT') { + $this->query .= "$type JOIN $table ON $on\n"; + return $this; + } + + /// + /// LIMIT, OFFSET, ORDER + /// + + public function limit($limit) { + $this->query .= "LIMIT ?\n"; + array_push($this->param, $limit); + return $this; + } + + public function offset($offset) { + $this->query .= "OFFSET ?\n"; + array_push($this->param, $offset); + return $this; + } + + public function order_by($column, $order = 'ASC') { + $this->query .= "ORDER BY " . $column . ' ' . $order . ' '; + return $this; + } + + /// + /// COLLECT + /// + + public function rows(...$params) { + $args = $this->param; + foreach ($params as $param) { + array_push($args, $param); + } + $stmt = $this->conn->prepare($this->query); + try { + $stmt->execute($args); + } catch (Exception $ex) { + echo $ex; + echo '<br> >> caused by <<<br>'; + echo str_replace("\n", "<br>", $this->query); + } + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + public function row(...$params) { + $args = $this->param; + foreach ($params as $param) { + array_push($args, $param); + } + $stmt = $this->conn->prepare($this->query); + $stmt->execute($args); + return $stmt->fetch(PDO::FETCH_ASSOC); + } + + public function execute(...$params) { + $args = $this->param; + foreach ($params as $param) { + array_push($args, $param); + } + $stmt = $this->conn->prepare($this->query); + try { + $stmt->execute($args); + return TRUE; + } catch (Exception $_e) { + echo $_e; + echo '<br> >> caused by <<<br>'; + echo str_replace("\n", "<br>", $this->query); + return FALSE; + } + } +} + +/** + * DatabaseHelper + * allows queries on the + * postgres database + */ +class DatabaseHelper { + + private $conn; + + function __construct() { + $this->conn = NULL; + } + + private function connect() { + if ($this->conn === NULL) { + $user = getenv("POSTGRES_USER"); + $pass = getenv("POSTGRES_PASSWORD"); + $db = getenv("POSTGRES_DB"); + $host = 'db'; + $port = '5432'; + + $conn_str = sprintf("pgsql:host=%s;port=%d;dbname=%s;user=%s;password=%s", + $host, + $port, + $db, + $user, + $pass + ); + $this->conn = new \PDO($conn_str); + $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + } + return $this->conn; + } + + public function select($select) { + $conn = $this->connect(); + $query = new DatabaseQuery($conn); + return $query->select($select); + } + + public function insert_into($insert, ...$columns) { + $conn = $this->connect(); + $query = new DatabaseQuery($conn); + return $query->insert_into($insert, ...$columns); + } + + public function query($query_str) { + $conn = $this->connect(); + $query = new DatabaseQuery($conn); + return $query->query($query_str); + } +} + diff --git a/src/web/helpers/image.php b/src/web/helpers/image.php new file mode 100644 index 0000000..c18154a --- /dev/null +++ b/src/web/helpers/image.php @@ -0,0 +1,94 @@ +<?php /* Copyright (c) 2024 Freya Murphy */ + +function __get_mime($type) { + switch ($type) { + case 'mp4': + return 'video/mp4'; + case 'webm': + return 'video/webm'; + case 'gif': + return 'image/gif'; + case 'png': + return 'image/png'; + case 'jpg': + return 'image/jpeg'; + case 'webp': + return 'image/webp'; + default: + return NULL; + } +} + +function __make_source( + $name, + $format, + $media +) { + if ($media) { + $media = "media=\"$media\""; + } else { + $media = ''; + } + $main = $GLOBALS['main_model']; + $path = $main->get_url('public/' . $name . '.' . $format); + $mime = __get_mime($format); + return sprintf('<source type="%s" srcset="%s" %s>', + $mime, $path, $media); +} + +function image( + $name, + $alt, + $formats = array('webp', 'png'), + $animated = FALSE, + $attrs = array(), + + $height = NULL, + $width = NULL, + $size = NULL, +) :string { + + if ($animated === TRUE) { + $animated = array('gif'); + } + + if (!$animated) { + $animated = array(); + } + + $out = "<picture>"; + + foreach ($formats as $format) { + $media = count($animated) ? '(prefers-reduced-motion: reduce)' : NULL; + $out .= __make_source($name, $format, $media); + } + + foreach ($animated as $format) { + $out .= __make_source($name, $format, NULL); + } + + $format = end($formats); + $main = $GLOBALS['main_model']; + $path = $main->get_url('public/' . $name . '.' . $format); + $out .= "<img src=\"$path\""; + if ($alt) { + $alt = lang($alt); + $attrs['alt'] = $alt; + } + if ($width) { + $attrs['width'] = $width; + } + if ($height) { + $attrs['height'] = $height; + } + if ($size) { + $attrs['width'] = $size; + $attrs['height'] = $size; + } + foreach ($attrs as $key => $value) { + $out .= " $key=\"$value\""; + } + $out .= '></picture>'; + + return $out; +} diff --git a/src/web/helpers/lang.php b/src/web/helpers/lang.php new file mode 100644 index 0000000..e8fa29e --- /dev/null +++ b/src/web/helpers/lang.php @@ -0,0 +1,79 @@ +<?php /* Copyright (c) 2024 Freya Murphy */ +$lang = array(); + +function lang($key, $default = NULL, $sub = NULL) { + $lang = $GLOBALS['lang']; + if(array_key_exists($key, $lang)) { + if ($sub) { + return sprintf($lang[$key], ...$sub); + } else { + return $lang[$key]; + } + } else if ($default !== NULL) { + return $default; + } else { + trigger_error('Undefined lang string: ' . $key, E_USER_WARNING); + return $key; + } +} + +function ilang($key, + $class = NULL, + $id = NULL, + $href = NULL, + $click = NULL, + $attrs = array(), + $sub = NULL, + $button = FALSE, + $container = 'span' +) { + $text = ucfirst(lang($key . "_text", FALSE, sub: $sub)); + $tip = lang($key . "_tip", FALSE, sub: $sub); + $icon = lang($key . "_icon", FALSE); + $content = lang($key . "_content", FALSE); + + if ($click || $button) { + echo '<button '; + } else { + echo '<a '; + } + if ($tip) { + echo 'title="' . $tip . '" '; + echo 'aria-label="' . $tip . '" '; + } + if ($class) { + echo 'class="' . $class . '" '; + } + if ($id) { + echo 'id="' . $id . '" '; + } + if ($click) { + echo 'onclick="' . $click . '" '; + } + if ($href) { + echo 'href="' . $href . '" '; + } + foreach ($attrs as $key => $attr) { + echo $key . '="' . $attr . '" '; + } + echo '> '; + if ($icon) { + echo '<i class="' . $icon . '">'; + if ($content) { + echo $content; + } + echo '</i>'; + } + if ($text) { + echo '<' . $container; + if ($icon) { + echo ' class="ml-sm"'; + } + echo '>' . $text . '</' . $container . '>'; + } + if ($click || $button) { + echo '</button>'; + } else { + echo '</a>'; + } +} diff --git a/src/web/helpers/markdown.php b/src/web/helpers/markdown.php new file mode 100644 index 0000000..39b430c --- /dev/null +++ b/src/web/helpers/markdown.php @@ -0,0 +1,33 @@ +<?php /* Copyright (c) 2024 Freya Murphy */ + +class MarkdownParser { + + private $parsedown; + + function __construct() { + $this->parsedown = new ParsedownExtra(); + } + + function parse($path) { + $content = file_get_contents($path); + $data = array( + 'meta' => array(), + 'content' => $content + ); + if (str_starts_with($content, '---')) { + $parts = explode('---', $content); + $data['content'] = trim(implode('---', array_slice($parts, 2))); + $meta = array_filter(explode("\n", $parts[1]), fn($x) => $x != ''); + foreach ($meta as $set) { + $parts = explode(": ", $set); + $key = trim($parts[0]); + $value = trim($parts[1]); + $data['meta'][$key] = $value; + } + + } + $data['content'] = $this->parsedown->text($data['content']); + return $data; + } + +} diff --git a/src/web/helpers/sanitize.php b/src/web/helpers/sanitize.php new file mode 100644 index 0000000..5d37852 --- /dev/null +++ b/src/web/helpers/sanitize.php @@ -0,0 +1,8 @@ +<?php /* Copyright (c) 2024 Freya Murphy */ + +function esc($data) { + $data = str_replace('&', '&', $data); + $data = str_replace('<', '<', $data); + $data = str_replace('>', '>', $data); + return $data; +} |