Skip to content
Open
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
48bffc6
Update post.class.php
el-choco Nov 6, 2025
e97ff1f
file to delete not deleted Posts in DB
el-choco Nov 6, 2025
c3adfdc
Update post.class.php
el-choco Nov 6, 2025
fdbd589
integrate some functions
el-choco Nov 10, 2025
7886cbe
Update config.ini
el-choco Nov 11, 2025
c437364
Update README.md
el-choco Nov 11, 2025
67955c5
Update README.md
el-choco Nov 11, 2025
194aeea
Update README.md
el-choco Nov 11, 2025
a0023a7
Update README.md
el-choco Nov 11, 2025
658a8c4
Update README.md
el-choco Nov 11, 2025
88155cf
Update README.md
el-choco Nov 11, 2025
2625541
Update README.md
el-choco Nov 11, 2025
5ccd8b7
added some functionality
el-choco Nov 11, 2025
327b865
Update config.ini
el-choco Nov 11, 2025
15d1b09
Update README.md
el-choco Nov 11, 2025
addb373
Update README.md
el-choco Nov 11, 2025
49cee29
Update README.md
el-choco Nov 11, 2025
1dc88ae
Update README.md
el-choco Nov 11, 2025
6f3b15e
added Toggle-Button functionality
el-choco Nov 11, 2025
cf5d371
added Toggle-Button functionality
el-choco Nov 11, 2025
8cb89a5
added collapse/ expand Animation
el-choco Nov 11, 2025
5996831
added Show Less = "Show Less"
el-choco Nov 11, 2025
425fdd9
Update config.ini
el-choco Nov 11, 2025
1441ade
Delete convert_bbcode_to_markdown.php
el-choco Nov 11, 2025
8952382
Delete app/convert_bbcode_to_markdown.php
el-choco Nov 11, 2025
f643549
added function to upload more the 1 image!
el-choco Nov 12, 2025
301680e
added function to Upload more then 1 image.
el-choco Nov 12, 2025
1182e4a
added function to Upload more then 1 image.
el-choco Nov 12, 2025
83ef3a5
Bugfix Toggle Button.
el-choco Nov 12, 2025
9ff530b
Update blog service image and port configuration
el-choco Nov 12, 2025
0058d0f
changed comments language to english
el-choco Nov 13, 2025
d5a25bf
changed comments language to english
el-choco Nov 13, 2025
7270351
changed comments language to english
el-choco Nov 13, 2025
ed6e73b
Add files via upload
el-choco Nov 14, 2025
744954f
Add files via upload
el-choco Nov 14, 2025
7d9892f
Add files via upload
el-choco Nov 14, 2025
5006f0c
Add files via upload
el-choco Nov 14, 2025
67c222f
update all Files
el-choco Nov 19, 2025
daba15f
Add files via upload
el-choco Nov 19, 2025
3c3d993
update all Files
el-choco Nov 19, 2025
1dab724
Add files via upload
el-choco Nov 19, 2025
727eb0c
Add files via upload
el-choco Nov 19, 2025
a65f494
Add files via upload
el-choco Nov 19, 2025
b1a06a7
Add files via upload
el-choco Nov 19, 2025
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
41 changes: 29 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# Modified by el-choco:
---
* **add Markdown**
* **add Markdown Picker Bar**
* **add Emojis**
* **add Emoji Picker Bar**
* **remove bbcode**
* **add HTML for example** `<center>Text<center> `
* **A toggle button solution was created in the post based on the prior one: Show more, then show fewer!**
---

# blog
This is a simple self-hosted, lightweight, singe-user PHP blog, where you can create your own Facebook-like feed. Give read access to other people, and you can share rich text with photos including highlighted code or links.

Expand All @@ -10,26 +21,26 @@ In this context lightweight means:
<details>
<summary>Light theme</summary>

![screenshot](https://raw.githubusercontent.com/m1k1o/blog/master/static/screenshot-theme02-light.png)
![screenshot](https://raw.githubusercontent.com/el-choco/blog/master/static/screenshot-theme02-light.png)
</details>

<details>
<summary>Dark theme</summary>

![screenshot](https://raw.githubusercontent.com/m1k1o/blog/master/static/screenshot-theme02-dark.png)
![screenshot](https://raw.githubusercontent.com/el-choco/blog/master/static/screenshot-theme02-dark.png)
</details>

<details>
<summary>Legacy theme (compatible with older browsers)</summary>

![screenshot](https://raw.githubusercontent.com/m1k1o/blog/master/static/screenshot-theme01.png)
![screenshot](https://raw.githubusercontent.com/el-choco/blog/master/static/screenshot-theme01.png)
</details>

## Zero configuration setup
Container will run without any initial configuration needed using SQLite as database provider. For better performance consider using MySQL.

```sh
docker run -d -p 80:80 -v $PWD/data:/var/www/html/data m1k1o/blog:latest
docker run -d -p 80:80 -v $PWD/data:/var/www/html/data el-choco/blog/blog:latest
```

You can set environment variables, prefixed with `BLOG_` and uppercase. They can be found in `config.ini`.
Expand All @@ -43,7 +54,7 @@ docker run -d \
-e "BLOG_PASS=password" \
-e "BLOG_LANG=en" \
-v $PWD/data:/var/www/html/data \
m1k1o/blog:latest
el-choco/blog:latest
```

Or for docker-compose format, see [docker-compose.yml](docker-compose.yml).
Expand All @@ -56,7 +67,7 @@ You need to install [docker-compose](https://docs.docker.com/compose/install/).
version: "3"
services:
webserver:
image: m1k1o/blog:latest
image: el-choco/blog:latest
container_name: blog_apache
environment:
TZ: Europe/Vienna
Expand Down Expand Up @@ -92,7 +103,7 @@ volumes:
version: "3"
services:
webserver:
image: m1k1o/blog:latest
image: el-choco/blog:latest
container_name: blog_apache
environment:
TZ: Europe/Vienna
Expand Down Expand Up @@ -142,7 +153,7 @@ Download default config file and copy to your new `./data/` directory.

```sh
mkdir data && cd data
wget https://raw.githubusercontent.com/m1k1o/blog/master/config.ini
wget https://raw.githubusercontent.com/el-choco/blog/blog/master/config.ini
```

Now you can modify your config. Or you can set environment variables, in uppercase, starting with `BLOG_`, e.g. `BLOG_NAME: Max's blog`.
Expand Down Expand Up @@ -190,17 +201,23 @@ To check if your server is set up correctly, turn on a debug mode (in config add

# Features


* Added Markdown in texts. **( New )**
* Added Markdown-Picker-Bar **( New )**
* Added Smilies **( New )**
* Added Smilies-Picker-Bar **( New )**
* Added toggle button solution was created in the post based on the prior one: Show more, then show fewer! **( New )**
---
* Dark mode, retina ready, legacy theme available.
* Use BBcode in texts.
* Make posts available for **everyone**, **only you** or just for **friends**.
* Extra fields in post: **Feeling**, **With** and **At**.
* Hide posts from timeline so they are visible only when you need them to be.
* All pasted links will get preview with page title, description and image (can be configured proxy).
* Upload images using button *(for mobile)*.
* Upload images using drag & drop *(drop it into textarea)*.
* Upload images using CTRL + V *(paste it into textarea)*.
* Highlight code in post using `[code]..your code..[/code]`.
* Highlight your goal using `[goal]Text of your goal.[/goal]`.
$~~* Highlight code in post using `[code]..your code..[/code]`.~~$
$~~* Highlight your goal using `[goal]Text of your goal.[/goal]`.
* Use tags in posts (allowed characters `A-Za-z0-9-_` terminated by space or EOL): `#song`.
* Sort posts in reverse order (oldest first): `http://blog/#sort=reverse`.
* Filter posts by hashtags: `http://blog/#tag=songs`.
Expand All @@ -223,7 +240,7 @@ In `docker-compose.yml` file, specify your credentials and friends like this:
version: "3"
services:
blog:
image: m1k1o/blog:latest
image:el-choco/blog:latest
restart: unless-stopped
environment:
TZ: Europe/Vienna
Expand Down
38 changes: 20 additions & 18 deletions ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,31 @@
$ajax = new Ajax();

try {
$ajax->token();
$ajax->token();

// Prepare inputs
$request = array_merge(@$_POST, @$_GET);
if(empty($request["action"])){
throw new Exception("No action specified.");
}
// Prepare inputs
$request = array_merge(@$_POST, @$_GET);
if(empty($request["action"])){
throw new Exception("No action specified.");
}

$method = ['Post', $request["action"]];
$action = $request["action"];

// If method exists
if(!is_callable($method)){
throw new Exception("Method was not found.");
}
// Prüfen, ob Methode in Post existiert
if(!method_exists('Post', $action)){
throw new Exception("Method was not found.");
}

// CAll method
$response = call_user_func($method, $request);
$ajax->set_response($response);
// Statischer Aufruf der Methode
$response = Post::$action($request);

$ajax->set_response($response);

// Log
Log::put("ajax_access", $request["action"]);

// Log
Log::put("ajax_access", $request["action"]);
} catch (Exception $e) {
$ajax->set_error($e->getMessage());
$ajax->set_error($e->getMessage());
}

$ajax->json_response();
$ajax->json_response();
7 changes: 4 additions & 3 deletions app/ajax.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public function set_error($msg = null){
"msg" => $msg
];

// Incldue debug info
// Include debug info
if(ob_get_length() > 0 && Config::get_safe('debug', false)){
$this->_response["debug"] = ob_get_clean();
}
Expand Down Expand Up @@ -48,7 +48,8 @@ public function json_response(){
ob_clean();
}

header('Content-Type: application/json');
echo json_encode($this->_response);
header('Content-Type: application/json; charset=utf-8');
// WICHTIG: JSON_UNESCAPED_UNICODE damit Emojis richtig übertragen werden
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The comment is in German while the rest of the codebase uses English comments. For consistency, consider:

// IMPORTANT: JSON_UNESCAPED_UNICODE ensures emojis are transmitted correctly
Suggested change
// WICHTIG: JSON_UNESCAPED_UNICODE damit Emojis richtig übertragen werden
// IMPORTANT: JSON_UNESCAPED_UNICODE ensures emojis are transmitted correctly

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it should be in EN.

echo json_encode($this->_response, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
}
108 changes: 108 additions & 0 deletions app/cleanup_posts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php
/**
* Cleanup Posts Script
* Run this script periodically to clean up orphaned images and old data
*
* Usage: php cleanup_posts.php
* Or set up as a cron job: 0 2 * * * php /path/to/cleanup_posts.php
*/

// Include required files
require_once __DIR__ . '/config.class.php';
require_once __DIR__ . '/db.class.php';
require_once __DIR__ . '/image.class.php';
require_once __DIR__ . '/log.class.php';

// Only allow CLI execution
if (php_sapi_name() !== 'cli') {
die('This script can only be run from command line');
}

// Initialize
try {
echo "Starting cleanup process...\n";
echo "----------------------------\n\n";

// Load configuration
$config = new Config();
echo "✓ Configuration loaded\n";

// Connect to database
$db = DB::getInstance($config);
echo "✓ Database connected\n";

// Initialize classes
$image = new Image($config);
$log = new Log($config);
echo "✓ Classes initialized\n\n";

// 1. Clean up orphaned images
echo "1. Cleaning up orphaned images...\n";
$deleted_images = $image->cleanupOrphanedImages($db->getPDO());
echo " Deleted $deleted_images orphaned image(s)\n\n";

// 2. Clean up old log files
echo "2. Cleaning up old log files...\n";
$log_retention_days = $config->get('log_retention_days', 30);
$deleted_logs = $log->cleanOldLogs($log_retention_days);
echo " Deleted $deleted_logs old log file(s)\n\n";

// 3. Rotate large log files
echo "3. Rotating large log files...\n";
$log_files = $log->getLogFiles();
$rotated_count = 0;
foreach ($log_files as $log_file) {
if ($log->rotateLog($log_file)) {
$rotated_count++;
echo " Rotated: $log_file\n";
}
}
echo " Rotated $rotated_count log file(s)\n\n";

// 4. Clean up deleted user data
echo "4. Cleaning up deleted user data...\n";
$stmt = $db->prepare("
DELETE FROM posts
WHERE user_id NOT IN (SELECT id FROM users)
");
$stmt->execute();
$deleted_posts = $stmt->rowCount();
echo " Deleted $deleted_posts orphaned post(s)\n\n";

// 5. Optimize database (SQLite only)
if ($db->getType() === 'sqlite') {
echo "5. Optimizing database...\n";
$db->exec('VACUUM');
$db->exec('ANALYZE');
echo " Database optimized\n\n";
}

// 6. Database statistics
echo "6. Database statistics:\n";
$stmt = $db->query("SELECT COUNT(*) FROM users");
$user_count = $stmt->fetchColumn();
echo " Total users: $user_count\n";

$stmt = $db->query("SELECT COUNT(*) FROM posts");
$post_count = $stmt->fetchColumn();
echo " Total posts: $post_count\n";

$stmt = $db->query("SELECT COUNT(*) FROM posts WHERE is_sticky = 1");
$sticky_count = $stmt->fetchColumn();
echo " Sticky posts: $sticky_count\n\n";

// Log cleanup completion
$log->log("Cleanup completed: $deleted_images images, $deleted_logs logs, $deleted_posts orphaned posts");

echo "----------------------------\n";
echo "Cleanup completed successfully!\n";

} catch (Exception $e) {
echo "ERROR: " . $e->getMessage() . "\n";
if (isset($log)) {
$log->error("Cleanup failed: " . $e->getMessage());
}
exit(1);
}

exit(0);
Loading