Skip to content

Acorn scheduler is not loading wordpress correctly #383

@tgeorgel

Description

@tgeorgel

Version

v4.2.2

What did you expect to happen?

I'm using Acorn in combinaison with Radicle.

I did register a Kernel instance :

\Roots\bootloader()->boot(function ($app) {
    $app->singleton(
        \Illuminate\Contracts\Console\Kernel::class,
        \App\Console\Kernel::class
    );
});

Which provides schedules :

namespace App\Console;

use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Foundation\Application;
use Roots\Acorn\Console\Kernel as RootsKernel;
use Illuminate\Console\Scheduling\Schedule;

class Kernel extends RootsKernel
{
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('debug:dump')->everySecond();
    }

    public function __construct(Application $app, Dispatcher $events)
    {
        if (! defined('ARTISAN_BINARY')) {
            define('ARTISAN_BINARY', dirname(__DIR__, 2) . '/vendor/roots/acorn/bin/acorn');
        }

        $this->app = $app;
        $this->events = $events;

        // Make sure our schedules are getting registered
        $this->app->extend(Schedule::class, function ($app) {
            return tap(new Schedule($this->scheduleTimezone()), function ($schedule) {
                $this->schedule($schedule->useCache($this->scheduleCache()));
            });
        });

        $this->app->booted(function () {
            $this->defineConsoleSchedule();
        });
    }
}

Schedules are working nicely, but the load of Wordpress is not complete.
For example, If I would want to get the permalink of a page inside my command :

// App\Console\Commands\DebugDump

public function handle()
{
    ray(get_permalink(2));
}

When using WP-CLI, this works perfectly :

wp acorn debug:dump 

// http://site.test/my-page-name

But in the scheduler context, I get :

 wp acorn schedule:test

Running ['vendor/roots/acorn/bin/acorn' debug:dump] ................................................................................... 344ms DONE
  ⇂ '/opt/homebrew/Cellar/[email protected]/8.2.18/bin/php' 'vendor/roots/acorn/bin/acorn' debug:dump > '/dev/null' 2>&1
  
 // http://site.test/?page_id=2

What actually happens?

When running the scheduler with acorn, the acorn binary is called.

This binary loads wordpress and then expect acorn to boot on top :

require_once "{$rootPath}/{$composer['extra']['wordpress-install-dir']}/wp-blog-header.php";

Roots\Acorn\Bootloader::getInstance()->boot();

The seconds line nevers gets called.

What actually happens is that the wp-settings.php file is going to load the mu-plugins, which loads Acorn (00-acorn-boot.php), and the load of Acorn "captures" the "request", and so any code that should have run after the load of mu-plugins (inside wp-settings.php) won't run, including settings up default post_types and so on :

// file: wp-settings.php

// Load must-use plugins.
foreach ( wp_get_mu_plugins() as $mu_plugin ) {
    $_wp_plugin_file = $mu_plugin;
    include_once $mu_plugin; // <-- loading acorn will stop here.
    $mu_plugin = $_wp_plugin_file;
    do_action( 'mu_plugin_loaded', $mu_plugin );
}

/** Never reach this part */

/** ... */

create_initial_taxonomies();
create_initial_post_types();

/** ... */

This means that if I run a command with the scheduler :

 wp acorn schedule:test
  Running ['vendor/roots/acorn/bin/acorn' debug:dump] ................................................................................... 344ms DONE
  ⇂ '/opt/homebrew/Cellar/[email protected]/8.2.18/bin/php' 'vendor/roots/acorn/bin/acorn' debug:dump > '/dev/null' 2>&1

The debug:dump command won't be able to get a permalink (eg: get_permalink(1)) as the internal get_post_status_object() function could not return values because the core is not fully loaded.

Steps to reproduce

Create a Kernel class :

namespace App\Console;

use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Foundation\Application;
use Roots\Acorn\Console\Kernel as RootsKernel;
use Illuminate\Console\Scheduling\Schedule;

class Kernel extends RootsKernel
{
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('debug:dump')->everySecond();
    }

    public function __construct(Application $app, Dispatcher $events)
    {
        if (! defined('ARTISAN_BINARY')) {
            define('ARTISAN_BINARY', dirname(__DIR__, 2) . '/vendor/roots/acorn/bin/acorn');
        }

        $this->app = $app;
        $this->events = $events;

        // Make sure our schedules are getting registered
        $this->app->extend(Schedule::class, function ($app) {
            return tap(new Schedule($this->scheduleTimezone()), function ($schedule) {
                $this->schedule($schedule->useCache($this->scheduleCache()));
            });
        });

        $this->app->booted(function () {
            $this->defineConsoleSchedule();
        });
    }
}

Make sure to register the kernel class when booting acorn :

\Roots\bootloader()->boot(function ($app) {
    $app->singleton(
        \Illuminate\Contracts\Console\Kernel::class,
        \App\Console\Kernel::class
    );
});

Then, after creating a command which tries to display a permalink, test it thru the scheduler using wp acorn schedule:test.

System info

MacBook Air M1
MacOS Sonoma 14.5
PHP 8.2.18

Log output

No response

Please confirm this isn't a support request.

Yes

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions