-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.php
178 lines (164 loc) · 6.27 KB
/
index.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<?php
require 'PagesDb.php';
require 'BasicAuth.php';
class App {
public $db;
public $last = 0; // The last page ID
public function __construct()
{
// Instanciate the database
$this->db = new PagesDb;
// Grab the last page in the DB
$this->last = $this->lastPage();
// Authenticate the user
$this->authenticate();
// Route this request
$this->route();
}
/**
* Authenticate a request using the BasicAuth class
*/
private function authenticate() {
// Instantiate the class for HTTP Basic Authentication
$basic = new BasicAuth('users.ini');
// Make every request require authorization
if (!$basic->auth()) {
die;
}
}
/**
* Route a request based on the URI
*/
private function route() {
// Split the URI into pieces
$uriSegments = explode("/", parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
// Route the request
switch($uriSegments[1]) {
case 'page':
$this->handlePage($uriSegments[2]);
break;
case 'search':
$this->handleSearch();
break;
case 'save':
$this->handleSave($_POST['page'], $_POST['text']);
break;
case 'new':
$this->handleNew();
break;
case 'find':
$this->handleFind($_GET['search']);
break;
default:
$this->handlePage($this->last['id']);
}
}
/**
* Save the page data that was passed into the DB
*/
private function handleSave($pageId, $pageText) {
$now = date('Y-m-d');
// Grab the first 150 characters as a potential title
$potentialTitle = substr($pageText, 0, 150);
// Strip everything up to the first newline
$potentialTitle = strstr($potentialTitle, "\n" , true);
// Trim white space and #'s from the ends of the string
$pageTitle = trim($potentialTitle, "# \n\r\t\v\x00");
// Strip dangerous characters from title
$unsafe = array('%', '.', ',', ';', ':', '<', '>', '(', ')', '[', ']', '=', '&', '#', '?', '*', '|', '!', '/', '\\', '"', '\'', chr(0));
$pageTitle = str_replace($unsafe, ' ', $pageTitle);
// If the title is empty, set it to Untitled
if (empty($pageTitle)) {
$pageTitle = "Untitled";
}
$statement = $this->db->prepare('UPDATE `pages` SET `text` = :text, `title` = :title, `edited` = :now WHERE `id` = :id');
$statement->bindValue(':text', $pageText, SQLITE3_TEXT);
$statement->bindValue(':title', $pageTitle, SQLITE3_TEXT);
$statement->bindValue(':now', $now, SQLITE3_TEXT);
$statement->bindValue(':id', $pageId, SQLITE3_INTEGER);
$result = $statement->execute();
}
/**
* Load the requested page from the database and show the edit page
*/
private function handlePage($pageId) {
// Query the DB for the page information
$statement = $this->db->prepare('SELECT `id`, `title`, `text` FROM `pages` WHERE `id` = :id');
$statement->bindValue(':id', $pageId, SQLITE3_INTEGER);
$result = $statement->execute();
$page = $result->fetchArray(SQLITE3_ASSOC);
// Set some variables for the template based on the values from the DB
$id = $page['id'];
$title = $page['title'];
$text = $page['text'];
$prev = $page['id'] - 1;
$next = $page['id'] + 1;
// Template variable to wrap the prev page to the last page if we're already at the first page
if ($prev < 1) {
$prev = $this->last['id'];
}
// Template variable to wrap the next page to the first page if we're already at the last page
if ($next > $this->last['id']) {
$next = 1;
}
// Pull in the editor UI
require 'view/edit/index.html';
}
/**
* Handle a request for a new page to be added
*/
private function handleNew() {
// If the last page is not blank, create a new blank page
if ($this->last['text'] != '') {
// Format todays date so we can write it into the DB
$now = date('Y-m-d');
// Query to insert a new blank page with todays created date
$statement = $this->db->prepare('INSERT INTO `pages` (`title`, `text`, `created`) VALUES ("Untitled", "", :now)');
$statement->bindValue(':now', $now, SQLITE3_TEXT);
$result = $statement->execute();
}
// Redirect back to the main page which automatically switches to the newest page
header("Location: /");
}
/**
* Handle a request for the search page
*/
private function handleSearch() {
// Pull in the search UI
require 'view/search/index.html';
}
/**
* Handle a request to find search results
*/
private function handleFind($search) {
// Query for matching documents
$statement = $this->db->prepare('SELECT `id`, `title`, SUBSTR(`text`, 1, 80) AS `fragment` FROM `pages` WHERE `text` LIKE :search ORDER BY `id` DESC');
$statement->bindValue(':search', "%{$search}%", SQLITE3_TEXT);
$result = $statement->execute();
// Loop through the results
while ($page = $result->fetchArray(SQLITE3_ASSOC)) {
echo "<p><a href=\"/page/{$page['id']}\">{$page['title']}</strong> ({$page['id']})</a><br>{$page['fragment']}</p>";
}
}
private function handleComponent($component) {
switch($component) {
case 'menu':
include 'components/menu.html';
break;
default:
}
}
/**
* Fetch the last page (highest page id) from the database and return an array
* containing the id and text body.
*/
private function lastPage(): array {
// Query for the newest document id
$statement = $this->db->prepare('SELECT `id`, `text` FROM `pages` ORDER BY `id` DESC LIMIT 1');
$result = $statement->execute();
$page = $result->fetchArray(SQLITE3_ASSOC);
// Grab the last page ID so we know how to wrap navigation
return $page;
}
}
$app = new App;