Skip to content
Closed

Demo #60

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# FoOlSlideX .gitignore

# Configuration files
config.php
session.php
.installed

# Secrets
library/secrets/

# Database files
database/*/_cnt.sdb
database/*/cache/
database/*/data/

# IDE and OS files
.DS_Store
Thumbs.db
.vscode/
*.swp
*.swo

# Logs
*.log
1 change: 1 addition & 0 deletions .installed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2025-08-13 18:01:32
101 changes: 101 additions & 0 deletions app/Controllers/Api/ApiController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

namespace App\Controllers\Api;

use App\Core\Controller;
use App\Models\Title;
use App\Models\Chapter;
use App\Models\User;

class ApiController extends Controller
{
public function index()
{
$this->jsonResponse([
'name' => 'FoOlSlideX API',
'version' => '1.0',
'endpoints' => [
'GET /api/titles' => 'Get all titles',
'GET /api/titles/{id}' => 'Get a specific title',
'GET /api/titles/{id}/chapters' => 'Get chapters for a title',
'GET /api/chapters/{id}' => 'Get a specific chapter',
'GET /api/search' => 'Search titles'
]
]);
}

public function titles()
{
$page = $_GET['page'] ?? 1;
$limit = $_GET['limit'] ?? 20;
$offset = ($page - 1) * $limit;

$titles = Title::query()
->orderBy(['title' => 'ASC'])
->limit($limit)
->skip($offset)
->getQuery()
->fetch();

$this->jsonResponse([
'data' => $titles,
'page' => (int)$page,
'limit' => (int)$limit,
'total' => Title::count()
]);
}

public function title($id)
{
$title = Title::find($id);

if (!$title) {
$this->jsonResponse(['error' => 'Title not found'], 404);
return;
}

$this->jsonResponse($title);
}

public function titleChapters($id)
{
$chapters = Chapter::findByTitle($id);

if (!$chapters) {
$this->jsonResponse(['error' => 'No chapters found for this title'], 404);
return;
}

$this->jsonResponse($chapters);
}

public function chapter($id)
{
$chapter = Chapter::find($id);

if (!$chapter) {
$this->jsonResponse(['error' => 'Chapter not found'], 404);
return;
}

$this->jsonResponse($chapter);
}

public function search()
{
$query = $_GET['q'] ?? '';

if (empty($query)) {
$this->jsonResponse(['error' => 'Search query is required'], 400);
return;
}

$titles = Title::searchByTitle($query);

$this->jsonResponse([
'query' => $query,
'results' => $titles,
'count' => count($titles)
]);
}
}
17 changes: 17 additions & 0 deletions app/Controllers/ApiController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace App\Controllers;

use App\Core\Controller;

class ApiController extends Controller
{
public function index()
{
global $config;

// For now, just redirect to the original API page
// In the future, this would be implemented as a proper API controller
$this->redirect('api.php');
}
}
112 changes: 112 additions & 0 deletions app/Controllers/AuthController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

namespace App\Controllers;

use App\Core\Controller;

class AuthController extends Controller
{
public function showLogin()
{
global $config, $logged;

if ($logged) {
$this->redirect('index.php');
return;
}

$this->render("pages/login.tpl", [
"pagetitle" => "Login " . $config["divider"] . " " . $config["title"]
]);
}

public function login()
{
global $db, $config, $logged;

if ($logged) {
$this->redirect('index.php');
return;
}

// This would be implemented to handle the actual login logic
// For now, we'll just redirect to the original login page
$this->redirect('ajax/account/login.php');
}

public function showSignup()
{
global $config, $logged;

if ($logged) {
$this->redirect('index.php');
return;
}

$this->render("pages/signup.tpl", [
"pagetitle" => "Sign Up " . $config["divider"] . " " . $config["title"]
]);
}

public function signup()
{
global $db, $config, $logged;

if ($logged) {
$this->redirect('index.php');
return;
}

// This would be implemented to handle the actual signup logic
// For now, we'll just redirect to the original signup page
$this->redirect('ajax/account/signup.php');
}

public function logout()
{
global $config;

// This would be implemented to handle the actual logout logic
// For now, we'll just redirect to the original logout page
$this->redirect('ajax/account/logout.php');
}

public function activate()
{
global $config, $logged, $user;

if (!$logged) {
$this->redirect('index.php');
return;
}

if ($logged && $user["level"] >= 50) {
$this->redirect('index.php');
return;
}

if (!isset($_GET["token"]) || empty($_GET["token"])) {
$this->redirect('index.php');
return;
}

$token = clean($_GET["token"] ?? "");

if (empty($token)) {
$this->redirect('index.php');
return;
}

$check = $db["activation"]->findOneBy(["token", "==", $token]);
if (empty($check)) {
$this->redirect('index.php');
return;
}

$data = array(
"level" => 50
);
$db["users"]->updateById($user["id"], $data);
$this->redirect('index.php');
}
}
100 changes: 100 additions & 0 deletions app/Controllers/ChapterController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

namespace App\Controllers;

use App\Core\Controller;

class ChapterController extends Controller
{
public function show($id)
{
global $db, $config, $readingmode;

if (empty($id) || !is_numeric($id)) {
$this->redirect('index.php');
return;
}

$id = cat($id);
$chapter = $db["chapters"]->findById($id);
$title = $db["titles"]->findById($chapter["title"]);

if (empty($title)) {
$this->redirect('titles.php');
return;
}

if (empty($chapter)) {
$this->redirect('title.php?id=' . $title["id"]);
return;
}

$fct = formatChapterTitle($chapter["volume"], $chapter["number"], "full");

$chapters = $db["chapters"]->findBy(["title", "==", $title["id"]]);

$isNextChapter = false;
$isPrevChapter = false;

foreach ($chapters as $key => $ch) {
if ($ch["id"] == $id) {
if (!empty($chapters[($key + 1)])) $isNextChapter = $chapters[($key + 1)]["id"];
if (!empty($chapters[($key - 1)])) $isPrevChapter = $chapters[($key - 1)]["id"];
}
}

$images = glob(ps(__DIR__ . "/../data/chapters/{$id}/*.{jpg,png,jpeg,webp,gif}"), GLOB_BRACE);
natsort($images);

$comments = $db["chapterComments"]->findBy(["chapter.id", "==", $title["id"]], ["id" => "DESC"]);

chapterVisit($chapter);

$imgind = [];
$ic = 1;
foreach ($images as $ii) {
$ii = pathinfo($ii);
$imgind[$ic]["order"] = $ic;
$imgind[$ic]["name"] = $ii["filename"];
$imgind[$ic]["ext"] = $ii["extension"];
$ic++;
}

$page = 1;
if ($readingmode == "single") {
if (!isset($_GET["page"]) || empty($_GET["page"]) || $_GET["page"] == "0") {
$this->redirect('chapter.php?id=' . $id . '&page=1');
return;
}

$page = cat($_GET["page"]);

$isNextPage = true;
$isPrevPage = true;

$nextPage = $page + 1;
$prevPage = $page - 1;

$imgCount = count($images);

if ($nextPage >= $imgCount) $isNextPage = false;
if ($prevPage <= 0) $isPrevPage = false;
}

$this->render("pages/chapter.tpl", [
"fullChapterTitle" => $fct,
"chapters" => $chapters,
"nextChapter" => $isNextChapter,
"prevChapter" => $isPrevChapter,
"images" => $images,
"commentsCount" => count($comments),
"title" => $title,
"chapter" => $chapter,
"imgind" => $imgind,
"pagetitle" => "Read " . $title["title"] . " " . formatChapterTitle($chapter["volume"], $chapter["number"]) . " " . $config["divider"] . " " . $config["title"],
"isNextPage" => $isNextPage ?? null,
"isPrevPage" => $isPrevPage ?? null,
"currentPage" => $page ?? null
]);
}
}
30 changes: 30 additions & 0 deletions app/Controllers/ErrorController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace App\Controllers;

use App\Core\Controller;

class ErrorController extends Controller
{
public function notFound()
{
global $config;

http_response_code(404);

$this->render("pages/404.tpl", [
"pagetitle" => "Page Not Found " . $config["divider"] . " " . $config["title"]
]);
}

public function forbidden()
{
global $config;

http_response_code(403);

$this->render("pages/403.tpl", [
"pagetitle" => "Access Forbidden " . $config["divider"] . " " . $config["title"]
]);
}
}
Loading
Loading