commit 5a54fe251d55dffde9d386fcefdb4663d7363e76 Author: garrettmills Date: Sun Dec 6 13:58:02 2020 -0600 Initial commit 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

+ + +