diff --git a/.cliffignore b/.cliffignore
deleted file mode 100644
index 187668fd1..000000000
--- a/.cliffignore
+++ /dev/null
@@ -1,7 +0,0 @@
-9766c534bddad8e82e6d19f9bad5cf70b9887f9a
-92ce77ec0ec703c08a659419087a373f76e711f7
-2d53efc945c7747be1755d0b66557a86bdc12cbd
-602137b65129b817811b80975a369ebde3270c6d
-4eb26ae37e1f4c82a45961517ffeb54c20200408
-e59adce848a9e10ee5775254045cbbd915236b8b
-9e0a64108d62236ab07b3f8d10e8c78269b8e1d1
diff --git a/.github/ISSUE_TEMPLATE/feature---enhancement-request.md b/.github/ISSUE_TEMPLATE/feature---enhancement-request.md
deleted file mode 100644
index 9f68fc3a6..000000000
--- a/.github/ISSUE_TEMPLATE/feature---enhancement-request.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: Feature / Enhancement request
-about: Suggest an idea for TorrentPier
-title: "[Feature]"
-labels: [Feature, Enhancement]
-assignees: ''
----
diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
deleted file mode 100644
index 8e256db33..000000000
--- a/.github/workflows/cd.yml
+++ /dev/null
@@ -1,80 +0,0 @@
-name: Continuous Deployment
-
-on:
- push:
- tags:
- - "v*.*.*"
-
-jobs:
- generate-changelog:
- name: Generate changelog
- runs-on: ubuntu-22.04
- outputs:
- release_body: ${{ steps.git-cliff.outputs.content }}
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 0
-
- - name: Generate a changelog
- uses: orhun/git-cliff-action@v4
- id: git-cliff
- with:
- config: cliff.toml
- args: -vv --latest --no-exec --github-repo ${{ github.repository }}
-
- - name: Print the changelog
- run: cat "${{ steps.git-cliff.outputs.changelog }}"
-
- release:
- name: Create release
- needs: [ generate-changelog ]
- runs-on: ubuntu-22.04
-
- steps:
- - uses: actions/checkout@v4
- - name: Set the release version
- shell: bash
- run: echo "RELEASE_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV
-
- - name: Setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: '8.3'
-
- - name: Install Composer dependencies
- run: composer install --no-dev --no-progress --prefer-dist --optimize-autoloader
-
- - name: Cleanup
- run: php _cleanup.php && rm _cleanup.php
-
- - name: Create archive
- id: create-zip
- run: |
- ZIP_NAME="torrentpier-v${{ env.RELEASE_VERSION }}.zip"
- zip -r "$ZIP_NAME" . -x ".git/*"
- echo "ZIP_NAME=$ZIP_NAME" >> $GITHUB_OUTPUT
-
- - name: Publish to GitHub
- if: ${{ !contains(github.ref, '-') }}
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GITHUB_TOKEN }}
- file: ${{ steps.create-zip.outputs.ZIP_NAME }}
- overwrite: true
- tag: ${{ github.ref }}
- release_name: "v${{ env.RELEASE_VERSION }}"
- body: "${{ needs.generate-changelog.outputs.release_body }}"
-
- - name: Publish to GitHub (pre-release)
- if: ${{ contains(github.ref, '-') }}
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GITHUB_TOKEN }}
- file: ${{ steps.create-zip.outputs.ZIP_NAME }}
- overwrite: true
- tag: ${{ github.ref }}
- release_name: "v${{ env.RELEASE_VERSION }}"
- body: "${{ needs.generate-changelog.outputs.release_body }}"
- prerelease: true
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index 424e53a1f..000000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,74 +0,0 @@
-name: Continuous Integration
-
-on:
- push:
- branches:
- - master
-
-jobs:
- nightly:
- name: Nightly builds ๐ฆ
- runs-on: ubuntu-22.04
-
- steps:
- - name: Checkout code ๐ณ
- uses: actions/checkout@v4
-
- - name: Setup PHP ๐ฉ
- uses: shivammathur/setup-php@v2
- with:
- php-version: '8.3'
-
- - name: Install Composer dependencies ๐ช
- run: composer install --no-dev --no-progress --prefer-dist --optimize-autoloader
-
- - name: Get commit hash ๐
- id: get-commit-hash
- run: |
- COMMIT_HASH=$(git rev-parse --short HEAD)
- echo "COMMIT_HASH=$COMMIT_HASH" >> $GITHUB_OUTPUT
-
- - name: Cleanup
- run: php _cleanup.php && rm _cleanup.php
-
- - name: Create archive ๐
- id: create-zip
- run: |
- ZIP_NAME="torrentpier-${{ steps.get-commit-hash.outputs.COMMIT_HASH }}.zip"
- zip -r "$ZIP_NAME" . -x ".git/*"
- echo "ZIP_NAME=$ZIP_NAME" >> $GITHUB_OUTPUT
-
- - name: Upload Archive ๐ค
- uses: actions/upload-artifact@v4
- with:
- name: TorrentPier-master
- path: ${{ steps.create-zip.outputs.ZIP_NAME }}
-
- deploy:
- name: ๐ Deploy
- runs-on: ubuntu-22.04
- steps:
- - name: ๐ Get latest code
- uses: actions/checkout@v4
-
- - name: ๐ฉ Setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: '8.3'
-
- - name: ๐ Install Composer dependencies
- run: composer install --no-dev --no-progress --prefer-dist --optimize-autoloader
-
- - name: ๐ Sync files
- uses: SamKirkland/FTP-Deploy-Action@v4.3.5
- with:
- server: ${{ secrets.FTP_SERVER }}
- username: ${{ secrets.FTP_USERNAME }}
- password: ${{ secrets.FTP_PASSWORD }}
- server-dir: ${{ secrets.FTP_DIR }}
- protocol: ${{ secrets.FTP_PROTOCOL }}
- port: ${{ secrets.FTP_PORT }}
- exclude: |
- **/.git*
- **/.git*/**
- .env
diff --git a/.github/workflows/phpmd.yml b/.github/workflows/phpmd.yml
deleted file mode 100644
index 3e06d7538..000000000
--- a/.github/workflows/phpmd.yml
+++ /dev/null
@@ -1,57 +0,0 @@
-# This workflow uses actions that are not certified by GitHub.
-# They are provided by a third-party and are governed by
-# separate terms of service, privacy policy, and support
-# documentation.
-# PHPMD is a spin-off project of PHP Depend and
-# aims to be a PHP equivalent of the well known Java tool PMD.
-# What PHPMD does is: It takes a given PHP source code base
-# and look for several potential problems within that source.
-# These problems can be things like:
-# Possible bugs
-# Suboptimal code
-# Overcomplicated expressions
-# Unused parameters, methods, properties
-# More details at https://phpmd.org/
-
-name: PHPMD
-
-on:
- push:
- branches: [ "master" ]
- pull_request:
- # The branches below must be a subset of the branches above
- branches: [ "master" ]
- schedule:
- - cron: '40 0 * * 3'
-
-permissions:
- contents: read
-
-jobs:
- PHPMD:
- name: Run PHPMD scanning
- runs-on: ubuntu-latest
- permissions:
- contents: read # for checkout to fetch code
- security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
- actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
-
- - name: Setup PHP
- uses: shivammathur/setup-php@aa1fe473f9c687b6fb896056d771232c0bc41161
- with:
- coverage: none
- tools: phpmd
-
- - name: Run PHPMD
- run: phpmd . sarif codesize --reportfile phpmd-results.sarif
- continue-on-error: true
-
- - name: Upload analysis results to GitHub
- uses: github/codeql-action/upload-sarif@v2
- with:
- sarif_file: phpmd-results.sarif
- wait-for-processing: true
diff --git a/.github/workflows/schedule.yml b/.github/workflows/schedule.yml
deleted file mode 100644
index c1ad4f3c1..000000000
--- a/.github/workflows/schedule.yml
+++ /dev/null
@@ -1,41 +0,0 @@
-name: Changelog generation
-
-on:
- schedule:
- - cron: '0 0 * * *'
- workflow_dispatch:
-
-jobs:
- changelog:
- name: Changelog generation
- runs-on: ubuntu-22.04
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 0
- ref: master
- token: ${{ secrets.REPO_TOKEN }}
-
- - name: Generate a changelog
- uses: orhun/git-cliff-action@v4
- id: git-cliff
- with:
- config: cliff.toml
- args: v2.4.6-alpha.4.. --verbose
- env:
- OUTPUT: CHANGELOG.md
- GITHUB_REPO: ${{ github.repository }}
-
- - name: Print the changelog
- run: cat "${{ steps.git-cliff.outputs.changelog }}"
-
- - name: Commit changelog
- run: |
- git checkout master
- git config --local user.name 'belomaxorka'
- git config --local user.email 'roman25052006.kelesh@gmail.com'
- set +e
- git add CHANGELOG.md
- git commit -m "changelog: Update CHANGELOG.md ๐"
- git push https://${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git master
diff --git a/.htaccess b/.htaccess
deleted file mode 100644
index a689fba84..000000000
--- a/.htaccess
+++ /dev/null
@@ -1,18 +0,0 @@
-## set default server charset
-AddDefaultCharset UTF-8
-
-## folder listing access control
-Options All -Indexes
-
-## sitemap and atom rewrite
-RewriteEngine On
-RewriteRule ^sitemap.xml$ sitemap/sitemap.xml [L]
-RewriteRule ^/internal_data/atom/(.*) /atom$1 [L]
-
-## deny access to git folder
-RedirectMatch 404 /\\.git(/|$)
-
-## deny access to system files
-
-Require all denied
-
diff --git a/_cleanup.php b/_cleanup.php
deleted file mode 100644
index d9802822a..000000000
--- a/_cleanup.php
+++ /dev/null
@@ -1,57 +0,0 @@
-php ' . basename(__FILE__) . ' in CLI mode');
-}
-
-// Get all constants
-require_once BB_ROOT . 'library/defines.php';
-
-// Include CLI functions
-require INC_DIR . '/functions_cli.php';
-
-// Welcoming message
-out("--- Release creation tool ---\n", 'info');
-
-$configFile = BB_PATH . '/library/config.php';
-
-if (!is_file($configFile)) {
- out('- Config file ' . basename($configFile) . ' not found', 'error');
- exit;
-}
-if (!is_readable($configFile)) {
- out('- Config file ' . basename($configFile) . ' is not readable', 'error');
- exit;
-}
-if (!is_writable($configFile)) {
- out('- Config file ' . basename($configFile) . ' is not writable', 'error');
- exit;
-}
-
-// Ask for version
-fwrite(STDOUT, 'Enter version number (e.g, v2.4.0): ');
-$version = trim(fgets(STDIN));
-
-if (empty($version)) {
- out("- Version cannot be empty. Please enter a valid version number", 'error');
- exit;
-} else {
- // Add 'v' prefix if missing
- if (!str_starts_with($version, 'v')) {
- $version = 'v' . $version;
- }
-
- out("- Using version: $version", 'info');
-}
-
-// Ask for version emoji
-fwrite(STDOUT, 'Enter version emoji: ');
-$versionEmoji = trim(fgets(STDIN));
-
-if (!empty($versionEmoji)) {
- out("- Using version emoji: $versionEmoji", 'info');
-}
-
-// Ask for release date or use today's date
-fwrite(STDOUT, "Enter release date (e.g. 25-05-2025), leave empty to use today's date: ");
-$date = trim(fgets(STDIN));
-
-if (empty($date)) {
- $date = date('d-m-Y');
- out("- Using current date: $date", 'info');
-} else {
- // Validate date format (dd-mm-yyyy)
- $dateObj = DateTime::createFromFormat('d-m-Y', $date);
- if (!$dateObj || $dateObj->format('d-m-Y') !== $date) {
- out("- Invalid date format. Expected format: DD-MM-YYYY", 'error');
- exit;
- }
-
- out("- Using date: $date", 'info');
-}
-
-// Read config file content
-$content = file_get_contents($configFile);
-
-// Update version
-$content = preg_replace(
- "/\\\$bb_cfg\['tp_version'\]\s*=\s*'[^']*';/",
- "\$bb_cfg['tp_version'] = '$version';",
- $content
-);
-
-// Update release date
-$content = preg_replace(
- "/\\\$bb_cfg\['tp_release_date'\]\s*=\s*'[^']*';/",
- "\$bb_cfg['tp_release_date'] = '$date';",
- $content
-);
-
-// Save updated config
-$bytesWritten = file_put_contents($configFile, $content);
-
-if ($bytesWritten === false) {
- out("- Failed to write to config file", 'error');
- exit;
-}
-
-if ($bytesWritten === 0) {
- out("- Config file was not updated (0 bytes written)", 'error');
- exit;
-}
-
-out("\n- Config file has been updated!", 'success');
-
-// Update CHANGELOG.md
-runProcess('npx git-cliff v2.4.6-alpha.4.. --config cliff.toml --tag "' . $version . '" > CHANGELOG.md');
-
-// Git add & commit
-runProcess('git add -A && git commit -m "release: ' . escapeshellarg($version) . (!empty($versionEmoji) ? (' ' . $versionEmoji) : '') . '"');
-
-// Git tag
-runProcess("git tag -a \"$version\" -m \"Release $version\"");
-runProcess("git tag -v \"$version\"");
-
-// Git push
-runProcess("git push origin master");
-runProcess("git push origin $version");
-
-out("\n- Release $version has been successfully prepared, committed and pushed!", 'success');
diff --git a/cliff.toml b/cliff.toml
deleted file mode 100644
index 1798567f1..000000000
--- a/cliff.toml
+++ /dev/null
@@ -1,126 +0,0 @@
-# git-cliff ~ TorrentPier configuration file
-# https://git-cliff.org/docs/configuration
-#
-# Lines starting with "#" are comments.
-# Configuration options are organized into tables and keys.
-# See documentation for more information on available options.
-
-[remote.github]
-owner = "torrentpier"
-repo = "torrentpier"
-
-[changelog]
-# template for the changelog header
-header = """
-[](https://github.com/torrentpier)\n
-# ๐ Change Log\n
-"""
-# template for the changelog body
-# https://keats.github.io/tera/docs/#introduction
-body = """
-{%- macro remote_url() -%}
- https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}
-{%- endmacro -%}
-
-{%- macro nightly_url() -%}
- https://nightly.link/{{ remote.github.owner }}/{{ remote.github.repo }}/workflows/ci/master/TorrentPier-master
-{%- endmacro -%}
-
-{% macro print_commit(commit) -%}
- - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
- {% if commit.breaking %}[**breaking**] {% endif %}\
- {{ commit.message | upper_first }} - \
- ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
-{% endmacro -%}
-
-{% if version %}\
- {% if previous.version %}\
- ## [{{ version }}]\
- ({{ self::remote_url() }}/compare/{{ previous.version }}..{{ version }}) ({{ timestamp | date(format="%Y-%m-%d") }})
- {% else %}\
- ## {{ version }} ({{ timestamp | date(format="%Y-%m-%d") }})
- {% endif %}\
-{% else %}\
- ## [nightly]({{ self::nightly_url() }})
-{% endif %}\
-
-{% for group, commits in commits | group_by(attribute="group") %}
- ### {{ group | striptags | trim | upper_first }}
- {% for commit in commits
- | filter(attribute="scope")
- | sort(attribute="scope") %}
- {{ self::print_commit(commit=commit) }}
- {%- endfor %}
- {% for commit in commits %}
- {%- if not commit.scope -%}
- {{ self::print_commit(commit=commit) }}
- {% endif -%}
- {% endfor -%}
-{% endfor -%}
-{%- if github -%}
-{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
- ## New Contributors โค๏ธ
-{% endif %}\
-{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}
- * @{{ contributor.username }} made their first contribution
- {%- if contributor.pr_number %} in \
- [#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
- {%- endif %}
-{%- endfor -%}
-{%- endif %}
-
-
-"""
-# template for the changelog footer
-footer = """
-"""
-# remove the leading and trailing whitespace from the templates
-trim = true
-# postprocessors
-postprocessors = [
- { pattern = '', replace = "https://github.com/torrentpier/torrentpier" }, # replace repository URL
-]
-
-[git]
-# parse the commits based on https://www.conventionalcommits.org
-conventional_commits = true
-# filter out the commits that are not conventional
-filter_unconventional = true
-# process each line of a commit as an individual commit
-split_commits = false
-# regex for preprocessing the commit messages
-commit_preprocessors = [
- # Replace issue numbers
- { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/pull/${2}))" },
- # Check spelling of the commit with https://github.com/crate-ci/typos
- # If the spelling is incorrect, it will be automatically fixed.
- # { pattern = '.*', replace_command = 'typos --write-changes -' },
-]
-# regex for parsing and grouping commits
-commit_parsers = [
- { message = "^feat", group = "๐ Features" },
- { message = "^fix", group = "๐ Bug Fixes" },
- { message = "^doc", group = "๐ Documentation" },
- { message = "^perf", group = "โก Performance" },
- { message = "^refactor", group = "๐ Refactor" },
- { message = "^style", group = "๐จ Styling" },
- { message = "^test", group = "๐งช Testing" },
- { message = "^ignore|^release|^changelog", skip = true },
- { message = "^chore|^ci|^misc", group = "โ๏ธ Miscellaneous" },
- { body = ".*security", group = "๐ก๏ธ Security" },
- { message = "^revert", group = "โ๏ธ Revert" },
- { message = "^crowdin|^crodwin", group = "๐ณ New translations" }, # crowdin pulls supporting
- { message = "^Composer", group = "๐ฆ Dependencies" }, # dependabot pulls supporting
- { message = "^rem|^drop|^removed", group = "๐๏ธ Removed" },
- { message = ".*", group = "๐ผ Other" },
-]
-# protect breaking changes from being skipped due to matching a skipping commit_parser
-protect_breaking_commits = false
-# filter out the commits that are not matched by commit parsers
-filter_commits = false
-# regex for matching git tags
-tag_pattern = "v[0-9].*"
-# sort the tags topologically
-topo_order = false
-# sort the commits inside sections by oldest/newest order
-sort_commits = "newest"
diff --git a/config/README.md b/config/README.md
deleted file mode 100644
index 1d4ccad07..000000000
--- a/config/README.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# Application Configuration
-
-System configuration files using PHP arrays for type safety and IDE support:
-
-- **app.php**: Core application settings
- - Site name, URL, timezone
- - Debug mode, environment
- - Feature flags and toggles
-
-- **database.php**: Database connection settings
- - Multiple connection definitions
- - Read/write splitting configuration
- - Connection pooling settings
-
-- **cache.php**: Cache driver configurations
- - Redis, Memcached, file-based settings
- - TTL defaults per cache type
- - Cache key prefixes
-
-- **tracker.php**: BitTorrent tracker settings
- - Announce intervals
- - Peer limits
- - Ratio requirements
-
-- **environments/**: Environment-specific overrides
- - Development, staging, production settings
- - Local developer configurations
-
-Example database configuration:
-```php
- env('DB_CONNECTION', 'mysql'),
-
- 'connections' => [
- 'mysql' => [
- 'driver' => 'mysql',
- 'host' => env('DB_HOST', '127.0.0.1'),
- 'port' => env('DB_PORT', 3306),
- 'database' => env('DB_DATABASE', 'tp'),
- 'username' => env('DB_USERNAME', 'root'),
- 'password' => env('DB_PASSWORD', ''),
- 'charset' => 'utf8mb4',
- 'collation' => 'utf8mb4_unicode_ci',
- 'options' => [
- PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
- PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
- PDO::ATTR_EMULATE_PREPARES => false,
- ],
- ],
- ],
-];
-```
\ No newline at end of file
diff --git a/config/container.php b/config/container.php
deleted file mode 100644
index cc72536ee..000000000
--- a/config/container.php
+++ /dev/null
@@ -1,26 +0,0 @@
- env('APP_ENV', 'development'),
- 'debug' => env('APP_DEBUG', false),
-
- // Enable/disable features
- 'autowiring' => true,
- 'annotations' => false,
-
- // Compilation settings for production
- 'compilation_dir' => __DIR__ . '/../internal_data/cache/container',
- 'proxies_dir' => __DIR__ . '/../internal_data/cache/proxies',
-
- // Additional definition files to load
- 'definition_files' => [
- // Add custom definition files here
- // __DIR__ . '/services/custom.php',
- ],
-
- // Container-specific settings
- 'container' => [
- // Add any PHP-DI specific settings here
- ],
-];
diff --git a/config/environments/.keep b/config/environments/.keep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/config/services.php b/config/services.php
deleted file mode 100644
index 5070cdf57..000000000
--- a/config/services.php
+++ /dev/null
@@ -1,30 +0,0 @@
- factory(function () {
- // $logger = new \Monolog\Logger('torrentpier');
- // $logger->pushHandler(new \Monolog\Handler\StreamHandler(__DIR__ . '/../internal_data/logs/app.log'));
- // return $logger;
- // }),
-
- // Configuration service example
- // 'config' => factory(function () {
- // return [
- // 'app' => require __DIR__ . '/app.php',
- // 'database' => require __DIR__ . '/database.php',
- // 'cache' => require __DIR__ . '/cache.php',
- // ];
- // }),
-
- // Interface to implementation binding example
- // 'ServiceInterface' => autowire('ConcreteService'),
-];
diff --git a/docs/examples/di-container-usage.php b/docs/examples/di-container-usage.php
deleted file mode 100644
index fcfc0bdf9..000000000
--- a/docs/examples/di-container-usage.php
+++ /dev/null
@@ -1,99 +0,0 @@
-has('some.service'); // Check if service exists
-
-// ===== PHASE 2: Domain Modeling (FUTURE) =====
-
-// 3. Repository interfaces (when implemented in Domain layer)
-// $userRepository = app('TorrentPier\Domain\User\Repository\UserRepositoryInterface');
-// $torrentRepository = app('TorrentPier\Domain\Tracker\Repository\TorrentRepositoryInterface');
-// $forumRepository = app('TorrentPier\Domain\Forum\Repository\ForumRepositoryInterface');
-
-// ===== PHASE 3: Application Services (FUTURE) =====
-
-// 4. Command/Query handlers (when implemented)
-// $registerUserHandler = app('TorrentPier\Application\User\Handler\RegisterUserHandler');
-// $announceHandler = app('TorrentPier\Application\Tracker\Handler\ProcessAnnounceHandler');
-// $createPostHandler = app('TorrentPier\Application\Forum\Handler\CreatePostHandler');
-
-// 5. Making command instances with parameters
-// $command = $container->make('TorrentPier\Application\User\Command\RegisterUserCommand', [
-// 'username' => 'john_doe',
-// 'email' => 'john@example.com',
-// 'password' => 'secure_password'
-// ]);
-
-// ===== PHASE 4: Infrastructure (FUTURE) =====
-
-// 6. Database and cache (when infrastructure is implemented)
-// $database = app('database.connection.default');
-// $cache = app('cache.factory')('forum'); // Get cache instance for 'forum' namespace
-
-// ===== PHASE 5: Presentation (FUTURE) =====
-
-// 7. Controllers (when implemented)
-// $userController = app('TorrentPier\Presentation\Http\Controllers\Api\UserController');
-// $trackerController = app('TorrentPier\Presentation\Http\Controllers\Web\TrackerController');
-
-// ===== TESTING EXAMPLES =====
-
-// 8. Testing with custom container (works now)
-$testContainer = ContainerFactory::create([
- 'definitions' => [
- 'test.service' => \DI\factory(function () {
- return new class {
- public function test() { return 'test'; }
- };
- }),
- ],
- 'environment' => 'testing',
-]);
-
-// 9. Safe service resolution (works now)
-try {
- $service = app('optional.service');
-} catch (RuntimeException $e) {
- // Service not found, handle gracefully
- $service = null;
-}
-
-// ===== LEGACY INTEGRATION (CURRENT) =====
-
-// 10. Integration with legacy code
-// In legacy files, after including common.php or similar:
-if (!Bootstrap::getContainer()) {
- Bootstrap::init(BB_ROOT ?? __DIR__ . '/../..');
-}
-
-// 11. Method injection (works now if service exists)
-class ExampleService
-{
- public function processData(string $data)
- {
- // Container can inject dependencies when calling this method
- return "Processed: $data";
- }
-}
-
-$exampleService = new ExampleService();
-$result = $container->call([$exampleService, 'processData'], [
- 'data' => 'test data'
-]);
\ No newline at end of file
diff --git a/docs/specs/hexagonal-architecture-spec.md b/docs/specs/hexagonal-architecture-spec.md
deleted file mode 100644
index 07dc0a672..000000000
--- a/docs/specs/hexagonal-architecture-spec.md
+++ /dev/null
@@ -1,436 +0,0 @@
-# Hexagonal Architecture Directory Structure Specification
-
-## Overview
-
-This document specifies the new hexagonal architecture directory structure for TorrentPier 3.0. The structure follows Domain-Driven Design (DDD) principles and implements a clean separation of concerns through hexagonal architecture (ports and adapters pattern).
-
-## Directory Structure
-
-```
-/src/
-โโโ Domain/ # Core business logic - no framework dependencies
-โ โโโ Forum/ # Forum bounded context
-โ โ โโโ Model/ # Aggregates and entities
-โ โ โโโ ValueObject/ # Value objects (PostId, ThreadTitle, etc.)
-โ โ โโโ Repository/ # Repository interfaces
-โ โ โโโ Exception/ # Domain-specific exceptions
-โ โโโ Tracker/ # BitTorrent tracker bounded context
-โ โ โโโ Model/ # Torrent, Peer aggregates
-โ โ โโโ ValueObject/ # InfoHash, PeerId, etc.
-โ โ โโโ Repository/ # Repository interfaces
-โ โ โโโ Exception/ # Tracker-specific exceptions
-โ โโโ User/ # User management bounded context
-โ โ โโโ Model/ # User aggregate
-โ โ โโโ ValueObject/ # UserId, Email, Username
-โ โ โโโ Repository/ # User repository interface
-โ โ โโโ Exception/ # Authentication/authorization exceptions
-โ โโโ Shared/ # Shared kernel - minimal shared concepts
-โ โโโ Model/ # Base classes (AggregateRoot, Entity)
-โ โโโ ValueObject/ # Common value objects (Id, DateTime)
-โ โโโ Event/ # Domain events base classes
-โ
-โโโ Application/ # Application services - orchestration layer
-โ โโโ Forum/
-โ โ โโโ Command/ # Commands (CreatePost, LockThread)
-โ โ โโโ Query/ # Queries (GetThreadList, SearchPosts)
-โ โ โโโ Handler/ # Command and query handlers
-โ โโโ Tracker/
-โ โ โโโ Command/ # Commands (RegisterTorrent, ProcessAnnounce)
-โ โ โโโ Query/ # Queries (GetPeerList, GetTorrentStats)
-โ โ โโโ Handler/ # Command and query handlers
-โ โโโ User/
-โ โโโ Command/ # Commands (RegisterUser, ChangePassword)
-โ โโโ Query/ # Queries (GetUserProfile, SearchUsers)
-โ โโโ Handler/ # Command and query handlers
-โ
-โโโ Infrastructure/ # External concerns and implementations
-โ โโโ Persistence/ # Data persistence layer
-โ โ โโโ Database/ # Database adapter and connection management
-โ โ โโโ Migration/ # Database migrations
-โ โ โโโ Repository/ # Repository implementations
-โ โโโ Cache/ # Caching implementations
-โ โ โโโ Redis/ # Redis adapter
-โ โ โโโ Memcached/ # Memcached adapter
-โ โ โโโ File/ # File-based cache adapter
-โ โโโ Email/ # Email service implementations
-โ โ โโโ Template/ # Email templates
-โ โ โโโ Transport/ # SMTP, API transports
-โ โโโ FileStorage/ # File storage abstractions
-โ โโโ Local/ # Local filesystem storage
-โ โโโ S3/ # AWS S3 storage adapter
-โ
-โโโ Presentation/ # User interface layer
- โโโ Http/ # Web interface
- โ โโโ Controllers/ # HTTP controllers
- โ โ โโโ Admin/ # Admin panel controllers
- โ โ โโโ Api/ # REST API controllers
- โ โ โโโ Web/ # Web UI controllers
- โ โโโ Middleware/ # HTTP middleware (auth, CORS, etc.)
- โ โโโ Requests/ # Request DTOs and validation
- โ โโโ Responses/ # Response transformers
- โโโ Cli/ # Command line interface
- โโโ Commands/ # Console commands
-
-# Additional directories (outside /src/)
-/config/ # Application configuration
-โโโ app.php # Main application settings
-โโโ database.php # Database connections
-โโโ cache.php # Cache drivers configuration
-โโโ tracker.php # BitTorrent tracker settings
-โโโ environments/ # Environment-specific overrides
-
-/tests/ # Test suites (Pest)
-โโโ Unit/ # Unit tests (mirrors src/ structure)
-โโโ Feature/ # Feature/Integration tests
-โโโ Pest.php # Pest configuration
-โโโ TestCase.php # Base test case
-```
-
-## Directory README.md Templates
-
-### Domain Layer READMEs
-
-#### `/src/Domain/README.md`
-```markdown
-# Domain Layer
-
-This directory contains the core business logic of TorrentPier. Code here should:
-- Have no dependencies on frameworks or infrastructure
-- Represent pure business rules and domain models
-- Be testable in isolation
-- Use only PHP language features and domain concepts
-
-## Bounded Contexts
-- **Forum**: Discussion forums, posts, threads
-- **Tracker**: BitTorrent tracking, peers, torrents
-- **User**: User management, authentication, profiles
-- **Shared**: Minimal shared concepts between contexts
-```
-
-#### `/src/Domain/Tracker/Model/README.md`
-```markdown
-# Tracker Domain Models
-
-Contains aggregate roots and entities for the BitTorrent tracker:
-- `Torrent`: Aggregate root for torrent management
-- `Peer`: Entity representing a BitTorrent peer
-- `TorrentStatistics`: Value object for torrent stats
-
-Example:
-```php
-class Torrent extends AggregateRoot
-{
- public function announce(Peer $peer, AnnounceEvent $event): void
- {
- // Business logic for handling announces
- }
-}
-```
-
-#### `/src/Domain/Tracker/ValueObject/README.md`
-```markdown
-# Tracker Value Objects
-
-Immutable objects representing domain concepts:
-- `InfoHash`: 20-byte torrent identifier
-- `PeerId`: Peer client identifier
-- `Port`: Network port (1-65535)
-- `BytesTransferred`: Upload/download bytes
-
-Example:
-```php
-final class InfoHash
-{
- private string $hash;
-
- public function __construct(string $hash)
- {
- $this->guardAgainstInvalidHash($hash);
- $this->hash = $hash;
- }
-}
-```
-
-### Application Layer READMEs
-
-#### `/src/Application/README.md`
-```markdown
-# Application Layer
-
-Contains application services that orchestrate domain objects to fulfill use cases.
-- Commands: Write operations that change state
-- Queries: Read operations for data retrieval
-- Handlers: Process commands and queries
-
-This layer should:
-- Coordinate domain objects
-- Handle transactions
-- Dispatch domain events
-- Not contain business logic
-```
-
-#### `/src/Application/Tracker/Command/README.md`
-```markdown
-# Tracker Commands
-
-Commands representing write operations:
-- `RegisterTorrentCommand`: Register new torrent
-- `UpdateTorrentCommand`: Modify torrent details
-- `DeleteTorrentCommand`: Remove torrent from tracker
-
-Example:
-```php
-final class RegisterTorrentCommand
-{
- public function __construct(
- public readonly string $infoHash,
- public readonly int $uploaderId,
- public readonly string $name,
- public readonly int $size
- ) {}
-}
-```
-
-### Infrastructure Layer READMEs
-
-#### `/src/Infrastructure/README.md`
-```markdown
-# Infrastructure Layer
-
-Technical implementations and external service adapters:
-- Database persistence
-- Caching mechanisms
-- Email services
-- File storage
-- Third-party integrations
-
-Infrastructure depends on domain, not vice versa.
-```
-
-#### `/src/Infrastructure/Persistence/Repository/README.md`
-```markdown
-# Repository Implementations
-
-Concrete implementations of domain repository interfaces:
-- Uses database adapter for persistence
-- Implements caching strategies
-- Handles query optimization
-- Supports multiple database backends
-
-Example:
-```php
-class TorrentRepository implements TorrentRepositoryInterface
-{
- public function __construct(
- private DatabaseAdapterInterface $db
- ) {}
-
- public function findByInfoHash(InfoHash $infoHash): ?Torrent
- {
- // Database adapter implementation
- $row = $this->db->select('torrents')
- ->where('info_hash', $infoHash->toString())
- ->first();
-
- return $row ? $this->hydrateFromRow($row) : null;
- }
-}
-```
-
-### Presentation Layer READMEs
-
-#### `/src/Presentation/README.md`
-```markdown
-# Presentation Layer
-
-User interface implementations:
-- HTTP controllers for web and API
-- CLI commands for console operations
-- Request/response handling
-- Input validation
-- Output formatting
-
-This layer translates between external format and application format.
-```
-
-#### `/src/Presentation/Http/Controllers/Api/README.md`
-```markdown
-# API Controllers
-
-RESTful API endpoints following OpenAPI specification:
-- JSON request/response format
-- Proper HTTP status codes
-- HATEOAS where applicable
-- Rate limiting aware
-
-Example:
-```php
-class UserController
-{
- public function register(RegisterRequest $request): JsonResponse
- {
- $command = new RegisterUserCommand(
- $request->getUsername(),
- $request->getEmail(),
- $request->getPassword()
- );
-
- $userId = $this->commandBus->handle($command);
-
- return new JsonResponse([
- 'id' => $userId,
- 'username' => $request->getUsername()
- ], Response::HTTP_CREATED);
- }
-}
-```
-
-#### `/src/Presentation/Http/Controllers/Admin/README.md`
-```markdown
-# Admin Panel Controllers
-
-Administrative interface controllers with enhanced security:
-- Role-based access control (RBAC)
-- Audit logging for all actions
-- Additional authentication checks
-- Administrative dashboards and reports
-
-Example:
-```php
-class AdminUserController
-{
- public function index(Request $request): Response
- {
- $query = new GetUsersQuery(
- page: $request->getPage(),
- filters: $request->getFilters()
- );
-
- $users = $this->queryBus->handle($query);
-
- return $this->render('admin/users/index', [
- 'users' => $users,
- 'filters' => $request->getFilters()
- ]);
- }
-}
-```
-
-#### `/config/README.md`
-```markdown
-# Application Configuration
-
-System configuration files using PHP arrays for type safety and IDE support:
-
-- **app.php**: Core application settings
- - Site name, URL, timezone
- - Debug mode, environment
- - Feature flags and toggles
-
-- **database.php**: Database connection settings
- - Multiple connection definitions
- - Read/write splitting configuration
- - Connection pooling settings
-
-- **cache.php**: Cache driver configurations
- - Redis, Memcached, file-based settings
- - TTL defaults per cache type
- - Cache key prefixes
-
-- **tracker.php**: BitTorrent tracker settings
- - Announce intervals
- - Peer limits
- - Ratio requirements
-
-- **environments/**: Environment-specific overrides
- - Development, staging, production settings
- - Local developer configurations
-
-Example database configuration:
-```php
- env('DB_CONNECTION', 'mysql'),
-
- 'connections' => [
- 'mysql' => [
- 'driver' => 'mysql',
- 'host' => env('DB_HOST', '127.0.0.1'),
- 'port' => env('DB_PORT', 3306),
- 'database' => env('DB_DATABASE', 'tp'),
- 'username' => env('DB_USERNAME', 'root'),
- 'password' => env('DB_PASSWORD', ''),
- 'charset' => 'utf8mb4',
- 'collation' => 'utf8mb4_unicode_ci',
- 'options' => [
- PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
- PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
- PDO::ATTR_EMULATE_PREPARES => false,
- ],
- ],
- ],
-];
-```
-
-## Implementation Order
-
-1. **Phase 1: Foundation**
-
- - Create directory structure
- - Set up base classes in Domain/Shared
- - Configure dependency injection
-
-2. **Phase 2: Domain Modeling**
-
- - Implement core aggregates
- - Create value objects
- - Define repository interfaces
-
-3. **Phase 3: Application Services**
-
- - Create commands and queries
- - Implement handlers
- - Set up event dispatching
-
-4. **Phase 4: Infrastructure**
-
- - Implement repositories
- - Configure database adapter
- - Set up caching
-
-5. **Phase 5: Presentation**
-
- - Create controllers
- - Implement middleware
- - Build CLI commands
-
-## Migration Strategy
-
-- Existing code remains in current locations
-- New features built in hexagonal architecture
-- Gradual migration using strangler fig pattern
-- Legacy adapters bridge old and new code
-- Feature flags control rollout
-
-## Key Principles
-
-1. **Dependency Rule**: Dependencies point inward (Presentation โ Application โ Domain)
-2. **Domain Isolation**: Business logic has no framework dependencies
-3. **Interface Segregation**: Small, focused interfaces
-4. **CQRS**: Separate read and write models
-5. **Event-Driven**: Domain events for cross-context communication
-
-## Testing Strategy
-
-- **Domain**: Pure unit tests, no mocks needed
-- **Application**: Unit tests with mocked repositories
-- **Infrastructure**: Integration tests with real services
-- **Presentation**: E2E tests for user journeys
-
-## Notes for Developers
-
-- Start reading code from the Domain layer
-- Business rules live in aggregates, not services
-- Use value objects for type safety
-- Prefer composition over inheritance
-- Keep bounded contexts loosely coupled
diff --git a/install/Caddyfile b/install/Caddyfile
deleted file mode 100644
index 683d69994..000000000
--- a/install/Caddyfile
+++ /dev/null
@@ -1,27 +0,0 @@
-# Example Caddy configuration for TorrentPier
-
-example.com {
- root * /path/to/root
- encode gzip zstd
- php_fastcgi unix//run/php/php-fpm.sock
- try_files {path} {path}/ /index.php?{query}
- file_server
-
- @blocked {
- path /install/* /internal_data/* /library/*
- path /.ht* /.en*
- path /.git/*
- path *.sql *.tpl *.db *.inc *.log *.md
- }
- respond @blocked 404
-
- redir /sitemap.xml /sitemap/sitemap.xml
-
- @html_css_js {
- path *.html *.css *.js *.json *.xml *.txt
- }
- header @html_css_js Content-Type "{mime}; charset=utf-8"
-}
-
-# Refer to the Caddy docs for more information:
-# https://caddyserver.com/docs/caddyfile
diff --git a/install/nginx.conf b/install/nginx.conf
deleted file mode 100644
index 49a407ba4..000000000
--- a/install/nginx.conf
+++ /dev/null
@@ -1,39 +0,0 @@
-# Example nginx configuration for TorrentPier
-
-server {
- listen 80; # port
- server_name example.com; # your domain
- root /path/to/root; # folder with TorrentPier installed
- index index.php;
- charset utf-8;
-
- location / {
- try_files \$uri \$uri/ /index.php?\$args;
- }
-
- location ~ \/(install|internal_data|library)\/ {
- return 404;
- }
-
- location ~ /\.(ht|en) {
- return 404;
- }
-
- location ~ /\.git {
- return 404;
- }
-
- location ~ \.(.*sql|tpl|db|inc|log|md)$ {
- return 404;
- }
-
- rewrite ^/sitemap.xml$ /sitemap/sitemap.xml;
-
- location ~ \.php$ {
- include fastcgi_params;
- fastcgi_pass unix:/run/php/php-fpm.sock;
- fastcgi_index index.php;
- fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
- include fastcgi_params;
- }
-}
diff --git a/phpunit.xml b/phpunit.xml
deleted file mode 100644
index e6198e0e7..000000000
--- a/phpunit.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
- ./tests
-
-
-
-
- app
- src
-
-
-
diff --git a/src/Application/Forum/Command/README.md b/src/Application/Forum/Command/README.md
deleted file mode 100644
index eae098d4a..000000000
--- a/src/Application/Forum/Command/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Forum Commands
-
-Commands representing write operations:
-
-- `CreateThreadCommand`: Start new discussion
-- `CreatePostCommand`: Reply to thread
-- `EditPostCommand`: Modify existing post
-- `LockThreadCommand`: Lock thread from replies
-- `DeletePostCommand`: Remove post
-
-Commands are simple DTOs containing operation data.
\ No newline at end of file
diff --git a/src/Application/Forum/Handler/README.md b/src/Application/Forum/Handler/README.md
deleted file mode 100644
index 4af804611..000000000
--- a/src/Application/Forum/Handler/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Forum Handlers
-
-Command and query handlers for forum operations:
-
-- `CreateThreadHandler`: Handles thread creation
-- `CreatePostHandler`: Handles post creation
-- `GetThreadListHandler`: Retrieves thread listings
-
-Handlers coordinate between domain and infrastructure layers.
\ No newline at end of file
diff --git a/src/Application/Forum/Query/README.md b/src/Application/Forum/Query/README.md
deleted file mode 100644
index 845ef3948..000000000
--- a/src/Application/Forum/Query/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Forum Queries
-
-Read-only queries for forum data:
-
-- `GetThreadListQuery`: Paginated thread listing
-- `GetPostsByThreadQuery`: Thread posts with pagination
-- `SearchPostsQuery`: Full-text post search
-- `GetForumStatsQuery`: Forum statistics
-
-Queries return DTOs optimized for presentation.
\ No newline at end of file
diff --git a/src/Application/README.md b/src/Application/README.md
deleted file mode 100644
index f7a27973c..000000000
--- a/src/Application/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Application Layer
-
-Contains application services that orchestrate domain objects to fulfill use cases.
-
-- Commands: Write operations that change state
-- Queries: Read operations for data retrieval
-- Handlers: Process commands and queries
-
-This layer should:
-
-- Coordinate domain objects
-- Handle transactions
-- Dispatch domain events
-- Not contain business logic
\ No newline at end of file
diff --git a/src/Application/Tracker/Command/README.md b/src/Application/Tracker/Command/README.md
deleted file mode 100644
index 800c6579d..000000000
--- a/src/Application/Tracker/Command/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Tracker Commands
-
-Commands representing write operations:
-
-- `RegisterTorrentCommand`: Register new torrent
-- `UpdateTorrentCommand`: Modify torrent details
-- `DeleteTorrentCommand`: Remove torrent from tracker
-
-Example:
-
-```php
-final class RegisterTorrentCommand
-{
- public function __construct(
- public readonly string $infoHash,
- public readonly int $uploaderId,
- public readonly string $name,
- public readonly int $size
- ) {}
-}
-```
\ No newline at end of file
diff --git a/src/Application/Tracker/Handler/README.md b/src/Application/Tracker/Handler/README.md
deleted file mode 100644
index b30755d33..000000000
--- a/src/Application/Tracker/Handler/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Tracker Handlers
-
-Command and query handlers for tracker operations:
-
-- `RegisterTorrentHandler`: Processes torrent registration
-- `GetTorrentDetailsHandler`: Retrieves torrent information
-- `UpdateTorrentHandler`: Handles torrent updates
-
-Note: High-performance announce operations bypass this layer.
\ No newline at end of file
diff --git a/src/Application/Tracker/Query/README.md b/src/Application/Tracker/Query/README.md
deleted file mode 100644
index 05e42e39f..000000000
--- a/src/Application/Tracker/Query/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Tracker Queries
-
-Read-only queries for tracker data:
-
-- `GetTorrentDetailsQuery`: Single torrent information
-- `GetPeerListQuery`: Active peers for torrent
-- `GetTorrentStatsQuery`: Download/upload statistics
-- `SearchTorrentsQuery`: Browse and filter torrents
-
-Optimized for high-performance read operations.
\ No newline at end of file
diff --git a/src/Application/User/Command/README.md b/src/Application/User/Command/README.md
deleted file mode 100644
index fbf0342be..000000000
--- a/src/Application/User/Command/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# User Commands
-
-Commands for user management operations:
-
-- `RegisterUserCommand`: New user registration
-- `ChangePasswordCommand`: Password update
-- `UpdateProfileCommand`: Profile modifications
-- `ActivateUserCommand`: Account activation
-- `BanUserCommand`: User suspension
-
-These commands trigger domain events for cross-context synchronization.
\ No newline at end of file
diff --git a/src/Application/User/Handler/README.md b/src/Application/User/Handler/README.md
deleted file mode 100644
index 8f34ce418..000000000
--- a/src/Application/User/Handler/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# User Handlers
-
-Command and query handlers for user operations:
-
-- `RegisterUserHandler`: Processes user registration
-- `ChangePasswordHandler`: Handles password changes
-- `GetUserProfileHandler`: Retrieves user profiles
-
-Handlers manage transactions and event dispatching.
\ No newline at end of file
diff --git a/src/Application/User/Query/README.md b/src/Application/User/Query/README.md
deleted file mode 100644
index 1307a51ec..000000000
--- a/src/Application/User/Query/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# User Queries
-
-Read operations for user data:
-
-- `GetUserProfileQuery`: User profile details
-- `SearchUsersQuery`: User search with filters
-- `GetUserStatisticsQuery`: Upload/download stats
-- `GetUserPermissionsQuery`: Authorization data
-
-Returns DTOs suitable for presentation layer.
\ No newline at end of file
diff --git a/src/Cache/README.md b/src/Cache/README.md
deleted file mode 100644
index e2151819b..000000000
--- a/src/Cache/README.md
+++ /dev/null
@@ -1,422 +0,0 @@
-# Unified Cache System
-
-A modern, unified caching solution for TorrentPier 3.0 that uses **Nette Caching** internally. **Breaking changes**: This replaces the legacy Cache and Datastore APIs and requires code migration.
-
-## Overview
-
-The Unified Cache System addresses the complexity and duplication in TorrentPier's caching architecture by:
-
-- **Unifying** Cache and Datastore systems into a single, coherent solution
-- **Modernizing** the caching layer with Nette's advanced features and breaking changes for better architecture
-- **Reducing** complexity and maintenance overhead
-- **Improving** performance with efficient singleton pattern and advanced features
-
-## Architecture
-
-### Core Components
-
-1. **UnifiedCacheSystem** - Main singleton orchestrator following TorrentPier's architectural patterns
-2. **CacheManager** - Cache interface using Nette Caching internally with singleton pattern
-3. **DatastoreManager** - Datastore interface that uses CacheManager internally for unified functionality
-
-### Singleton Architecture
-
-The system follows TorrentPier's consistent singleton pattern, similar to `config()`, `dev()`, `censor()`, and `DB()`:
-
-```php
-// Main singleton instance
-TorrentPier\Cache\UnifiedCacheSystem::getInstance(config()->all());
-
-// Clean global functions with proper return types
-function CACHE(string $cache_name): \TorrentPier\Cache\CacheManager
-function datastore(): \TorrentPier\Cache\DatastoreManager
-
-// Usage (exactly like before)
-$cache = CACHE('bb_cache');
-$datastore = datastore();
-```
-
-### Key Benefits
-
-- โ
**Single Source of Truth**: One caching system instead of two separate ones
-- โ
**Modern Foundation**: Built on Nette Caching v3.3 with all its advanced features
-- โ
**Zero Breaking Changes**: All existing `CACHE()` and `$datastore` calls work unchanged
-- โ
**Consistent Architecture**: Proper singleton pattern matching other TorrentPier services
-- โ
**Advanced Features**: Dependencies, tags, bulk operations, memoization, output buffering
-- โ
**Better Debugging**: Unified debug interface with compatibility for Dev.php
-- โ
**Performance**: 456,647+ operations per second with efficient memory usage
-- โ
**Clean Architecture**: No redundant configuration logic, single storage creation path
-
-## Usage
-
-### Basic Cache Operations (100% Backward Compatible)
-
-```php
-// All existing cache calls work exactly the same
-$cache = CACHE('bb_cache');
-$value = $cache->get('key');
-$cache->set('key', $value, 3600);
-$cache->rm('key');
-```
-
-### Datastore Operations (100% Backward Compatible)
-
-```php
-// All existing datastore calls work exactly the same
-$datastore = datastore();
-$forums = $datastore->get('cat_forums');
-$datastore->store('custom_data', $data);
-$datastore->update(['cat_forums', 'stats']);
-```
-
-### Advanced Nette Caching Features
-
-```php
-// Get cache manager for advanced features
-$cache = CACHE('bb_cache');
-
-// Load with callback (compute if not cached)
-$value = $cache->load('expensive_key', function() {
- return expensive_computation();
-});
-
-// Cache with time expiration
-$cache->save('key', $value, [
- \Nette\Caching\Cache::Expire => '1 hour'
-]);
-
-// Cache with file dependencies
-$cache->save('config', $data, [
- \Nette\Caching\Cache::Files => ['/path/to/config.php']
-]);
-
-// Memoize function calls
-$result = $cache->call('expensive_function', $param1, $param2);
-
-// Bulk operations
-$values = $cache->bulkLoad(['key1', 'key2', 'key3'], function($key) {
- return "computed_value_for_$key";
-});
-
-// Clean by tags (requires SQLite storage)
-$cache->clean([\Nette\Caching\Cache::Tags => ['user-123']]);
-
-// Output buffering
-$content = $cache->capture('output_key', function() {
- echo "This content will be cached";
-});
-```
-
-### Datastore Advanced Features
-
-```php
-$datastore = datastore();
-
-// All standard operations work
-$forums = $datastore->get('cat_forums');
-$datastore->store('custom_data', $data);
-
-// Access underlying CacheManager for advanced features
-$manager = $datastore->getCacheManager();
-$value = $manager->load('complex_data', function() {
- return build_complex_data();
-}, [
- \Nette\Caching\Cache::Expire => '30 minutes',
- \Nette\Caching\Cache::Tags => ['forums', 'categories']
-]);
-```
-
-## Integration & Initialization
-
-### Automatic Integration
-
-The system integrates seamlessly in `library/includes/functions.php`:
-
-```php
-// Singleton initialization (done once)
-TorrentPier\Cache\UnifiedCacheSystem::getInstance(config()->all());
-
-// Global functions provide backward compatibility
-function CACHE(string $cache_name): \TorrentPier\Cache\CacheManager {
- return TorrentPier\Cache\UnifiedCacheSystem::getInstance()->getCache($cache_name);
-}
-
-function datastore(): \TorrentPier\Cache\DatastoreManager {
- return TorrentPier\Cache\UnifiedCacheSystem::getInstance()->getDatastore(config()->get('datastore_type', 'file'));
-}
-```
-
-### Debug Compatibility
-
-The system maintains full compatibility with Dev.php debugging:
-
-```php
-// Dev.php can access debug information via magic __get() methods
-$cache = CACHE('bb_cache');
-$debug_info = $cache->dbg; // Array of operations
-$engine_name = $cache->engine; // Storage engine name
-$total_time = $cache->sql_timetotal; // Total operation time
-
-$datastore = datastore();
-$datastore_debug = $datastore->dbg; // Datastore debug info
-```
-
-## Configuration
-
-The system uses existing configuration seamlessly:
-
-```php
-// library/config.php
-$bb_cfg['cache'] = [
- 'db_dir' => realpath(BB_ROOT) . '/internal_data/cache/filecache/',
- 'prefix' => 'tp_',
- 'engines' => [
- 'bb_cache' => ['file'], // Uses Nette FileStorage
- 'session_cache' => ['sqlite'], // Uses Nette SQLiteStorage
- 'tr_cache' => ['file'], // Uses Nette FileStorage
- // ... other caches
- ],
-];
-
-$bb_cfg['datastore_type'] = 'file'; // Uses Nette FileStorage
-```
-
-## Storage Types
-
-### Supported Storage Types
-
-| Legacy Type | Nette Storage | Features |
-|------------|---------------|----------|
-| `file` | `FileStorage` | File-based, persistent, dependencies |
-| `sqlite` | `SQLiteStorage` | Database, supports tags and complex dependencies |
-| `memory` | `MemoryStorage` | In-memory, fastest, non-persistent |
-| `memcached` | `MemcachedStorage` | Distributed memory, high-performance |
-
-### Storage Features Comparison
-
-| Feature | FileStorage | SQLiteStorage | MemoryStorage | MemcachedStorage |
-|---------|-------------|---------------|---------------|------------------|
-| Persistence | โ
| โ
| โ | โ
|
-| File Dependencies | โ
| โ
| โ
| โ
|
-| Tags | โ | โ
| โ
| โ |
-| Callbacks | โ
| โ
| โ
| โ
|
-| Bulk Operations | โ
| โ
| โ
| โ
|
-| Performance | High | Medium | Highest | Very High |
-| Distributed | โ | โ | โ | โ
|
-
-## Migration Guide
-
-### Zero Migration Required
-
-All existing code continues to work without any modifications:
-
-```php
-// โ
This works exactly as before - no changes needed
-$cache = CACHE('bb_cache');
-$forums = $datastore->get('cat_forums');
-
-// โ
All debug functionality preserved
-global $CACHES;
-foreach ($CACHES->obj as $cache_name => $cache_obj) {
- echo "Cache: $cache_name\n";
-}
-```
-
-### Enhanced Capabilities for New Code
-
-New code can take advantage of advanced features:
-
-```php
-// โ
Enhanced caching with dependencies and tags
-$cache = CACHE('bb_cache');
-$forums = $cache->load('forums_with_stats', function() {
- return build_forums_with_statistics();
-}, [
- \Nette\Caching\Cache::Expire => '1 hour',
- \Nette\Caching\Cache::Files => ['/path/to/forums.config'],
- \Nette\Caching\Cache::Tags => ['forums', 'statistics']
-]);
-
-// โ
Function memoization
-$expensive_result = $cache->call('calculate_user_stats', $user_id);
-
-// โ
Output buffering
-$rendered_page = $cache->capture("page_$page_id", function() {
- include_template('complex_page.php');
-});
-```
-
-## Performance Benefits
-
-### Benchmarks
-
-- **456,647+ operations per second** in production testing
-- **Singleton efficiency**: Each cache namespace instantiated only once
-- **Memory optimization**: Shared storage and efficient instance management
-- **Nette optimizations**: Advanced algorithms for cache invalidation and cleanup
-
-### Advanced Features Performance
-
-- **Bulk Operations**: Load multiple keys in single operation
-- **Memoization**: Automatic function result caching with parameter-based keys
-- **Dependencies**: Smart cache invalidation based on files, time, or custom logic
-- **Output Buffering**: Cache generated output directly without intermediate storage
-
-## Critical Issues Resolved
-
-### Sessions Compatibility
-
-**Issue**: Legacy cache returns `false` for missing values, Nette returns `null`
-**Solution**: CacheManager->get() returns `$result ?? false` for backward compatibility
-
-### Debug Integration
-
-**Issue**: Dev.php expected `->db` property on cache objects for debug logging
-**Solution**: Added `__get()` magic methods returning compatible debug objects with `dbg[]`, `engine`, `sql_timetotal` properties
-
-### Architecture Consistency
-
-**Issue**: Inconsistent initialization pattern compared to other TorrentPier singletons
-**Solution**: Converted to proper singleton pattern with `getInstance()` method and clean global functions
-
-## Implementation Details
-
-### Architecture Flow (Refactored)
-
-**Clean, Non-Redundant Architecture:**
-```
-UnifiedCacheSystem (singleton)
-โโโ _buildStorage() โ Creates Nette Storage instances directly
-โโโ get_cache_obj() โ Returns CacheManager with pre-built storage
-โโโ getDatastore() โ Returns DatastoreManager with pre-built storage
-
-CacheManager (receives pre-built Storage)
-โโโ Constructor receives: Storage instance + minimal config
-โโโ No redundant initializeStorage() switch statement
-โโโ Focuses purely on cache operations
-
-DatastoreManager (uses CacheManager internally)
-โโโ Constructor receives: Storage instance + minimal config
-โโโ Uses CacheManager internally for unified functionality
-โโโ Maintains datastore-specific methods and compatibility
-```
-
-**Benefits of Refactored Architecture:**
-- **Single Source of Truth**: Only UnifiedCacheSystem creates storage instances
-- **No Redundancy**: Eliminated duplicate switch statements and configuration parsing
-- **Cleaner Separation**: CacheManager focuses on caching, not storage creation
-- **Impossible Path Bugs**: Storage is pre-built, no configuration mismatches possible
-- **Better Maintainability**: One place to modify storage creation logic
-
-### Directory Structure
-
-```
-src/Cache/
-โโโ CacheManager.php # Cache interface with Nette Caching + singleton pattern
-โโโ DatastoreManager.php # Datastore interface using CacheManager internally
-โโโ UnifiedCacheSystem.php # Main singleton orchestrator + storage factory
-โโโ README.md # This documentation
-```
-
-### Removed Development Files
-
-The following development and testing files were removed after successful integration:
-- `Example.php` - Migration examples (no longer needed)
-- `Integration.php` - Testing utilities (production-ready)
-- `cache_test.php` - Performance testing script (completed)
-
-### Key Features Achieved
-
-1. **100% Backward Compatibility**: All existing APIs work unchanged
-2. **Modern Foundation**: Built on stable, well-tested Nette Caching v3.3
-3. **Advanced Features**: Dependencies, tags, bulk operations, memoization, output buffering
-4. **Efficient Singletons**: Memory-efficient instance management following TorrentPier patterns
-5. **Unified Debugging**: Consistent debug interface compatible with Dev.php
-6. **Production Ready**: Comprehensive error handling, validation, and performance optimization
-7. **Clean Architecture**: Eliminated redundant configuration logic and switch statements
-8. **Single Storage Source**: All storage creation centralized in UnifiedCacheSystem
-
-### Architectural Consistency
-
-Following TorrentPier's established patterns:
-
-```php
-// Consistent with other singletons
-config() -> Config::getInstance()
-dev() -> Dev::getInstance()
-censor() -> Censor::getInstance()
-DB() -> DB::getInstance()
-CACHE() -> UnifiedCacheSystem::getInstance()->getCache()
-datastore() -> UnifiedCacheSystem::getInstance()->getDatastore()
-```
-
-## Testing & Verification
-
-### Backward Compatibility Verified
-
-```php
-// โ
All existing functionality preserved
-$cache = CACHE('bb_cache');
-assert($cache->set('test', 'value', 60) === true);
-assert($cache->get('test') === 'value');
-assert($cache->rm('test') === true);
-
-$datastore = datastore();
-$datastore->store('test_item', ['data' => 'test']);
-assert($datastore->get('test_item')['data'] === 'test');
-```
-
-### Advanced Features Verified
-
-```php
-// โ
Nette features working correctly
-$cache = CACHE('advanced_test');
-
-// Memoization
-$result1 = $cache->call('expensive_function', 'param');
-$result2 = $cache->call('expensive_function', 'param'); // From cache
-
-// Dependencies
-$cache->save('file_dependent', $data, [
- \Nette\Caching\Cache::Files => [__FILE__]
-]);
-
-// Bulk operations
-$values = $cache->bulkLoad(['key1', 'key2'], function($key) {
- return "value_$key";
-});
-
-// Performance: 456,647+ ops/sec verified
-```
-
-### Debug Functionality Verified
-
-```php
-// โ
Dev.php integration working
-$cache = CACHE('bb_cache');
-$debug = $cache->dbg; // Returns array of operations
-$engine = $cache->engine; // Returns storage type
-$time = $cache->sql_timetotal; // Returns total time
-
-// โ
Singleton behavior verified
-$instance1 = TorrentPier\Cache\UnifiedCacheSystem::getInstance();
-$instance2 = TorrentPier\Cache\UnifiedCacheSystem::getInstance();
-assert($instance1 === $instance2); // Same instance
-```
-
-## Future Enhancements
-
-### Planned Storage Implementations
-- Redis storage adapter for Nette
-- Memcached storage adapter for Nette
-- APCu storage adapter for Nette
-
-### Advanced Features Roadmap
-- Distributed caching support
-- Cache warming and preloading
-- Advanced metrics and monitoring
-- Multi-tier caching strategies
-
----
-
-This unified cache system represents a significant architectural improvement in TorrentPier while ensuring seamless backward compatibility and providing a robust foundation for future enhancements. The clean singleton pattern, advanced Nette Caching features, and comprehensive debug support make it a production-ready replacement for the legacy Cache and Datastore systems.
diff --git a/src/Database/README.md b/src/Database/README.md
deleted file mode 100644
index b7cc5b05b..000000000
--- a/src/Database/README.md
+++ /dev/null
@@ -1,362 +0,0 @@
-# TorrentPier Database Layer
-
-This directory contains the new database layer for TorrentPier 3.0 that uses Nette Database internally. **Breaking changes**: This replaces the legacy SqlDb interface and requires code migration.
-
-## Overview
-
-The new database system has completely replaced the legacy SqlDb/Dbs system and provides:
-
-- **Modern API** - New `DB()->method()` calls with improved functionality
-- **Nette Database integration** - Modern, efficient database layer under the hood
-- **Singleton pattern** - Efficient connection management
-- **Complete feature parity** - All original functionality preserved
-
-## Architecture
-
-### Classes
-
-1. **`Database`** - Main singleton database class using Nette Database Connection
-2. **`DatabaseFactory`** - Factory that has completely replaced the legacy SqlDb/Dbs system
-3. **`DatabaseDebugger`** - Dedicated debug functionality extracted from Database class
-4. **`DebugSelection`** - Debug-enabled wrapper for Nette Database Selection
-
-### Key Features
-
-- **Singleton Pattern**: Ensures single database connection per server configuration
-- **Multiple Database Support**: Handles multiple database servers via DatabaseFactory
-- **Raw SQL Support**: Uses Nette Database's Connection class (SQL way) for minimal code impact
-- **Complete Error Handling**: Maintains existing error handling behavior
-- **Full Debug Support**: Preserves all debugging, logging, and explain functionality
-- **Performance Tracking**: Query timing and slow query detection
-- **Clean Architecture**: Debug functionality extracted to dedicated DatabaseDebugger class
-- **Modular Design**: Single responsibility principle with separate debug and database concerns
-
-## Implementation Status
-
-- โ
**Complete Replacement**: Legacy SqlDb/Dbs classes have been removed from the codebase
-- โ
**Backward Compatibility**: All existing `DB()->method()` calls work unchanged
-- โ
**Debug System**: Full explain(), logging, and performance tracking
-- โ
**Error Handling**: Complete error handling with sql_error() support
-- โ
**Connection Management**: Singleton pattern with proper initialization
-- โ
**Clean Architecture**: Debug functionality extracted to dedicated classes
-- โ
**Class Renaming**: Renamed DB โ Database, DbFactory โ DatabaseFactory for consistency
-
-## Usage
-
-### Standard Database Operations
-```php
-// All existing code works unchanged
-$user = DB()->fetch_row("SELECT * FROM users WHERE id = ?", 123);
-$users = DB()->fetch_rowset("SELECT * FROM users");
-$affected = DB()->affected_rows();
-
-// Raw queries
-$result = DB()->sql_query("UPDATE users SET status = ? WHERE id = ?", 1, 123);
-
-// Data building
-$data = ['name' => 'John', 'email' => 'john@example.com'];
-$sql = DB()->build_array('INSERT', $data);
-```
-
-### Multiple Database Servers
-```php
-// Access different database servers
-$main_db = DB('db'); // Main database
-$tracker_db = DB('tr'); // Tracker database
-$stats_db = DB('stats'); // Statistics database
-```
-
-### Error Handling
-```php
-$result = DB()->sql_query("SELECT * FROM users");
-if (!$result) {
- $error = DB()->sql_error();
- echo "Error: " . $error['message'];
-}
-```
-
-## Configuration
-
-The database configuration is handled through the existing TorrentPier config system:
-
-```php
-// Initialized in common.php
-TorrentPier\Database\DatabaseFactory::init(
- config()->get('db'), // Database configurations
- config()->get('db_alias', []) // Database aliases
-);
-```
-
-## Benefits
-
-### Performance
-- **Efficient Connections**: Singleton pattern prevents connection overhead
-- **Modern Database Layer**: Nette Database v3.2 optimizations
-- **Resource Management**: Automatic cleanup and proper connection handling
-
-### Maintainability
-- **Modern Codebase**: Uses current PHP standards and type declarations
-- **Better Architecture**: Clean separation of concerns
-- **Nette Ecosystem**: Part of actively maintained Nette framework
-
-### Reliability
-- **Proven Technology**: Nette Database is battle-tested
-- **Regular Updates**: Automatic security and bug fixes through composer
-- **Type Safety**: Better error detection and IDE support
-
-## Debugging Features
-
-All original debugging features are preserved and enhanced:
-
-### Query Logging
-- SQL query logging with timing
-- Slow query detection and logging
-- Memory usage tracking
-
-### Debug Information
-```php
-// Enable debugging (same as before)
-DB()->debug('start');
-// ... run queries ...
-DB()->debug('stop');
-```
-
-### Explain Functionality
-```php
-// Explain queries (same interface as before)
-DB()->explain('start');
-DB()->explain('display');
-```
-
-## Technical Details
-
-### Nette Database Integration
-- Uses Nette Database **Connection** class (SQL way)
-- Maintains raw SQL approach for minimal migration impact
-- PDO-based with proper parameter binding
-
-### Compatibility Layer
-- All original method signatures preserved
-- Same return types and behavior
-- Error handling matches original implementation
-
-### Connection Management
-- Single connection per database server
-- Lazy connection initialization
-- Proper connection cleanup
-
-## Migration Notes
-
-This is a **complete replacement** that maintains 100% backward compatibility:
-
-1. **No Code Changes Required**: All existing `DB()->method()` calls work unchanged
-2. **Same Configuration**: Uses existing database configuration
-3. **Same Behavior**: Error handling, return values, and debugging work identically
-4. **Enhanced Performance**: Better connection management and modern database layer
-
-## Dependencies
-
-- **Nette Database v3.2**: Already included in composer.json
-- **PHP 8.0+**: Required for type declarations and modern features
-
-## Files
-
-- `Database.php` - Main database class with full backward compatibility
-- `DatabaseFactory.php` - Factory for managing database instances
-- `DatabaseDebugger.php` - Dedicated debug functionality class
-- `DebugSelection.php` - Debug-enabled Nette Selection wrapper
-- `README.md` - This documentation
-
-## Future Enhancement: Gradual Migration to Nette Explorer
-
-While the current implementation uses Nette Database's **Connection** class (SQL way) for maximum compatibility, TorrentPier can gradually migrate to **Nette Database Explorer** for more modern ORM-style database operations.
-
-### Phase 1: Hybrid Approach
-
-Add Explorer support alongside existing Connection-based methods:
-
-```php
-// Current Connection-based approach (maintains compatibility)
-$users = DB()->fetch_rowset("SELECT * FROM users WHERE status = ?", 1);
-
-// New Explorer-based approach (added gradually)
-$users = DB()->table('users')->where('status', 1)->fetchAll();
-```
-
-### Phase 2: Explorer Method Examples
-
-#### Basic Table Operations
-```php
-// Select operations
-$user = DB()->table('users')->get(123); // Get by ID
-$users = DB()->table('users')->where('status', 1)->fetchAll(); // Where condition
-$count = DB()->table('users')->where('status', 1)->count(); // Count records
-
-// Insert operations
-$user_id = DB()->table('users')->insert([
- 'username' => 'john',
- 'email' => 'john@example.com',
- 'reg_time' => time()
-]);
-
-// Update operations
-DB()->table('users')
- ->where('id', 123)
- ->update(['last_visit' => time()]);
-
-// Delete operations
-DB()->table('users')
- ->where('status', 0)
- ->delete();
-```
-
-#### Advanced Explorer Features
-```php
-// Joins and relationships
-$posts = DB()->table('posts')
- ->select('posts.*, users.username')
- ->where('posts.forum_id', 5)
- ->order('posts.post_time DESC')
- ->limit(20)
- ->fetchAll();
-
-// Aggregations
-$stats = DB()->table('torrents')
- ->select('forum_id, COUNT(*) as total, SUM(size) as total_size')
- ->where('approved', 1)
- ->group('forum_id')
- ->fetchAll();
-
-// Subqueries
-$active_users = DB()->table('users')
- ->where('last_visit > ?', time() - 86400)
- ->where('id IN', DB()->table('posts')
- ->select('user_id')
- ->where('post_time > ?', time() - 86400)
- )
- ->fetchAll();
-```
-
-#### Working with Related Data
-```php
-// One-to-many relationships
-$user = DB()->table('users')->get(123);
-$user_posts = $user->related('posts')->order('post_time DESC');
-
-// Many-to-many through junction table
-$torrent = DB()->table('torrents')->get(456);
-$seeders = $torrent->related('bt_tracker', 'torrent_id')
- ->where('seeder', 'yes')
- ->select('user_id');
-```
-
-### Phase 3: Migration Strategy
-
-#### Step-by-Step Conversion
-1. **Identify Patterns**: Find common SQL patterns in the codebase
-2. **Create Helpers**: Build wrapper methods for complex queries
-3. **Test Incrementally**: Convert one module at a time
-4. **Maintain Compatibility**: Keep both approaches during transition
-
-#### Example Migration Pattern
-```php
-// Before: Raw SQL
-$result = DB()->sql_query("
- SELECT t.*, u.username
- FROM torrents t
- JOIN users u ON t.poster_id = u.user_id
- WHERE t.forum_id = ? AND t.approved = 1
- ORDER BY t.reg_time DESC
- LIMIT ?
-", $forum_id, $limit);
-
-$torrents = [];
-while ($row = DB()->sql_fetchrow($result)) {
- $torrents[] = $row;
-}
-
-// After: Explorer ORM
-$torrents = DB()->table('torrents')
- ->alias('t')
- ->select('t.*, u.username')
- ->where('t.forum_id', $forum_id)
- ->where('t.approved', 1)
- ->order('t.reg_time DESC')
- ->limit($limit)
- ->fetchAll();
-```
-
-### Phase 4: Advanced Explorer Features
-
-#### Custom Repository Classes
-```php
-// Create specialized repository classes
-class TorrentRepository
-{
- private $db;
-
- public function __construct($db)
- {
- $this->db = $db;
- }
-
- public function getApprovedByForum($forum_id, $limit = 20)
- {
- return $this->db->table('torrents')
- ->where('forum_id', $forum_id)
- ->where('approved', 1)
- ->order('reg_time DESC')
- ->limit($limit)
- ->fetchAll();
- }
-
- public function getTopSeeded($limit = 10)
- {
- return $this->db->table('torrents')
- ->where('approved', 1)
- ->order('seeders DESC')
- ->limit($limit)
- ->fetchAll();
- }
-}
-
-// Usage
-$torrentRepo = new TorrentRepository(DB());
-$popular = $torrentRepo->getTopSeeded();
-```
-
-#### Database Events and Caching
-```php
-// Add caching layer
-$cached_result = DB()->table('users')
- ->where('status', 1)
- ->cache('active_users', 3600) // Cache for 1 hour
- ->fetchAll();
-
-// Database events for logging
-DB()->onQuery[] = function ($query, $parameters, $time) {
- if ($time > 1.0) { // Log slow queries
- error_log("Slow query ({$time}s): $query");
- }
-};
-```
-
-### Benefits of Explorer Migration
-
-#### Developer Experience
-- **Fluent Interface**: Chainable method calls
-- **IDE Support**: Better autocomplete and type hints
-- **Less SQL**: Reduced raw SQL writing
-- **Built-in Security**: Automatic parameter binding
-
-#### Code Quality
-- **Readable Code**: Self-documenting query building
-- **Reusable Patterns**: Common queries become methods
-- **Type Safety**: Better error detection
-- **Testing**: Easier to mock and test
-
-#### Performance
-- **Query Optimization**: Explorer can optimize queries
-- **Lazy Loading**: Load related data only when needed
-- **Connection Pooling**: Better resource management
-- **Caching Integration**: Built-in caching support
diff --git a/src/Domain/Forum/Exception/README.md b/src/Domain/Forum/Exception/README.md
deleted file mode 100644
index 07a483fe6..000000000
--- a/src/Domain/Forum/Exception/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Forum Domain Exceptions
-
-Domain-specific exceptions for forum operations:
-
-- `ThreadLockedException`: Attempt to post in locked thread
-- `PostEditTimeExpiredException`: Edit time limit exceeded
-- `ForumAccessDeniedException`: Insufficient permissions
-- `InvalidPostContentException`: Post validation failed
\ No newline at end of file
diff --git a/src/Domain/Forum/Model/README.md b/src/Domain/Forum/Model/README.md
deleted file mode 100644
index 6dafb0894..000000000
--- a/src/Domain/Forum/Model/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Forum Domain Models
-
-Contains aggregate roots and entities for the forum system:
-
-- `Forum`: Forum category aggregate
-- `Thread`: Discussion thread aggregate root
-- `Post`: Individual post entity
-- `Attachment`: File attachment entity
-
-Business rules enforced at this level:
-
-- Post editing time limits
-- Thread locking rules
-- Forum access permissions
-- Post moderation workflow
\ No newline at end of file
diff --git a/src/Domain/Forum/Repository/README.md b/src/Domain/Forum/Repository/README.md
deleted file mode 100644
index 1a8430801..000000000
--- a/src/Domain/Forum/Repository/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Forum Repository Interfaces
-
-Repository interfaces for forum aggregates:
-
-- `ForumRepositoryInterface`: Forum aggregate persistence
-- `ThreadRepositoryInterface`: Thread aggregate persistence
-- `PostRepositoryInterface`: Post queries (read-only)
-
-These interfaces define contracts that infrastructure must implement.
\ No newline at end of file
diff --git a/src/Domain/Forum/ValueObject/README.md b/src/Domain/Forum/ValueObject/README.md
deleted file mode 100644
index eb8aec659..000000000
--- a/src/Domain/Forum/ValueObject/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Forum Value Objects
-
-Immutable objects representing forum concepts:
-
-- `PostId`: Unique post identifier
-- `ThreadTitle`: Thread title with validation
-- `PostContent`: Formatted post content
-- `ForumSlug`: URL-friendly forum identifier
-
-These objects ensure type safety and encapsulate validation rules.
\ No newline at end of file
diff --git a/src/Domain/README.md b/src/Domain/README.md
deleted file mode 100644
index cb9254a68..000000000
--- a/src/Domain/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Domain Layer
-
-This directory contains the core business logic of TorrentPier. Code here should:
-
-- Have no dependencies on frameworks or infrastructure
-- Represent pure business rules and domain models
-- Be testable in isolation
-- Use only PHP language features and domain concepts
-
-## Bounded Contexts
-
-- **Forum**: Discussion forums, posts, threads
-- **Tracker**: BitTorrent tracking, peers, torrents
-- **User**: User management, authentication, profiles
-- **Shared**: Minimal shared concepts between contexts
\ No newline at end of file
diff --git a/src/Domain/Shared/Event/README.md b/src/Domain/Shared/Event/README.md
deleted file mode 100644
index 11656fb4a..000000000
--- a/src/Domain/Shared/Event/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Domain Events
-
-Base classes and interfaces for domain event system:
-
-- `DomainEvent`: Base event interface
-- `EventRecording`: Trait for aggregate event recording
-- `AggregateHistory`: Event sourcing support
-
-Example events:
-
-- `UserRegisteredEvent`
-- `TorrentUploadedEvent`
-- `ThreadCreatedEvent`
-
-Events enable loose coupling between bounded contexts.
\ No newline at end of file
diff --git a/src/Domain/Shared/Exception/README.md b/src/Domain/Shared/Exception/README.md
deleted file mode 100644
index 2c5a556bd..000000000
--- a/src/Domain/Shared/Exception/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Shared Domain Exceptions
-
-Base exception classes used across all bounded contexts:
-
-- `DomainException`: Base domain exception
-- `InvalidArgumentException`: Invalid input validation
-- `EntityNotFoundException`: Generic entity not found
-- `BusinessRuleViolationException`: Business rule violations
-
-These provide common exception handling patterns without coupling contexts.
\ No newline at end of file
diff --git a/src/Domain/Shared/Model/README.md b/src/Domain/Shared/Model/README.md
deleted file mode 100644
index 4daf36150..000000000
--- a/src/Domain/Shared/Model/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Shared Domain Models
-
-Base classes and interfaces used across bounded contexts:
-
-- `AggregateRoot`: Base class for all aggregates
-- `Entity`: Base class for entities
-- `DomainEvent`: Interface for domain events
-- `ValueObject`: Base value object interface
-
-These provide common functionality while maintaining context boundaries.
\ No newline at end of file
diff --git a/src/Domain/Shared/Repository/README.md b/src/Domain/Shared/Repository/README.md
deleted file mode 100644
index 999f9d300..000000000
--- a/src/Domain/Shared/Repository/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Shared Repository Interfaces
-
-Common repository patterns and base interfaces:
-
-- `RepositoryInterface`: Base repository contract
-- `ReadOnlyRepositoryInterface`: Query-only operations
-- `AggregateRepositoryInterface`: Aggregate-specific methods
-
-These define common persistence patterns without implementation details.
\ No newline at end of file
diff --git a/src/Domain/Shared/ValueObject/README.md b/src/Domain/Shared/ValueObject/README.md
deleted file mode 100644
index afc5b7bc6..000000000
--- a/src/Domain/Shared/ValueObject/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Shared Value Objects
-
-Common value objects used across contexts:
-
-- `Id`: Generic identifier base class
-- `DateTime`: Immutable datetime wrapper
-- `Money`: Monetary value representation
-- `Percentage`: Percentage value (0-100)
-
-These are minimal shared concepts that don't violate bounded context principles.
\ No newline at end of file
diff --git a/src/Domain/Tracker/Exception/README.md b/src/Domain/Tracker/Exception/README.md
deleted file mode 100644
index 73ae0f882..000000000
--- a/src/Domain/Tracker/Exception/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Tracker Domain Exceptions
-
-Domain-specific exceptions for tracker operations:
-
-- `InvalidInfoHashException`: Malformed info hash
-- `InactiveTorrentException`: Torrent not active
-- `PeerLimitExceededException`: Too many peers
-- `InvalidAnnounceException`: Protocol violation
\ No newline at end of file
diff --git a/src/Domain/Tracker/Model/README.md b/src/Domain/Tracker/Model/README.md
deleted file mode 100644
index 124456276..000000000
--- a/src/Domain/Tracker/Model/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Tracker Domain Models
-
-Contains aggregate roots and entities for the BitTorrent tracker:
-
-- `Torrent`: Aggregate root for torrent management
-- `Peer`: Entity representing a BitTorrent peer
-- `TorrentStatistics`: Value object for torrent stats
-
-Example:
-
-```php
-class Torrent extends AggregateRoot
-{
- public function announce(Peer $peer, AnnounceEvent $event): void
- {
- // Business logic for handling announces
- }
-}
-```
\ No newline at end of file
diff --git a/src/Domain/Tracker/Repository/README.md b/src/Domain/Tracker/Repository/README.md
deleted file mode 100644
index 3745d6e4e..000000000
--- a/src/Domain/Tracker/Repository/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Tracker Repository Interfaces
-
-Repository interfaces for tracker aggregates:
-
-- `TorrentRepositoryInterface`: Torrent aggregate persistence
-- `PeerRepositoryInterface`: Peer data access
-- `TrackerStatsRepositoryInterface`: Statistics queries
-
-These define persistence contracts without implementation details.
\ No newline at end of file
diff --git a/src/Domain/Tracker/ValueObject/README.md b/src/Domain/Tracker/ValueObject/README.md
deleted file mode 100644
index cd3fcf0ee..000000000
--- a/src/Domain/Tracker/ValueObject/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Tracker Value Objects
-
-Immutable objects representing domain concepts:
-
-- `InfoHash`: 20-byte torrent identifier
-- `PeerId`: Peer client identifier
-- `Port`: Network port (1-65535)
-- `BytesTransferred`: Upload/download bytes
-
-Example:
-
-```php
-final class InfoHash
-{
- private string $hash;
-
- public function __construct(string $hash)
- {
- $this->guardAgainstInvalidHash($hash);
- $this->hash = $hash;
- }
-}
-```
\ No newline at end of file
diff --git a/src/Domain/User/Exception/README.md b/src/Domain/User/Exception/README.md
deleted file mode 100644
index f689a7943..000000000
--- a/src/Domain/User/Exception/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# User Domain Exceptions
-
-Domain-specific exceptions for user operations:
-
-- `UserNotFoundException`: User not found
-- `DuplicateUsernameException`: Username already taken
-- `InvalidCredentialsException`: Authentication failed
-- `UserNotActivatedException`: Account not activated
-- `PasswordComplexityException`: Weak password
\ No newline at end of file
diff --git a/src/Domain/User/Model/README.md b/src/Domain/User/Model/README.md
deleted file mode 100644
index 2001b3ebd..000000000
--- a/src/Domain/User/Model/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# User Domain Models
-
-Contains user management aggregates and entities:
-
-- `User`: User aggregate root
-- `UserProfile`: User profile information
-- `UserCredentials`: Authentication credentials
-- `UserPermissions`: Authorization rules
-
-Business rules:
-
-- Password complexity requirements
-- Username uniqueness
-- Email verification workflow
-- Account activation/deactivation
\ No newline at end of file
diff --git a/src/Domain/User/Repository/README.md b/src/Domain/User/Repository/README.md
deleted file mode 100644
index 9d4c463c7..000000000
--- a/src/Domain/User/Repository/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# User Repository Interface
-
-Repository interface for user aggregate:
-
-- `UserRepositoryInterface`: User persistence and retrieval
- - `findById(UserId $id): ?User`
- - `findByUsername(Username $username): ?User`
- - `findByEmail(Email $email): ?User`
- - `save(User $user): void`
- - `delete(User $user): void`
\ No newline at end of file
diff --git a/src/Domain/User/ValueObject/README.md b/src/Domain/User/ValueObject/README.md
deleted file mode 100644
index 79c930883..000000000
--- a/src/Domain/User/ValueObject/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# User Value Objects
-
-Immutable objects for user domain:
-
-- `UserId`: Unique user identifier
-- `Username`: Username with validation
-- `Email`: Email address with format validation
-- `HashedPassword`: Secure password representation
-- `UserRole`: User role enumeration
-
-These ensure data integrity and type safety.
\ No newline at end of file
diff --git a/src/Infrastructure/Cache/File/README.md b/src/Infrastructure/Cache/File/README.md
deleted file mode 100644
index 9f781c1b9..000000000
--- a/src/Infrastructure/Cache/File/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# File Cache Adapter
-
-File system-based caching implementation:
-
-- Simple file-based storage
-- Suitable for single-server deployments
-- Directory structure optimization
-- Lock file support for concurrency
-- Automatic garbage collection
\ No newline at end of file
diff --git a/src/Infrastructure/Cache/Memcached/README.md b/src/Infrastructure/Cache/Memcached/README.md
deleted file mode 100644
index 2e60b7e0b..000000000
--- a/src/Infrastructure/Cache/Memcached/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Memcached Cache Adapter
-
-Memcached-based caching implementation:
-
-- Simple key-value caching
-- Distributed cache support
-- Automatic key expiration
-- Connection pooling
-- Consistent hashing for distribution
\ No newline at end of file
diff --git a/src/Infrastructure/Cache/Redis/README.md b/src/Infrastructure/Cache/Redis/README.md
deleted file mode 100644
index da7e090aa..000000000
--- a/src/Infrastructure/Cache/Redis/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Redis Cache Adapter
-
-Redis-based caching implementation:
-
-- High-performance key-value storage
-- Support for data structures (lists, sets, hashes)
-- TTL management
-- Pub/sub for cache invalidation
-- Cluster support for scalability
\ No newline at end of file
diff --git a/src/Infrastructure/DependencyInjection/README.md b/src/Infrastructure/DependencyInjection/README.md
deleted file mode 100644
index e65de5a19..000000000
--- a/src/Infrastructure/DependencyInjection/README.md
+++ /dev/null
@@ -1,171 +0,0 @@
-# Dependency Injection Infrastructure
-
-This directory contains the dependency injection container implementation using PHP-DI, following hexagonal architecture principles.
-
-## Architecture Overview
-
-The DI container is placed in the Infrastructure layer because:
-- Dependency injection is a technical implementation detail
-- It handles wiring and bootstrapping, not business logic
-- The domain layer remains pure without framework dependencies
-
-## Structure
-
-```
-DependencyInjection/
-โโโ Container.php # Wrapper around PHP-DI container
-โโโ ContainerFactory.php # Factory for building configured containers
-โโโ Bootstrap.php # Application bootstrapper
-โโโ Definitions/ # Service definitions by layer
- โโโ DomainDefinitions.php
- โโโ ApplicationDefinitions.php
- โโโ InfrastructureDefinitions.php
- โโโ PresentationDefinitions.php
-```
-
-## Usage
-
-### Basic Bootstrap (Works Now)
-
-```php
-use TorrentPier\Infrastructure\DependencyInjection\Bootstrap;
-
-// Initialize the container
-$container = Bootstrap::init(__DIR__ . '/../..');
-
-// Basic usage
-$containerInstance = app(); // Get container itself
-$hasService = $container->has('some.service'); // Check if service exists
-```
-
-### Manual Container Creation (Works Now)
-
-```php
-use TorrentPier\Infrastructure\DependencyInjection\ContainerFactory;
-
-$config = [
- 'environment' => 'production',
- 'definitions' => [
- 'custom.service' => \DI\factory(function () {
- return new CustomService();
- }),
- ],
-];
-
-$container = ContainerFactory::create($config);
-```
-
-### Future Usage (When Services Are Implemented)
-
-```php
-// These will work when the respective layers are implemented:
-// $userRepository = $container->get(UserRepositoryInterface::class);
-// $commandBus = $container->get(CommandBusInterface::class);
-```
-
-## Service Definitions
-
-Services are organized by architectural layer following the hexagonal architecture spec:
-
-### Domain Layer (`DomainDefinitions.php`)
-- Repository interface mappings (when implemented in Phase 2)
-- Domain service factories
-- No direct infrastructure dependencies
-
-### Application Layer (`ApplicationDefinitions.php`)
-- Command/Query buses (when implemented in Phase 3)
-- Command/Query handlers
-- Event dispatcher
-- Application services
-
-### Infrastructure Layer (`InfrastructureDefinitions.php`)
-- Database connections (when Nette Database integration is ready)
-- Cache implementations (when cache infrastructure is ready)
-- Repository implementations (when implemented in Phase 4)
-- External service adapters
-
-### Presentation Layer (`PresentationDefinitions.php`)
-- HTTP controllers (when implemented in Phase 5)
-- CLI commands
-- Middleware
-- Response transformers
-
-**Note**: Most definitions are currently commented out as examples until the actual services are implemented according to the implementation phases.
-
-## Configuration
-
-Configuration is loaded from multiple sources:
-
-1. **Environment Variables** (`.env` file)
-2. **Configuration Files** (`/config/*.php`)
-3. **Runtime Configuration** (passed to factory)
-
-### Production Optimization
-
-In production mode, the container:
-- Compiles definitions for performance
-- Generates proxies for lazy loading
-- Caches resolved dependencies
-
-Enable by setting `APP_ENV=production` in your `.env` file.
-
-## Best Practices
-
-1. **Use Interfaces**: Define interfaces in domain, implement in infrastructure
-2. **Explicit Definitions**: Prefer explicit over magic for complex services
-3. **Layer Separation**: Keep definitions organized by architectural layer
-4. **Lazy Loading**: Use factories for expensive services
-5. **Immutable Services**: Services should be stateless and immutable
-
-## Example Service Registration
-
-### Current Usage (Works Now)
-```php
-// In services.php or custom definitions
-return [
- 'custom.service' => \DI\factory(function () {
- return new CustomService();
- }),
-
- 'test.service' => \DI\autowire(TestService::class),
-];
-```
-
-### Future Examples (When Infrastructure Is Ready)
-```php
-// These will be uncommented when the services are implemented:
-// UserRepositoryInterface::class => autowire(UserRepository::class)
-// ->constructorParameter('connection', get('database.connection.default'))
-// ->constructorParameter('cache', get('cache.factory')),
-//
-// 'email.service' => factory(function (ContainerInterface $c) {
-// $config = $c->get('config')['email'];
-// return new SmtpEmailService($config);
-// }),
-```
-
-## Testing
-
-For testing, create a test container with mocked services:
-
-```php
-// Current testing approach (works now)
-$testConfig = [
- 'definitions' => [
- 'test.service' => \DI\factory(function () {
- return new MockTestService();
- }),
- ],
- 'environment' => 'testing',
-];
-
-$container = ContainerFactory::create($testConfig);
-
-// Future testing (when services are implemented)
-// $testConfig = [
-// 'definitions' => [
-// UserRepositoryInterface::class => $mockUserRepository,
-// EmailServiceInterface::class => $mockEmailService,
-// ],
-// ];
-```
diff --git a/src/Infrastructure/Email/Template/README.md b/src/Infrastructure/Email/Template/README.md
deleted file mode 100644
index 3497a96ba..000000000
--- a/src/Infrastructure/Email/Template/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Email Templates
-
-Email template management:
-
-- HTML and plain text templates
-- Template variables and placeholders
-- Multi-language support
-- Template caching
-- Preview functionality
-
-Common templates:
-
-- User registration confirmation
-- Password reset
-- Torrent notifications
-- Forum post notifications
\ No newline at end of file
diff --git a/src/Infrastructure/Email/Transport/README.md b/src/Infrastructure/Email/Transport/README.md
deleted file mode 100644
index 0de823895..000000000
--- a/src/Infrastructure/Email/Transport/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Email Transport
-
-Email delivery mechanisms:
-
-- `SmtpTransport`: Traditional SMTP delivery
-- `SendgridTransport`: SendGrid API integration
-- `MailgunTransport`: Mailgun API integration
-- `NullTransport`: Testing/development transport
-
-Supports queuing and retry mechanisms.
\ No newline at end of file
diff --git a/src/Infrastructure/FileStorage/Local/README.md b/src/Infrastructure/FileStorage/Local/README.md
deleted file mode 100644
index cb0fdac49..000000000
--- a/src/Infrastructure/FileStorage/Local/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Local File Storage
-
-Local filesystem storage implementation:
-
-- Direct disk storage
-- Directory structure management
-- File permissions handling
-- Atomic file operations
-- Cleanup and maintenance
-
-Used for torrent files, avatars, and attachments.
\ No newline at end of file
diff --git a/src/Infrastructure/FileStorage/S3/README.md b/src/Infrastructure/FileStorage/S3/README.md
deleted file mode 100644
index c008d9f5a..000000000
--- a/src/Infrastructure/FileStorage/S3/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# S3 File Storage
-
-Amazon S3 (or compatible) storage implementation:
-
-- Cloud object storage
-- Pre-signed URLs for direct uploads
-- CDN integration support
-- Lifecycle policies
-- Multi-region support
-
-Provides scalable storage for large deployments.
\ No newline at end of file
diff --git a/src/Infrastructure/Persistence/Database/README.md b/src/Infrastructure/Persistence/Database/README.md
deleted file mode 100644
index c250b60e8..000000000
--- a/src/Infrastructure/Persistence/Database/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Database Adapter
-
-Database connection and query building layer:
-
-- `DatabaseAdapterInterface`: Common database operations
-- `QueryBuilder`: Fluent query construction
-- `ConnectionPool`: Connection management
-
-Provides abstraction over raw database access.
diff --git a/src/Infrastructure/Persistence/Migration/README.md b/src/Infrastructure/Persistence/Migration/README.md
deleted file mode 100644
index 1f203e645..000000000
--- a/src/Infrastructure/Persistence/Migration/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Database Migrations
-
-Schema version control and migration management:
-
-- Migration files for schema changes
-- Seed data for initial setup
-- Rollback support
-- Migration history tracking
-
-Uses Phinx or similar migration tool.
\ No newline at end of file
diff --git a/src/Infrastructure/Persistence/Repository/README.md b/src/Infrastructure/Persistence/Repository/README.md
deleted file mode 100644
index 002760d4a..000000000
--- a/src/Infrastructure/Persistence/Repository/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Repository Implementations
-
-Concrete implementations of domain repository interfaces:
-
-- Uses database adapter for persistence
-- Implements caching strategies
-- Handles query optimization
-- Supports multiple database backends
-
-Example:
-
-```php
-class TorrentRepository implements TorrentRepositoryInterface
-{
- public function __construct(
- private DatabaseAdapterInterface $db
- ) {}
-
- public function findByInfoHash(InfoHash $infoHash): ?Torrent
- {
- // Database adapter implementation
- $row = $this->db->select('torrents')
- ->where('info_hash', $infoHash->toString())
- ->first();
-
- return $row ? $this->hydrateFromRow($row) : null;
- }
-}
-```
\ No newline at end of file
diff --git a/src/Infrastructure/README.md b/src/Infrastructure/README.md
deleted file mode 100644
index 2098a9f97..000000000
--- a/src/Infrastructure/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Infrastructure Layer
-
-Technical implementations and external service adapters:
-
-- Database persistence
-- Caching mechanisms
-- Email services
-- File storage
-- Third-party integrations
-
-Infrastructure depends on domain, not vice versa.
\ No newline at end of file
diff --git a/src/Presentation/Cli/Commands/README.md b/src/Presentation/Cli/Commands/README.md
deleted file mode 100644
index 5e2cf1239..000000000
--- a/src/Presentation/Cli/Commands/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# CLI Commands
-
-Console commands for administrative tasks:
-
-- `UserCreateCommand`: Create users from CLI
-- `CacheClearCommand`: Clear cache stores
-- `MigrateCommand`: Run database migrations
-- `CronCommand`: Execute scheduled tasks
-
-Built using Symfony Console component.
\ No newline at end of file
diff --git a/src/Presentation/Http/Controllers/Admin/README.md b/src/Presentation/Http/Controllers/Admin/README.md
deleted file mode 100644
index 6e478949b..000000000
--- a/src/Presentation/Http/Controllers/Admin/README.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Admin Panel Controllers
-
-Administrative interface controllers with enhanced security:
-
-- Role-based access control (RBAC)
-- Audit logging for all actions
-- Additional authentication checks
-- Administrative dashboards and reports
-
-Example:
-
-```php
-class AdminUserController
-{
- public function index(Request $request): Response
- {
- $query = new GetUsersQuery(
- page: $request->getPage(),
- filters: $request->getFilters()
- );
-
- $users = $this->queryBus->handle($query);
-
- return $this->render('admin/users/index', [
- 'users' => $users,
- 'filters' => $request->getFilters()
- ]);
- }
-}
-```
\ No newline at end of file
diff --git a/src/Presentation/Http/Controllers/Api/README.md b/src/Presentation/Http/Controllers/Api/README.md
deleted file mode 100644
index 7d944db2e..000000000
--- a/src/Presentation/Http/Controllers/Api/README.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# API Controllers
-
-RESTful API endpoints following OpenAPI specification:
-
-- JSON request/response format
-- Proper HTTP status codes
-- HATEOAS where applicable
-- Rate limiting aware
-
-Example:
-
-```php
-class UserController
-{
- public function register(RegisterRequest $request): JsonResponse
- {
- $command = new RegisterUserCommand(
- $request->getUsername(),
- $request->getEmail(),
- $request->getPassword()
- );
-
- $userId = $this->commandBus->handle($command);
-
- return new JsonResponse([
- 'id' => $userId,
- 'username' => $request->getUsername()
- ], Response::HTTP_CREATED);
- }
-}
-```
\ No newline at end of file
diff --git a/src/Presentation/Http/Controllers/Web/README.md b/src/Presentation/Http/Controllers/Web/README.md
deleted file mode 100644
index 015c2d19c..000000000
--- a/src/Presentation/Http/Controllers/Web/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Web Controllers
-
-Traditional web interface controllers:
-
-- HTML response generation
-- Template rendering
-- Form handling
-- Session management
-- CSRF protection
-
-Controllers for:
-
-- Forum browsing and posting
-- Torrent browsing and downloading
-- User profiles and settings
-- Search functionality
\ No newline at end of file
diff --git a/src/Presentation/Http/Middleware/README.md b/src/Presentation/Http/Middleware/README.md
deleted file mode 100644
index c5a1d1a0c..000000000
--- a/src/Presentation/Http/Middleware/README.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# HTTP Middleware
-
-Request/response pipeline middleware:
-
-- `AuthenticationMiddleware`: User authentication
-- `AuthorizationMiddleware`: Permission checks
-- `CsrfProtectionMiddleware`: CSRF token validation
-- `RateLimitMiddleware`: Request throttling
-- `LocalizationMiddleware`: Language detection
-- `CorsMiddleware`: Cross-origin resource sharing
-
-Middleware follows PSR-15 standard.
\ No newline at end of file
diff --git a/src/Presentation/Http/Requests/README.md b/src/Presentation/Http/Requests/README.md
deleted file mode 100644
index 8e0a47d1c..000000000
--- a/src/Presentation/Http/Requests/README.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# HTTP Requests
-
-Request objects and validation:
-
-- Request DTOs with validation rules
-- Type-safe access to request data
-- File upload handling
-- Input sanitization
-- Custom validation rules
-
-Example:
-
-```php
-class RegisterRequest extends FormRequest
-{
- public function rules(): array
- {
- return [
- 'username' => ['required', 'string', 'min:3', 'max:20', 'unique:users'],
- 'email' => ['required', 'email', 'unique:users'],
- 'password' => ['required', 'string', 'min:8', 'confirmed'],
- ];
- }
-}
-```
\ No newline at end of file
diff --git a/src/Presentation/Http/Responses/README.md b/src/Presentation/Http/Responses/README.md
deleted file mode 100644
index bce8c8325..000000000
--- a/src/Presentation/Http/Responses/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# HTTP Responses
-
-Response transformation and formatting:
-
-- Response factories
-- JSON transformers
-- View presenters
-- Error response formatting
-- Content negotiation
-
-Ensures consistent API responses and proper HTTP semantics.
\ No newline at end of file
diff --git a/src/Presentation/README.md b/src/Presentation/README.md
deleted file mode 100644
index 3e99a424b..000000000
--- a/src/Presentation/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Presentation Layer
-
-User interface implementations:
-
-- HTTP controllers for web and API
-- CLI commands for console operations
-- Request/response handling
-- Input validation
-- Output formatting
-
-This layer translates between external format and application format.
\ No newline at end of file
diff --git a/src/Whoops/README.md b/src/Whoops/README.md
deleted file mode 100644
index 572b42980..000000000
--- a/src/Whoops/README.md
+++ /dev/null
@@ -1,132 +0,0 @@
-# TorrentPier Whoops Enhanced Error Reporting
-
-This directory contains enhanced Whoops error handlers specifically designed for TorrentPier to provide better debugging information when database errors occur.
-
-## Features
-
-### Enhanced Database Error Reporting
-
-The enhanced Whoops handlers provide comprehensive database information when errors occur:
-
-1. **Current SQL Query** - Shows the exact query that caused the error
-2. **Recent Query History** - Displays the last 5 SQL queries executed
-3. **Database Connection Status** - Connection state, server info, database name
-4. **Error Context** - PDO error codes, exception details, source location
-5. **TorrentPier Environment** - Debug mode status, system information
-
-### Components
-
-#### EnhancedPrettyPageHandler
-
-Extends Whoops' default `PrettyPageHandler` to include:
-- **Database Information** table with connection details and current query
-- **Recent SQL Queries** table showing query history with timing
-- **TorrentPier Environment** table with system status
-
-#### DatabaseErrorHandler
-
-Specialized handler that:
-- Adds database context to exception stack frames
-- Identifies database-related code in the call stack
-- Collects comprehensive database state information
-- Formats SQL queries for readable display
-
-## Usage
-
-The enhanced handlers are automatically activated when `DBG_USER` is enabled in TorrentPier configuration.
-
-### Automatic Integration
-
-```php
-// In src/Dev.php - automatically configured
-$prettyPageHandler = new \TorrentPier\Whoops\EnhancedPrettyPageHandler();
-```
-
-### Database Error Logging
-
-Database errors are now automatically logged even when they occur in Nette Database layer:
-
-```php
-// Enhanced error handling in Database.php
-try {
- $row = $result->fetch();
-} catch (\Exception $e) {
- // Log the error including the query that caused it
- $this->debugger->log_error($e);
- throw $e; // Re-throw for Whoops display
-}
-```
-
-## Error Information Displayed
-
-When a database error occurs, Whoops will now show:
-
-### Database Information
-- Connection Status: Connected/Disconnected
-- Database Server: Host and port information
-- Selected Database: Current database name
-- Database Engine: MySQL/PostgreSQL/etc.
-- Total Queries: Number of queries executed
-- Total Query Time: Cumulative execution time
-- Current Query: The SQL that caused the error
-- Last Database Error: Error code and message
-- PDO Driver: Database driver information
-- Server Version: Database server version
-
-### Recent SQL Queries
-- **Query #1-5**: Last 5 queries executed
- - SQL: Formatted query text
- - Time: Execution time in seconds
- - Source: File and line where query originated
- - Info: Additional query information
- - Memory: Memory usage if available
-
-### TorrentPier Environment
-- Application Environment: local/production/etc.
-- Debug Mode: Enabled/Disabled
-- SQL Debug: Enabled/Disabled
-- TorrentPier Version: Current version
-- Config Loaded: Configuration status
-- Cache System: Availability status
-- Language System: Status and encoding
-- Template System: Twig-based availability
-- Execution Time: Request processing time
-- Peak Memory: Maximum memory used
-- Current Memory: Current memory usage
-- Request Method: GET/POST/etc.
-- Request URI: Current page
-- User Agent: Browser information
-- Remote IP: Client IP address
-
-## Configuration
-
-The enhanced handlers respect TorrentPier's debug configuration:
-
-- `DBG_USER`: Must be enabled to show enhanced error pages
-- `SQL_DEBUG`: Enables SQL query logging and timing
-- `APP_ENV`: Determines environment-specific features
-
-## Logging
-
-Database errors are now logged in multiple locations:
-
-1. **PHP Error Log**: Basic error message
-2. **TorrentPier bb_log**: Detailed error with context (`database_errors.log`)
-3. **Whoops Log**: Complete error details (`php_whoops.log`)
-
-## Security
-
-The enhanced handlers maintain security by:
-- Only showing detailed information when `DBG_USER` is enabled
-- Using Whoops' blacklist for sensitive data
-- Logging detailed information to files (not user-accessible)
-- Providing generic error messages to non-debug users
-
-## Integration with TorrentPier 3.0
-
-All enhancements are:
-
-- **Integrated** with the new TorrentPier 3.0 architecture
-- **Modern** - designed for the rewritten codebase
-- **Optional** - only activated in debug mode
-- **Safe** - no security implications for production use
diff --git a/tests/Feature/ContainerIntegrationTest.php b/tests/Feature/ContainerIntegrationTest.php
deleted file mode 100644
index d972ee3ef..000000000
--- a/tests/Feature/ContainerIntegrationTest.php
+++ /dev/null
@@ -1,193 +0,0 @@
-createTestRootDirectory();
- $this->createTestConfigFiles($rootPath, [
- 'services' => [
- 'integration.test' => 'integration_value',
- ],
- ]);
-
- $container = Bootstrap::init($rootPath);
-
- expect($container)->toBeInstanceOf(Container::class);
- expect($container->get('integration.test'))->toBe('integration_value');
-
- removeTempDirectory($rootPath);
- });
-
- it('integrates with global helper functions', function () {
- $rootPath = $this->createTestRootDirectory();
- $this->createTestConfigFiles($rootPath, [
- 'services' => [
- 'helper.test' => 'helper_value',
- ],
- ]);
-
- Bootstrap::init($rootPath);
-
- // Test container() helper
- expect(container())->toBeInstanceOf(Container::class);
-
- // Test app() helper without parameter
- expect(app())->toBeInstanceOf(Container::class);
-
- // Test app() helper with service ID
- expect(app('helper.test'))->toBe('helper_value');
-
- removeTempDirectory($rootPath);
- });
-
- it('handles missing services gracefully in helpers', function () {
- $rootPath = $this->createTestRootDirectory();
- Bootstrap::init($rootPath);
-
- // Should throw RuntimeException for missing service
- expect(fn() => app('missing.service'))
- ->toThrow(RuntimeException::class)
- ->toThrow('not found in container');
-
- removeTempDirectory($rootPath);
- });
-
- it('supports autowiring for simple classes', function () {
- $rootPath = $this->createTestRootDirectory();
- $container = Bootstrap::init($rootPath);
-
- // Should be able to autowire stdClass
- expect($container->has(stdClass::class))->toBeTrue();
- expect($container->get(stdClass::class))->toBeInstanceOf(stdClass::class);
-
- removeTempDirectory($rootPath);
- });
-
- it('loads all architectural layer definitions', function () {
- $rootPath = $this->createTestRootDirectory();
- $container = Bootstrap::init($rootPath);
-
- // Container should be created successfully with all layer definitions loaded
- // Even though most definitions are commented out, the loading should work
- expect($container)->toBeInstanceOf(Container::class);
-
- // Container should have itself registered
- expect($container->get(Container::class))->toBe($container);
- expect($container->get('container'))->toBe($container);
-
- removeTempDirectory($rootPath);
- });
-
- it('supports environment-based configuration', function () {
- $rootPath = $this->createTestRootDirectory();
- $this->createTestConfigFiles($rootPath, [
- 'container' => [
- 'environment' => 'production',
- 'compilation_dir' => $rootPath . '/internal_data/cache/container',
- 'proxies_dir' => $rootPath . '/internal_data/cache/proxies',
- ],
- ]);
-
- $container = Bootstrap::init($rootPath);
-
- expect($container)->toBeInstanceOf(Container::class);
-
- removeTempDirectory($rootPath);
- });
-
- it('supports service provider registration', function () {
- $testProviderClass = new class implements \TorrentPier\Infrastructure\DependencyInjection\ServiceProvider {
- public static bool $wasRegistered = false;
- public static bool $wasBooted = false;
-
- public function register(\TorrentPier\Infrastructure\DependencyInjection\Container $container): void
- {
- self::$wasRegistered = true;
- $container->getWrappedContainer()->set('provider.test', 'provider_registered');
- }
-
- public function boot(\TorrentPier\Infrastructure\DependencyInjection\Container $container): void
- {
- self::$wasBooted = true;
- }
- };
-
- $rootPath = $this->createTestRootDirectory();
- $this->createTestConfigFiles($rootPath, [
- 'container' => [
- 'providers' => [get_class($testProviderClass)],
- ],
- ]);
-
- $container = Bootstrap::init($rootPath);
-
- expect($testProviderClass::$wasRegistered)->toBeTrue();
- expect($testProviderClass::$wasBooted)->toBeTrue();
- expect($container->get('provider.test'))->toBe('provider_registered');
-
- removeTempDirectory($rootPath);
- });
-
- it('handles configuration file loading priority', function () {
- $rootPath = $this->createTestRootDirectory();
- $this->createTestConfigFiles($rootPath, [
- 'services' => [
- 'priority.test' => \DI\factory(function () {
- return 'from_services_file';
- }),
- ],
- ]);
-
- // Initialize with runtime config that should override file config
- $container = Bootstrap::init($rootPath, [
- 'definitions' => [
- 'priority.test' => \DI\factory(function () {
- return 'from_runtime_config';
- }),
- 'runtime.only' => \DI\factory(function () {
- return 'runtime_value';
- }),
- ],
- ]);
-
- // Runtime config should override file config
- expect($container->get('priority.test'))->toBe('from_runtime_config');
- expect($container->get('runtime.only'))->toBe('runtime_value');
-
- removeTempDirectory($rootPath);
- });
-
- it('provides meaningful error messages', function () {
- $rootPath = $this->createTestRootDirectory();
- Bootstrap::init($rootPath);
-
- try {
- app('definitely.missing.service');
- fail('Expected exception to be thrown');
- } catch (RuntimeException $e) {
- expect($e->getMessage())->toContain('definitely.missing.service');
- expect($e->getMessage())->toContain('not found in container');
- }
-
- removeTempDirectory($rootPath);
- });
-
- it('supports performance measurement', function () {
- $rootPath = $this->createTestRootDirectory();
-
- $time = measureExecutionTime(function () use ($rootPath) {
- Bootstrap::init($rootPath);
- });
-
- // Container initialization should be reasonably fast
- expect($time)->toBeLessThan(1.0); // Should take less than 1 second
-
- removeTempDirectory($rootPath);
- });
-});
diff --git a/tests/Pest.php b/tests/Pest.php
deleted file mode 100644
index f1c9a7613..000000000
--- a/tests/Pest.php
+++ /dev/null
@@ -1,95 +0,0 @@
-extend(Tests\TestCase::class)->in('Feature');
-pest()->extend(Tests\TestCase::class)->in('Unit');
-
-/*
-|--------------------------------------------------------------------------
-| Expectations
-|--------------------------------------------------------------------------
-|
-| When you're writing tests, you often need to check that values meet certain conditions. The
-| "expect()" function gives you access to a set of "expectations" methods that you can use
-| to assert different things. Of course, you may extend the Expectation API at any time.
-|
-*/
-
-expect()->extend('toBeOne', function () {
- return $this->toBe(1);
-});
-
-/*
-|--------------------------------------------------------------------------
-| Functions
-|--------------------------------------------------------------------------
-|
-| While Pest is very powerful out-of-the-box, you may have some testing code specific to your
-| project that you don't want to repeat in every file. Here you can also expose helpers as
-| global functions to help you to reduce the number of lines of code in your test files.
-|
-*/
-
-/**
- * Performance Testing Helpers
- */
-function measureExecutionTime(callable $callback): float
-{
- $start = microtime(true);
- $callback();
- return microtime(true) - $start;
-}
-
-function expectExecutionTimeUnder(callable $callback, float $maxSeconds): void
-{
- $time = measureExecutionTime($callback);
- expect($time)->toBeLessThan($maxSeconds, "Execution took {$time}s, expected under {$maxSeconds}s");
-}
-
-/**
- * File System Helpers
- */
-function createTempDirectory(): string
-{
- $tempDir = sys_get_temp_dir() . '/torrentpier_test_' . uniqid();
- mkdir($tempDir, 0755, true);
- return $tempDir;
-}
-
-function removeTempDirectory(string $dir): void
-{
- if (is_dir($dir)) {
- $files = array_diff(scandir($dir), ['.', '..']);
- foreach ($files as $file) {
- $path = $dir . '/' . $file;
- is_dir($path) ? removeTempDirectory($path) : unlink($path);
- }
- rmdir($dir);
- }
-}
-
-/**
- * Exception Testing Helpers
- */
-function expectException(callable $callback, string $exceptionClass, ?string $message = null): void
-{
- try {
- $callback();
- fail("Expected exception $exceptionClass was not thrown");
- } catch (Throwable $e) {
- expect($e)->toBeInstanceOf($exceptionClass);
- if ($message) {
- expect($e->getMessage())->toContain($message);
- }
- }
-}
diff --git a/tests/README.md b/tests/README.md
deleted file mode 100644
index 1ec09dc6b..000000000
--- a/tests/README.md
+++ /dev/null
@@ -1,433 +0,0 @@
-# ๐งช TorrentPier 3.0 Testing Infrastructure
-
-This document outlines the testing infrastructure for TorrentPier 3.0, built using **Pest PHP** and following the hexagonal architecture principles outlined in the project specification.
-
-## ๐ Table of Contents
-
-- [Overview](#overview)
-- [Hexagonal Architecture Testing](#hexagonal-architecture-testing)
-- [Test Organization](#test-organization)
-- [DI Container Testing](#di-container-testing)
-- [Testing Patterns](#testing-patterns)
-- [Test Execution](#test-execution)
-- [Best Practices](#best-practices)
-
-## ๐ฏ Overview
-
-TorrentPier 3.0's testing suite is designed following the hexagonal architecture testing strategy:
-
-- **Domain**: Pure unit tests, no mocks needed
-- **Application**: Unit tests with mocked repositories
-- **Infrastructure**: Integration tests with real services
-- **Presentation**: E2E tests for user journeys
-
-### Core Testing Principles
-
-1. **Architecture-Driven**: Tests follow the hexagonal architecture layers
-2. **Phase-Aligned**: Testing matches the 5-phase implementation strategy
-3. **Clean Slate**: No legacy dependencies, modern PHP 8.3+ testing
-4. **Infrastructure First**: Focus on foundational DI container testing
-5. **Future-Ready**: Structure prepared for upcoming domain/application layers
-
-## ๐๏ธ Hexagonal Architecture Testing
-
-### Testing Strategy by Layer
-
-#### Domain Layer Testing (Phase 2 - Future)
-```php
-// Pure unit tests, no framework dependencies
-it('validates business rules without external dependencies', function () {
- $user = new User(new UserId(1), new Email('test@example.com'));
- expect($user->canPost())->toBeTrue();
-});
-```
-
-#### Application Layer Testing (Phase 3 - Future)
-```php
-// Unit tests with mocked repositories
-it('handles user registration command', function () {
- $mockRepo = Mockery::mock(UserRepositoryInterface::class);
- $handler = new RegisterUserHandler($mockRepo);
-
- $command = new RegisterUserCommand('john', 'john@example.com');
- $handler->handle($command);
-
- $mockRepo->shouldHaveReceived('save');
-});
-```
-
-#### Infrastructure Layer Testing (Phase 1 - Current)
-```php
-// Integration tests with real services
-it('creates container with real PHP-DI integration', function () {
- $container = ContainerFactory::create();
- expect($container)->toBeInstanceOf(Container::class);
-});
-```
-
-#### Presentation Layer Testing (Phase 5 - Future)
-```php
-// E2E tests for user journeys
-it('handles API request end-to-end', function () {
- $response = $this->post('/api/users', ['name' => 'John']);
- expect($response->status())->toBe(201);
-});
-```
-
-## ๐ Test Organization
-
-### Directory Structure
-
-```
-tests/
-โโโ README.md # This documentation
-โโโ Pest.php # Clean Pest configuration
-โโโ TestCase.php # Enhanced base test case with DI utilities
-โโโ Unit/Infrastructure/DependencyInjection/ # DI Container tests (Phase 1)
-โ โโโ ContainerTest.php # Container wrapper tests
-โ โโโ ContainerFactoryTest.php # Factory functionality tests
-โ โโโ BootstrapTest.php # Application bootstrapping tests
-โ โโโ ServiceProviderTest.php # Service provider interface tests
-โ โโโ Definitions/ # Layer-specific definition tests
-โ โโโ DomainDefinitionsTest.php
-โ โโโ ApplicationDefinitionsTest.php
-โ โโโ InfrastructureDefinitionsTest.php
-โ โโโ PresentationDefinitionsTest.php
-โโโ Feature/ # Integration tests
- โโโ ContainerIntegrationTest.php # End-to-end container tests
-```
-
-### Future Structure (As Phases Are Implemented)
-
-```
-tests/
-โโโ Unit/
-โ โโโ Domain/ # Phase 2: Pure business logic tests
-โ โ โโโ User/
-โ โ โโโ Forum/
-โ โ โโโ Tracker/
-โ โโโ Application/ # Phase 3: Use case orchestration tests
-โ โ โโโ User/
-โ โ โโโ Forum/
-โ โ โโโ Tracker/
-โ โโโ Infrastructure/ # Phase 4: External service integration tests
-โ โ โโโ Persistence/
-โ โ โโโ Cache/
-โ โ โโโ Email/
-โ โโโ Presentation/ # Phase 5: Interface layer tests
-โ โโโ Http/
-โ โโโ Cli/
-โโโ Feature/ # Cross-layer integration tests
-```
-
-## ๐ ๏ธ DI Container Testing
-
-### Current Implementation (Phase 1)
-
-The DI container is the foundation of TorrentPier 3.0's architecture. Our tests ensure:
-
-#### Container Wrapper Testing
-```php
-// tests/Unit/Infrastructure/DependencyInjection/ContainerTest.php
-it('implements PSR-11 ContainerInterface', function () {
- expect($this->container)->toBeInstanceOf(\Psr\Container\ContainerInterface::class);
-});
-
-it('can resolve autowired classes', function () {
- $result = $this->container->get(stdClass::class);
- expect($result)->toBeInstanceOf(stdClass::class);
-});
-
-it('throws NotFoundExceptionInterface for non-existent services', function () {
- expect(fn() => $this->container->get('non.existent.service'))
- ->toThrow(NotFoundExceptionInterface::class);
-});
-```
-
-#### Factory Configuration Testing
-```php
-// tests/Unit/Infrastructure/DependencyInjection/ContainerFactoryTest.php
-it('applies configuration correctly', function () {
- $config = [
- 'environment' => 'testing',
- 'autowiring' => true,
- 'definitions' => [
- 'test.service' => \DI\factory(fn() => 'test_value'),
- ],
- ];
-
- $container = ContainerFactory::create($config);
- expect($container->get('test.service'))->toBe('test_value');
-});
-```
-
-#### Bootstrap Integration Testing
-```php
-// tests/Unit/Infrastructure/DependencyInjection/BootstrapTest.php
-it('loads configuration from multiple sources', function () {
- $rootPath = $this->createTestRootDirectory();
- $this->createTestConfigFiles($rootPath, [
- 'env' => ['APP_ENV' => 'testing'],
- 'services' => ['config.service' => \DI\factory(fn() => 'merged_config')],
- ]);
-
- $container = Bootstrap::init($rootPath);
- expect($container->get('config.service'))->toBe('merged_config');
-});
-```
-
-### Test Utilities
-
-#### Enhanced TestCase
-```php
-// tests/TestCase.php
-abstract class TestCase extends BaseTestCase
-{
- protected function createTestContainer(array $config = []): Container
- {
- $defaultConfig = [
- 'environment' => 'testing',
- 'autowiring' => true,
- 'definitions' => [],
- ];
-
- return ContainerFactory::create(array_merge($defaultConfig, $config));
- }
-
- protected function assertCanResolve(Container $container, string $serviceId): void
- {
- $this->assertTrue($container->has($serviceId));
- $this->assertNotNull($container->get($serviceId));
- }
-}
-```
-
-## ๐จ Testing Patterns
-
-### 1. Infrastructure Integration Testing
-```php
-// Real service integration (current phase)
-it('integrates with real PHP-DI container', function () {
- $container = $this->createTestContainer([
- 'definitions' => [
- 'real.service' => \DI\autowire(stdClass::class),
- ],
- ]);
-
- $service = $container->get('real.service');
- expect($service)->toBeInstanceOf(stdClass::class);
-});
-```
-
-### 2. Configuration-Driven Testing
-```php
-// Environment-based configuration
-it('adapts to different environments', function () {
- $prodContainer = $this->createTestContainer(['environment' => 'production']);
- $devContainer = $this->createTestContainer(['environment' => 'development']);
-
- expect($prodContainer)->toBeInstanceOf(Container::class);
- expect($devContainer)->toBeInstanceOf(Container::class);
-});
-```
-
-### 3. Service Provider Testing
-```php
-// Modular service registration
-it('registers services through providers', function () {
- $provider = new class implements ServiceProvider {
- public function register(Container $container): void {
- $container->getWrappedContainer()->set('provider.service', 'registered');
- }
- public function boot(Container $container): void {}
- };
-
- $container = $this->createTestContainer();
- $provider->register($container);
-
- expect($container->get('provider.service'))->toBe('registered');
-});
-```
-
-### 4. Layer Definition Testing
-```php
-// Architectural layer compliance
-it('follows domain layer principles', function () {
- $definitions = DomainDefinitions::getDefinitions();
-
- // Domain definitions should be empty in Phase 1
- expect($definitions)->toBe([]);
-
- // Structure should be prepared for Phase 2
- expect($definitions)->toBeArray();
-});
-```
-
-## ๐ Test Execution
-
-### Running Tests
-
-```bash
-# Run all tests
-./vendor/bin/pest
-
-# Run DI container tests specifically
-./vendor/bin/pest tests/Unit/Infrastructure/DependencyInjection/
-
-# Run integration tests
-./vendor/bin/pest tests/Feature/
-
-# Run with coverage
-./vendor/bin/pest --coverage
-
-# Run specific test file
-./vendor/bin/pest tests/Unit/Infrastructure/DependencyInjection/ContainerTest.php
-```
-
-### Performance Testing
-```bash
-# Measure container bootstrap performance
-./vendor/bin/pest --filter="performance"
-
-# Container creation should be fast
-expectExecutionTimeUnder(fn() => Bootstrap::init($rootPath), 1.0);
-```
-
-## ๐ Best Practices
-
-### 1. Phase-Aligned Testing
-```php
-// Current Phase 1: Test infrastructure only
-it('provides foundation for future phases', function () {
- $container = $this->createTestContainer();
-
- // Infrastructure works now
- expect($container)->toBeInstanceOf(Container::class);
-
- // Ready for future domain services
- expect($container->has(stdClass::class))->toBeTrue();
-});
-```
-
-### 2. Architecture Compliance
-```php
-// Ensure clean architectural boundaries
-it('keeps domain layer pure', function () {
- $definitions = DomainDefinitions::getDefinitions();
-
- // Domain should have no infrastructure dependencies
- expect($definitions)->toBeArray();
-
- // Future domain services will be dependency-free
-});
-```
-
-### 3. Configuration Testing
-```php
-// Test multiple configuration sources
-it('merges configuration correctly', function () {
- $rootPath = $this->createTestRootDirectory();
- $this->createTestConfigFiles($rootPath, [
- 'container' => ['autowiring' => true],
- 'services' => ['test.service' => \DI\factory(fn() => 'test')],
- ]);
-
- $container = Bootstrap::init($rootPath, [
- 'definitions' => ['runtime.service' => \DI\factory(fn() => 'runtime')],
- ]);
-
- expect($container->get('test.service'))->toBe('test');
- expect($container->get('runtime.service'))->toBe('runtime');
-});
-```
-
-### 4. Error Handling
-```php
-// Comprehensive error testing
-it('provides meaningful error messages', function () {
- $container = $this->createTestContainer();
-
- try {
- $container->get('missing.service');
- fail('Expected exception');
- } catch (RuntimeException $e) {
- expect($e->getMessage())->toContain('missing.service');
- expect($e->getMessage())->toContain('not found in container');
- }
-});
-```
-
-## ๐ Current Implementation Status
-
-### โ
Phase 1 Complete: Infrastructure Foundation
-
-- **DI Container**: Fully tested container wrapper with PSR-11 compliance
-- **Factory Pattern**: Comprehensive configuration and creation testing
-- **Bootstrap Process**: Environment loading and configuration merging
-- **Service Providers**: Modular service registration interface
-- **Helper Functions**: Global container access with proper error handling
-- **Layer Definitions**: Prepared structure for all architectural layers
-
-### ๐ Testing Coverage
-
-- **Container Core**: 100% coverage of wrapper functionality
-- **Configuration**: All config sources and merging scenarios tested
-- **Error Handling**: Complete PSR-11 exception compliance
-- **Integration**: End-to-end bootstrap and usage scenarios
-- **Performance**: Container creation and resolution timing validation
-
-### ๐ฎ Future Phase Testing
-
-As TorrentPier 3.0 phases are implemented:
-
-#### Phase 2: Domain Layer
-```php
-// Domain entity testing (future)
-it('validates user business rules', function () {
- $user = new User(UserId::generate(), new Email('test@example.com'));
- expect($user->isActive())->toBeTrue();
-});
-```
-
-#### Phase 3: Application Layer
-```php
-// Command handler testing (future)
-it('processes registration command', function () {
- $handler = app(RegisterUserHandler::class);
- $command = new RegisterUserCommand('john', 'john@example.com');
-
- $userId = $handler->handle($command);
- expect($userId)->toBeInstanceOf(UserId::class);
-});
-```
-
-#### Phase 4: Infrastructure Layer
-```php
-// Repository integration testing (future)
-it('persists user through repository', function () {
- $repository = app(UserRepositoryInterface::class);
- $user = User::create('john', 'john@example.com');
-
- $repository->save($user);
- expect($repository->findById($user->getId()))->not->toBeNull();
-});
-```
-
-#### Phase 5: Presentation Layer
-```php
-// Controller integration testing (future)
-it('handles user registration via API', function () {
- $response = $this->postJson('/api/users', [
- 'username' => 'john',
- 'email' => 'john@example.com',
- ]);
-
- expect($response->status())->toBe(201);
-});
-```
-
----
-
-**TorrentPier 3.0 Testing Philosophy**: Tests serve as both validation and documentation of the hexagonal architecture. Each layer has distinct testing strategies that ensure clean separation of concerns and maintainable code.
-
-For questions about testing patterns or contributions, refer to the [TorrentPier GitHub repository](https://github.com/torrentpier/torrentpier) or the hexagonal architecture specification at `/docs/specs/hexagonal-architecture-spec.md`.
\ No newline at end of file
diff --git a/tests/TestCase.php b/tests/TestCase.php
deleted file mode 100644
index e876511f2..000000000
--- a/tests/TestCase.php
+++ /dev/null
@@ -1,120 +0,0 @@
- 'testing',
- 'autowiring' => true,
- 'definitions' => [],
- ];
-
- return ContainerFactory::create(array_merge($defaultConfig, $config));
- }
-
- /**
- * Create a container with custom service definitions
- */
- protected function createContainerWithDefinitions(array $definitions): Container
- {
- return $this->createTestContainer([
- 'definitions' => $definitions,
- ]);
- }
-
- /**
- * Create a temporary test root directory
- */
- protected function createTestRootDirectory(): string
- {
- $tempDir = createTempDirectory();
-
- // Create basic directory structure
- mkdir($tempDir . '/config', 0755, true);
- mkdir($tempDir . '/internal_data/cache', 0755, true);
-
- return $tempDir;
- }
-
- /**
- * Create test configuration files
- */
- protected function createTestConfigFiles(string $rootPath, array $configs = []): void
- {
- $configPath = $rootPath . '/config';
-
- // Create container.php
- if (isset($configs['container'])) {
- file_put_contents(
- $configPath . '/container.php',
- ' $value) {
- if (is_string($value)) {
- $servicesContent .= " '$key' => factory(function () { return '$value'; }),\n";
- }
- }
- $servicesContent .= "];\n";
-
- file_put_contents($configPath . '/services.php', $servicesContent);
- }
-
- // Create .env file
- if (isset($configs['env'])) {
- $envContent = '';
- foreach ($configs['env'] as $key => $value) {
- $envContent .= "$key=$value\n";
- }
- file_put_contents($rootPath . '/.env', $envContent);
- }
- }
-
- /**
- * Assert that a service can be resolved from the container
- */
- protected function assertCanResolve(Container $container, string $serviceId): void
- {
- $this->assertTrue($container->has($serviceId), "Container should have service: $serviceId");
- $this->assertNotNull($container->get($serviceId), "Should be able to resolve service: $serviceId");
- }
-
- /**
- * Assert that a service cannot be resolved from the container
- */
- protected function assertCannotResolve(Container $container, string $serviceId): void
- {
- $this->assertFalse($container->has($serviceId), "Container should not have service: $serviceId");
- }
-}
diff --git a/tests/Unit/Infrastructure/DependencyInjection/BootstrapTest.php b/tests/Unit/Infrastructure/DependencyInjection/BootstrapTest.php
deleted file mode 100644
index 1a0fbaf16..000000000
--- a/tests/Unit/Infrastructure/DependencyInjection/BootstrapTest.php
+++ /dev/null
@@ -1,190 +0,0 @@
-createTestRootDirectory();
-
- $container = Bootstrap::init($rootPath);
-
- expect($container)->toBeInstanceOf(Container::class);
-
- removeTempDirectory($rootPath);
- });
-
- it('returns the same container on subsequent calls', function () {
- $rootPath = $this->createTestRootDirectory();
-
- $container1 = Bootstrap::init($rootPath);
- $container2 = Bootstrap::init($rootPath);
-
- expect($container1)->toBe($container2);
-
- removeTempDirectory($rootPath);
- });
-
- it('registers container instance with itself', function () {
- $rootPath = $this->createTestRootDirectory();
-
- $container = Bootstrap::init($rootPath);
-
- expect($container->get(Container::class))->toBe($container);
- expect($container->get('container'))->toBe($container);
-
- removeTempDirectory($rootPath);
- });
-
- it('loads environment variables from .env file', function () {
- $rootPath = $this->createTestRootDirectory();
- $this->createTestConfigFiles($rootPath, [
- 'env' => [
- 'TEST_VAR' => 'test_value',
- 'APP_ENV' => 'testing',
- ],
- ]);
-
- Bootstrap::init($rootPath);
-
- expect($_ENV['TEST_VAR'] ?? null)->toBe('test_value');
- expect($_ENV['APP_ENV'] ?? null)->toBe('testing');
-
- removeTempDirectory($rootPath);
- });
-
- it('loads configuration from config files', function () {
- $rootPath = $this->createTestRootDirectory();
- $this->createTestConfigFiles($rootPath, [
- 'container' => [
- 'environment' => 'testing',
- 'autowiring' => true,
- ],
- 'services' => [
- 'test.service' => 'config_value',
- ],
- ]);
-
- $container = Bootstrap::init($rootPath);
-
- expect($container->get('test.service'))->toBe('config_value');
-
- removeTempDirectory($rootPath);
- });
-
- it('handles missing config files gracefully', function () {
- $rootPath = $this->createTestRootDirectory();
-
- // Should not throw exception even without config files
- $container = Bootstrap::init($rootPath);
-
- expect($container)->toBeInstanceOf(Container::class);
-
- removeTempDirectory($rootPath);
- });
- });
-
- describe('getContainer() method', function () {
- it('returns null when not initialized', function () {
- expect(Bootstrap::getContainer())->toBeNull();
- });
-
- it('returns container after initialization', function () {
- $rootPath = $this->createTestRootDirectory();
-
- $container = Bootstrap::init($rootPath);
-
- expect(Bootstrap::getContainer())->toBe($container);
-
- removeTempDirectory($rootPath);
- });
- });
-
- describe('reset() method', function () {
- it('clears the container instance', function () {
- $rootPath = $this->createTestRootDirectory();
-
- Bootstrap::init($rootPath);
- expect(Bootstrap::getContainer())->not->toBeNull();
-
- Bootstrap::reset();
- expect(Bootstrap::getContainer())->toBeNull();
-
- removeTempDirectory($rootPath);
- });
-
- it('allows re-initialization after reset', function () {
- $rootPath = $this->createTestRootDirectory();
-
- $container1 = Bootstrap::init($rootPath);
- Bootstrap::reset();
- $container2 = Bootstrap::init($rootPath);
-
- expect($container1)->not->toBe($container2);
- expect($container2)->toBeInstanceOf(Container::class);
-
- removeTempDirectory($rootPath);
- });
- });
-
- describe('configuration loading', function () {
- it('merges configuration from multiple sources', function () {
- $rootPath = $this->createTestRootDirectory();
- $this->createTestConfigFiles($rootPath, [
- 'env' => [
- 'APP_ENV' => 'production',
- 'APP_DEBUG' => 'false',
- ],
- 'container' => [
- 'autowiring' => true,
- ],
- 'services' => [
- 'config.service' => 'merged_config',
- ],
- ]);
-
- $container = Bootstrap::init($rootPath, [
- 'definitions' => [
- 'runtime.service' => \DI\factory(function () {
- return 'runtime_config';
- }),
- ],
- ]);
-
- expect($container->get('config.service'))->toBe('merged_config');
- expect($container->get('runtime.service'))->toBe('runtime_config');
-
- removeTempDirectory($rootPath);
- });
-
- it('sets default environment when no .env file exists', function () {
- $rootPath = $this->createTestRootDirectory();
-
- $container = Bootstrap::init($rootPath);
-
- // Container should still be created successfully
- expect($container)->toBeInstanceOf(Container::class);
-
- removeTempDirectory($rootPath);
- });
- });
-
- describe('error handling', function () {
- it('handles invalid root path gracefully', function () {
- // Should not throw fatal error for non-existent path
- expect(function () {
- Bootstrap::init('/non/existent/path');
- })->not->toThrow(Throwable::class);
- });
- });
-});
diff --git a/tests/Unit/Infrastructure/DependencyInjection/ContainerFactoryTest.php b/tests/Unit/Infrastructure/DependencyInjection/ContainerFactoryTest.php
deleted file mode 100644
index ccd6e1ea8..000000000
--- a/tests/Unit/Infrastructure/DependencyInjection/ContainerFactoryTest.php
+++ /dev/null
@@ -1,206 +0,0 @@
-toBeInstanceOf(Container::class);
- });
-
- it('applies configuration correctly', function () {
- $config = [
- 'environment' => 'testing',
- 'autowiring' => true,
- 'annotations' => false,
- ];
-
- $container = ContainerFactory::create($config);
- expect($container)->toBeInstanceOf(Container::class);
- });
-
- it('loads custom definitions', function () {
- $config = [
- 'definitions' => [
- 'test.service' => \DI\factory(function () {
- return 'test_value';
- }),
- ],
- ];
-
- $container = ContainerFactory::create($config);
- expect($container->get('test.service'))->toBe('test_value');
- });
-
- it('configures autowiring when enabled', function () {
- $config = ['autowiring' => true];
- $container = ContainerFactory::create($config);
-
- // Should be able to autowire stdClass
- expect($container->has(stdClass::class))->toBeTrue();
- });
-
- it('loads definition files when specified', function () {
- $tempDir = createTempDirectory();
- $definitionFile = $tempDir . '/definitions.php';
-
- file_put_contents($definitionFile, ' \DI\factory(function () {
- return "from_file";
- }),
- ];');
-
- $config = [
- 'definition_files' => [$definitionFile],
- ];
-
- $container = ContainerFactory::create($config);
- expect($container->get('file.service'))->toBe('from_file');
-
- removeTempDirectory($tempDir);
- });
-
- it('handles non-existent definition files gracefully', function () {
- $config = [
- 'definition_files' => ['/non/existent/file.php'],
- ];
-
- // Should not throw an exception
- $container = ContainerFactory::create($config);
- expect($container)->toBeInstanceOf(Container::class);
- });
- });
-
- describe('service providers', function () {
- it('registers and boots service providers', function () {
- $providerClass = new class implements ServiceProvider {
- public static bool $registered = false;
- public static bool $booted = false;
-
- public function register(Container $container): void
- {
- self::$registered = true;
- $container->getWrappedContainer()->set('provider.service', 'provider_value');
- }
-
- public function boot(Container $container): void
- {
- self::$booted = true;
- }
- };
-
- $config = [
- 'providers' => [get_class($providerClass)],
- ];
-
- $container = ContainerFactory::create($config);
-
- expect($providerClass::$registered)->toBeTrue();
- expect($providerClass::$booted)->toBeTrue();
- expect($container->get('provider.service'))->toBe('provider_value');
- });
-
- it('handles invalid provider classes gracefully', function () {
- $config = [
- 'providers' => ['NonExistentProvider'],
- ];
-
- // Should not throw an exception
- $container = ContainerFactory::create($config);
- expect($container)->toBeInstanceOf(Container::class);
- });
-
- it('boots providers after all registrations', function () {
- // Use a simpler approach without constructor dependencies
- $testFile = sys_get_temp_dir() . '/provider_order_test.txt';
- if (file_exists($testFile)) {
- unlink($testFile);
- }
-
- $provider1Class = new class implements ServiceProvider {
- public function register(Container $container): void
- {
- $testFile = sys_get_temp_dir() . '/provider_order_test.txt';
- file_put_contents($testFile, "register1\n", FILE_APPEND);
- }
-
- public function boot(Container $container): void
- {
- $testFile = sys_get_temp_dir() . '/provider_order_test.txt';
- file_put_contents($testFile, "boot1\n", FILE_APPEND);
- }
- };
-
- $provider2Class = new class implements ServiceProvider {
- public function register(Container $container): void
- {
- $testFile = sys_get_temp_dir() . '/provider_order_test.txt';
- file_put_contents($testFile, "register2\n", FILE_APPEND);
- }
-
- public function boot(Container $container): void
- {
- $testFile = sys_get_temp_dir() . '/provider_order_test.txt';
- file_put_contents($testFile, "boot2\n", FILE_APPEND);
- }
- };
-
- $config = [
- 'providers' => [get_class($provider1Class), get_class($provider2Class)],
- ];
-
- ContainerFactory::create($config);
-
- // Read the order from the test file
- $content = file_get_contents($testFile);
- $lines = array_filter(explode("\n", trim($content)));
-
- // All registrations should happen before any boots
- expect($lines)->toBe(['register1', 'register2', 'boot1', 'boot2']);
-
- // Clean up
- unlink($testFile);
- });
- });
-
- describe('environment configuration', function () {
- it('enables compilation in production', function () {
- $tempDir = createTempDirectory();
-
- $config = [
- 'environment' => 'production',
- 'compilation_dir' => $tempDir . '/container',
- 'proxies_dir' => $tempDir . '/proxies',
- ];
-
- $container = ContainerFactory::create($config);
- expect($container)->toBeInstanceOf(Container::class);
-
- removeTempDirectory($tempDir);
- });
-
- it('skips compilation in development', function () {
- $config = [
- 'environment' => 'development',
- ];
-
- $container = ContainerFactory::create($config);
- expect($container)->toBeInstanceOf(Container::class);
- });
- });
-
- describe('layer definitions integration', function () {
- it('loads definitions from all architectural layers', function () {
- $container = ContainerFactory::create();
-
- // Container should be created successfully with all layer definitions
- expect($container)->toBeInstanceOf(Container::class);
-
- // Since most definitions are commented out, we just verify the container works
- expect($container->has(stdClass::class))->toBeTrue();
- });
- });
-});
diff --git a/tests/Unit/Infrastructure/DependencyInjection/ContainerTest.php b/tests/Unit/Infrastructure/DependencyInjection/ContainerTest.php
deleted file mode 100644
index d751ecf67..000000000
--- a/tests/Unit/Infrastructure/DependencyInjection/ContainerTest.php
+++ /dev/null
@@ -1,165 +0,0 @@
-container = $this->createTestContainer();
- });
-
- it('implements PSR-11 ContainerInterface', function () {
- expect($this->container)->toBeInstanceOf(\Psr\Container\ContainerInterface::class);
- });
-
- describe('get() method', function () {
- it('can resolve a simple service', function () {
- $container = $this->createContainerWithDefinitions([
- 'test.service' => \DI\factory(function () {
- return 'test_value';
- }),
- ]);
-
- $result = $container->get('test.service');
- expect($result)->toBe('test_value');
- });
-
- it('can resolve autowired classes', function () {
- $container = $this->createContainerWithDefinitions([
- 'test.class' => \DI\autowire(stdClass::class),
- ]);
-
- $result = $container->get('test.class');
- expect($result)->toBeInstanceOf(stdClass::class);
- });
-
- it('throws NotFoundExceptionInterface for non-existent services', function () {
- expectException(
- fn() => $this->container->get('non.existent.service'),
- NotFoundExceptionInterface::class,
- 'non.existent.service'
- );
- });
-
- it('returns same instance for singleton services', function () {
- $container = $this->createContainerWithDefinitions([
- 'singleton.service' => \DI\factory(function () {
- return new stdClass();
- }),
- ]);
-
- $instance1 = $container->get('singleton.service');
- $instance2 = $container->get('singleton.service');
-
- expect($instance1)->toBe($instance2);
- });
- });
-
- describe('has() method', function () {
- it('returns true for existing services', function () {
- $container = $this->createContainerWithDefinitions([
- 'existing.service' => \DI\factory(function () {
- return 'value';
- }),
- ]);
-
- expect($container->has('existing.service'))->toBeTrue();
- });
-
- it('returns false for non-existent services', function () {
- expect($this->container->has('non.existent.service'))->toBeFalse();
- });
-
- it('returns true for autowirable classes', function () {
- expect($this->container->has(stdClass::class))->toBeTrue();
- });
- });
-
- describe('make() method', function () {
- it('can make instances with parameters', function () {
- $result = $this->container->make(stdClass::class);
- expect($result)->toBeInstanceOf(stdClass::class);
- });
-
- it('creates new instances each time', function () {
- $instance1 = $this->container->make(stdClass::class);
- $instance2 = $this->container->make(stdClass::class);
-
- expect($instance1)->not->toBe($instance2);
- });
- });
-
- describe('call() method', function () {
- it('can call closures with dependency injection', function () {
- $result = $this->container->call(function (stdClass $class) {
- return get_class($class);
- });
-
- expect($result)->toBe('stdClass');
- });
-
- it('can call methods with parameters', function () {
- $service = new class {
- public function test(string $param): string
- {
- return "Hello $param";
- }
- };
-
- $result = $this->container->call([$service, 'test'], ['param' => 'World']);
- expect($result)->toBe('Hello World');
- });
- });
-
- describe('injectOn() method', function () {
- it('returns the object after injection', function () {
- $object = new stdClass();
-
- $result = $this->container->injectOn($object);
- expect($result)->toBe($object);
- });
- });
-
- describe('getWrappedContainer() method', function () {
- it('returns the underlying PHP-DI container', function () {
- $wrapped = $this->container->getWrappedContainer();
- expect($wrapped)->toBeInstanceOf(\DI\Container::class);
- });
-
- it('allows direct access to PHP-DI functionality', function () {
- $wrapped = $this->container->getWrappedContainer();
- $wrapped->set('direct.service', 'direct_value');
-
- expect($this->container->get('direct.service'))->toBe('direct_value');
- });
- });
-
- describe('error handling', function () {
- it('provides meaningful error messages for missing services', function () {
- expectException(
- fn() => $this->container->get('missing.service'),
- NotFoundExceptionInterface::class,
- 'missing.service'
- );
- });
-
- it('handles circular dependencies gracefully', function () {
- $container = $this->createContainerWithDefinitions([
- 'service.a' => \DI\factory(function (\Psr\Container\ContainerInterface $c) {
- return $c->get('service.b');
- }),
- 'service.b' => \DI\factory(function (\Psr\Container\ContainerInterface $c) {
- return $c->get('service.a');
- }),
- ]);
-
- expectException(
- fn() => $container->get('service.a'),
- ContainerExceptionInterface::class,
- 'Circular dependency'
- );
- });
- });
-});
diff --git a/tests/Unit/Infrastructure/DependencyInjection/Definitions/ApplicationDefinitionsTest.php b/tests/Unit/Infrastructure/DependencyInjection/Definitions/ApplicationDefinitionsTest.php
deleted file mode 100644
index 8d686cea1..000000000
--- a/tests/Unit/Infrastructure/DependencyInjection/Definitions/ApplicationDefinitionsTest.php
+++ /dev/null
@@ -1,100 +0,0 @@
-toBeArray();
- });
-
- it('returns empty array when no application services are implemented yet', function () {
- $definitions = ApplicationDefinitions::getDefinitions();
-
- // Since we're in Phase 1 and application services aren't implemented yet,
- // the definitions should be empty (all examples are commented out)
- expect($definitions)->toBe([]);
- });
-
- it('follows application layer principles', function () {
- // Application layer should orchestrate domain objects
- // This test verifies the structure is ready for future application services
-
- $definitions = ApplicationDefinitions::getDefinitions();
-
- // Should be an array (even if empty)
- expect($definitions)->toBeArray();
-
- // When application services are added, they should follow these principles:
- // - Command and Query handlers
- // - Application services that orchestrate domain logic
- // - Event dispatchers
- // - No direct infrastructure concerns
- });
-
- it('can be safely called multiple times', function () {
- $definitions1 = ApplicationDefinitions::getDefinitions();
- $definitions2 = ApplicationDefinitions::getDefinitions();
-
- expect($definitions1)->toBe($definitions2);
- });
-
- it('is prepared for future command/query handlers', function () {
- // This test documents the intended structure for Phase 3 implementation
-
- $definitions = ApplicationDefinitions::getDefinitions();
- expect($definitions)->toBeArray();
-
- // Future command/query handlers will be registered like:
- // 'TorrentPier\Application\User\Handler\RegisterUserHandler' => DI\autowire(),
- // 'CommandBusInterface' => DI\factory(function (ContainerInterface $c) {
- // return new CommandBus($c);
- // }),
-
- // For now, verify the method works without breaking
- expect(count($definitions))->toBeGreaterThanOrEqual(0);
- });
- });
-
- describe('architectural compliance', function () {
- it('follows hexagonal architecture principles', function () {
- // Application layer should orchestrate domain objects without infrastructure concerns
-
- $definitions = ApplicationDefinitions::getDefinitions();
-
- // Application definitions should focus on:
- // 1. Command and Query handlers
- // 2. Application services
- // 3. Event dispatchers
- // 4. Use case orchestration
-
- expect($definitions)->toBeArray();
- });
-
- it('supports CQRS pattern', function () {
- // Application layer should separate commands and queries
- // This test ensures the structure supports CQRS implementation
-
- $definitions = ApplicationDefinitions::getDefinitions();
-
- // Future implementation will separate:
- // - Command handlers (write operations)
- // - Query handlers (read operations)
- // - Command and Query buses
-
- expect($definitions)->toBeArray();
- });
-
- it('prepares for event-driven architecture', function () {
- // Application layer should support domain events
-
- $definitions = ApplicationDefinitions::getDefinitions();
-
- // Future event dispatcher will be registered here
- // 'EventDispatcherInterface' => DI\factory(...)
-
- expect($definitions)->toBeArray();
- });
- });
-});
diff --git a/tests/Unit/Infrastructure/DependencyInjection/Definitions/DomainDefinitionsTest.php b/tests/Unit/Infrastructure/DependencyInjection/Definitions/DomainDefinitionsTest.php
deleted file mode 100644
index 787083024..000000000
--- a/tests/Unit/Infrastructure/DependencyInjection/Definitions/DomainDefinitionsTest.php
+++ /dev/null
@@ -1,84 +0,0 @@
-toBeArray();
- });
-
- it('returns empty array when no domain services are implemented yet', function () {
- $definitions = DomainDefinitions::getDefinitions();
-
- // Since we're in Phase 1 and domain services aren't implemented yet,
- // the definitions should be empty (all examples are commented out)
- expect($definitions)->toBe([]);
- });
-
- it('follows domain layer principles', function () {
- // Domain definitions should not contain infrastructure dependencies
- // This test verifies the structure is ready for future domain services
-
- $definitions = DomainDefinitions::getDefinitions();
-
- // Should be an array (even if empty)
- expect($definitions)->toBeArray();
-
- // When domain services are added, they should follow these principles:
- // - No framework dependencies
- // - Repository interfaces mapped to implementations
- // - Pure business logic services
- });
-
- it('can be safely called multiple times', function () {
- $definitions1 = DomainDefinitions::getDefinitions();
- $definitions2 = DomainDefinitions::getDefinitions();
-
- expect($definitions1)->toBe($definitions2);
- });
-
- it('is prepared for future repository interface mappings', function () {
- // This test documents the intended structure for Phase 2 implementation
-
- $definitions = DomainDefinitions::getDefinitions();
- expect($definitions)->toBeArray();
-
- // Future repository interfaces will be mapped like:
- // 'TorrentPier\Domain\User\Repository\UserRepositoryInterface' =>
- // DI\factory(function (ContainerInterface $c) {
- // return $c->get('TorrentPier\Infrastructure\Persistence\Repository\UserRepository');
- // }),
-
- // For now, verify the method works without breaking
- expect(count($definitions))->toBeGreaterThanOrEqual(0);
- });
- });
-
- describe('architectural compliance', function () {
- it('follows hexagonal architecture principles', function () {
- // Domain layer should have no infrastructure dependencies
- // This test ensures the definition structure is correct
-
- $definitions = DomainDefinitions::getDefinitions();
-
- // Domain definitions should focus on:
- // 1. Repository interface mappings
- // 2. Domain service factories
- // 3. No framework dependencies
-
- expect($definitions)->toBeArray();
- });
-
- it('supports dependency injection inversion', function () {
- // Domain interfaces should be mapped to infrastructure implementations
- // following the dependency inversion principle
-
- $definitions = DomainDefinitions::getDefinitions();
-
- // Even though empty now, the structure supports proper DI mapping
- expect($definitions)->toBeArray();
- });
- });
-});
diff --git a/tests/Unit/Infrastructure/DependencyInjection/Definitions/InfrastructureDefinitionsTest.php b/tests/Unit/Infrastructure/DependencyInjection/Definitions/InfrastructureDefinitionsTest.php
deleted file mode 100644
index 64ba55cee..000000000
--- a/tests/Unit/Infrastructure/DependencyInjection/Definitions/InfrastructureDefinitionsTest.php
+++ /dev/null
@@ -1,159 +0,0 @@
-toBeArray();
- });
-
- it('accepts configuration parameter', function () {
- $config = ['test' => 'value'];
- $definitions = InfrastructureDefinitions::getDefinitions($config);
- expect($definitions)->toBeArray();
- });
-
- it('returns empty array when no infrastructure services are implemented yet', function () {
- $definitions = InfrastructureDefinitions::getDefinitions();
-
- // Since we're in Phase 1 and infrastructure services aren't implemented yet,
- // the definitions should be empty (all examples are commented out)
- expect($definitions)->toBe([]);
- });
-
- it('follows infrastructure layer principles', function () {
- // Infrastructure layer should handle external concerns
- // This test verifies the structure is ready for future infrastructure services
-
- $definitions = InfrastructureDefinitions::getDefinitions();
-
- // Should be an array (even if empty)
- expect($definitions)->toBeArray();
-
- // When infrastructure services are added, they should follow these principles:
- // - Database connections and repositories
- // - Cache implementations
- // - External service adapters
- // - File storage systems
- });
-
- it('can be safely called multiple times', function () {
- $definitions1 = InfrastructureDefinitions::getDefinitions();
- $definitions2 = InfrastructureDefinitions::getDefinitions();
-
- expect($definitions1)->toBe($definitions2);
- });
-
- it('can handle different configurations', function () {
- $config1 = ['database' => ['host' => 'localhost']];
- $config2 = ['cache' => ['driver' => 'redis']];
-
- $definitions1 = InfrastructureDefinitions::getDefinitions($config1);
- $definitions2 = InfrastructureDefinitions::getDefinitions($config2);
-
- // Should handle different configs without breaking
- expect($definitions1)->toBeArray();
- expect($definitions2)->toBeArray();
- });
-
- it('is prepared for future database services', function () {
- // This test documents the intended structure for Phase 4 implementation
-
- $definitions = InfrastructureDefinitions::getDefinitions([
- 'database' => [
- 'host' => '127.0.0.1',
- 'port' => 3306,
- 'database' => 'tp',
- 'username' => 'root',
- 'password' => '',
- 'charset' => 'utf8mb4',
- ],
- ]);
-
- expect($definitions)->toBeArray();
-
- // Future database services will be registered like:
- // 'database.connection.default' => DI\factory(function () use ($config) { ... }),
- // Connection::class => DI\get('database.connection.default'),
-
- // For now, verify the method works without breaking
- expect(count($definitions))->toBeGreaterThanOrEqual(0);
- });
-
- it('is prepared for future cache services', function () {
- $definitions = InfrastructureDefinitions::getDefinitions([
- 'cache' => [
- 'driver' => 'file',
- 'file' => ['path' => '/tmp/cache'],
- ],
- ]);
-
- expect($definitions)->toBeArray();
-
- // Future cache services will be registered like:
- // 'cache.storage' => DI\factory(function () use ($config) { ... }),
- // 'cache.factory' => DI\factory(function (ContainerInterface $c) { ... }),
- });
- });
-
- describe('architectural compliance', function () {
- it('follows hexagonal architecture principles', function () {
- // Infrastructure layer should handle external concerns and adapters
-
- $definitions = InfrastructureDefinitions::getDefinitions();
-
- // Infrastructure definitions should focus on:
- // 1. Database connections and persistence
- // 2. Cache implementations
- // 3. External service adapters
- // 4. File storage systems
- // 5. Third-party integrations
-
- expect($definitions)->toBeArray();
- });
-
- it('supports dependency inversion', function () {
- // Infrastructure should implement domain interfaces
-
- $definitions = InfrastructureDefinitions::getDefinitions();
-
- // Future repository implementations will be registered here:
- // 'TorrentPier\Infrastructure\Persistence\Repository\UserRepository' => DI\autowire()
- // ->constructorParameter('connection', DI\get('database.connection.default'))
-
- expect($definitions)->toBeArray();
- });
-
- it('handles configuration-based service creation', function () {
- // Infrastructure services should be configurable
-
- $config = [
- 'database' => ['driver' => 'mysql'],
- 'cache' => ['driver' => 'redis'],
- 'storage' => ['driver' => 's3'],
- ];
-
- $definitions = InfrastructureDefinitions::getDefinitions($config);
-
- // Should handle configuration without breaking
- expect($definitions)->toBeArray();
- });
-
- it('prepares for multiple database connections', function () {
- $config = [
- 'database' => [
- 'default' => 'mysql',
- 'connections' => [
- 'mysql' => ['driver' => 'mysql'],
- 'sqlite' => ['driver' => 'sqlite'],
- ],
- ],
- ];
-
- $definitions = InfrastructureDefinitions::getDefinitions($config);
- expect($definitions)->toBeArray();
- });
- });
-});
diff --git a/tests/Unit/Infrastructure/DependencyInjection/Definitions/PresentationDefinitionsTest.php b/tests/Unit/Infrastructure/DependencyInjection/Definitions/PresentationDefinitionsTest.php
deleted file mode 100644
index b751b70ba..000000000
--- a/tests/Unit/Infrastructure/DependencyInjection/Definitions/PresentationDefinitionsTest.php
+++ /dev/null
@@ -1,147 +0,0 @@
-toBeArray();
- });
-
- it('returns empty array when no presentation services are implemented yet', function () {
- $definitions = PresentationDefinitions::getDefinitions();
-
- // Since we're in Phase 1 and presentation services aren't implemented yet,
- // the definitions should be empty (all examples are commented out)
- expect($definitions)->toBe([]);
- });
-
- it('follows presentation layer principles', function () {
- // Presentation layer should handle user interface concerns
- // This test verifies the structure is ready for future presentation services
-
- $definitions = PresentationDefinitions::getDefinitions();
-
- // Should be an array (even if empty)
- expect($definitions)->toBeArray();
-
- // When presentation services are added, they should follow these principles:
- // - HTTP controllers for web and API interfaces
- // - CLI commands for console operations
- // - Middleware for request/response processing
- // - Response transformers for output formatting
- });
-
- it('can be safely called multiple times', function () {
- $definitions1 = PresentationDefinitions::getDefinitions();
- $definitions2 = PresentationDefinitions::getDefinitions();
-
- expect($definitions1)->toBe($definitions2);
- });
-
- it('is prepared for future HTTP controllers', function () {
- // This test documents the intended structure for Phase 5 implementation
-
- $definitions = PresentationDefinitions::getDefinitions();
- expect($definitions)->toBeArray();
-
- // Future HTTP controllers will be registered like:
- // 'TorrentPier\Presentation\Http\Controllers\Web\HomeController' => DI\autowire(),
- // 'TorrentPier\Presentation\Http\Controllers\Api\UserController' => DI\autowire(),
- // 'TorrentPier\Presentation\Http\Controllers\Admin\DashboardController' => DI\autowire(),
-
- // For now, verify the method works without breaking
- expect(count($definitions))->toBeGreaterThanOrEqual(0);
- });
-
- it('is prepared for future CLI commands', function () {
- $definitions = PresentationDefinitions::getDefinitions();
- expect($definitions)->toBeArray();
-
- // Future CLI commands will be registered like:
- // 'TorrentPier\Presentation\Cli\Commands\CacheCommand' => DI\autowire(),
- // 'TorrentPier\Presentation\Cli\Commands\MigrateCommand' => DI\autowire(),
- });
-
- it('is prepared for future middleware', function () {
- $definitions = PresentationDefinitions::getDefinitions();
- expect($definitions)->toBeArray();
-
- // Future middleware will be registered like:
- // 'AuthenticationMiddleware' => DI\autowire('TorrentPier\Presentation\Http\Middleware\AuthenticationMiddleware'),
- // 'CorsMiddleware' => DI\autowire('TorrentPier\Presentation\Http\Middleware\CorsMiddleware'),
- });
- });
-
- describe('architectural compliance', function () {
- it('follows hexagonal architecture principles', function () {
- // Presentation layer should handle user interface and external interfaces
-
- $definitions = PresentationDefinitions::getDefinitions();
-
- // Presentation definitions should focus on:
- // 1. HTTP controllers (Web, API, Admin)
- // 2. CLI commands
- // 3. Middleware for request processing
- // 4. Response transformers
- // 5. Input validation and output formatting
-
- expect($definitions)->toBeArray();
- });
-
- it('supports multiple interface types', function () {
- // Presentation layer should support web, API, and CLI interfaces
-
- $definitions = PresentationDefinitions::getDefinitions();
-
- // Future implementation will include:
- // - Web controllers for HTML responses
- // - API controllers for JSON responses
- // - Admin controllers for administrative interface
- // - CLI commands for console operations
-
- expect($definitions)->toBeArray();
- });
-
- it('prepares for middleware stack', function () {
- // Presentation layer should support request/response middleware
-
- $definitions = PresentationDefinitions::getDefinitions();
-
- // Future middleware will handle:
- // - Authentication and authorization
- // - CORS headers
- // - Rate limiting
- // - Request validation
- // - Response transformation
-
- expect($definitions)->toBeArray();
- });
-
- it('supports dependency injection for controllers', function () {
- // Controllers should have their dependencies injected
-
- $definitions = PresentationDefinitions::getDefinitions();
-
- // Future controllers will be autowired with dependencies:
- // - Application services (command/query handlers)
- // - Request validators
- // - Response transformers
-
- expect($definitions)->toBeArray();
- });
-
- it('prepares for different response formats', function () {
- // Presentation layer should support multiple response formats
-
- $definitions = PresentationDefinitions::getDefinitions();
-
- // Future response transformers:
- // 'JsonResponseTransformer' => DI\autowire(...),
- // 'HtmlResponseTransformer' => DI\autowire(...),
-
- expect($definitions)->toBeArray();
- });
- });
-});
diff --git a/tests/Unit/Infrastructure/DependencyInjection/ServiceProviderTest.php b/tests/Unit/Infrastructure/DependencyInjection/ServiceProviderTest.php
deleted file mode 100644
index 69c7c68ac..000000000
--- a/tests/Unit/Infrastructure/DependencyInjection/ServiceProviderTest.php
+++ /dev/null
@@ -1,144 +0,0 @@
-isInterface())->toBeTrue();
- expect($reflection->hasMethod('register'))->toBeTrue();
- expect($reflection->hasMethod('boot'))->toBeTrue();
- });
-
- it('register method has correct signature', function () {
- $reflection = new ReflectionClass(ServiceProvider::class);
- $method = $reflection->getMethod('register');
-
- expect($method->isPublic())->toBeTrue();
- expect($method->getParameters())->toHaveCount(1);
- expect($method->getParameters()[0]->getType()?->getName())->toBe(Container::class);
- expect($method->getReturnType()?->getName())->toBe('void');
- });
-
- it('boot method has correct signature', function () {
- $reflection = new ReflectionClass(ServiceProvider::class);
- $method = $reflection->getMethod('boot');
-
- expect($method->isPublic())->toBeTrue();
- expect($method->getParameters())->toHaveCount(1);
- expect($method->getParameters()[0]->getType()?->getName())->toBe(Container::class);
- expect($method->getReturnType()?->getName())->toBe('void');
- });
-});
-
-describe('ServiceProvider implementation examples', function () {
- it('can implement a basic service provider', function () {
- $provider = new class implements ServiceProvider {
- public function register(Container $container): void
- {
- $container->getWrappedContainer()->set('example.service', 'registered');
- }
-
- public function boot(Container $container): void
- {
- // Boot logic here
- }
- };
-
- $container = $this->createTestContainer();
-
- $provider->register($container);
-
- expect($container->get('example.service'))->toBe('registered');
- });
-
- it('can implement a provider with complex services', function () {
- $provider = new class implements ServiceProvider {
- public function register(Container $container): void
- {
- $container->getWrappedContainer()->set('complex.service', \DI\factory(function () {
- return new class {
- public function getValue(): string
- {
- return 'complex_value';
- }
- };
- }));
- }
-
- public function boot(Container $container): void
- {
- // Could perform additional setup here
- $service = $container->get('complex.service');
- // Setup complete
- }
- };
-
- $container = $this->createTestContainer();
-
- $provider->register($container);
- $provider->boot($container);
-
- $service = $container->get('complex.service');
- expect($service->getValue())->toBe('complex_value');
- });
-
- it('can implement a provider that registers multiple services', function () {
- $provider = new class implements ServiceProvider {
- public function register(Container $container): void
- {
- $wrapped = $container->getWrappedContainer();
-
- $wrapped->set('service.a', 'value_a');
- $wrapped->set('service.b', 'value_b');
- $wrapped->set('service.c', \DI\factory(function () {
- return 'value_c';
- }));
- }
-
- public function boot(Container $container): void
- {
- // Boot all registered services
- }
- };
-
- $container = $this->createTestContainer();
-
- $provider->register($container);
- $provider->boot($container);
-
- expect($container->get('service.a'))->toBe('value_a');
- expect($container->get('service.b'))->toBe('value_b');
- expect($container->get('service.c'))->toBe('value_c');
- });
-
- it('boot method can access services registered by register method', function () {
- $bootedServices = [];
-
- $provider = new class($bootedServices) implements ServiceProvider {
- public function __construct(private array &$bootedServices)
- {
- }
-
- public function register(Container $container): void
- {
- $container->getWrappedContainer()->set('bootable.service', 'registered_value');
- }
-
- public function boot(Container $container): void
- {
- $value = $container->get('bootable.service');
- $this->bootedServices[] = $value;
- }
- };
-
- $container = $this->createTestContainer();
-
- $provider->register($container);
- $provider->boot($container);
-
- expect($bootedServices)->toBe(['registered_value']);
- });
-});