diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..c6380ab --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +DB_HOST=localhost +DB_NAME=employees +DB_USER=root +DB_PASS=root \ No newline at end of file diff --git a/.gitignore b/.gitignore index adf1997..cb7f517 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /vendor/ /logs/* !/logs/README.md +/.env \ No newline at end of file diff --git a/README.md b/README.md index dcbc056..a06b000 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,18 @@ # Simple MVC Example Project for Web III +## Getting Started +1. Fork this repo +2. Clone your version of the repo: `git clone ` +3. Install dependencies: `composer install` +4. Run the app: `composer run start` + + +## Contributing + +1. Fork it +2. Create your feature branch (`git checkout -b feature/name-of-new-feature`) +3. Make your changes +4. Commit your changes (`git commit -am 'Added some feature'`) +5. Push to the branch (`git push origin feature/name-of-new-feature`) +6. Create new Pull Request \ No newline at end of file diff --git a/composer.json b/composer.json index 7c4ea18..c9b43b5 100644 --- a/composer.json +++ b/composer.json @@ -1,21 +1,21 @@ { - "name": "slim/slim-skeleton", - "description": "A Slim Framework skeleton application for rapid development", + "name": "bpd01001/web-three-mvc", + "description": "Sample MVC Infrastructure based on Slim", "keywords": ["microframework", "rest", "router", "psr7"], - "homepage": "http://github.com/slimphp/Slim-Skeleton", + "homepage": "https://github.uconn.edu/bpd01001/web-three-mvc", "license": "MIT", "authors": [ { - "name": "Josh Lockhart", - "email": "info@joshlockhart.com", - "homepage": "http://www.joshlockhart.com/" + "name": "Brian Daley", + "email": "brian@uconn.edu" } ], "require": { "php": ">=5.5.0", "slim/slim": "^3.1", "slim/php-view": "^2.0", - "monolog/monolog": "^1.17" + "monolog/monolog": "^1.17", + "vlucas/phpdotenv": "^3.3" }, "require-dev": { "phpunit/phpunit": ">=4.8 < 6.0" diff --git a/composer.lock b/composer.lock index 06e065a..f3f1c4c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5e16cb7781829836a704bd8767830833", + "content-hash": "fffa2b6a41920a1b3a2e2f5c009f6d89", "packages": [ { "name": "container-interop/container-interop", @@ -161,6 +161,56 @@ ], "time": "2018-02-13T20:26:39+00:00" }, + { + "name": "phpoption/phpoption", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/94e644f7d2051a5f0fcf77d81605f152eecff0ed", + "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "4.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-0": { + "PhpOption\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache2" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "time": "2015-07-25T16:39:46+00:00" + }, { "name": "pimple/pimple", "version": "v3.2.3", @@ -359,16 +409,16 @@ }, { "name": "slim/php-view", - "version": "2.2.0", + "version": "2.2.1", "source": { "type": "git", "url": "https://github.com/slimphp/PHP-View.git", - "reference": "122ed121a8d9cf91a94020814d2a3ee6c836754f" + "reference": "a13ada9d7962ca1b48799c0d9ffbca4c33245aed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slimphp/PHP-View/zipball/122ed121a8d9cf91a94020814d2a3ee6c836754f", - "reference": "122ed121a8d9cf91a94020814d2a3ee6c836754f", + "url": "https://api.github.com/repos/slimphp/PHP-View/zipball/a13ada9d7962ca1b48799c0d9ffbca4c33245aed", + "reference": "a13ada9d7962ca1b48799c0d9ffbca4c33245aed", "shasum": "" }, "require": { @@ -404,20 +454,20 @@ "template", "view" ], - "time": "2016-10-11T07:43:08+00:00" + "time": "2019-04-15T20:43:28+00:00" }, { "name": "slim/slim", - "version": "3.12.0", + "version": "3.12.1", "source": { "type": "git", "url": "https://github.com/slimphp/Slim.git", - "reference": "f4947cc900b6e51cbfda58b9f1247bca2f76f9f0" + "reference": "eaee12ef8d0750db62b8c548016d82fb33addb6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slimphp/Slim/zipball/f4947cc900b6e51cbfda58b9f1247bca2f76f9f0", - "reference": "f4947cc900b6e51cbfda58b9f1247bca2f76f9f0", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/eaee12ef8d0750db62b8c548016d82fb33addb6b", + "reference": "eaee12ef8d0750db62b8c548016d82fb33addb6b", "shasum": "" }, "require": { @@ -475,33 +525,145 @@ "micro", "router" ], - "time": "2019-01-15T13:21:25+00:00" + "time": "2019-04-16T16:47:29+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.11.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "82ebae02209c21113908c229e9883c419720738a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", + "reference": "82ebae02209c21113908c229e9883c419720738a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.11-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-02-06T07:57:58+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v3.3.3", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "dbcc609971dd9b55f48b8008b553d79fd372ddde" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/dbcc609971dd9b55f48b8008b553d79fd372ddde", + "reference": "dbcc609971dd9b55f48b8008b553d79fd372ddde", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0", + "phpoption/phpoption": "^1.5", + "symfony/polyfill-ctype": "^1.9" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.0 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "http://www.vancelucas.com" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "time": "2019-03-06T09:39:45+00:00" } ], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" + "reference": "a2c590166b2133a4633738648b6b064edae0814a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a", + "reference": "a2c590166b2133a4633738648b6b064edae0814a", "shasum": "" }, "require": { "php": "^7.1" }, "require-dev": { - "athletic/athletic": "~0.1.8", + "doctrine/coding-standard": "^6.0", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "^6.2.3", - "squizlabs/php_codesniffer": "^3.0.2" + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { @@ -526,25 +688,25 @@ } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ "constructor", "instantiate" ], - "time": "2017-07-22T11:58:36+00:00" + "time": "2019-03-17T17:37:11+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.8.1", + "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8" + "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", - "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", + "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", "shasum": "" }, "require": { @@ -579,7 +741,7 @@ "object", "object graph" ], - "time": "2018-06-11T23:09:50+00:00" + "time": "2019-04-07T13:18:21+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -1700,76 +1862,18 @@ "homepage": "https://github.com/sebastianbergmann/version", "time": "2016-10-03T07:35:21+00:00" }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.10.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - }, - { - "name": "Gert de Pagter", - "email": "backendtea@gmail.com" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "time": "2018-08-06T14:22:27+00:00" - }, { "name": "symfony/yaml", - "version": "v4.2.4", + "version": "v4.2.7", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "761fa560a937fd7686e5274ff89dcfa87a5047df" + "reference": "6712daf03ee25b53abb14e7e8e0ede1a770efdb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/761fa560a937fd7686e5274ff89dcfa87a5047df", - "reference": "761fa560a937fd7686e5274ff89dcfa87a5047df", + "url": "https://api.github.com/repos/symfony/yaml/zipball/6712daf03ee25b53abb14e7e8e0ede1a770efdb1", + "reference": "6712daf03ee25b53abb14e7e8e0ede1a770efdb1", "shasum": "" }, "require": { @@ -1815,7 +1919,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2019-02-23T15:17:42+00:00" + "time": "2019-03-30T15:58:42+00:00" }, { "name": "webmozart/assert", diff --git a/public/index.php b/public/index.php index 865530b..b7c47e7 100644 --- a/public/index.php +++ b/public/index.php @@ -13,6 +13,13 @@ error_reporting(E_ALL ^ E_NOTICE); require __DIR__ . '/../vendor/autoload.php'; +// Load Environment Variables +if(file_exists('../.env')){ + $dotenv = Dotenv\Dotenv::create('../'); + $dotenv->load(); + $dotenv->required(['DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASS']); +} + session_start(); // Instantiate the app diff --git a/src/controllers/HomeController.php b/src/controllers/HomeController.php index 550fc0f..4cc74b6 100644 --- a/src/controllers/HomeController.php +++ b/src/controllers/HomeController.php @@ -10,24 +10,92 @@ class HomeController $this->container = $container; $this->view = $container->get('view'); + /** + * Add your models here: + * Example: $this->model_name = new ModelName($container); + */ $this->employees = new Employees($container); } + /** + * Render the home page + */ public function home($request, $response, $args) { + return $this->view->render($response, 'Home.php', [ 'user' => $_SESSION['user'] ] ); + } + + /** + * Render the contact page + */ + public function contact($request, $response, $args) { + return $this->view->render($response, 'Contact.php', [ ]); + } + + /** + * This just renders the view "Login.php" + */ + public function login($request, $response, $args) { + return $this->view->render($response, 'Login.php'); + } + + + /** + * This controller method will process the submitted login form + */ + public function process_login($request, $response, $args) { - // Get search query - $query = $request->getQueryParam('q'); + /** + * Get the variables submitted by POST request + * from the login form. + */ + $user = $request->getParam('user'); + $pass = $request->getParam('pass'); + + /** + * If valid user, login. + * @todo Replace this with logic that uses a model to query for the + * user and check whether the password is correct. + */ + if( $user == 'admin' && $pass == 'password'){ - // Use the model to search our database - $results = $this->employees->searchByName($query); + /** + * Store the user in a session variable + * @todo Fill this user object with data from your user table + */ + $_SESSION['user'] = (object) [ + 'name' => 'Brian Daley', + 'email' => 'brian@uconn.edu' + ]; - // Send the results to our view for rendering - return $this->view->render($response, 'Search.php', [ 'results' => $results, 'q' => $query ]); + /** + * Redirect the user to the homepage + */ + return $response->withRedirect('/', 301); + + }else{ + + /** + * Invalid user. Return to login page + * @todo Make sure you display an error message + */ + return $this->view->render($response, 'Login.php', [ 'error' => 'Some error message']); + } } - public function contact($request, $response, $args) { - // your code - // to access items in the container... $this->container->get(''); - return $response; + + public function logout($request, $response, $args) { + + /** + * Delete the user and destroy our session + */ + unset($_SESSION['user']); + session_destroy(); + + /** + * Send the user back to the login page + */ + return $response->withRedirect('/login', 301); } + + } \ No newline at end of file diff --git a/src/dependencies.php b/src/dependencies.php index b3b9d67..63b0649 100644 --- a/src/dependencies.php +++ b/src/dependencies.php @@ -13,9 +13,7 @@ $container['view'] = function ($c) { * Add PDO to our container */ $container['db'] = function ($c) { - $db = $c['settings']['db']; - $pdo = new PDO('mysql:host=' . $db['host'] . ';dbname=' . $db['dbname'], - $db['user'], $db['pass']); + $pdo = new PDO('mysql:host=' . getenv('DB_HOST') . ';dbname=' . getenv('DB_NAME'), getenv('DB_USER'), getenv('DB_PASS')); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); return $pdo; diff --git a/src/middleware.php b/src/middleware.php index 116a0ff..2cb9dfa 100644 --- a/src/middleware.php +++ b/src/middleware.php @@ -2,3 +2,15 @@ // Application middleware // e.g: $app->add(new \Slim\Csrf\Guard); + + +$auth = function ($request, $response, $next) { + + /** Allow user to pass through if authenticated */ + if( is_object($_SESSION['user']) ){ + return $next($request, $response); + }else{ + /** Otherwise redirect to the login page */ + return $response->withRedirect('/login', 301); + } +}; \ No newline at end of file diff --git a/src/routes.php b/src/routes.php index 829ed5b..0bcd7af 100644 --- a/src/routes.php +++ b/src/routes.php @@ -12,5 +12,8 @@ use Slim\Http\Response; // }); -$app->get('/', 'HomeController:home'); -$app->get('/about', 'HomeController:contact'); \ No newline at end of file +$app->get('/', 'HomeController:home')->add($auth); +$app->get('/login', 'HomeController:login'); +$app->post('/login', 'HomeController:process_login'); +$app->get('/logout', 'HomeController:logout'); +$app->get('/about', 'HomeController:contact')->add($auth); \ No newline at end of file diff --git a/src/settings.php b/src/settings.php index ab547e2..c498bee 100644 --- a/src/settings.php +++ b/src/settings.php @@ -8,14 +8,5 @@ return [ 'views' => [ 'template_path' => __DIR__ . '/views/', ], - - // Database settings - 'db' => [ - 'host' => 'localhost', - 'dbname' => 'employees', - 'user' => 'root', - 'pass' => 'root' - ], ], - ]; diff --git a/src/views/Home.php b/src/views/Home.php new file mode 100644 index 0000000..98a5fb1 --- /dev/null +++ b/src/views/Home.php @@ -0,0 +1,28 @@ + + + + + Welcome! + + + + +
+ +
+
+

Welcome!

+

Hi, name ?>

+ + + Log Out + +
+

+ ©2019 Acme Corp. All rights reserved. +

+
+
+ + + diff --git a/src/views/Login.php b/src/views/Login.php new file mode 100644 index 0000000..3d4587c --- /dev/null +++ b/src/views/Login.php @@ -0,0 +1,46 @@ + + + + + Login to Web Three MVC + + + + +
+ +
+
+
+ + +
+
+ + + +
+
+ + +
+
+

+ Demo User: admin, Demo Password: password +

+

+ ©2019 Acme Corp. All rights reserved. +

+
+
+ + + diff --git a/src/views/Search.php b/src/views/Search.php deleted file mode 100644 index 022c8f3..0000000 --- a/src/views/Search.php +++ /dev/null @@ -1,47 +0,0 @@ - - - - - Slim 3 - - - - -

Search

- -
- - -
- - -

full_name; ?>

- - - - -