diff --git a/.plan/I18N_INTEGRATION_TEST_PLAN.md b/.plan/I18N_INTEGRATION_TEST_PLAN.md new file mode 100644 index 000000000..05969856a --- /dev/null +++ b/.plan/I18N_INTEGRATION_TEST_PLAN.md @@ -0,0 +1,407 @@ +# Language Switcher Integration Tests - Implementation Plan + +**Project:** Blogware/Scriptlog CMS +**Date:** April 2026 +**Status:** Planning + +--- + +## Executive Summary + +This document outlines the implementation plan for integration tests that verify the complete frontend language switching flow. These tests will run against a live or simulated environment to validate the end-to-end functionality. + +--- + +## Current State + +### Unit Tests Passing ✅ +- `LanguageSwitcherTest.php` - 9 tests, 42 assertions +- `LocaleDetectorTest.php` - 17 tests +- `ThemeI18nTest.php` - 26 tests + +### What's NOT Tested Yet +The full frontend language switching flow from click to display is not automated: +1. User clicks language dropdown → URL changes to `?switch-lang=XX` +2. `lib/main.php` processes `switch-lang` parameter +3. Session/cookie is set +4. User is redirected to original URL +5. Page displays in new language + +--- + +## Integration Test Implementation Plan + +### Phase 1: HTTP Integration Tests + +Create `tests/integration/LanguageSwitcherIntegrationTest.php` that simulates HTTP requests. + +#### Test 1.1: Switch-Lang Parameter Processing +```php +public function testSwitchLangParameterIsProcessed() +{ + // Simulate request: /?switch-lang=ar + $_GET['switch-lang'] = 'ar'; + $_SERVER['REQUEST_URI'] = '/'; + + // Process through main.php logic + $langCode = preg_replace('/[^a-z]{2}/', '', strtolower($_GET['switch-lang'])); + + $this->assertEquals('ar', $langCode); + $this->assertTrue(in_array($langCode, ['en', 'ar', 'zh', 'fr', 'ru', 'es', 'id'])); +} +``` + +#### Test 1.2: Redirect URL Construction +```php +public function testRedirectUrlIsProperlyConstructed() +{ + $_SERVER['REQUEST_URI'] = '/blog/my-post?foo=bar'; + + // Simulate redirect logic from lib/main.php + $urlParts = parse_url($_SERVER['REQUEST_URI']); + $path = $urlParts['path'] ?? '/'; + parse_str($urlParts['query'] ?? '', $query); + unset($query['switch-lang']); + $newQuery = !empty($query) ? '?' . http_build_query($query) : ''; + $redirectUrl = $path . $newQuery; + + $this->assertEquals('/blog/my-post?foo=bar', $redirectUrl); +} +``` + +#### Test 1.3: Session/Cookie Storage +```php +public function testLocaleIsStoredInSessionAndCookie() +{ + // Simulate the logic from lib/main.php + $langCode = 'ar'; + + $_SESSION['scriptlog_locale'] = $langCode; + + // Verify session is set + $this->assertEquals('ar', $_SESSION['scriptlog_locale']); +} +``` + +### Phase 2: Database Integration Tests + +Create tests that verify content filtering by locale. + +#### Test 2.1: Posts Filtered by Locale +```php +public function testPostsAreFilteredByLocale() +{ + // Create test posts with different locales + // Post 1: post_locale = 'en' + // Post 2: post_locale = 'ar' + + // Set current locale to 'ar' + $_SESSION['scriptlog_locale'] = 'ar'; + + // Fetch posts - should only return 'ar' posts + // Verify Post 2 is returned, Post 1 is filtered out +} +``` + +#### Test 2.2: Topics Filtered by Locale +```php +public function testTopicsAreFilteredByLocale() +{ + // Create test topics with different locales + // Set locale, verify filtering works +} +``` + +#### Test 2.3: Menu Items Filtered by Locale +```php +public function testMenuItemsAreFilteredByLocale() +{ + // Create test menu items with different locales + // Set locale, verify only matching items shown +} +``` + +### Phase 3: RTL Integration Tests + +Verify RTL layout is applied correctly. + +#### Test 3.1: RTL Detection +```php +public function testRTLIsDetectedForArabic() +{ + $_SESSION['scriptlog_locale'] = 'ar'; + + // Simulate is_rtl() check + $rtlLocales = ['ar']; + $isRtl = in_array($_SESSION['scriptlog_locale'], $rtlLocales); + + $this->assertTrue($isRtl); +} +``` + +#### Test 3.2: HTML Direction Attribute +```php +public function testHtmlDirAttributeIsSetCorrectly() +{ + // Test LTR + $_SESSION['scriptlog_locale'] = 'en'; + $dir = ($_SESSION['scriptlog_locale'] === 'ar') ? 'rtl' : 'ltr'; + $this->assertEquals('ltr', $dir); + + // Test RTL + $_SESSION['scriptlog_locale'] = 'ar'; + $dir = ($_SESSION['scriptlog_locale'] === 'ar') ? 'rtl' : 'ltr'; + $this->assertEquals('rtl', $dir); +} +``` + +### Phase 4: End-to-End Flow Tests + +Simulate the complete user journey. + +#### Test 4.1: Complete Language Switch Flow +```php +public function testCompleteLanguageSwitchFlow() +{ + // Step 1: User is on English page + $_SESSION['scriptlog_locale'] = 'en'; + $this->assertEquals('en', $_SESSION['scriptlog_locale']); + + // Step 2: User clicks Arabic + $_GET['switch-lang'] = 'ar'; + $_SERVER['REQUEST_URI'] = '/blog/my-post'; + + // Step 3: Process switch-lang + $langCode = preg_replace('/[^a-z]{2}/', '', strtolower($_GET['switch-lang'])); + $_SESSION['scriptlog_locale'] = $langCode; + + // Step 4: Verify locale changed + $this->assertEquals('ar', $_SESSION['scriptlog_locale']); + $this->assertTrue(is_rtl()); + + // Step 5: Verify redirect URL is correct + $urlParts = parse_url($_SERVER['REQUEST_URI']); + $redirectUrl = $urlParts['path']; + $this->assertEquals('/blog/my-post', $redirectUrl); +} +``` + +#### Test 4.2: Language Switches Persist +```php +public function testLanguageSwitchPersistsAcrossRequests() +{ + // First request - set locale + $_SESSION['scriptlog_locale'] = 'fr'; + $_COOKIE['scriptlog_locale'] = 'fr'; + + // Second request - detect locale from session + // (Simulate new request context) + $detectedLocale = $_SESSION['scriptlog_locale'] ?? + $_COOKIE['scriptlog_locale'] ?? + 'en'; + + $this->assertEquals('fr', $detectedLocale); +} +``` + +--- + +## Test Implementation Order + +### Priority 1: Core Logic Tests +1. `testSwitchLangParameterIsProcessed` - Basic parameter handling +2. `testRedirectUrlIsProperlyConstructed` - URL manipulation +3. `testLocaleIsStoredInSession` - Session storage +4. `testLocaleIsStoredInCookie` - Cookie storage + +### Priority 2: Content Filtering Tests +5. `testPostsFilteredByLocale` - Post content filtering +6. `testTopicsFilteredByLocale` - Topic filtering +7. `testMenuItemsFilteredByLocale` - Menu filtering + +### Priority 3: UI/Presentation Tests +8. `testRTLIsDetectedForArabic` - RTL detection +9. `testHtmlDirAttributeIsSetCorrectly` - HTML attribute +10. `testLanguageSwitcherDisplaysCorrectLanguage` - UI verification + +### Priority 4: End-to-End Tests +11. `testCompleteLanguageSwitchFlow` - Full flow +12. `testLanguageSwitchPersistsAcrossRequests` - Persistence +13. `testInvalidLocaleIsRejected` - Error handling +14. `testDefaultLocaleFallbackWorks` - Fallback + +--- + +## Test Data Requirements + +### Required Test Data in Database + +```sql +-- Languages +INSERT INTO tbl_languages (lang_code, lang_name, lang_native, lang_direction) VALUES +('en', 'English', 'English', 'ltr'), +('ar', 'Arabic', 'العربية', 'rtl'), +('zh', 'Chinese', '中文', 'ltr'), +('fr', 'French', 'Français', 'ltr'); + +-- Posts (with locales) +INSERT INTO tbl_posts (post_title, post_locale, post_status) VALUES +('English Post', 'en', 'publish'), +('Arabic Post', 'ar', 'publish'), +('Chinese Post', 'zh', 'publish'); + +-- Topics (with locales) +INSERT INTO tbl_topics (topic_title, topic_locale, topic_status) VALUES +('English Category', 'en', 'Y'), +('Arabic Category', 'ar', 'Y'); + +-- Menu items (with locales) +INSERT INTO tbl_menu (menu_label, menu_locale, menu_status) VALUES +('Home', 'en', 'Y'), +('الرئيسية', 'ar', 'Y'); +``` + +--- + +## Test Execution Strategy + +### Option A: HTTP Client Tests (Recommended) +Use Guzzle HTTP client to make real requests: + +```php +public function testLiveLanguageSwitch() +{ + $client = new GuzzleHttp\Client(['base_uri' => 'http://localhost']); + + // Click Arabic language + $response = $client->get('/?switch-lang=ar'); + + // Follow redirect + $this->assertEquals(302, $response->getStatusCode()); + $location = $response->getHeader('Location')[0]; + + // Verify redirect to original URL + $this->assertEquals('/', $location); + + // Make request to page with Arabic locale cookie + $response = $client->get('/', [ + 'cookies' => $cookies + ]); + + // Verify content is in Arabic + $body = (string) $response->getBody(); + $this->assertStringContainsString('العربية', $body); +} +``` + +### Option B: Simulated Request Tests +Simulate the request/response cycle without HTTP: + +```php +public function testSimulatedLanguageSwitch() +{ + // Simulate environment + $_SERVER['REQUEST_URI'] = '/blog/my-post'; + $_GET['switch-lang'] = 'ar'; + $_GET['redirect'] = '/blog/my-post'; + + // Process through main.php logic (without header output) + ob_start(); + // Include only the relevant logic, not full main.php + $langCode = preg_replace('/[^a-z]{2}/', '', strtolower($_GET['switch-lang'])); + $_SESSION['scriptlog_locale'] = $langCode; + setcookie('scriptlog_locale', $langCode, time() + 86400, '/'); + ob_end_clean(); + + // Verify results + $this->assertEquals('ar', $_SESSION['scriptlog_locale']); + $this->assertEquals('ar', $_COOKIE['scriptlog_locale']); +} +``` + +### Option C: Browser Automation (Selenium/Playwright) +For full end-to-end testing with JavaScript: + +```php +public function testBrowserLanguageSwitch() +{ + $driver = SeleniumDriver::chrome(); + + $driver->get('http://localhost/'); + + // Click language dropdown + $driver->findElement(WebDriverBy::cssSelector('#languageMenu')) + ->click(); + + // Click Arabic + $driver->findElement(WebDriverBy::linkText('العربية')) + ->click(); + + // Wait for redirect + $driver->wait()->until(WebDriverExpectedCondition::urlContains('/')); + + // Verify locale + $html = $driver->getPageSource(); + $this->assertStringContainsString('dir="rtl"', $html); +} +``` + +--- + +## Files to Create/Modify + +### New Files +| File | Purpose | +|------|---------| +| `tests/integration/LanguageSwitcherIntegrationTest.php` | Main integration test file | +| `tests/fixtures/language_switcher_fixture.php` | Test data fixtures | + +### Modified Files +| File | Change | +|------|--------| +| `tests/bootstrap.php` | Add integration test bootstrap | +| `dev-docs/I18N_TESTING_GUIDE.md` | Update with integration tests | + +--- + +## Estimated Implementation Time + +| Phase | Tests | Estimated Time | +|-------|-------|---------------| +| Phase 1: HTTP Integration | 4 tests | 2 hours | +| Phase 2: Database Integration | 3 tests | 3 hours | +| Phase 3: RTL Integration | 2 tests | 1 hour | +| Phase 4: End-to-End | 4 tests | 4 hours | +| Documentation | - | 1 hour | +| **Total** | **13 tests** | **~11 hours** | + +--- + +## Success Criteria + +All integration tests must pass: + +1. ✅ Switch-lang parameter is correctly processed +2. ✅ Session and cookie are set with locale +3. ✅ Redirect URL is correct +4. ✅ Content is filtered by locale (posts, topics, menus) +5. ✅ RTL layout is applied for Arabic +6. ✅ Language persists across page requests +7. ✅ Invalid locales are rejected +8. ✅ Default locale fallback works + +--- + +## Next Steps + +1. **Approve this plan** - Review and approve implementation approach +2. **Create Phase 1 tests** - Start with HTTP integration tests +3. **Set up test database** - Add required test data +4. **Run and iterate** - Execute tests, fix failures, expand coverage +5. **Document results** - Update testing guide with passing tests + +--- + +**Document Version:** 1.0 +**Author:** Senior Fullstack Engineer +**Date:** April 2026 diff --git a/.plan/INSTALLATION_TESTING_PLAN.md b/.plan/INSTALLATION_TESTING_PLAN.md new file mode 100755 index 000000000..63961a379 --- /dev/null +++ b/.plan/INSTALLATION_TESTING_PLAN.md @@ -0,0 +1,259 @@ +# Installation Testing Plan + +This document outlines the testing procedures for verifying the Blogware/Scriptlog installation system works correctly with multi-language support. + +## Test Environment + +- **PHP Version**: 7.4+ (recommended 8.0+) +- **Database**: MySQL 5.7+ or MariaDB 10.2+ +- **Web Server**: Apache/Nginx +- **Test Domain**: http://blogware.site (or local equivalent) + +--- + +## Pre-Installation Checklist + +Before running tests, ensure: + +- [ ] Web server is running and pointing to `/var/www/blogware/public_html` +- [ ] Database server is running with MySQL/MariaDB +- [ ] PHP extensions installed: `pdo`, `pdo_mysql`, `mbstring`, `xml`, `curl`, `gd` +- [ ] Write permissions on `public/files/`, `public/cache/`, `public/log/` +- [ ] Clean database (drop existing tables if any) + +--- + +## Test Cases + +### Test 1: Fresh Installation - English (Default) + +**Objective**: Verify clean installation works with default English language + +**Steps**: +1. Navigate to `http://blogware.site/install/` +2. Select "English" from language dropdown +3. Click "Continue" through system requirements +4. Fill in database credentials (host, user, password, database name) +5. Fill in admin account details (username, email, password) +6. Complete installation +7. Verify redirect to admin login + +**Expected Results**: +- Installation completes without errors +- Admin user created in `tbl_users` +- Default language (English) set in `tbl_languages` and `tbl_settings` +- 41 translation keys populated in `tbl_translations` + +**Verification Queries**: +```sql +SELECT * FROM tbl_users WHERE user_login = 'administrator'; +SELECT * FROM tbl_languages WHERE lang_is_default = 1; +SELECT COUNT(*) AS translation_count FROM tbl_translations; +``` + +--- + +### Test 2: Fresh Installation - Chinese + +**Objective**: Verify installation works with Chinese language + +**Steps**: +1. Navigate to `http://blogware.site/install/` +2. Select "中文 (Chinese)" from language dropdown +3. Complete installation with Chinese selected +4. Verify admin panel displays in Chinese after login + +**Expected Results**: +- Installation completes successfully +- Default language set to Chinese in database +- All UI text appears in Chinese + +--- + +### Test 3: Fresh Installation - Arabic (RTL) + +**Objective**: Verify installation works with Arabic (RTL language) + +**Steps**: +1. Navigate to `http://blogware.site/install/` +2. Select "العربية (Arabic)" from language dropdown +3. Complete installation +4. Verify RTL layout is applied in admin panel + +**Expected Results**: +- Installation completes successfully +- RTL direction set in `tbl_languages` +- Admin panel displays right-to-left + +**Verification Query**: +```sql +SELECT lang_direction FROM tbl_languages WHERE lang_code = 'ar'; +``` + +--- + +### Test 4: Fresh Installation - French + +**Objective**: Verify installation works with French language + +**Steps**: +1. Navigate to `http://blogware.site/install/` +2. Select "Français (French)" from language dropdown +3. Complete installation +4. Verify French translations are applied + +**Expected Results**: +- Installation completes successfully +- French set as default language + +--- + +### Test 5: System Requirements Check + +**Objective**: Verify system requirements page displays correctly + +**Steps**: +1. Navigate to `http://blogware.site/install/` +2. Observe system requirements check on first page + +**Expected Results**: +- All required PHP extensions detected +- Directory permissions validated +- Pass/Fail indicators for each requirement + +--- + +### Test 6: Database Connection Validation + +**Objective**: Verify installer validates database connection + +**Steps**: +1. Start installation +2. Enter incorrect database credentials +3. Submit form + +**Expected Results**: +- Error message displayed: "Cannot connect to database" +- User can correct credentials and retry + +--- + +### Test 7: Admin Account Security + +**Objective**: Verify admin password meets security requirements + +**Steps**: +1. During installation, enter weak password (e.g., "123") +2. Submit form + +**Expected Results**: +- Validation error prevents submission +- Message indicates minimum password strength required + +--- + +### Test 8: Translation Cache Generation + +**Objective**: Verify translation cache is generated after installation + +**Steps**: +1. Complete installation with any language +2. Check `public/files/cache/translations/` directory + +**Expected Results**: +- JSON cache file created (e.g., `en.json`) +- Contains all 41 translation keys + +**Verification**: +```bash +ls -la public/files/cache/translations/ +cat public/files/cache/translations/en.json +``` + +--- + +## Manual Testing Checklist + +After successful installation, verify the following: + +### Admin Panel +- [ ] Login at `admin/index.php` with credentials (administrator / 4dMin(*)^) +- [ ] Dashboard loads without PHP errors +- [ ] All admin menu items accessible +- [ ] Language switcher works in settings + +### Frontend +- [ ] Homepage loads at `/` +- [ ] Blog posts display correctly +- [ ] Theme assets load (CSS, JS, images) +- [ ] No PHP errors in logs + +### Database +- [ ] All 12+ tables created in database +- [ ] Default settings populated in `tbl_settings` +- [ ] Default topic created (if applicable) + +--- + +## Troubleshooting + +### Common Issues + +| Issue | Solution | +|-------|----------| +| "Headers already sent" | Check for BOM in PHP files; ensure no whitespace before `= 7.4 + +--- + +## 1. Executive Summary + +This plan outlines the implementation of **mutation testing** for Blogware/Scriptlog using **Infection 0.26.x** (PHP 7.4 compatible). The project maintains PHP 7.4+ backward compatibility while leveraging mutation testing to improve test quality. + +### Current State + +| Metric | Value | +|--------|-------| +| **PHP Runtime** | 8.3.30 | +| **PHP Platform Config** | 7.4.33 (unchanged) | +| **PHPUnit Version** | 9.6.34 | +| **Xdebug Version** | 3.5.0 | +| **Total Tests** | 62 passing assertions | +| **Test Files** | 70 files | +| **Infection Version** | 0.26.6 (PHP 7.4 compatible) | + +--- + +## 2. PHP Version Compatibility + +### Infection Version Selection + +| PHP Version | Infection Version | Selected | +|-------------|-------------------|----------| +| 8.2.0+ | >= 0.29.10 | ❌ | +| 8.1.0+ | >= 0.26.16 | ❌ | +| **7.4.0+** | **>= 0.18, <= 0.26.6** | **✅ 0.26.6** | +| 7.3.12 | 0.16-0.17 | ❌ | + +**Decision:** Use **Infection 0.26.6** - latest version compatible with PHP 7.4+. + +### Platform Configuration + +**NO CHANGE** to `composer.json` platform config: +```json +"config": { + "platform": { + "php": "7.4.33" + } +} +``` + +The project remains PHP 7.4+ backwards compatible. + +--- + +## 3. Installation + +### 3.1 Install Infection 0.26.6 + +```bash +cd /var/www/blogware/public_html +composer require --dev infection/infection:^0.26 --no-update +composer update infection/infection --with-dependencies +``` + +### 3.2 Verify Installation + +```bash +php lib/vendor/bin/infection --version +``` + +--- + +## 4. Configuration + +### 4.1 Create `infection.json` + +```json +{ + "source": { + "directories": [ + "lib" + ], + "excludes": [ + "lib/vendor", + "lib/core/HTMLPurifier", + "lib/utility/db-mysqli.php" + ] + }, + "logs": { + "text": "infection/output/infection-log.txt", + "summary": "infection/output/summary.txt", + "json": "infection/output/infection.json", + "html": "infection/output/html" + }, + "mutators": { + "@default": true + }, + "testFramework": "phpunit", + "testFrameworkOptions": "--configuration=phpunit.xml", + "coverage": { + "path": "infection/coverage" + }, + "minMsi": 30, + "minCoveredMsi": 40, + "ignoreMsiWithNoMutations": true +} +``` + +### 4.2 Create Output Directory + +```bash +mkdir -p infection/output +``` + +--- + +## 5. Implementation Phases + +### Phase 1: Setup & Baseline (Week 1) + +| Task | Description | Priority | +|------|-------------|----------| +| Install Infection 0.26.6 | `composer require --dev infection/infection:^0.26` | HIGH | +| Create infection.json | Configure source, logs, mutators | HIGH | +| Create output directory | `mkdir -p infection/output` | HIGH | +| Run initial baseline | `php lib/vendor/bin/infection --threads=$(nproc)` | HIGH | +| Document baseline results | Record MSI, escaped mutants, killed mutants | HIGH | + +**Deliverable:** Baseline mutation score report + +### Phase 2: Fix Low-Hanging Fruit (Week 2) + +| Task | Description | Priority | +|------|-------------|----------| +| Review escaped mutants | Identify tests that should have caught mutations | HIGH | +| Add missing assertions | Strengthen tests that pass but shouldn't | MEDIUM | +| Target utility functions | Focus on `lib/utility/*.php` first | MEDIUM | +| Target DAO methods | Focus on `lib/dao/*.php` | MEDIUM | + +**Deliverable:** Improved mutation score by 10-15% + +### Phase 3: Service Layer Coverage (Week 3) + +| Task | Description | Priority | +|------|-------------|----------| +| Target service methods | `lib/service/*.php` | HIGH | +| Add edge case tests | Boundary conditions, null handling | MEDIUM | +| Test error paths | Exception handling, validation failures | MEDIUM | + +**Deliverable:** Service layer mutation score > 40% + +### Phase 4: Controller & Core (Week 4) + +| Task | Description | Priority | +|------|-------------|----------| +| Target controller methods | `lib/controller/*.php` | MEDIUM | +| Target core classes | `lib/core/*.php` | MEDIUM | +| Refactor untestable code | Extract pure functions from complex methods | LOW | + +**Deliverable:** Overall MSI > 30% + +--- + +## 6. Mutator Categories (Infection 0.26.x) + +### 6.1 Arithmetic Mutators + +| Mutator | Example | +|---------|---------| +| `Plus` | `$a + $b` → `$a - $b` | +| `Minus` | `$a - $b` → `$a + $b` | +| `Multiply` | `$a * $b` → `$a / $b` | +| `Division` | `$a / $b` → `$a * $b` | +| `Modulus` | `$a % $b` → `$a * $b` | + +### 6.2 Comparison Mutators + +| Mutator | Example | +|---------|---------| +| `Equal` | `$a == $b` → `$a != $b` | +| `NotEqual` | `$a != $b` → `$a == $b` | +| `Identical` | `$a === $b` → `$a !== $b` | +| `NotIdentical` | `$a !== $b` → `$a === $b` | +| `LessThan` | `$a < $b` → `$a <= $b` | +| `GreaterThan` | `$a > $b` → `$a >= $b` | + +### 6.3 Logical Mutators + +| Mutator | Example | +|---------|---------| +| `LogicalAnd` | `$a && $b` → `$a \|\| $b` | +| `LogicalOr` | `$a \|\| $b` → `$a && $b` | +| `LogicalNot` | `!$a` → `$a` | + +### 6.4 Conditional Mutators + +| Mutator | Example | +|---------|---------| +| `TrueValue` | `true` → `false` | +| `FalseValue` | `false` → `true` | +| `NullValue` | `null` → `""` | +| `ArrayItem` | `$arr[0]` → `$arr[1]` | +| `Concat` | `$a . $b` → `""` | + +### 6.5 Function Call Mutators + +| Mutator | Example | +|---------|---------| +| `FunctionCallRemoval` | `trim($a)` → `$a` | +| `MethodCallRemoval` | `$obj->method()` → (removed) | + +### 6.6 Return Value Mutators + +| Mutator | Example | +|---------|---------| +| `ReturnValue` | `return true` → `return false` | +| `YieldValue` | `yield $a` → `yield null` | + +--- + +## 7. Target Files (Priority Order) + +### High Priority (Start Here) + +| File | Reason | +|------|--------| +| `lib/utility/protected-post.php` | Critical security - password handling | +| `lib/utility/encrypt-decrypt.php` | Critical security - encryption | +| `lib/utility/email-validation.php` | Input validation | +| `lib/utility/check-password.php` | Password strength checks | +| `lib/service/PostService.php` | Core business logic | +| `lib/service/UserService.php` | User management | + +### Medium Priority + +| File | Reason | +|------|--------| +| `lib/dao/PostDao.php` | Data access | +| `lib/dao/UserDao.php` | Data access | +| `lib/controller/PostController.php` | Request handling | +| `lib/core/Authentication.php` | Authentication | +| `lib/core/Dispatcher.php` | Routing | + +### Low Priority (Later) + +| File | Reason | +|------|--------| +| `lib/core/HTMLPurifier/` | Third-party, excluded | +| `lib/vendor/` | Third-party, excluded | +| `lib/utility/db-mysqli.php` | Legacy, excluded | + +--- + +## 8. Success Metrics + +| Metric | Target | Current | +|--------|--------|---------| +| **MSI (Mutation Score Indicator)** | ≥ 30% | 0% (not measured) | +| **Covered MSI** | ≥ 40% | 0% (not measured) | +| **Killed Mutants** | ≥ 50% | 0% | +| **Escaped Mutants** | ≤ 30% | 100% | +| **Untested Code** | ≤ 20% | 100% | + +--- + +## 9. CI/CD Integration + +### 9.1 GitHub Actions Workflow + +```yaml +name: Mutation Testing + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + mutation: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '7.4' + coverage: xdebug + - name: Install dependencies + run: composer install --no-interaction + - name: Run mutation testing + run: php lib/vendor/bin/infection --threads=$(nproc) --min-msi=30 +``` + +### 9.2 Pre-merge Gate + +- Block PRs if MSI drops below 30% +- Report mutation score in PR comments + +--- + +## 10. Risks & Mitigations + +| Risk | Impact | Mitigation | +|------|--------|------------| +| Long execution time | High | Use `--threads=$(nproc)` | +| False positives | Medium | Review mutants manually | +| Untestable code | Medium | Refactor to extract pure functions | +| Third-party code | Low | Exclude from source directories | +| PHP 7.4 compatibility | High | Use Infection 0.26.x | + +--- + +## 11. Timeline + +| Phase | Duration | Deliverable | +|-------|----------|-------------| +| Phase 1: Setup | 1 week | Baseline report | +| Phase 2: Quick Wins | 1 week | +10-15% MSI | +| Phase 3: Service Layer | 1 week | Service MSI > 40% | +| Phase 4: Controllers | 1 week | Overall MSI > 30% | + +**Total Estimated Duration:** 4 weeks + +--- + +## 12. Commands Reference + +```bash +# Run all mutations +php lib/vendor/bin/infection --threads=$(nproc) + +# Run with HTML report +php lib/vendor/bin/infection --threads=$(nproc) --show-mutations + +# Run specific file +php lib/vendor/bin/infection --filter=lib/utility/protected-post.php + +# Run with minimum MSI threshold +php lib/vendor/bin/infection --min-msi=30 + +# Run with coverage-only mode (faster) +php lib/vendor/bin/infection --only-covered + +# Generate summary only +php lib/vendor/bin/infection --show-summary +``` + +--- + +*Last Updated: April 2026 | Version 1.0 | PHP Compatibility: >= 7.4* diff --git a/.plan/PERFORMANCE_OPTIMIZATION_PLAN.md b/.plan/PERFORMANCE_OPTIMIZATION_PLAN.md new file mode 100755 index 000000000..490aedce5 --- /dev/null +++ b/.plan/PERFORMANCE_OPTIMIZATION_PLAN.md @@ -0,0 +1,160 @@ +# Blogware Performance Optimization Plan (Target: 100/100) + +## Executive Summary +This document outlines a strategic technical roadmap to elevate the Blogware platform's performance score to 100/100. Based on Lighthouse audit results and comparative load testing, the plan prioritizes Time to First Byte (TTFB) and Critical Rendering Path optimizations. + +## Load Test Results Verification (April 4, 2026) + +**Test Configuration:** +- Test Duration: 12,419 seconds (~3.4 hours) +- Total Iterations: 1,000 +- Requests per Test: 100 +- Concurrency Level: 10 + +### Actual Performance Metrics (Verified by Load Test) + +| Endpoint Type | URL | Avg RPS | Avg Response Time | P95 Latency | P99 Latency | Success Rate | +|--------------|-----|---------|-------------------|-------------|-------------|--------------| +| **Static** | /admin/login.php | 25.14 req/s | 409.03 ms | 599.12 ms | 1018 ms | 100% | +| **Dynamic** | /?p=3 | 12.60 req/s | 818.75 ms | 1119.32 ms | 1848 ms | 100% | +| **404 Not Found** | /this-page-is-not-real | 4675.51 req/s | 2.42 ms | 3.72 ms | 11 ms | 100% | + +### Stability Analysis + +| Endpoint Type | Coefficient of Variation (CV) | Stability Assessment | +|---------------|-------------------------------|---------------------| +| Static | 15.6% | Moderate | +| Dynamic | 16.5% | Moderate | +| 404 Not Found | 28.2% | High variability | + +--- + +## Phase 1: Infrastructure & Server-Side Efficiency (TTFB Optimization) + +*Goal: Reduce TTFB from ~824ms to <100ms.* + +| Item | Plan Status | Actual Status | Verification | +|------|-------------|---------------|--------------| +| OPcache Tuning | Server-level config | **NOT VERIFIED** - No server config access to confirm | Requires server-level verification | +| Page Caching (lib/utility/page-cache.php) | COMPLETED | **COMPLETED** | 404 responses show 2.42ms avg - confirms caching working | +| Application-Level 404 Handling (Dispatcher.php) | COMPLETED | **COMPLETED** | 404 RPS: 4675.51 req/s confirms efficient 404 handling | +| Database Query Optimization (N+1, Indexes) | COMPLETED | **COMPLETED** | No failed requests in tests | + +**Phase 1 Assessment: PARTIALLY COMPLETED** +- Page caching and 404 handling verified by excellent 404 performance +- OPcache status unknown (requires server verification) +- DB optimization verified (no failures in 300K requests) + +--- + +## Phase 2: Optimized Asset Delivery (FCP & SI Optimization) + +*Goal: Reduce FCP to <1.8s and Speed Index to <3.4s.* + +| Item | Plan Status | Actual Status | Verification | +|------|-------------|---------------|--------------| +| Minification (JS/CSS) | COMPLETED | **COMPLETED** | Files verified in public/themes/blog/assets/ | +| Critical CSS Inlining (header.php) | COMPLETED | **COMPLETED** | Implementation verified in code | +| Resource Hints (preconnect, preload) | COMPLETED | **COMPLETED** | Implementation verified in header.php | + +**Note on Compression:** Enable Gzip/Brotli compression at the web server level (Nginx or Apache). This is a server configuration matter and not handled by the application code to maintain web server interoperability. + +**Phase 2 Assessment: COMPLETED** - All items verified in code + +--- + +## Phase 3: Visual & Content Optimization (LCP & CLS Optimization) + +*Goal: Reduce LCP to <2.5s and CLS to <0.1.* + +| Item | Plan Status | Actual Status | Verification | +|------|-------------|---------------|--------------| +| Modern Image Formats (WebP/AVIF) | COMPLETED | **COMPLETED** | invoke_webp_image() and invoke_responsive_image() verified | +| Explicit Aspect Ratios (width/height) | COMPLETED | **COMPLETED** | invoke_responsive_image() adds dimensions | +| LCP Image Prioritization (fetchpriority) | COMPLETED | **COMPLETED** | fetchpriority="high" implemented | + +**Phase 3 Assessment: COMPLETED** - All items verified in code + +--- + +## Phase 4: Script Execution & Interactivity (TBT Optimization) + +*Goal: Reduce Total Blocking Time to <200ms.* + +| Item | Plan Status | Actual Status | Verification | +|------|-------------|---------------|--------------| +| JavaScript Deferral | "To be implemented" | **NOT COMPLETED** | No evidence in header.php/footer.php | +| Third-Party Audit (summernote) | "To be implemented" | **NOT COMPLETED** | No evidence of route-based loading | + +**Phase 4 Assessment: NOT COMPLETED** - JavaScript deferral and third-party script optimization pending + +--- + +## Performance Gap Analysis + +### Target vs Actual (Based on Load Test Results) + +| Metric | Target | Actual (Static) | Actual (Dynamic) | Gap | +|--------|--------|-----------------|-------------------|-----| +| **TTFB** | <100ms | 409.03 ms | 818.75 ms | ❌ 309-719ms over target | +| **LCP** | <2.5s | Not measured | Not measured | ⚠️ Requires Lighthouse | +| **FCP** | <1.8s | Not measured | Not measured | ⚠️ Requires Lighthouse | +| **CLS** | <0.1 | Not measured | Not measured | ⚠️ Requires Lighthouse | +| **TBT** | <200ms | Not measured | Not measured | ⚠️ Requires Lighthouse | + +### Key Findings from Load Test + +1. **Dynamic Content Bottleneck**: Response time is 2x slower than static (819ms vs 409ms) +2. **P99 Latency Concern**: Dynamic content P99 reaches 1848ms (1.8 seconds) +3. **Excellent 404 Performance**: 4675 RPS with 2.42ms response confirms caching working +4. **100% Reliability**: Zero failures across 300,000 requests proves system stability + +--- + +## Remaining Action Items + +### High Priority + +1. **Verify OPcache Configuration** - Requires server-level access to confirm PHP opcode caching is enabled +2. **Implement JavaScript Deferral** - Move non-critical scripts to defer attribute +3. **Optimize Dynamic Content** - Further reduce 819ms response time: + - Database query profiling + - PHP opcode caching verification + - Content caching layer + +### Medium Priority + +4. **Server-Side Compression** - Enable Gzip/Brotli at web server level +5. **Third-Party Script Audit** - Implement route-based loading for admin scripts +6. **Monitor P95/P99 Alerts** - Set up alerting for latency thresholds + +--- + +## Strategic Roadmap Summary (Updated with Actual Results) + +| Metric | Pre-Optimization | Current (Verified) | Target | Status | +|--------|------------------|---------------------|--------|--------| +| **TTFB (Static)** | ~824ms (est.) | 409.03 ms | <100ms | ❌ Not met | +| **TTFB (Dynamic)** | ~824ms (est.) | 818.75 ms | <100ms | ❌ Not met | +| **404 Handling** | N/A | 4675.51 req/s | N/A | ✅ Excellent | +| **Reliability** | N/A | 100% success | 100% | ✅ Achieved | + +**Overall Status: PHASES 1-3 COMPLETED, PHASE 4 INCOMPLETE** + +Phase 1-3 implementations verified in code and partially confirmed by load test (404 performance proves caching works). Phase 4 (JavaScript deferral and third-party scripts) requires implementation. + +--- + +## Web Server Interoperability + +This software is designed to work on both **Nginx** and **Apache** without requiring server-specific configuration: + +- **URL Rewriting:** Uses PHP-based routing in `lib/core/Dispatcher.php`. No `.htaccess` or Nginx config required. +- **404 Handling:** Handled at application level in the Dispatcher. +- **Static Files:** Served directly by the web server from `public/` directory. +- **Compression:** Configure at web server level (Nginx: `gzip on;`, Apache: `mod_deflate`). + +--- + +*Last Updated: April 4, 2026* +*Performance Data Source: Load test results in /var/www/blogware/load_test_results_20260404_175932/* diff --git a/.plan/PHPCODESNIFFER_IMPLEMENTATION_PLAN.md b/.plan/PHPCODESNIFFER_IMPLEMENTATION_PLAN.md new file mode 100755 index 000000000..3a1fb3ebf --- /dev/null +++ b/.plan/PHPCODESNIFFER_IMPLEMENTATION_PLAN.md @@ -0,0 +1,280 @@ +# PHP_CodeSniffer PSR12 Implementation Plan + +## Executive Summary + +This plan outlines the integration of PHP_CodeSniffer to ensure the codebase conforms to PSR12 coding standard. The project contains **3,028 PHP files**. + +--- + +## PHP Version Compatibility + +| Component | Version | Min PHP | Project Compatible? | +|-----------|---------|---------|---------------------| +| squizlabs/php_codesniffer | ^4.0 | 7.2 | ✅ Yes (7.4.33) | +| friendsofphp/php-cs-fixer | ^3.57 | 7.4 | ✅ Yes (7.4.33) | +| PSR12 Coding Standard | - | 7.0+ | ✅ Yes | + +> **Note**: PSR12 is purely a code style standard (braces, spacing, indentation) - no PHP runtime features involved. + +--- + +## Current Codebase Analysis + +| Directory | PHP Files | Priority | +|-----------|-----------|----------| +| lib/ | 2,792 | High (core classes) | +| admin/ | 95 | High | +| public/themes/ | 22 | Medium | +| install/ | 11 | Low | +| api/ | 1 | Low | + +### Identified PSR12 Violations (Sample) + +1. **Class braces**: Opening brace on same line (should be new line) +2. **Method braces**: Opening brace on same line (should be new line) +3. **Indentation**: Inconsistent (mix of 2, 3, 4 spaces) +4. **Spacing**: Inconsistent around operators and parentheses +5. **Line length**: Some lines exceed 120 characters + +--- + +## Implementation Strategy + +### Phase 1: Installation & Configuration + +1. Add to Composer: + ```bash + composer require --dev squizlabs/php_codesniffer:^4.0 + ``` + +2. Create `phpcs.xml` configuration: + ```xml + + + Blogware PSR12 Coding Standard + + + + + + + + + + + + + + lib/vendor/* + admin/assets/* + + + lib + admin + public/themes + install + api + + ``` + +3. Excluded directories rationale: + - `lib/vendor/` - Third-party code + - `admin/assets/` - Frontend assets + - `public/themes/assets/` - Theme assets + +--- + +### Phase 2: Initial Analysis + +1. Run initial scan: + ```bash + ./vendor/bin/phpcs --standard=PSR12 lib/ admin/ public/themes/ install/ api/ + ``` + +2. Generate error report: + ```bash + # JSON report for parsing + ./vendor/bin/phpcs --standard=PSR12 --report-json lib/ > phpcs-report.json + + # Summary by severity + ./vendor/bin/phpcs --standard=PSR12 --report=summary lib/ + ``` + +3. Categorize violations by type: + - Brace placement (class/method) + - Indentation + - Spacing + - Line length + - Other + +--- + +### Phase 3: Auto-Fix Issues + +1. Install PHP-CS-Fixer: + ```bash + composer require --dev friendsofphp/php-cs-fixer:^3.57 + ``` + +2. Create `.php-cs-fixer.dist.php`: + ```php + in(['lib', 'admin', 'public/themes', 'install', 'api']) + ->exclude('vendor') + ->exclude('assets') + ->notName('*.min.css') + ->notName('*.min.js') + ->files(); + + return (new PhpCsFixer\Config()) + ->setRules([ + '@PSR12' => true, + 'braces' => ['position_after_functions_and_declarations' => 'next'], + 'indentation_type' => true, + 'line_ending' => true, + 'no_trailing_whitespace' => true, + 'no_unused_imports' => true, + ]) + ->setFinder($finder); + ``` + +3. Run auto-fix: + ```bash + # Preview changes + ./vendor/bin/php-cs-fixer fix --dry-run --diff + + # Apply fixes + ./vendor/bin/php-cs-fixer fix --diff + ``` + +--- + +### Phase 4: Manual Fixes + +| Category | Estimated Fixes | Approach | +|----------|-----------------|----------| +| Class braces | ~500 | Regex + IDE batch | +| Method braces | ~800 | Regex + IDE batch | +| Indentation | Variable | Manual per file | +| Control structures | Variable | php-cs-fixer | +| Complex files | 20-50 | Manual review | + +Priority order: +1. lib/core/Bootstrap.php +2. lib/core/Dispatcher.php +3. lib/dao/*.php +4. lib/service/*.php +5. admin/*.php + +--- + +### Phase 5: CI/CD Integration + +Create `.github/workflows/phpcs.yml`: + +```yaml +name: Code Quality + +on: [push, pull_request] + +jobs: + phpcs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + + - name: Install dependencies + run: composer install --no-interaction + + - name: Run PHP_CodeSniffer + run: ./vendor/bin/phpcs --standard=PSR12 --colors lib/ admin/ public/themes/ + + - name: Run PHP-CS-Fixer (check mode) + run: ./vendor/bin/php-cs-fixer fix --dry-run --diff +``` + +Optional: Add pre-commit hook. + +--- + +### Phase 6: Verification + +1. Final scan: + ```bash + ./vendor/bin/phpcs --standard=PSR12 lib/ admin/ public/themes/ install/ api/ + # Exit code 0 = no errors + ``` + +2. Run tests: + ```bash + ./vendor/bin/phpunit + ``` + +--- + +## Timeline Estimate + +| Phase | Duration | +|-------|----------| +| Phase 1: Setup | 1 day | +| Phase 2: Analysis | 1-2 days | +| Phase 3: Auto-fix | 1 day | +| Phase 4: Manual fix | 5 days | +| Phase 5: CI/CD | 1 day | +| Phase 6: Verification | 1 day | + +**Total: ~10-12 days** + +--- + +## Commands Reference + +```bash +# Install +composer require --dev squizlabs/php_codesniffer:^4.0 +composer require --dev friendsofphp/php-cs-fixer:^3.57 + +# Check code +./vendor/bin/phpcs --standard=PSR12 lib/ +./vendor/bin/phpcs --standard=PSR12 --report=summary lib/ + +# Auto-fix +./vendor/bin/php-cs-fixer fix --diff + +# Specific directory +./vendor/bin/phpcs --standard=PSR12 lib/core/ + +# CI check +./vendor/bin/phpcs --standard=PSR12 --colors lib/ admin/ public/themes/ +``` + +--- + +## Risk Assessment + +| Risk | Impact | Mitigation | +|------|--------|------------| +| Breaking production code | High | Run full test suite before commit | +| Auto-fix corruption | Medium | Use git, test frequently | +| Time for full fix | High | Prioritize core files first | +| CI build failures | Medium | Fix violations incrementally | + +--- + +## Success Criteria + +- [ ] PHP_CodeSniffer installed via Composer +- [ ] phpcs.xml configuration created +- [ ] Initial scan completed with error report +- [ ] PHP-CS-Fixer applied for auto-fixable issues +- [ ] Manual fixes applied to remaining violations +- [ ] CI/CD workflow created +- [ ] Full scan passes with exit code 0 +- [ ] All PHPUnit tests pass diff --git a/.plan/SUMMERNOTE_AJAX_IMAGE_UPLOAD_PLAN.md b/.plan/SUMMERNOTE_AJAX_IMAGE_UPLOAD_PLAN.md new file mode 100644 index 000000000..cc1d27ed2 --- /dev/null +++ b/.plan/SUMMERNOTE_AJAX_IMAGE_UPLOAD_PLAN.md @@ -0,0 +1,184 @@ +# AJAX Image Upload for Summernote Editor - Implementation Plan + +## 1. Project Overview + +**Goal**: Integrate AJAX image upload in Summernote WYSIWYG editor + +**Scope**: Only Summernote editor AJAX upload - do NOT touch Featured Image (sidebar form) + +**Current State**: +- Summernote in `admin/admin-layout.php` calls `/admin/media-upload.php` +- No CSRF protection +- Images not saved to database via API + +**Target State**: +- AJAX upload to `/admin/media-upload.php` (direct admin endpoint) +- CSRF validation (optional) +- Save to `tbl_media` + link to post via `tbl_mediameta` +- Use existing `upload_photo()` for resizing + +--- + +## 2. Files Involved + +| File | Action | +|------|--------| +| `admin/media-upload.php` | New endpoint for upload handling | +| `admin/admin-layout.php` | Update AJAX URL + add CSRF/post_id to formData | +| `lib/core/Authentication.php` | Cookie path fix for cross-path AJAX | +| `lib/controller/api/MediaApiController.php` | API fallback with auth cookie support | + +--- + +## 3. Implementation Steps + +### Step 1: Create Direct Admin Upload Endpoint + +**File**: `admin/media-upload.php` + +This endpoint is placed in the admin folder to use admin session authentication directly. + +Key features: +- Uses `Session::getInstance()` for authentication (works in admin context) +- Saves to database via `MediaDao` +- Uses `upload_photo()` for resizing to 3 sizes + WebP +- Proper output buffering to prevent HTML errors in JSON response +- Returns clean JSON response + +```php +// Key authentication check +$session = Session::getInstance(); +if (!isset($session->scriptlog_session_login)) { + sendJsonResponse(401, false, 'UNAUTHORIZED', 'Admin authentication required'); +} +``` + +### Step 2: Update Summernote AJAX + +**File**: `admin/admin-layout.php` + +- Keep URL as `/admin/media-upload.php` (not `/api/v1/media/upload`) +- Add `withCredentials: true` to AJAX call +- Hidden inputs for CSRF and post_id are already in place + +```javascript +$.ajax({ + url: '/admin/media-upload.php', + method: 'POST', + data: formData, + processData: false, + contentType: false, + xhrFields: { + withCredentials: true + }, + success: function(response) { + if (response.success && response.data && response.data.url) { + $('#summernote').summernote('insertImage', response.data.url); + } + } +}); +``` + +### Step 3: Cookie Path Fix + +**File**: `lib/core/Authentication.php` + +Changed `COOKIE_PATH` from `APP_ADMIN` (`/admin/`) to `/` so the session cookie is sent to all paths including `/api/*`. + +```php +// Before +public const COOKIE_PATH = APP_ADMIN; // /admin/ + +// After +public const COOKIE_PATH = '/'; // Available at root level +``` + +**Note**: Users need to log out and log back in for the new cookie to be set. + +### Step 4: API Fallback (Optional) + +**File**: `api/index.php` and `lib/controller/api/MediaApiController.php` + +Added session initialization to API and auth cookie fallback support as backup solution. + +--- + +## 4. Response Format + +```json +{ + "success": true, + "status": 201, + "data": { + "url": "/public/files/pictures/abc123_image.jpg", + "filename": "abc123_image.jpg", + "media_id": 42, + "post_id": 5 + } +} +``` + +**URL**: Direct filesystem path for fast loading (`/public/files/pictures/...`) + +--- + +## 5. Database + +**tbl_media** - Image metadata: +- `media_filename` = 'abc123_image.jpg' +- `media_type` = 'image' +- `media_target` = 'blog' +- `media_user` = username + +**tbl_mediameta** - Post linkage: +- `media_id` = 42 +- `meta_key` = 'post_id' +- `meta_value` = '5' + +--- + +## 6. Files to Modify/Create + +1. `admin/media-upload.php` - New direct upload endpoint +2. `admin/admin-layout.php` - AJAX URL and withCredentials +3. `lib/core/Authentication.php` - Cookie path fix +4. `api/index.php` - Session initialization (backup) +5. `lib/controller/api/MediaApiController.php` - Auth cookie fallback (backup) + +--- + +## 7. Testing + +1. Log out and log back in (to get new cookie with path `/`) +2. Go to Posts → Add New +3. Click image button in Summernote toolbar +4. Select image → verify uploads +5. Check: + - Files: `public/files/pictures/` has 4 versions + WebP + - Database: `tbl_media` and `tbl_mediameta` have new records + +--- + +## 8. Troubleshooting + +### Error: "Failed to upload image: Unauthorized" +- Cookie path issue: `COOKIE_PATH` was `/admin/`, need to change to `/` +- Solution: Log out and log back in + +### Error: "Failed to upload image: SyntaxError: Unexpected token '<'" +- PHP output before JSON: `lib/main.php` or `upload_photo()` outputting HTML +- Solution: Use output buffering and proper JSON response helper + +--- + +## 9. Implementation Summary + +| Date | Commit | Description | +|------|--------|-------------| +| April 6, 2026 | `f2e1d91` | Fix Summernote AJAX image upload authentication | +| April 6, 2026 | `5db174e` | Fix cookie path for AJAX API requests | +| April 6, 2026 | `a593f39` | Use direct admin endpoint for Summernote image upload | +| April 6, 2026 | `44db5e7` | Fix JSON response in media upload handler | + +*Plan updated: April 6, 2026* +*Focus: ONLY Summernote AJAX upload - do NOT touch Featured Image sidebar* diff --git a/.plan/security-testing/SECURITY_TESTING_PLAN.md b/.plan/security-testing/SECURITY_TESTING_PLAN.md new file mode 100755 index 000000000..bb3f7988d --- /dev/null +++ b/.plan/security-testing/SECURITY_TESTING_PLAN.md @@ -0,0 +1,455 @@ +# Blogware/Scriptlog Security Testing Plan + +**Version:** 2.0 +**Date:** March 27, 2026 +**Target:** Blogware/Scriptlog PHP MVC Blog System +**Tester:** Security Assessment Team +**Scope:** Local & Remote Instance Testing + +--- + +## Document Information + +| Field | Value | +|-------|-------| +| Document Status | Active | +| Last Updated | March 27, 2026 | +| Test Tool | Socrates Blade v3.2 | +| OWASP Version | Top 10 2021 | + +--- + +## 1. Executive Summary + +This document outlines a comprehensive security testing plan for the Blogware/Scriptlog CMS. The plan addresses OWASP Top 10 vulnerabilities, authentication flaws, and application-specific security concerns through automated and manual testing procedures. + +### Testing Capabilities + +- **Local Testing**: Target `http://localhost`, `http://127.0.0.1`, or custom local URLs +- **Remote Testing**: Target any publicly accessible Blogware instance +- **Aggressive Testing**: Time-based attacks with configurable delays (up to 30s) +- **Brute Force Testing**: Credential brute-forcing against login endpoints +- **Dual Reporting**: JSON and HTML output formats + +### Test Environment + +| Environment | URL | Notes | +|-------------|-----|-------| +| Local | `http://blogware.site` | Default development instance | +| Production | Configurable | Remote production instances | +| Admin Credentials | `administrator` / `4dMin(*)^` | Primary test account | + +--- + +## 2. Testing Scope + +### 2.1 In-Scope Components + +| Component | Description | Priority | +|-----------|-------------|----------| +| Frontend (Public) | Public-facing blog pages, posts, categories, tags, archives | HIGH | +| Admin Panel | `/admin/*` - All admin functionality | CRITICAL | +| Authentication | Login, logout, session management, password reset | CRITICAL | +| API Endpoints | `/api/*` - REST API endpoints | HIGH | +| Import/Export | WordPress, Ghost, Blogspot import functionality | HIGH | +| Media Library | File upload and management | HIGH | +| Plugin System | Plugin installation and activation | CRITICAL | + +### 2.2 Out-of-Scope + +- Third-party plugins not part of core installation +- Server infrastructure and network-level attacks +- Denial of Service testing (resource exhaustion) +- Physical security testing + +--- + +## 3. OWASP Top 10 2021 Coverage + +| OWASP Category | Blogware Risk | Test Method | Priority | +|----------------|---------------|-------------|----------| +| A01 Broken Access Control | IDOR in posts/pages, privilege escalation | Tool + Manual | CRITICAL | +| A02 Cryptographic Failures | Session handling, cookie encryption | Manual review | HIGH | +| A03 Injection | SQLi in search/comments, XSS in content | Tool + Manual | CRITICAL | +| A04 Insecure Design | Missing rate limiting, weak CSRF | Tool + Manual | HIGH | +| A05 Security Misconfiguration | Missing headers, debug mode | Tool | MEDIUM | +| A06 Vulnerable Components | Outdated vendor libraries | Manual | MEDIUM | +| A07 Auth Failures | Brute force, session hijacking | Tool + Manual | HIGH | +| A08 Data Integrity Failures | CSRF on admin actions | Tool | HIGH | +| A09 Logging Failures | Insufficient audit trail | Manual | LOW | +| A10 SSRF | Media URL fetching, import URLs | Tool | MEDIUM | + +--- + +## 4. Test Cases + +### 4.1 A01 - Broken Access Control + +| ID | Test Case | Endpoint | Method | Expected Result | +|----|-----------|----------|--------|----------------| +| TC-001 | IDOR in Post Viewing | `/post/{id}/{slug}` | GET | 403 or redirect for private posts | +| TC-002 | IDOR in Admin Post Editing | `admin/posts.php?action=edit&Id={id}` | GET | 403 Forbidden | +| TC-003 | IDOR in Comment Deletion | `admin/comments.php?action=delete&Id={id}` | GET | 403 Forbidden | +| TC-004 | Privilege Escalation | `admin/users.php` | POST | Redirect to 403 page | +| TC-005 | Direct Object Reference in Media | `/admin/medialib.php` | GET | 403 for private media | +| TC-006 | Admin Page Access Without Auth | All `admin/*.php` | GET | Redirect to login | +| TC-007 | Category Access Control | `/category/{id}` | GET | Respect post visibility | +| TC-008 | Archive Access Control | `/archive/{month}/{year}` | GET | 404 for non-existent archives | + +### 4.2 A02 - Cryptographic Failures + +| ID | Test Case | Method | Expected Result | +|----|-----------|--------|----------------| +| TC-009 | Session Token Entropy | Code review | Minimum 128-bit entropy | +| TC-010 | Cookie Security Flags | GET | HttpOnly, Secure, SameSite=Strict | +| TC-011 | Password Hashing | Code review | `password_hash()` with cost >= 12 | +| TC-012 | Session Fixation | Login flow | `session_regenerate_id(true)` called | +| TC-013 | Cookie Encryption | Code review | AES-256-GCM or AES-256-CBC with HMAC | + +### 4.3 A03 - Injection + +#### XSS Tests + +| ID | Test Case | Endpoint | Payload Type | +|----|-----------|----------|--------------| +| TC-014 | Reflected XSS in Search | `/?search=", + "", + "", + + # Image onerror injection + "", + "", + "", + + # SVG injection + "", + "", + "", + + # Event handlers + "", + "