Panel button to run PHP code/job/task

The Janitor Plugin: Panel button to run PHP backend code and react on data returned: reload panel view, copy to clipboard, open url or trigger download file. It supports forwarding kirby query language to your backend code as well.

2 Likes

I’m a newby with plugins and I’m trying to create a job for janitor inside a plugin I’m developing. Could you please explain me a little bit how to do it? I’m really confused with the classes and the name spaces :sleepy:

Thanks in advance

sure. lets assume your plugin is called awesome/stuff. what you need are:

  • a plugin
  • the plugin needs to define a job (array of callbacks) option
  • the plugins jobs must be registered with the janitor
  • you can have jobs from classes but you do not have to. you can even mix classes and closures.
  • you can load classes with composer, kirbys load helper or a plain require_once.
  • a janitor button in a blueprint to trigger the job (unless you use the CLI or trigger it somewhere else)

i will show you how to do all that.

site/plugins/awesome-stuff/index.php

<?php

load([
    'Awesome\\Stuff\\LegendaryJob.php' => __DIR__ . '/classes/awesome/stuff/LegendaryJob.php',
]);

Kirby::plugin('awesome/stuff', [
   'options' => [
        'jobs' => [
            'cool' => function(Kirby\Cms\Page $page = null, string $data = null) {
                // $page => page object where the button as pressed
                // $data => 'Perfectly'
                // TODO: do stuff
                return [
                    'status' => 200,
                    'label' => $data . ' ' . $page->title(),
                ];
            },
            'legendary' => 'Awesome\\Stuff\\LegendaryJob',
        ],
   ],
   // ... rest of your plugin
]); 

site/plugins/awesome-stuff/classes/awesome/stuff/LegendaryJob.php

<?php

namespace Awesome\Stuff;

class LegendaryJob extends \Bnomei\JanitorJob
{
    /**
     * @return array
     */
    public function job(): array
    {
        // TODO: do stuff
        return [
            'status' => 200,
            'label' => $this->data() . ' Legendary',
        ];
    }
}

site/config/config.php

    // other options
    'bnomei.janitor.jobs.extends' => [
        'awesome.stuff.jobs',
    ],
    // rest of config

site/blueprints/pages/default.yml

fields:

  cooljobfield: # any name you want
    type: janitor
    label: Cool
    progress: Cool...
    job: cool
    data: Perfectly # (string) forwarded to job context

  legendaryjobfield: # any name you want
    type: janitor
    label: Legendary
    progress: Legendary...
    job: legendary
    data: Ultra # (string) forwarded to job context

trigger the jobs somewhere else

<?php

$legendary = janitor('legendary'); // ATTENTION: no page context support (yet)
/*
        [
            'status' => 200,
            'label' => ' Legendary',
        ]
*/
1 Like

Thank you for such detailed explanation. You are the best! The “legendary” job is exactly what I’m trying to achieve. I will try to implement it now.
Thanks again, best.

1 Like

Sorry, one more question. How can I use $page and $data when the job is inside a class? When I try to use them I get an error.

they are available from getter methods $this->page() and $this->data() which are defined in the \Bnomei\JanitorJob class your job needs to extend.

<?php

namespace Awesome\Stuff;

class LegendaryJob extends \Bnomei\JanitorJob
{
    /**
     * @return array
     */
    public function job(): array
    {
        // TODO: do stuff
        $page = $this->page();
        $data = $this->data();
        return [
            'status' => 200,
            'label' =>  '',
        ];
    }
}

Thats exactly what I tried. Any ideas? The job without $user and $data I think its working because the button gets green but when I add any of them to the job it gets stuck.

@guidoferreyra you where right there was a bug in my implementation. thanks for bringing it to my attention.

i fixed it with current release 2.2.3 and also added a jobs from classes example similar to the one in previous post but with :space_invader::space_invader::space_invader:.

Thank you a lot, its working now :slight_smile:

1 Like

Hi @bnomei I’m having an issue with a job and I was wondering if you can give a hint.
My job perform some tasks on files inside a child page, but if the page where I’m executing the job has Draft status, it doesn‘t work. It works fine with listed and unlisted.

Basically, I can’t do this if the page is in Draft.

$page = $this->page();
$childrenPageFiles = $page->find('children-page')->files();

Any idea, thanks!

find() only finds pages, not drafts, use findPageOrDraft() instead.

1 Like

janitor and drafts

1 Like

Oh thanks!
In $data I’m getting this "pageId+S_L_A_S_H+childrenId" I managed to make the find in index by replacing the "S_L_A_S_H" by "/".

Is this correct or I’m doing something wrong and thats why I get the “S_L_A_S_H”?

Thaks again!

i assume you have been using a “job from class”, right? i fixed that just now.

data for closures should not have the slash placeholder unless there is a bug i missed.

since site()->index(true) might not be very performant consider using data : '{{ page.parent.id }}#{{ page.id }}' and page(explode('#', $data)[0])->findByID(explode('#', $data)[1]).

Excelent! Thanks a lot!

I only changed findById() by findPageOrDraft() because It didn‘t worked for me.