Skip to content
Browse files

Add Nette tutorial

  • Loading branch information...
0 parents commit dcd3fde678c09da6f4117a61266be95d11b6a171 @abtris committed Nov 1, 2010
2 app/.htaccess
@@ -0,0 +1,2 @@
+Order Allow,Deny
+Deny from all
58 app/bootstrap.php
@@ -0,0 +1,58 @@
+<?php
+
+use Nette\Debug,
+ Nette\Environment,
+ Nette\Application\Route,
+ Nette\Application\SimpleRouter;
+
+
+
+// Step 1: Load Nette Framework
+// this allows load Nette Framework classes automatically so that
+// you don't have to litter your code with 'require' statements
+require LIBS_DIR . '/Nette/Nette/loader.php';
+
+
+
+// Step 2: Configure environment
+// 2a) enable Nette\Debug for better exception and error visualisation
+Debug::enable();
+
+// 2b) load configuration from config.ini file
+Environment::loadConfig();
+
+
+
+// Step 3: Configure application
+// 3a) get and setup a front controller
+$application = Environment::getApplication();
+
+// 3b) establish database connection
+$application->onStartup[] = 'Albums::initialize';
+
+
+
+// Step 4: Setup application router
+$router = $application->getRouter();
+
+// mod_rewrite detection
+if (function_exists('apache_get_modules') && in_array('mod_rewrite', apache_get_modules())) {
+ $router[] = new Route('index.php', array(
+ 'presenter' => 'Dashboard',
+ 'action' => 'default',
+ ), Route::ONE_WAY);
+
+ $router[] = new Route('<presenter>/<action>/<id>', array(
+ 'presenter' => 'Dashboard',
+ 'action' => 'default',
+ 'id' => NULL,
+ ));
+
+} else {
+ $router[] = new SimpleRouter('Dashboard:default');
+}
+
+
+
+// Step 5: Run the application!
+$application->run();
24 app/config.ini
@@ -0,0 +1,24 @@
+;
+; SECURITY WARNING: it is CRITICAL that this file & directory are NOT accessible directly via a web browser!
+; http://nette.org/security-warning
+;
+[common]
+; PHP configuration
+php.date.timezone = "Europe/Prague"
+
+; services
+service.Nette-Security-IAuthenticator = UsersModel
+
+service.Nette-Loaders-RobotLoader.option.directory[] = %appDir%
+service.Nette-Loaders-RobotLoader.option.directory[] = %libsDir%
+service.Nette-Loaders-RobotLoader.run = TRUE
+
+[production < common]
+; common database connection
+database.driver = sqlite
+database.file = "%appDir%/models/demo.db"
+database.lazy = TRUE
+
+[development < production]
+; database options in development mode
+database.profiler = TRUE
66 app/models/Albums.php
@@ -0,0 +1,66 @@
+<?php
+
+use Nette\Object,
+ Nette\Environment;
+
+
+/**
+ * Albums model.
+ */
+class Albums extends Object
+{
+ /** @var string */
+ private $table = 'albums';
+
+ /** @var DibiConnection */
+ private $connection;
+
+
+ public static function initialize()
+ {
+ dibi::connect(Environment::getConfig('database'));
+ }
+
+
+
+ public function __construct()
+ {
+ $this->connection = dibi::getConnection();
+ }
+
+
+
+ public function findAll()
+ {
+ return $this->connection->select('*')->from($this->table);
+ }
+
+
+
+ public function find($id)
+ {
+ return $this->connection->select('*')->from($this->table)->where('id=%i', $id);
+ }
+
+
+
+ public function update($id, array $data)
+ {
+ return $this->connection->update($this->table, $data)->where('id=%i', $id)->execute();
+ }
+
+
+
+ public function insert(array $data)
+ {
+ return $this->connection->insert($this->table, $data)->execute(dibi::IDENTIFIER);
+ }
+
+
+
+ public function delete($id)
+ {
+ return $this->connection->delete($this->table)->where('id=%i', $id)->execute();
+ }
+
+}
48 app/models/UsersModel.php
@@ -0,0 +1,48 @@
+<?php
+
+use Nette\Object,
+ Nette\Security\AuthenticationException;
+
+
+/**
+ * Users authenticator.
+ */
+class UsersModel extends Object implements Nette\Security\IAuthenticator
+{
+
+ /**
+ * Performs an authentication
+ * @param array
+ * @return IIdentity
+ * @throws AuthenticationException
+ */
+ public function authenticate(array $credentials)
+ {
+ list($username, $password) = $credentials;
+ $row = dibi::select('*')->from('users')->where('username=%s', $username)->fetch();
+
+ if (!$row) {
+ throw new AuthenticationException("User '$username' not found.", self::IDENTITY_NOT_FOUND);
+ }
+
+ if ($row->password !== $this->calculateHash($password)) {
+ throw new AuthenticationException("Invalid password.", self::INVALID_CREDENTIAL);
+ }
+
+ unset($row->password);
+ return new Nette\Security\Identity($row->id, NULL, $row);
+ }
+
+
+
+ /**
+ * Computes salted password hash.
+ * @param string
+ * @return string
+ */
+ public function calculateHash($password)
+ {
+ return md5($password . str_repeat('*random salt*', 10));
+ }
+
+}
BIN app/models/demo.db
Binary file not shown.
8 app/presenters/BasePresenter.php
@@ -0,0 +1,8 @@
+<?php
+
+use Nette\Application\Presenter;
+
+
+abstract class BasePresenter extends Presenter
+{
+}
153 app/presenters/DashboardPresenter.php
@@ -0,0 +1,153 @@
+<?php
+
+use Nette\Application\AppForm,
+ Nette\Forms\Form;
+
+
+
+class DashboardPresenter extends BasePresenter
+{
+
+ protected function startup()
+ {
+ // user authentication
+ if (!$this->user->isLoggedIn()) {
+ if ($this->user->logoutReason === Nette\Web\User::INACTIVITY) {
+ $this->flashMessage('You have been signed out due to inactivity. Please sign in again.');
+ }
+ $backlink = $this->application->storeRequest();
+ $this->redirect('Sign:in', array('backlink' => $backlink));
+ }
+
+ parent::startup();
+ }
+
+
+
+ /********************* view default *********************/
+
+
+
+ public function renderDefault()
+ {
+ $album = new Albums;
+ $this->template->albums = $album->findAll()->orderBy('artist')->orderBy('title');
+ }
+
+
+
+ /********************* views add & edit *********************/
+
+
+
+ public function renderAdd()
+ {
+ $this['albumForm']['save']->caption = 'Add';
+ }
+
+
+
+ public function renderEdit($id = 0)
+ {
+ $form = $this['albumForm'];
+ if (!$form->isSubmitted()) {
+ $album = new Albums;
+ $row = $album->find($id)->fetch();
+ if (!$row) {
+ throw new Nette\Application\BadRequestException('Record not found');
+ }
+ $form->setDefaults($row);
+ }
+ }
+
+
+
+ /********************* view delete *********************/
+
+
+
+ public function renderDelete($id = 0)
+ {
+ $album = new Albums;
+ $this->template->album = $album->find($id)->fetch();
+ if (!$this->template->album) {
+ throw new Nette\Application\BadRequestException('Record not found');
+ }
+ }
+
+
+
+ /********************* component factories *********************/
+
+
+
+ /**
+ * Album edit form component factory.
+ * @return mixed
+ */
+ protected function createComponentAlbumForm()
+ {
+ $form = new AppForm;
+ $form->addText('artist', 'Artist:')
+ ->addRule(Form::FILLED, 'Please enter an artist.');
+
+ $form->addText('title', 'Title:')
+ ->addRule(Form::FILLED, 'Please enter a title.');
+
+ $form->addSubmit('save', 'Save')->setAttribute('class', 'default');
+ $form->addSubmit('cancel', 'Cancel')->setValidationScope(NULL);
+ $form->onSubmit[] = callback($this, 'albumFormSubmitted');
+
+ $form->addProtection('Please submit this form again (security token has expired).');
+ return $form;
+ }
+
+
+
+ public function albumFormSubmitted(AppForm $form)
+ {
+ if ($form['save']->isSubmittedBy()) {
+ $id = (int) $this->getParam('id');
+ $album = new Albums;
+ if ($id > 0) {
+ $album->update($id, $form->values);
+ $this->flashMessage('The album has been updated.');
+ } else {
+ $album->insert($form->values);
+ $this->flashMessage('The album has been added.');
+ }
+ }
+
+ $this->redirect('default');
+ }
+
+
+
+ /**
+ * Album delete form component factory.
+ * @return mixed
+ */
+ protected function createComponentDeleteForm()
+ {
+ $form = new AppForm;
+ $form->addSubmit('cancel', 'Cancel');
+ $form->addSubmit('delete', 'Delete')->setAttribute('class', 'default');
+ $form->onSubmit[] = callback($this, 'deleteFormSubmitted');
+ $form->addProtection('Please submit this form again (security token has expired).');
+ return $form;
+ }
+
+
+
+ public function deleteFormSubmitted(AppForm $form)
+ {
+ if ($form['delete']->isSubmittedBy()) {
+ $album = new Albums;
+ $album->delete($this->getParam('id'));
+ $this->flashMessage('Album has been deleted.');
+ }
+
+ $this->redirect('default');
+ }
+
+}
70 app/presenters/SignPresenter.php
@@ -0,0 +1,70 @@
+<?php
+
+use Nette\Application\AppForm,
+ Nette\Forms\Form,
+ Nette\Security\AuthenticationException;
+
+
+
+class SignPresenter extends BasePresenter
+{
+ /** @persistent */
+ public $backlink = '';
+
+
+
+ public function startup()
+ {
+ parent::startup();
+ $this->session->start(); // required by $form->addProtection()
+ }
+
+
+
+ /********************* component factories *********************/
+
+
+
+ /**
+ * Sign in form component factory.
+ * @return Nette\Application\AppForm
+ */
+ protected function createComponentSignInForm()
+ {
+ $form = new AppForm;
+ $form->addText('username', 'Username:')
+ ->addRule(Form::FILLED, 'Please provide a username.');
+
+ $form->addPassword('password', 'Password:')
+ ->addRule(Form::FILLED, 'Please provide a password.');
+
+ $form->addSubmit('send', 'Sign in');
+
+ $form->onSubmit[] = callback($this, 'signInFormSubmitted');
+ return $form;
+ }
+
+
+
+ public function signInFormSubmitted($form)
+ {
+ try {
+ $this->user->login($form['username']->value, $form['password']->value);
+ $this->application->restoreRequest($this->backlink);
+ $this->redirect('Dashboard:');
+
+ } catch (AuthenticationException $e) {
+ $form->addError($e->getMessage());
+ }
+ }
+
+
+
+ public function actionOut()
+ {
+ $this->getUser()->logout();
+ $this->flashMessage('You have been signed out.');
+ $this->redirect('in');
+ }
+
+}
36 app/templates/@layout.phtml
@@ -0,0 +1,36 @@
+{**
+ * Layout of Nette Framework example CD collection (Akrabat)
+ *
+ * @package MyApplication
+ *
+ * @param string $robots tell robots how to index the content of a page (optional)
+ * @param string $basePath web base path
+ * @param array $flashes flash messages
+ * @param Nette\Web\User $user current user
+ *}
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta http-equiv="Content-Language" content="en" />
+
+ <meta name="description" content="Nette Framework example" />
+ <meta n:ifset="$robots" name="robots" content="{$robots}">
+
+ <title>{block #title|striptags|trim}{/block} | Nette example</title>
+
+ <link rel="stylesheet" type="text/css" media="screen" href="{$basePath}/css/site.css" />
+ <script src="http://nette.github.com/resources/js/netteForms.js"></script>
+</head>
+
+<body>
+ <div n:foreach="$flashes as $flash" class="flash {$flash->type}">{$flash->message}</div>
+
+ <div id="content">
+ {include #content}
+ </div>
+
+ <p id="logged-in" n:if="$user->loggedIn">Signed in as {$user->identity->real_name}. <a href="{link Sign:out}">Sign out</a></p>
+</body>
+</html>
5 app/templates/Dashboard/add.phtml
@@ -0,0 +1,5 @@
+{block #content}
+
+<h1 n:block="title">Add New Album</h1>
+
+{control albumForm}
24 app/templates/Dashboard/default.phtml
@@ -0,0 +1,24 @@
+{block #content}
+
+<h1 n:block="title">My Albums</h1>
+
+<p><a href="{link add}">Add new album</a></p>
+
+<table class="grid">
+<tr>
+ <th>Title</th>
+ <th>Artist</th>
+ <th>&nbsp;</th>
+</tr>
+
+{foreach $albums as $album}
+<tr>
+ <td>{$album->title}</td>
+ <td>{$album->artist}</td>
+ <td>
+ <a href="{link edit, $album->id}">Edit</a>
+ <a href="{link delete, $album->id}">Delete</a>
+ </td>
+</tr>
+{/foreach}
+</table>
11 app/templates/Dashboard/delete.phtml
@@ -0,0 +1,11 @@
+{block #content}
+
+<h1 n:block="title">Delete Album</h1>
+
+{if $album}
+ <p>Are you sure that you want to delete ‘{$album->title}’ by ‘{$album->artist}’?</p>
+ {control deleteForm}
+
+{else}
+ <p>Cannot find album.</p>
+{/if}
5 app/templates/Dashboard/edit.phtml
@@ -0,0 +1,5 @@
+{block #content}
+
+<h1 n:block="title">Edit Album</h1>
+
+{control albumForm}
9 app/templates/Sign/in.phtml
@@ -0,0 +1,9 @@
+{var $robots = noindex}
+
+{block #content}
+
+<h1 n:block="title">Sign in</h1>
+
+{control signInForm}
+
+<p>Default username is <i>demo</i>, with password <i>xxx</i></p>
16 app/web.config
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+ <system.webServer>
+ <rewrite>
+ <rules>
+ <rule name="RequestBlockingRule1" patternSyntax="Wildcard" stopProcessing="true">
+ <match url="*" />
+ <conditions>
+ <add input="{URL}" pattern="*" />
+ </conditions>
+ <action type="CustomResponse" statusCode="403" statusReason="Forbidden: Access is denied." statusDescription="You do not have permission to view this directory or page using the credentials that you supplied." />
+ </rule>
+ </rules>
+ </rewrite>
+ </system.webServer>
+</configuration>
13 document_root/.htaccess
@@ -0,0 +1,13 @@
+# disable directory listing
+Options -Indexes
+
+# mod_rewrite
+<IfModule mod_rewrite.c>
+ RewriteEngine On
+ # RewriteBase /
+
+ # front controller
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteRule !\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$ index.php [L]
+</IfModule>
108 document_root/css/site.css
@@ -0,0 +1,108 @@
+body {
+ font: 16px/1.5 "Trebuchet MS", "Geneva CE", lucida, sans-serif;
+ color: #333;
+ background-color: #fff;
+ margin: 2em;
+}
+
+h1 {
+ font-size: 1.9em;
+ color: #3484D2;
+}
+
+h2 {
+ font-size: 1.2em;
+ color: #3484D2;
+}
+
+#content {
+ width: 770px;
+ margin: 0 5px;
+}
+
+a {
+ color: #000080;
+}
+
+#logged-in {
+ margin-top: 3em;
+ font-size: 90%;
+}
+
+div.flash {
+ color: black;
+ background: #FFFFDD;
+ border: 1px solid #FFD700;
+ padding: 1em;
+ margin: 1em 0;
+}
+
+
+
+/*------------------------------------------------------------------*/
+
+
+table.grid {
+ padding: 0;
+ margin: 0;
+ border-collapse:collapse;
+}
+
+table.grid td, table.grid th {
+ background: #fff;
+ border: 1px solid #add4fb;
+ padding: 6px 6px 6px 12px;
+}
+
+table.grid th {
+ color: #7a7772;
+ background: #E4F1FC;
+ text-align: left;
+ font-weight: normal;
+ font-size: 80%;
+}
+
+table.grid .alt td {
+ background: #f8f8f0;
+}
+
+
+
+/*------------------------------------------------------------------*/
+
+
+
+form {
+ max-width: 500px;
+ padding: .8em 1.6em;
+ background: #E4F1FC;
+ border: solid 2px #add4fb;
+}
+
+form input {
+ margin: 2px 0;
+ font-size: 100%;
+}
+
+form input.default {
+ font-weight: bold;
+ font-size: 105%;
+}
+
+form input.text {
+ padding: 4px 2px;
+ border: solid 1px #add4fb;
+ min-width: 200px;
+}
+
+form label {
+ width: 100px;
+ display: block;
+ text-align: right;
+ margin-right: 5px;
+ font-weight: normal;
+}
+
+form .required label {
+ font-weight: bold;
+}
16 document_root/index.php
@@ -0,0 +1,16 @@
+<?php
+
+// absolute filesystem path to the web root
+define('WWW_DIR', __DIR__);
+
+// absolute filesystem path to the application root
+define('APP_DIR', WWW_DIR . '/../app');
+
+// absolute filesystem path to the libraries
+define('LIBS_DIR', WWW_DIR . '/../../libs');
+
+// absolute filesystem path to the temporary files
+define('TEMP_DIR', WWW_DIR . '/../temp');
+
+// load bootstrap file
+require APP_DIR . '/bootstrap.php';
17 document_root/web.config
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+ <system.webServer>
+ <rewrite>
+ <rules>
+ <rule name="Imported Rule 1" stopProcessing="true">
+ <match url="\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$" ignoreCase="false" negate="true" />
+ <conditions logicalGrouping="MatchAll">
+ <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
+ <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
+ </conditions>
+ <action type="Rewrite" url="index.php" />
+ </rule>
+ </rules>
+ </rewrite>
+ </system.webServer>
+</configuration>
2 log/.gitignore
@@ -0,0 +1,2 @@
+*
+!.*
2 log/.htaccess
@@ -0,0 +1,2 @@
+Order Allow,Deny
+Deny from all
11 readme.txt
@@ -0,0 +1,11 @@
+Nette Framework example CD collection (Akrabat)
+-----------------------------------------------
+
+Classic Zend Framework Tutorial rewritten for Nette.
+
+The example shows an important feature of the Nette Framework: the URLs are
+not used inside the application including the templates. The URLs are in
+responsibility of the router and can be changed anytime. The target of a link
+is always a combination "Presenter:action" or "Presenter:signal!".
+
+Source: http://akrabat.com/zend-framework-tutorial/ (Getting Started with the Zend Framework 1.5)
3 temp/.gitignore
@@ -0,0 +1,3 @@
+*
+!.*
+!*/.*
2 temp/.htaccess
@@ -0,0 +1,2 @@
+Order Allow,Deny
+Deny from all

0 comments on commit dcd3fde

Please sign in to comment.
Something went wrong with that request. Please try again.