mirror of
https://github.com/torrentpier/torrentpier
synced 2025-07-06 04:51:43 -07:00
* feat(migrations): implement Phinx database migration system and update installation process - Introduced a modern database migration system using Phinx, replacing the legacy SQL import method. - Updated `install.php` to run migrations instead of importing SQL dumps. - Added migration configuration file `phinx.php` and initial migration files for schema and data seeding. - Created a new admin panel for migration status management. - Updated UPGRADE_GUIDE.md to include migration setup instructions and benefits. - Ensured backward compatibility for existing installations while facilitating a smoother transition to the new system. * update runProcess to return process exit code * refactor(migrations): clean up whitespace and formatting in migration files - Removed unnecessary whitespace and adjusted formatting for consistency across migration files. * fix(migrations): enforce NOT NULL constraints on migration columns - Updated various migration columns to enforce NOT NULL constraints, ensuring data integrity across the schema. - Adjusted default values and nullability for multiple fields in the initial schema migration files. * refactor(database): standardize table engines to InnoDB for reliability - Updated UPGRADE_GUIDE.md to reflect the use of InnoDB for all tables, emphasizing data integrity and reliability. - Modified migration files to change table engines from MyISAM to InnoDB for various tracker and temporary tables. - Optimized session variable settings in cron jobs for InnoDB compatibility. - Ensured consistency across the schema by enforcing InnoDB usage in all relevant areas. * fix(migrations): correct MySQL integer field types to match original schema - Fix bb_forums table: forum_status (INT→TINYINT), forum_tpl_id (INT→SMALLINT) - Fix bb_users table: avatar_ext_id remains TINYINT as per original schema - Fix bb_groups table: avatar_ext_id (SMALLINT→INT) to match original INT(15) - Fix bb_topics table: topic_show_first_post, topic_allow_robots (TINYINT(1)→TINYINT UNSIGNED) - Remove incorrect 'limit' => 11 from standard INT fields, use default Phinx behavior - Fix search_size field to use proper INT type instead of maximum value hack - Correct poll table field types: vote_id (TINYINT), user_id (MEDIUMINT), vote_result (MEDIUMINT UNSIGNED) - Standardize all timestamp and ID fields to use appropriate MySQL integer types Ensures migration creates database schema identical to install/sql/mysql.sql while maintaining InnoDB engine for all tables instead of MyISAM. * fix(cache): auto-create cache directories when using FileStorage The UnifiedCacheSystem was constructing directory paths for Nette FileStorage but not creating them, causing "Directory not found" errors when accessing caches like 'bb_login_err'. FileStorage expects directories to already exist. Changes: - Add automatic directory creation using bb_mkdir() before FileStorage init - Handle both regular cache directories and SQLite parent directories - Apply to both _buildStorage() and _buildDatastoreStorage() methods - Add proper error handling with RuntimeException for failed creation - Maintain consistency with TorrentPier's directory creation patterns This ensures cache directories are created automatically when first accessed, eliminating the need for manual directory creation during deployment. Fixes: Cache initialization failures with missing directories * refactor(docs): update README for clarity and remove legacy SQL file - Improved formatting and clarity in the README, ensuring consistent line breaks and spacing. - Updated installation instructions to reflect the new migration process, emphasizing the use of `phinx` for database setup. - Removed the legacy SQL dump file `mysql.sql` and the `legacy-changes.txt` file, streamlining the installation process and reducing confusion for new users. - Enhanced the documentation to guide users through the setup process more effectively. * docs: enhance CLAUDE.md with migration details and directory updates - Updated the `/library/` section to clarify its purpose. - Added a new `/migrations/` directory section detailing database migration files managed by Phinx. - Included migration commands for running and checking migration status. - Revised the initial schema and seed data references for clarity. - Improved formatting for consistency throughout the document. * refactor(cron): remove demo_mode.php cron job and related functionality - Deleted the demo_mode.php cron job file, which was responsible for managing demo mode operations. - Added a migration to remove the demo_mode.php entry from the bb_cron table, ensuring a clean database state. - Updated the initial schema migration comment to reflect the creation of essential database schema for fresh installations. * refactor(docs): Fixed some typos * chore: update changelog generation starting from v2.4.6-alpha.4 * refactor: Changed some `php_sapi_name()` to `PHP_SAPI` constants * refactor: Extract hardcoded migrations to class property * refactor: Use `count()` to count $initialMigrations elements * feat(migrations): enhance migration management UI with new language variables - Added new language variables for migration status, instructions, and applied/pending migrations to improve user interface clarity. - Updated admin migration template to utilize these new language variables for better localization and maintainability. - Introduced a new file 'CLAUDE.md' to the cleanup process for documentation purposes. --------- Co-authored-by: Roman Kelesidis <roman25052006.kelesh@gmail.com>
161 lines
3.9 KiB
PHP
161 lines
3.9 KiB
PHP
<?php
|
||
/**
|
||
* TorrentPier – Bull-powered BitTorrent tracker engine
|
||
*
|
||
* @copyright Copyright (c) 2005-2025 TorrentPier (https://torrentpier.com)
|
||
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
|
||
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
|
||
*/
|
||
|
||
if (!defined('BB_ROOT')) {
|
||
die(basename(__FILE__));
|
||
}
|
||
|
||
/**
|
||
* Remove target file
|
||
*
|
||
* @param string $file Path to file
|
||
* @param bool $withoutOutput Hide output
|
||
*/
|
||
function removeFile(string $file, bool $withoutOutput = false): void
|
||
{
|
||
if (unlink($file)) {
|
||
if ($withoutOutput === false) {
|
||
echo "- File removed: $file" . PHP_EOL;
|
||
}
|
||
} else {
|
||
if ($withoutOutput === false) {
|
||
echo "- File cannot be removed: $file" . PHP_EOL;
|
||
}
|
||
exit;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Remove folder (recursively)
|
||
*
|
||
* @param string $dir Path to folder
|
||
* @param bool $withoutOutput Hide output
|
||
*/
|
||
function removeDir(string $dir, bool $withoutOutput = false): void
|
||
{
|
||
$it = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
|
||
$files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
|
||
|
||
foreach ($files as $file) {
|
||
if ($file->isDir()) {
|
||
removeDir($file->getPathname(), $withoutOutput);
|
||
} else {
|
||
removeFile($file->getPathname(), $withoutOutput);
|
||
}
|
||
}
|
||
|
||
if (rmdir($dir)) {
|
||
if ($withoutOutput === false) {
|
||
echo "- Folder removed: $dir" . PHP_EOL;
|
||
}
|
||
} else {
|
||
if ($withoutOutput === false) {
|
||
echo "- Folder cannot be removed: $dir" . PHP_EOL;
|
||
}
|
||
exit;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Colored console output
|
||
*
|
||
* @param string $str
|
||
* @param string $type
|
||
* @return void
|
||
*/
|
||
function out(string $str, string $type = ''): void
|
||
{
|
||
echo match ($type) {
|
||
'error' => "\033[31m$str \033[0m\n",
|
||
'success' => "\033[32m$str \033[0m\n",
|
||
'warning' => "\033[33m$str \033[0m\n",
|
||
'info' => "\033[36m$str \033[0m\n",
|
||
'debug' => "\033[90m$str \033[0m\n",
|
||
default => "$str\n",
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Run process with realtime output
|
||
*
|
||
* @param string $cmd
|
||
* @param string|null $input
|
||
* @return int
|
||
*/
|
||
function runProcess(string $cmd, ?string $input = null): int
|
||
{
|
||
$descriptorSpec = [
|
||
0 => ['pipe', 'r'],
|
||
1 => ['pipe', 'w'],
|
||
2 => ['pipe', 'w'],
|
||
];
|
||
|
||
$process = proc_open($cmd, $descriptorSpec, $pipes);
|
||
|
||
if (!is_resource($process)) {
|
||
out('- Could not start subprocess', 'error');
|
||
return -1;
|
||
}
|
||
|
||
// Write input if provided
|
||
if ($input !== null) {
|
||
fwrite($pipes[0], $input);
|
||
fclose($pipes[0]);
|
||
}
|
||
|
||
// Read and print output in real-time
|
||
while (!feof($pipes[1])) {
|
||
echo stream_get_contents($pipes[1], 1);
|
||
flush(); // Flush output buffer for immediate display
|
||
}
|
||
|
||
// Read and print error output
|
||
while (!feof($pipes[2])) {
|
||
echo stream_get_contents($pipes[2], 1);
|
||
flush();
|
||
}
|
||
|
||
fclose($pipes[1]);
|
||
fclose($pipes[2]);
|
||
|
||
return proc_close($process);
|
||
}
|
||
|
||
/**
|
||
* Setting permissions recursively
|
||
*
|
||
* @param string $dir
|
||
* @param int $dirPermissions
|
||
* @param int $filePermissions
|
||
* @return void
|
||
*/
|
||
function chmod_r(string $dir, int $dirPermissions, int $filePermissions): void
|
||
{
|
||
$dp = opendir($dir);
|
||
while ($file = readdir($dp)) {
|
||
if (($file == '.') || ($file == '..')) {
|
||
continue;
|
||
}
|
||
|
||
$fullPath = realpath($dir . '/' . $file);
|
||
if (is_dir($fullPath)) {
|
||
out("- Directory: $fullPath");
|
||
chmod($fullPath, $dirPermissions);
|
||
chmod_r($fullPath, $dirPermissions, $filePermissions);
|
||
} elseif (is_file($fullPath)) {
|
||
// out("- File: $fullPath");
|
||
chmod($fullPath, $filePermissions);
|
||
} else {
|
||
out("- Cannot find target path: $fullPath", 'error');
|
||
return;
|
||
}
|
||
}
|
||
|
||
closedir($dp);
|
||
}
|