From 5a54fe251d55dffde9d386fcefdb4663d7363e76 Mon Sep 17 00:00:00 2001 From: garrettmills Date: Sun, 6 Dec 2020 13:58:02 -0600 Subject: [PATCH] Initial commit --- AdminHome.html | 17 +++ CreatePosts.html | 16 +++ CreatePosts.php | 35 ++++++ CreateUser.html | 14 +++ CreateUser.php | 29 +++++ DeletePost.html | 41 +++++++ DeletePost.php | 24 ++++ ViewUserPosts.html | 26 +++++ ViewUserPosts.php | 44 +++++++ ViewUsers.php | 23 ++++ app/PostRepository.php | 11 ++ app/UserRepository.php | 11 ++ assets/common.css | 28 +++++ common/Page.php | 208 +++++++++++++++++++++++++++++++++ common/Request.php | 40 +++++++ common/autoload.php | 20 ++++ common/database/Connection.php | 81 +++++++++++++ common/database/Repository.php | 134 +++++++++++++++++++++ common/functions_config.php | 18 +++ common/functions_debugging.php | 8 ++ common/functions_system.php | 54 +++++++++ config/database.php | 8 ++ configuration.php | 11 ++ index.html | 10 ++ 24 files changed, 911 insertions(+) create mode 100644 AdminHome.html create mode 100644 CreatePosts.html create mode 100644 CreatePosts.php create mode 100644 CreateUser.html create mode 100644 CreateUser.php create mode 100644 DeletePost.html create mode 100644 DeletePost.php create mode 100644 ViewUserPosts.html create mode 100644 ViewUserPosts.php create mode 100644 ViewUsers.php create mode 100644 app/PostRepository.php create mode 100644 app/UserRepository.php create mode 100644 assets/common.css create mode 100644 common/Page.php create mode 100644 common/Request.php create mode 100644 common/autoload.php create mode 100644 common/database/Connection.php create mode 100644 common/database/Repository.php create mode 100644 common/functions_config.php create mode 100644 common/functions_debugging.php create mode 100644 common/functions_system.php create mode 100644 config/database.php create mode 100644 configuration.php create mode 100644 index.html diff --git a/AdminHome.html b/AdminHome.html new file mode 100644 index 0000000..639db62 --- /dev/null +++ b/AdminHome.html @@ -0,0 +1,17 @@ +title('EECS 448 Lab 10 - Exercise 4') + ->header('Admin Home') + ->writes(" + + "); + +$page->write(); diff --git a/CreatePosts.html b/CreatePosts.html new file mode 100644 index 0000000..915451a --- /dev/null +++ b/CreatePosts.html @@ -0,0 +1,16 @@ +title('Exercise 3 - EECS 448 Lab 10') + ->header('Create a New Post') + ->div(function() use($page) { + $page->form(system_url('CreatePosts.php'), function() use($page) { + $page->writes('')->line_break(); + $page->writes('')->line_break(); + $page->submit(); + }); + }) + ->write(); diff --git a/CreatePosts.php b/CreatePosts.php new file mode 100644 index 0000000..e378668 --- /dev/null +++ b/CreatePosts.php @@ -0,0 +1,35 @@ +title('Exercise 3 - EECS 448 Lab 10') + ->header('Create a New Post'); + +if ( !$request->input('username') ) { + $page->fail_to('You must specify the username.', system_url('CreatePosts.html')); +} + +if ( !$request->input('content') ) { + $page->fail_to('You must specify post content.', system_url('CreatePosts.html')); +} + +$user = $users->find_one([ 'username' => $request->input('username') ]); +if ( !$user ) { + $page->fail_to('Sorry, a user with that username does not exist.', system_url('CreatePosts.html')); +} + +$post = $posts->save([ + 'user_id' => $user['user_id'], + 'content' => $request->input('content'), +]); + +$page->div(function() use($page) { + $page->writes('Post created successfully.'); +}); + +$page->write(); diff --git a/CreateUser.html b/CreateUser.html new file mode 100644 index 0000000..e718141 --- /dev/null +++ b/CreateUser.html @@ -0,0 +1,14 @@ +title('Exercise 2 - EECS 448 Lab 10') + ->header('Create a New User') + ->form(system_url('CreateUser.php'), function() use($page) { + $page->writes(''); + $page->submit(); + }); + +$page->write(); diff --git a/CreateUser.php b/CreateUser.php new file mode 100644 index 0000000..ea5e34d --- /dev/null +++ b/CreateUser.php @@ -0,0 +1,29 @@ +title('Exercise 2 - EECS 448 Lab 10') + ->header('Create a New User'); + +if ( !$request->input('username') ) { + $page->fail_to('You must specify a username.', system_url('CreateUser.html')); +} + +$existing_user = $users->find_one([ 'username' => $request->input('username') ]); +if ( $existing_user ) { + $page->fail_to('A user with that username already exists.', system_url('CreateUser.html')); +} + +$new_user = $users->save([ + 'username' => $request->input('username'), +]); + +$page->div(function() use($page, $new_user) { + $page->writes('User ' . $new_user['username'] . ' created successfully.'); +}); + +$page->write(); diff --git a/DeletePost.html b/DeletePost.html new file mode 100644 index 0000000..1cde34e --- /dev/null +++ b/DeletePost.html @@ -0,0 +1,41 @@ +connect(); + +$page = new common\Page; + +$page->title('EECS 448 Lab 10 - Exercise 7') + ->header('Delete Posts'); + +$query = "SELECT post.post_id, user.username, post.content + FROM posts post + LEFT JOIN users user + ON user.user_id = post.post_id"; + +$results = $db->fetch($query); + +$post_display = array_merge([ + ['Post ID', 'Username', 'Content', 'Delete?'], +], array_map(function($post) { + $id = 'post-' . $post['post_id']; + + return [ + $post['post_id'], + $post['username'], + $post['content'], + ' + ' + ]; +}, $results)); + +$page->writes('

Select the posts you want to delete.') + ->form(system_url('DeletePost.php'), function() use($page, $post_display) { + $page->table($post_display) + ->writes('
') + ->submit(); + }); + +$page->write(); diff --git a/DeletePost.php b/DeletePost.php new file mode 100644 index 0000000..ce51b30 --- /dev/null +++ b/DeletePost.php @@ -0,0 +1,24 @@ +input() as $post_key => $value ) { + if ( $value !== 'yes' ) continue; + + $post_id = explode('-', $post_key)[1]; + $post_ids[] = $post_id; + + $posts->delete(['post_id' => $post_id]); +} + +$page->title('EECS 448 Lab 10 - Exercise 7') + ->header('Posts Deleted') + ->writes('

Posts with the following IDs were deleted: ' . implode(', ', $post_ids) . '

') + ->writes('Admin Home'); + +$page->write(); diff --git a/ViewUserPosts.html b/ViewUserPosts.html new file mode 100644 index 0000000..a225a65 --- /dev/null +++ b/ViewUserPosts.html @@ -0,0 +1,26 @@ +' . $user['username'] . ''; +}, $users->find()); + +$page->title('EECS 448 Lab 10 - Exercise 6') + ->header('View Posts by User') + ->form(system_url('ViewUserPosts.php'), function() use($page, $user_options) { + $page->writes(' + + + '); + + $page->submit(); + }); + +$page->write(); diff --git a/ViewUserPosts.php b/ViewUserPosts.php new file mode 100644 index 0000000..de08720 --- /dev/null +++ b/ViewUserPosts.php @@ -0,0 +1,44 @@ +title('EECS 448 Lab 10 - Exercise 6') + ->header('View Posts by User'); + +if ( !$request->input('user_id') ) { + $page->fail_to('Please select a user.', system_url('ViewUserPosts.html')); +} + +$user = $users->find_by_id($request->input('user_id')); + +if ( !$user ) { + $page->fail_to('Invalid user.', system_url('ViewUserPosts.html')); +} + +$user_posts = $posts->find([ + 'user_id' => $user['user_id'], +]); + +$post_display = array_merge([ + ['Post ID', 'Post Content'] +], array_map(function($post) { + return [$post['post_id'], $post['content']]; +}, $user_posts)); + + +$page->div(function() use($page, $user) { + $page->writes('Posts by ' . $user['username'] . ':'); +}); + +$page->table($post_display); + +$page->div(function() use($page) { + $page->writes('Select a different user'); +}); + +$page->write(); diff --git a/ViewUsers.php b/ViewUsers.php new file mode 100644 index 0000000..c1727ed --- /dev/null +++ b/ViewUsers.php @@ -0,0 +1,23 @@ +title('EECS 448 Lab 10 - Exercise 5') + ->header('View Registered Users'); + +$registered_users = $users->find(); + +$table_display = array_merge([ + // Add the table headers + ['User ID', 'Username'], +], array_map(function($user) { + // Map from associative array to keyed + return array_values($user); +}, $registered_users)); + +$page->table($table_display); + +$page->write(); diff --git a/app/PostRepository.php b/app/PostRepository.php new file mode 100644 index 0000000..1b76b2a --- /dev/null +++ b/app/PostRepository.php @@ -0,0 +1,11 @@ +_writers[] = $writer; + + if ( $this->_writing ) { + $writer(); + } + + return $this; + } + + public function writes($string) { + $this->calls(function() use($string) { + echo $string; + }); + + return $this; + } + + public function script($src) { + $this->_scripts[] = $src; + return $this; + } + + public function stylesheet($src) { + $this->_styles[] = $src; + return $this; + } + + public function title($title = null) { + if ( $title ) { + $this->_title = $title; + return $this; + } else { + return $this->_title; + } + } + + public function header($string = null) { + if ( !$string ) $string = $this->title(); + + return $this->writes('

' . $string . '

'); + } + + public function form($submit, callable $inner) { + $this->writes('
'); + $this->calls($inner); + $this->writes('
'); + return $this; + } + + public function submit($text = 'Submit') { + $this->writes(''); + } + + public function div(callable $inner) { + $this->writes('
'); + $this->calls($inner); + $this->writes('
'); + return $this; + } + + public function line_break() { + $this->writes('
'); + return $this; + } + + public function table($nested_array) { + if ( is_array($nested_array) ) { + $this->calls(function() use($nested_array) { + echo ''; + + foreach ( $nested_array as $row_idx => $row ) { + echo ''; + + foreach ( $row as $col_idx => $col ) { + $tag = $row_idx === 0 ? 'th' : 'td'; + + echo "<{$tag}>{$col}"; + } + + echo ''; + } + + echo '
'; + }); + } else { + $this->writes(''); + $this->calls($nested_array); + $this->writes('
'); + } + + return $this; + } + + public function table_row_cell(callable $inner, $span = 1) { + $this->table_row(function() use($inner, $span) { + $this->writes(''); + $this->calls($inner); + $this->writes(''); + }); + + return $this; + } + + public function table_row($inner = null) { + $this->writes(''); + if ( $inner ) $this->calls($inner); + $this->writes(''); + + return $this; + } + + public function table_head(callable $inner) { + $this->writes(''); + $this->calls($inner); + $this->writes(''); + + return $this; + } + + public function table_cell($inner = null) { + $this->writes(''); + if ( $inner ) $this->calls($inner); + $this->writes(''); + + return $this; + } + + public function fail_to($message, $redirect_url) { + $this->writes('

' . $message . '

') + ->writes('

Try Again

') + ->write(); + + exit; + } + + public function preamble() { + if ( $this->_wrote_pre ) return; + $this->_styles[] = system_url('assets/common.css'); + + $styles = []; + foreach ( $this->_styles as $style ) { + $styles[] = ''; + } + + ?> + + + + <?= $this->_title ?> + + + + _wrote_pre = true; + } + + public function postamble() { + if ( $this->_wrote_post ) return; + + $scripts = []; + foreach ( $this->_scripts as $script ) { + $scripts[] = ''; + } + + ?> + + + + _wrote_post = true; + } + + public function write() { + $this->_writing = true; + $this->preamble(); + foreach ( $this->_writers as $writer ) { + $writer(); + } + $this->postamble(); + $this->_writing = false; + } + + public function compile() { + ob_start(); + $this->_wrote_pre = false; + $this->_wrote_post = false; + $this->write(); + $this->_wrote_pre = false; + $this->_wrote_post = false; + return ob_get_clean(); + } +} diff --git a/common/Request.php b/common/Request.php new file mode 100644 index 0000000..f8f689f --- /dev/null +++ b/common/Request.php @@ -0,0 +1,40 @@ +_get = $_GET; + $req->_post = $_POST; + return $req; + } + + public function input($path = null) { + if ( !$path ) { + return array_merge($this->_get, $this->_post); + } + + $path_parts = explode('.', $path); + + $get_value = $this->_get; + foreach ( $path_parts as $part ) { + if ( $get_value ) { + $get_value = $get_value[$part]; + } + } + + $post_value = $this->_post; + foreach ( $path_parts as $part ) { + if ( $post_value ) { + $post_value = $post_value[$part]; + } + } + + if ( $get_value ) return $get_value; + if ( $post_value ) return $post_value; + } +} diff --git a/common/autoload.php b/common/autoload.php new file mode 100644 index 0000000..c3237e6 --- /dev/null +++ b/common/autoload.php @@ -0,0 +1,20 @@ +config = config('database'); + } + + public function connect() { + if ( !static::$mysqli ) { + static::$mysqli = new \mysqli( + $this->config['url'], + $this->config['username'], + $this->config['password'], + $this->config['database'] + ); + } + + if ( static::$mysqli->connect_errno ) { + throw new \Exception('Unable to connect to database: ' . static::$mysqli->connect_error); + } + } + + public function escape($value) { + return static::$mysqli->real_escape_string($value); + } + + public function execute($query, $args = [], $returns_statement = false) { + $statement = static::$mysqli->prepare($query); + + if ( sizeof($args) > 0 ) { + $types = ''; + foreach ( $args as $arg ) { + if ( is_int($arg) ) { + $types .= 'i'; + } else if ( is_float($arg) || is_double($arg) ) { + $types .= 'd'; + } else if ( is_string($arg) ) { + $types .= 's'; + } else { + $types .= 'b'; + } + } + + $statement->bind_param($types, ...$args); + } + + $statement->execute(); + + if ( $returns_statement ) return $statement; + return $statement->get_result(); + } + + public function insert($query, $args = []) { + $statement = $this->execute($query, $args, true); + return $statement->insert_id; + } + + public function fetch($query, $args = []) { + $result = $this->execute($query, $args); + + $rows = []; + while ( $row = $result->fetch_assoc() ) { + $rows[] = $row; + } + + return $rows; + } + + public function close() { + if ( static::$mysqli ) { + static::$mysqli->close(); + static::$mysqli = null; + } + } +} diff --git a/common/database/Repository.php b/common/database/Repository.php new file mode 100644 index 0000000..8cb2266 --- /dev/null +++ b/common/database/Repository.php @@ -0,0 +1,134 @@ +connection = new Connection(); + $this->connection->connect(); + } + + function __destruct() { + $this->connection->close(); + } + + public function create($record) { + $fields = []; + $arg_parts = []; + $args = []; + + foreach ( $this->fields as $field ) { + if ( isset($record[$field]) ) { + $fields[] = $field; + $args[] = $record[$field]; + $arg_parts[] = '?'; + } + } + + $query = 'INSERT INTO ' . $this->table . ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $arg_parts) . ')'; + $insert_id = $this->connection->insert($query, $args); + + $record[$this->primary_key] = $insert_id; + return $record; + } + + public function find_by_id($primary_key) { + $query = 'SELECT ' . implode(', ', $this->fields) . ' FROM ' . $this->table . ' WHERE ' . $this->primary_key . ' = ?'; + $results = $this->connection->fetch($query, [$primary_key]); + + if ( sizeof($results) > 0 ) { + return $results[0]; + } + } + + public function find($filter = []) { + $query = 'SELECT ' . implode(', ', $this->fields) . ' FROM ' . $this->table . ' WHERE '; + list($wheres, $where_args) = $this->build_wheres_from_filter($filter); + + $query .= implode(' AND ', $wheres); + $query .= ' ORDER BY ' . $this->primary_key . ' ASC'; + return $this->connection->fetch($query, $where_args); + } + + public function find_one($filter = []) { + $query = 'SELECT ' . implode(', ', $this->fields) . ' FROM ' . $this->table . ' WHERE '; + list($wheres, $where_args) = $this->build_wheres_from_filter($filter); + + $query .= implode(' AND ', $wheres) . ' LIMIT 1'; + $results = $this->connection->fetch($query, $where_args); + + if ( sizeof($results) > 0 ) { + return $results[0]; + } + } + + public function update($record) { + $query = 'UPDATE ' . $this->table . ' SET '; + $query_args = []; + + $sets = []; + foreach ( $this->fields as $field ) { + if ( isset($record[$field]) ) { + $sets[] = $field . '=?'; + $query_args[] = $record[$field]; + } + } + + $query = 'UPDATE ' . $this->table . ' SET ' . implode(', ', $sets) . ' WHERE ' . $this->primary_key . ' = ?'; + $query_args[] = $record[$this->primary_key]; + + $this->connection->execute($query, $query_args); + return $record; + } + + public function save($record) { + if ( isset($record[$this->primary_key]) ) { + return $this->update($record); + } else { + return $this->create($record); + } + } + + public function delete($record) { + $primary_key = $record[$this->primary_key]; + + $query = 'DELETE FROM ' . $this->table . ' WHERE ' . $this->primary_key . ' = ?'; + $this->connection->execute($query, [$primary_key]); + } + + protected function build_wheres_from_filter($filter = []) { + if ( !$filter ) { + return [['1=1'], []]; + } + + $wheres = []; + $where_args = []; + foreach ( $this->fields as $field ) { + if ( isset($filter[$field]) ) { + $val = $filter[$field]; + + if ( is_string($val) || is_numeric($val) ) { + $wheres[] = $field . ' = ?'; + $where_args[] = $val; + } else if ( is_array($val) ) { + $where_items = []; + + foreach ( $val as $item ) { + $where_items[] = '?'; + $where_args[] = $item; + } + + $wheres[] = $field . ' IN (' . implode(',', $where_items) . ')'; + } + } + } + + return [$wheres, $where_args]; + } +} diff --git a/common/functions_config.php b/common/functions_config.php new file mode 100644 index 0000000..b395b0e --- /dev/null +++ b/common/functions_config.php @@ -0,0 +1,18 @@ + $part ) { + if ( $i !== 0 && $config ) { + $config = $config[$part]; + } + } + + return $config; +} diff --git a/common/functions_debugging.php b/common/functions_debugging.php new file mode 100644 index 0000000..88a9280 --- /dev/null +++ b/common/functions_debugging.php @@ -0,0 +1,8 @@ +"; + var_dump($something); + echo ""; + exit; +} diff --git a/common/functions_system.php b/common/functions_system.php new file mode 100644 index 0000000..014b344 --- /dev/null +++ b/common/functions_system.php @@ -0,0 +1,54 @@ + 'mysql.eecs.ku.edu', + 'username' => 'garretmills', + 'password' => '', // omitted for public repo + 'database' => 'garretmills', +]; diff --git a/configuration.php b/configuration.php new file mode 100644 index 0000000..78d5663 --- /dev/null +++ b/configuration.php @@ -0,0 +1,11 @@ + + +

Simple Posts

+ + +