Structure field hooks

hi and thanks for kirby,

i need to intercept structure field add and save actions. any ideas?

Hm, could you please provide more information what you are trying to achieve?

hi,

for this project a need to generate an ID (or unique number) when the user add o save the structure field.

You might want to check out the AutoID plugin: https://github.com/bnomei/kirby3-autoid

i already checked, but it only generate on “page save hook”, the problem is that i need to generate an ID like this format:

R-GLOBALCOUNTERNUMBER-ALEATORYNUMBER

R-345-AER
R-346-RGF
R-348-OGM

and so…

i tweaked de DEFAULT GENERATOR FUNCTION to read a site field with the counter number,.

if i only create 1 structure it works ok, but when i create 2 or more it create

R-345-AER
R-345-RGF
R-345-OGM

this is AUTOID modified code

  public static function getToken($length = 40, $withLower = true, $withUpper = true, $withNumbers = true)
    {
        $token = "";
        $codeAlphabet = "";
        $contador = site()->contador();

        $contador = site()->contador()->int() + 1;
        kirby()->impersonate('kirby');

        site()->update([
             'contador' => $contador,
        ]);


        if ($withUpper) {
            $codeAlphabet .= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        }
        if ($withLower) {
            $codeAlphabet .= "abcdefghijklmnopqrstuvwxyz";
        }
        if ($withNumbers) {
            $codeAlphabet .= "0123456789";
        }

        $token .= $contador . "-";

        $max = strlen($codeAlphabet); // edited
        for ($i=0; $i < $length; $i++) {
            $token .= $codeAlphabet[self::cryptoRandSecure(0, $max-1)];
        }
        return $token;
    }

you can search for “auto incrementing id” in the forum and find different solutions how to set it up with autoid. it usually involves storing a global counter at the site object (site.yml blueprint). this will work fine unless you have many concurrent ids being created (like 20 per second).

  1. call $site->increment(‘myincrementid’) to prepare new value. https://getkirby.com/docs/reference/objects/site/increment
  2. read $site->myincrementid()->toInt()

on a side note: if you override autoid core logic you will lock yourself out of updates. consider using the generator callback which you can set in the config to provide your own. it can reuse the getToken function to generate parts if your string.

thanks for the answer.

for test purposes :

new function on kirby3-autoid/classes/AUTOID.php

public static function testGenerator(): string
    {
        $contador = "";
        $token = "";

        $contador = site()->increment('contador');

        $con = site()->contador()->int();

        $token .= "R-" . $con;

        return $token;
    }

replace on kirby3-autoid/index.php

'generator' => function (string $seed = null) {

          return \Bnomei\AutoID::testGenerator();
        },

result 1: when i only generate 1 structure and save. the counter works good, it add 1.
result 2: when i generate 2 or more structures and save. the counter only add 1 and the counter repeat

sure i am missing something. my expected result is that the client can generate 2 or more invoices and on page save the invoices have consecutives numbers.

extending the autoid class will reset if you update the plugin.
to avoid that please put everything from testGenerator() into the generator callback.

you are not missing something. there is no api call, no hook for adding structure item. a structure is just a special field. it gets updated on parent object save. the structure is not a “first order” cms object like the page or a file.

my suggestion would be: to get what you want you need to change the structure to a pages section and add pages for each invoice. the info option of the section field can be forwarded html code. you could use a page model/method to create a nice summary of the invoice this way.

edited: you will have to exclude the invoices from sitemap/feeds and protect them from access (for example: make their template redirect to parent objects url).

hi and thanks for the answer,

What I do not understand, is that with the “default generator” when I create 2 or more structures this generates two unique id

but with “test generator” no, I don’t understand how it doesn’t trigger site-> update () twice

Will there be any way to add a consecutive counter?

adding two or more items to a structure results in only one page update hook.
maybe incrementing a field in site index twice within the one page update call does not work. i have no time to check this myself. maybe @texnixe can help you with that or ask someone in the thread linked above.

I actually think in this case maybe a custom solution would be better, with an internal counter that reads the site value only once and updates it when all items have their unique ID applied.

However, I see a general problem with this approach when using multiple structure fields that all update the site value. So knowing a bit more about your use case would be helpful.