Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b02960b46 | |||
| bedf615ad3 | |||
| 5d2281b713 | |||
| 7e877465a6 | |||
| 7360c279ae | |||
| 641fdb17c5 | |||
| 45e10dcacd | |||
| 28513d367d | |||
| 0c41ca9b65 | |||
| d183c4c1e0 | |||
| f76bbfb27c | |||
| aca652c22e | |||
| 0d4b62ffb9 | |||
| 7cd3071905 | |||
| 77b60d34f6 | |||
| b858af3b55 | |||
| 937e4581ba | |||
| f19f59d53a | |||
| 0c96ba6c90 | |||
| 713a44ad98 | |||
| ea40fc8e38 | |||
| 8190b5ed71 |
26
README.md
26
README.md
@@ -1,4 +1,4 @@
|
|||||||

|

|
||||||
|
|
||||||
# Novaconium PHP: A PHP Framework Built from the Past
|
# Novaconium PHP: A PHP Framework Built from the Past
|
||||||
|
|
||||||
@@ -11,13 +11,25 @@ Master Repo: https://git.4lt.ca/4lt/novaconium
|
|||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
### Installation
|
Novaconium is heavly influenced by docker, but you can use composer outside of docker.
|
||||||
|
You can [learn more about how novaconium works with composer](https://git.4lt.ca/4lt/novaconium/src/branch/master/docs/Install-Composer-On-Debian.md).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir project_name;
|
PROJECTNAME=novaproject
|
||||||
cd project_name;
|
mkdir -p $PROJECTNAME/novaconium;
|
||||||
mkdir -p App/controllers App/templates App/views public
|
cd $PROJECTNAME;
|
||||||
touch App/controllers/404.php App/controllers/index.php App/views/index.html.twig public/index.php public/.htaccess App/routes.php
|
|
||||||
|
|
||||||
composer require 4lt/novaconium
|
docker run --rm --interactive --tty --volume ./novaconium/:/app composer:latest require 4lt/novaconium
|
||||||
|
|
||||||
|
cp -R novaconium/vendor/4lt/novaconium/skeleton/. .
|
||||||
|
|
||||||
|
# Edit .env
|
||||||
|
# Edit novaconium/App/config.php
|
||||||
|
|
||||||
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
* [Novaconiumm Official Repo](https://git.4lt.ca/4lt/novaconium)
|
||||||
|
* [CORXN Apache and PHP Container for Novaconium](https://git.4lt.ca/4lt/CORXN)
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
<svg width="100%" height="200" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<rect width="100%" height="100%" fill="black"/>
|
|
||||||
<defs>
|
|
||||||
<radialGradient id="star-gradient" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
|
|
||||||
<stop offset="0%" style="stop-color: white; stop-opacity: 1" />
|
|
||||||
<stop offset="100%" style="stop-color: white; stop-opacity: 0" />
|
|
||||||
</radialGradient>
|
|
||||||
<g id="star">
|
|
||||||
<circle cx="0" cy="0" r="2" fill="white" />
|
|
||||||
</g>
|
|
||||||
</defs>
|
|
||||||
|
|
||||||
<!-- Lots of stars moving outward slower -->
|
|
||||||
<g>
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(-300,-150) scale(1)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(300,-150) scale(1)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(-300,150) scale(1)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(300,150) scale(1)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(-150,-75) scale(0.5)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(150,-75) scale(0.5)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(-150,75) scale(0.5)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(150,75) scale(0.5)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(-75,-37) scale(0.7)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(75,-37) scale(0.7)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(-75,37) scale(0.7)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(75,37) scale(0.7)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(-350,-175) scale(0.4)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(350,-175) scale(0.4)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(-350,175) scale(0.4)" />
|
|
||||||
<use href="#star" x="50%" y="50%" transform="translate(350,175) scale(0.4)" />
|
|
||||||
<animateTransform attributeName="transform" type="scale" from="1" to="10" dur="2s" repeatCount="indefinite"/>
|
|
||||||
<animate attributeName="opacity" from="1" to="0" dur="2s" repeatCount="indefinite" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<!-- Centered Title -->
|
|
||||||
<text x="50%" y="50%" fill="white" font-size="40" text-anchor="middle" font-family="Arial" dy=".3em">
|
|
||||||
Novaconium PHP
|
|
||||||
</text>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.2 KiB |
BIN
_assets/novaconium-logo.png
Normal file
BIN
_assets/novaconium-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "4lt/novaconium",
|
"name": "4lt/novaconium",
|
||||||
"description": "A high-performance PHP framework built from the past.",
|
"description": "A high-performance PHP framework built from the past.",
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
|||||||
18
docs/Composer.md
Normal file
18
docs/Composer.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# PHP Composer Cheatsheet
|
||||||
|
|
||||||
|
Install novaconium with composer: ```composer require 4lt/novaconium```
|
||||||
|
|
||||||
|
Install novaconium with composer in docker: ```docker run --rm --interactive --tty --volume $PWD:/app composer:latest require 4lt/novaconium```
|
||||||
|
|
||||||
|
Update novaconium with composer in docker: ```docker run --rm --interactive --tty --volume $PWD:/app composer:latest update```
|
||||||
|
|
||||||
|
## Install Composer natively on Debian
|
||||||
|
|
||||||
|
Assuming you have nala installed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nala install curl php-cli php-mbstring git unzip
|
||||||
|
curl -sS https://getcomposer.org/installer -o composer-setup.php
|
||||||
|
sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer
|
||||||
|
rm composer-setup.php
|
||||||
|
```
|
||||||
9
docs/docker.md
Normal file
9
docs/docker.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Docker Cheatsheet (for Novaconium)
|
||||||
|
|
||||||
|
## Sample Docker Compose File
|
||||||
|
|
||||||
|
See the skeleton directory for an example docker setup.
|
||||||
|
|
||||||
|
## Start Docker
|
||||||
|
|
||||||
|
```docker compose up -d```
|
||||||
3
docs/twig-overrides.md
Normal file
3
docs/twig-overrides.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Twig Overrides
|
||||||
|
|
||||||
|
You can override twig templates by creating the same file in the templates directory.
|
||||||
@@ -1 +0,0 @@
|
|||||||
<h1>This is 404</h1>
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
<?php
|
|
||||||
echo $twig->render('index.html.twig');
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?php
|
|
||||||
error_reporting(E_ALL);
|
|
||||||
ini_set('display_errors', 1);
|
|
||||||
define('BASEPATH', dirname(__DIR__, 1));
|
|
||||||
require_once(BASEPATH . '/vendor/4lt/novaconium/src/bootstrap.php');
|
|
||||||
?>
|
|
||||||
2
skeleton/.env
Normal file
2
skeleton/.env
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
MYSQL_ROOT_PASSWORD: random
|
||||||
|
MYSQL_PASSWORD: random
|
||||||
56
skeleton/docker-compose.yml
Normal file
56
skeleton/docker-compose.yml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Sample Docker Compose
|
||||||
|
services:
|
||||||
|
corxn:
|
||||||
|
image: 4lights/corxn:6.0.0
|
||||||
|
ports:
|
||||||
|
- "8000:80"
|
||||||
|
volumes:
|
||||||
|
- ./novaconium:/data
|
||||||
|
- ./data/logs:/var/log/apache2 # Optional Logs
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- internal
|
||||||
|
- proxy
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:latest
|
||||||
|
networks:
|
||||||
|
- internal
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
mariadb:
|
||||||
|
image: mariadb:latest
|
||||||
|
container_name: mariadb
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||||
|
MYSQL_DATABASE: novadb
|
||||||
|
MYSQL_USER: novaconium
|
||||||
|
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- ./data/db:/var/lib/mysql
|
||||||
|
networks:
|
||||||
|
- internal
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
phpmyadmin:
|
||||||
|
image: phpmyadmin/phpmyadmin:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8001:80"
|
||||||
|
networks:
|
||||||
|
- internal
|
||||||
|
environment:
|
||||||
|
- PMA_ARBITRARY=-1
|
||||||
|
- PMA_HOST=mariadb
|
||||||
|
- PMA_USER=root
|
||||||
|
- PMA_PASSWORD=${MYSQL_ROOT_PASSWORD}
|
||||||
|
- UPLOAD_LIMIT=200M
|
||||||
|
volumes:
|
||||||
|
- "/etc/timezone:/etc/timezone:ro"
|
||||||
|
- "/etc/localtime:/etc/localtime:ro"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
proxy:
|
||||||
|
external: true
|
||||||
|
internal:
|
||||||
|
driver: bridge
|
||||||
11
skeleton/novaconium/App/config.php
Normal file
11
skeleton/novaconium/App/config.php
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
$config = [
|
||||||
|
'database' => [
|
||||||
|
'host' => 'mariadb',
|
||||||
|
'name' => 'novadb',
|
||||||
|
'user' => 'novaconium',
|
||||||
|
'pass' => '',
|
||||||
|
'port' => 3306
|
||||||
|
],
|
||||||
|
'base_url' => 'http://localhost:8000'
|
||||||
|
];
|
||||||
15
skeleton/novaconium/App/controllers/404.php
Normal file
15
skeleton/novaconium/App/controllers/404.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Define our status code and message
|
||||||
|
$status_code = 404;
|
||||||
|
$status_message = 'The requested resource could not be found.';
|
||||||
|
|
||||||
|
// Set the HTTP response code and message
|
||||||
|
http_response_code($status_code);
|
||||||
|
header("Content-Type: text/html");
|
||||||
|
?>
|
||||||
|
|
||||||
|
<h1>Error 404 Resource Not found</h1>
|
||||||
|
<p><?php echo $status_message; ?></p>
|
||||||
|
<p style="font-size:10px; margin-top:60px">Novaconium Default 404 page.</p>
|
||||||
|
|
||||||
2
skeleton/novaconium/App/controllers/index.php
Normal file
2
skeleton/novaconium/App/controllers/index.php
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
view('index');
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
$routes = [
|
$routes = [
|
||||||
'/about' => [
|
'/about' => [
|
||||||
'file' => 'about'
|
'get' => 'about'
|
||||||
],
|
],
|
||||||
'/' => [
|
'/' => [
|
||||||
'file' => 'index'
|
'get' => 'index'
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
1
skeleton/novaconium/App/templates/override.html.twig
Normal file
1
skeleton/novaconium/App/templates/override.html.twig
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{# Overrides go here #}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
RewriteEngine On
|
RewriteEngine On
|
||||||
|
|
||||||
RewriteCond %{REQUEST_FILENAME} !-f
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
RewriteCond %{REQUEST_FILENAME} !-d
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
|
||||||
RewriteRule ^(.*)$ index.php?_uri=$1 [QSA,L]
|
RewriteRule ^(.*)$ index.php?_uri=$1 [QSA,L]
|
||||||
6
skeleton/novaconium/public/index.php
Normal file
6
skeleton/novaconium/public/index.php
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
// error_reporting(E_ALL);
|
||||||
|
// ini_set('display_errors', 1);
|
||||||
|
define('BASEPATH', dirname(__DIR__, 1));
|
||||||
|
require_once(BASEPATH . '/vendor/4lt/novaconium/src/novaconium.php');
|
||||||
|
?>
|
||||||
78
src/Database.php
Normal file
78
src/Database.php
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Database {
|
||||||
|
|
||||||
|
private $conn;
|
||||||
|
|
||||||
|
public function __construct($dbinfo) {
|
||||||
|
$this->conn = new mysqli($dbinfo['host'], $dbinfo['user'], $dbinfo['pass'], $dbinfo['name']);
|
||||||
|
if ($this->conn->connect_error) {
|
||||||
|
die("Connection failed: " . $this->conn->connect_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function query($query, $params = []) {
|
||||||
|
// Prepare the SQL query
|
||||||
|
if ($stmt = $this->conn->prepare($query)) {
|
||||||
|
// Bind parameters to the prepared statement (if any)
|
||||||
|
if (!empty($params)) {
|
||||||
|
$types = str_repeat('s', count($params)); // Assuming all params are strings
|
||||||
|
$stmt->bind_param($types, ...$params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute the statement
|
||||||
|
if (!$stmt->execute()) {
|
||||||
|
throw new Exception("Query execution failed: " . $stmt->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the statement result
|
||||||
|
return $stmt;
|
||||||
|
} else {
|
||||||
|
throw new Exception("Query preparation failed: " . $this->conn->error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRow($query, $params = []) {
|
||||||
|
try {
|
||||||
|
// Perform the query using prepared statement
|
||||||
|
$stmt = $this->query($query, $params);
|
||||||
|
|
||||||
|
// Get the result of the query
|
||||||
|
$result = $stmt->get_result();
|
||||||
|
|
||||||
|
// Fetch the first row from the result
|
||||||
|
return $result->fetch_assoc();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Handle the exception (log it, display a message, etc.)
|
||||||
|
echo "An error occurred: " . $e->getMessage();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRows($query, $params = []) {
|
||||||
|
$stmt = $this->conn->prepare($query);
|
||||||
|
if (!$stmt) {
|
||||||
|
die("Query preparation failed: " . $this->conn->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind parameters if provided
|
||||||
|
if (!empty($params)) {
|
||||||
|
$types = str_repeat('s', count($params)); // Assuming all are strings, adjust as needed
|
||||||
|
$stmt->bind_param($types, ...$params);
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt->execute();
|
||||||
|
$result = $stmt->get_result(); // Requires MySQL Native Driver (mysqlnd)
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close() {
|
||||||
|
$this->conn->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
62
src/MessageHandler.php
Normal file
62
src/MessageHandler.php
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class MessageHandler {
|
||||||
|
private $messages = [
|
||||||
|
'error' => [],
|
||||||
|
'warning' => [],
|
||||||
|
'notice' => [],
|
||||||
|
'success' => []
|
||||||
|
];
|
||||||
|
|
||||||
|
// Add a message of a specific type
|
||||||
|
public function addMessage($type, $message) {
|
||||||
|
if (!isset($this->messages[$type])) {
|
||||||
|
throw new Exception("Invalid message type: $type");
|
||||||
|
}
|
||||||
|
$this->messages[$type][] = $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all messages of a specific type
|
||||||
|
public function getMessages($type) {
|
||||||
|
return $this->messages[$type] ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all messages of all types
|
||||||
|
public function getAllMessages() {
|
||||||
|
return $this->messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the count of messages for a specific type
|
||||||
|
public function count($type) {
|
||||||
|
return isset($this->messages[$type]) ? count($this->messages[$type]) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the total count of all messages
|
||||||
|
public function totalCount() {
|
||||||
|
return array_sum(array_map('count', $this->messages));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there are any messages of a specific type
|
||||||
|
public function hasMessages($type) {
|
||||||
|
return !empty($this->messages[$type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there are any messages at all
|
||||||
|
public function hasAnyMessages() {
|
||||||
|
return $this->totalCount() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear messages of a specific type
|
||||||
|
public function clear($type) {
|
||||||
|
if (isset($this->messages[$type])) {
|
||||||
|
$this->messages[$type] = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all messages
|
||||||
|
public function clearAll() {
|
||||||
|
foreach ($this->messages as $type => $list) {
|
||||||
|
$this->messages[$type] = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/Post.php
Normal file
25
src/Post.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Post {
|
||||||
|
private $data = [];
|
||||||
|
|
||||||
|
public function __construct($post) {
|
||||||
|
$this->sanitize($post);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sanitize($post) {
|
||||||
|
foreach ($post as $key => $value) {
|
||||||
|
$this->data[$key] = is_array($value)
|
||||||
|
? filter_var_array($value, FILTER_SANITIZE_FULL_SPECIAL_CHARS)
|
||||||
|
: filter_var($value, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get($key, $default = null) {
|
||||||
|
return $this->data[$key] ?? $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function all() {
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/Redirect.php
Normal file
40
src/Redirect.php
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use
|
||||||
|
* $redirect->to('/login');
|
||||||
|
* to trigger a redirect
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
class Redirect {
|
||||||
|
private ?string $url = null;
|
||||||
|
private int $statusCode = 303;
|
||||||
|
|
||||||
|
public function url(string $relativeUrl, int $statusCode = 303): void {
|
||||||
|
$this->statusCode = $statusCode;
|
||||||
|
|
||||||
|
// Detect HTTPS
|
||||||
|
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https" : "http";
|
||||||
|
|
||||||
|
// Get Hostname
|
||||||
|
$host = $_SERVER['HTTP_HOST'];
|
||||||
|
|
||||||
|
// Get Base Directory
|
||||||
|
$basePath = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/\\');
|
||||||
|
|
||||||
|
// Construct Absolute URL
|
||||||
|
$this->url = "$protocol://$host$basePath/" . ltrim($relativeUrl, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isset(): bool {
|
||||||
|
return !is_null($this->url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(): void {
|
||||||
|
if ($this->url) {
|
||||||
|
header("Location: " . $this->url, true, $this->statusCode);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
115
src/Router.php
115
src/Router.php
@@ -4,22 +4,45 @@ class Router {
|
|||||||
public $routes = [];
|
public $routes = [];
|
||||||
public $query = [];
|
public $query = [];
|
||||||
public $path;
|
public $path;
|
||||||
public $controllerPath = BASEPATH . '/App/controllers/404.php';
|
public $controller;
|
||||||
|
public $controllerPath;
|
||||||
|
public $parameters = [];
|
||||||
|
public $requestType = 'get';
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->loadRoutes();
|
$this->routes = $this->loadRoutes();
|
||||||
$this->preparePath();
|
$this->path = $this->preparePath();
|
||||||
$this->prepareQuery();
|
$this->query = $this->prepareQuery();
|
||||||
$this->setRouteFile();
|
$this->requestType = $this->getRequestType();
|
||||||
|
$this->controller = $this->findController();
|
||||||
|
$this->controllerPath = $this->setRouteFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadRoutes() {
|
private function loadRoutes() {
|
||||||
|
// Check if Path exists
|
||||||
|
if (file_exists(BASEPATH . '/App/routes.php')) {
|
||||||
require_once( BASEPATH . '/App/routes.php');
|
require_once( BASEPATH . '/App/routes.php');
|
||||||
$this->routes = $routes;
|
} else {
|
||||||
|
require_once(FRAMEWORKPATH . '/defaults/App/routes.php');
|
||||||
|
}
|
||||||
|
return $routes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function preparePath() {
|
private function preparePath() {
|
||||||
$this->path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
||||||
|
|
||||||
|
//homepage
|
||||||
|
if ($path === '/') {
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove empty directory path
|
||||||
|
$path = rtrim($path, '/'); // remove trailing slash
|
||||||
|
|
||||||
|
//remove anything after and including ampersand
|
||||||
|
$path = preg_replace('/&.+$/', '', $path);
|
||||||
|
|
||||||
|
return $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function prepareQuery() {
|
private function prepareQuery() {
|
||||||
@@ -28,16 +51,84 @@ class Router {
|
|||||||
if (isset($parsedUri['query'])) {
|
if (isset($parsedUri['query'])) {
|
||||||
parse_str($parsedUri['query'], $queryArray);
|
parse_str($parsedUri['query'], $queryArray);
|
||||||
}
|
}
|
||||||
$this->query = $queryArray;
|
return $queryArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getRequestType() {
|
||||||
|
// is the requewst a get or post?
|
||||||
|
if (empty($_POST)) {
|
||||||
|
return 'get';
|
||||||
|
} else {
|
||||||
|
return 'post';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findController() {
|
||||||
|
|
||||||
|
// one to one match
|
||||||
|
if (array_key_exists($this->path, $this->routes)) {
|
||||||
|
return $this->routes[$this->path][$this->requestType];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setRouteFile() {
|
|
||||||
foreach ($this->routes as $key => $value) {
|
foreach ($this->routes as $key => $value) {
|
||||||
if ( $this->path == $key) {
|
// Check if key contains a curly bracket, if not continue. We already checked above.
|
||||||
$this->controllerPath = BASEPATH . '/App/controllers/' . $value['file'] . '.php';
|
if (!strpos($key, '{')) continue;
|
||||||
break;
|
|
||||||
|
// Remove everything after the curly bracket, from key
|
||||||
|
$keyPath = substr($key, 0, strpos($key, '{'));
|
||||||
|
|
||||||
|
//see if keyPath matches the first characters of $this->path, only the first characters have to match
|
||||||
|
if (strpos($this->path, $keyPath) === 0) {
|
||||||
|
|
||||||
|
// We have a potential match. Now check if the parameter count is equal
|
||||||
|
$keyParams = explode('/', $key);
|
||||||
|
$pathParams = explode('/', $this->path);
|
||||||
|
$keyParamCount = count($keyParams);
|
||||||
|
$pathParamCount = count($pathParams);
|
||||||
|
if ($keyParamCount === $pathParamCount) {
|
||||||
|
for ($i=0; $i < $pathParamCount; $i++) {
|
||||||
|
if (strpos($keyParams[$i], '{') !== false) {
|
||||||
|
$keyParams[$i] = substr($keyParams[$i], 1, -1);
|
||||||
|
$this->parameters[$keyParams[$i]] = $pathParams[$i];
|
||||||
|
return $this->routes[$key][$this->requestType];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return '404';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks if the file exists, sets file path
|
||||||
|
private function setRouteFile() {
|
||||||
|
|
||||||
|
$cp = BASEPATH . '/App/controllers/' . $this->controller . '.php';
|
||||||
|
|
||||||
|
if (file_exists($cp)) {
|
||||||
|
return $cp;
|
||||||
|
} else {
|
||||||
|
//Check if 404 exits
|
||||||
|
if (file_exists(BASEPATH . '/App/controllers/404.php')) {
|
||||||
|
return BASEPATH . '/App/controllers/404.php';
|
||||||
|
} else {
|
||||||
|
return FRAMEWORKPATH . '/defaults/App/controllers/404.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function debug() {
|
||||||
|
echo '<div id="router-debug-container" class="debug">';
|
||||||
|
echo '<table border="1" cellpadding="10" cellspacing="0">';
|
||||||
|
echo '<tr><th>Url Path</th><td>' . htmlspecialchars($this->path) . '</td></tr>';
|
||||||
|
echo '<tr><th>Controller Path</th><td>' . htmlspecialchars($this->controllerPath) . '</td></tr>';
|
||||||
|
echo '<tr><th>Parameters</th><td><pre>' . print_r($this->parameters, true) . '</pre></td></tr>';
|
||||||
|
echo '<tr><th>Routes</th><td><pre>' . print_r($this->routes, true) . '</pre></td></tr>';
|
||||||
|
echo '</table></div>';
|
||||||
|
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
57
src/Session.php
Normal file
57
src/Session.php
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Session {
|
||||||
|
private $session;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
session_start();
|
||||||
|
if (!isset($_SESSION)) {
|
||||||
|
$this->session = $_SESSION;
|
||||||
|
$this->setToken();
|
||||||
|
$this->session['messages'] = [];
|
||||||
|
} else {
|
||||||
|
$this->session = $_SESSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setToken() {
|
||||||
|
if (!isset($this->session['token'])) {
|
||||||
|
$this->session['token'] = bin2hex(random_bytes(32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set($key, $value) {
|
||||||
|
$this->session[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get($key) {
|
||||||
|
return isset($this->session[$key]) ? $this->session[$key] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function flash($key) {
|
||||||
|
$return = $this->get($key);
|
||||||
|
$this->delete($key);
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function debug() {
|
||||||
|
return $this->session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete($key) {
|
||||||
|
if (isset($this->session[$key])) {
|
||||||
|
unset($this->session[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write() {
|
||||||
|
$_SESSION = $this->session;
|
||||||
|
session_write_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function kill() {
|
||||||
|
session_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once(BASEPATH . '/vendor/autoload.php');
|
|
||||||
|
|
||||||
//Twig
|
|
||||||
$loader = new Twig\Loader\FilesystemLoader(BASEPATH . '/App/views/');
|
|
||||||
$loader->addPath(BASEPATH . '/vendor/4lt/novaconium/twig', 'novaconium');
|
|
||||||
$loader->addPath(BASEPATH . '/App/templates', 'override');
|
|
||||||
$twig = new Twig\Environment($loader);
|
|
||||||
|
|
||||||
// Load a controller
|
|
||||||
require_once('Router.php');
|
|
||||||
$router = new Router();
|
|
||||||
require_once($router->controllerPath);
|
|
||||||
29
src/functions.php
Normal file
29
src/functions.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump and Die
|
||||||
|
*/
|
||||||
|
function dd(...$vars) {
|
||||||
|
echo "<pre style='background:#222;color:#0f0;padding:10px;border-radius:5px;'>";
|
||||||
|
foreach ($vars as $var) {
|
||||||
|
var_dump($var);
|
||||||
|
echo "\n";
|
||||||
|
}
|
||||||
|
echo "</pre>";
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeitso() {
|
||||||
|
global $session, $db, $redirect, $config, $messages;
|
||||||
|
|
||||||
|
if (!empty($config['database']['host'])) {
|
||||||
|
$db->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
$session->set('messages', $messages->getAllMessages());
|
||||||
|
$session->write();
|
||||||
|
|
||||||
|
$redirect->execute();
|
||||||
|
|
||||||
|
exit();
|
||||||
|
}
|
||||||
49
src/novaconium.php
Normal file
49
src/novaconium.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
define('FRAMEWORKPATH', BASEPATH . '/vendor/4lt/novaconium');
|
||||||
|
|
||||||
|
require_once(BASEPATH . '/vendor/autoload.php');
|
||||||
|
|
||||||
|
//Check if config file exists
|
||||||
|
if (file_exists(BASEPATH . '/App/config.php')) {
|
||||||
|
require_once(BASEPATH . '/App/config.php');
|
||||||
|
} else {
|
||||||
|
require_once(FRAMEWORKPATH . '/defaults/App/config.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global Functions
|
||||||
|
require_once(FRAMEWORKPATH . '/src/functions.php');
|
||||||
|
|
||||||
|
// Creates the view() function using twig
|
||||||
|
require_once(FRAMEWORKPATH . '/src/twig.php');
|
||||||
|
|
||||||
|
// Messages
|
||||||
|
require_once(FRAMEWORKPATH . '/src/MessageHandler.php');
|
||||||
|
$messages = new MessageHandler;
|
||||||
|
|
||||||
|
// Start a Session
|
||||||
|
require_once(FRAMEWORKPATH . '/src/Session.php');
|
||||||
|
$session = new Session();
|
||||||
|
|
||||||
|
// Load Database Class
|
||||||
|
if (!empty($config['database']['host'])) {
|
||||||
|
require_once(FRAMEWORKPATH . '/src/Database.php');
|
||||||
|
$db = new Database($config['database']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanatize POST Data
|
||||||
|
if (!empty($_POST)) {
|
||||||
|
require_once(FRAMEWORKPATH . '/src/Post.php');
|
||||||
|
$post = new POST($_POST);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start a Redirect
|
||||||
|
require_once(FRAMEWORKPATH . '/src/Redirect.php');
|
||||||
|
$redirect = new Redirect();
|
||||||
|
|
||||||
|
// Load a controller
|
||||||
|
require_once(FRAMEWORKPATH . '/src/Router.php');
|
||||||
|
$router = new Router();
|
||||||
|
//$router->debug();
|
||||||
|
require_once($router->controllerPath);
|
||||||
|
|
||||||
|
makeitso();
|
||||||
24
src/twig.php
Normal file
24
src/twig.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
//Twig
|
||||||
|
function view($name = '', $data = []) {
|
||||||
|
global $config; // Use the globally included $config
|
||||||
|
|
||||||
|
$loader = new Twig\Loader\FilesystemLoader(BASEPATH . '/App/views/');
|
||||||
|
$loader->addPath(BASEPATH . '/vendor/4lt/novaconium/twig', 'novaconium');
|
||||||
|
$loader->addPath(BASEPATH . '/App/templates', 'override');
|
||||||
|
|
||||||
|
$twig = new Twig\Environment($loader);
|
||||||
|
|
||||||
|
// Add config to Twig globally
|
||||||
|
$twig->addGlobal('config', $config);
|
||||||
|
|
||||||
|
// Check if the template exists
|
||||||
|
if (file_exists(BASEPATH . '/App/views/' . $name . '.html.twig')) {
|
||||||
|
echo $twig->render("$name.html.twig", $data);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
echo "Error: Twig Template ($name) Not Found.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user