Add a tag on page creation

Hello,

I need to add tags when a new article is created.
I have a yml file article with a tag field ready to be populated.
I have a hook in my config file which is supposed to add a tag when an article is created.
The tag should be the name of the parent page.

I don’t understand what’s wrong but it’s not working.
Any help would be much appreciated !

here is the hook:

return [
    'debug' => true,
    'languages' => true,
    'environment' => 'production',

    'hooks' => [
        'page.create:after' => function ($page) {
            // Ensure the created page is an article
            if ($page->intendedTemplate() === 'article') {
                $parent = $page->parent(); // Get the parent page

                // Check if parent exists
                if ($parent) {
                    // Use the parent's title as the tag
                    $tag = $parent->title(); // Use the title for simplicity

                    // Ensure the 'tags' field is not null
                    $tags = $page->tags() ? $page->tags()->split(',') : []; // Get existing tags
                    $tags[] = $tag; // Add the parent's title as a tag
                    $tags = array_unique($tags); // Ensure no duplicate tags

                    // Update the page with the new tags
                    $page->update([
                        'tags' => implode(',', $tags)
                    ]);
                }
            }
        },
    ],
];

and the yml file structure of the article page:


title: Article

fields:
  title:
    label: Title
    type: text

  date:
    label: Publication Date
    type: date
    required: true

  tags:
    label: Tags
    type: tags

  text:
    label: Contenu de la page
    type: blocks
    fieldsets:
      text:
        label: Texte
        type: group
        fieldsets:
          - heading
          - text
          - list
      media:
        label: Media
        type: group
        fieldsets:
          - image
          - video

The hook callback needs name arguments, see page.update:after | Kirby CMS

On a side note, the condition here will always be true

and can therefore be simplified to

$tags = $page->tags()->split(',')

thank you for your reply texnixe, i’ve tried with
'page.create:after' => function ($page, $parent) {
or
'page.create:after' => function (Page $page) {

but still no results, the parent page’s name dont go in the field ‘tags:’ of in the article children file created.
thanks for your help :pray:

What the docs say, is that you have to use $newPage and $oldPage ( hence “named” parameters) as params, not anything else.

thank you, so I tried with $newPage and $oldPage as params but it doesn’t work either.
Still trying to add the name of the parent page to the tag field of the article in which its created.

return [
    'debug' => true,
    'languages' => true

    'hooks' => [
        'page.create:after' => function ($newPage, $oldPage) {
            if ($newPage->intendedTemplate() === 'article') {
                $parent = $newPage->parent(); 

                if ($parent) {
                    $tag = $parent->title(); 

                    $tags = $newPage->tags()->split(',');
                    $tags[] = $tag; 
                    $tags = array_unique($tags); 

                    $newPage->update([
                        'tags' => implode(',', $tags)
                    ]);
                }
            }
        },
    ],
];

Thank you for your advices

This condition won’t work, because intendedTemplate() return a Template object, not a string, so the strict comparison fails, change to

 if ($newPage->intendedTemplate()->name() === 'article') { 

Thanks Texnixe, still not adding the tag. I’m adding a little more of context below:

the structure is

/content
├── communication
│   ├── formation.txt
│   ├── article-1
│   │   ├── article.txt

I have in my config file:

return [
    'debug' => true,
    'languages' => true,
    'environment' => 'production',

    'hooks' => [
        'page.create:after' => function ($newPage, $oldPage) {
            if ($newPage->intendedTemplate()->name() === 'article') { 
                $parent = $newPage->parent(); 

                if ($parent) {
                    $tag = $parent->title(); 

                    $tags = $newPage->tags()->split(',');
                    $tags[] = $tag; 
                    $tags = array_unique($tags); 

                    $newPage->update([
                        'tags' => implode(',', $tags)
                    ]);
                }
            }
        },
    ],
];

The formation yml:

options:
  template: formation
  children:
    template:
      - article


tabs:

  # main content
  main:
    label: Présentation
    width: 2/3
    sections:
      content:
        type: fields
        fields:

          tags:
            label: Tags
            type: multiselect
            options: query
            query:
              fetch: site.tagList.split(",")
              text: "{{ item.toString }}"
              value: "{{ item.toString }}"
            help: "Select or assign tags for this page."

          contentBlocks:
            label: Content Blocks
            type: blocks
            fieldsets:
              text:
                label: Text
                type: text
              heading:
                label: Heading
                type: heading
              image:
                label: Image
                type: image
              video:
                label: Video
                type: video

  sidebar:
    label: Articles
    width: 1/3
    sections:
      articles:
        label: Articles
        type: pages
        parent: page
        query: page.children.sortBy("date", "desc")
        layout: list
        info: "Date: {{ page.date.toDate('d/m/Y') }}"
        template:
          - article
        create:
          - article

The article yml:

title: Article

fields:
  title:
    label: Title
    type: text

  date:
    label: Publication Date
    type: date
    required: true

  tags:
    label: Tags
    type: tags

  text:
    label: Contenu de la page
    type: blocks
    fieldsets:
      text:
        label: Texte
        type: group
        fieldsets:
          - heading
          - text
          - list
      media:
        label: Media
        type: group
        fieldsets:
          - image
          - video

I would like to add as a tag in the article, the name of the parent page (communication).

Sorry, my bad, was on the wrong track, since you are using a page.create:after hook and not an update hook, the only issue was the comparison, so back to:

	'hooks' => [
		'page.create:after' => function ($page) {
			if ($page->intendedTemplate()->name() === 'article') {
				$parent = $page->parent();
				
				if ($parent) {
					$tag = $parent->title();
					
					$tags = $page->tags()->split(',');
					$tags[] = $tag;
					$tags = array_unique($tags);
					
					$page->update([
						'tags' => implode(',', $tags)
					]);
				}
			}
		},
	],

ok no problem.
The tags field of the article (children page of the category communication) still not getting the name of the parent page when its creation.
Is it something wrong with my blueprints, is it something i can achieve with kirby ?
thank you

Hm, the blueprint must not have a title field in your article.yml and the options in your formation.yml are like AI hallucinations :wink:… Don’t know if that might cause issues. Cannot test your code now.

Thank you texnixe.
I started with a blueprint from the starterkit, where it is mentioned that blueprints should have title. I will continue the search but let me know if you have time to check it out, curious to understand where i’m making a mistake.

Right, the blueprint itself should have a title at the top. But there shouldn’t be a title field in your blueprint, because Kirby adds the title automatically.

This is what your blueprints should look like:

formation.yml

title: formation

tabs:

  # main content
  main:
    label: Présentation
    width: 2/3
    sections:
      content:
        type: fields
        fields:

          tags:
            label: Tags
            type: multiselect
            options: query
            query:
              fetch: site.tagList.split(",")
              text: "{{ item.toString }}"
              value: "{{ item.toString }}"
            help: "Select or assign tags for this page."

          contentBlocks:
            label: Content Blocks
            type: blocks
            fieldsets:
              text:
                label: Text
                type: text
              heading:
                label: Heading
                type: heading
              image:
                label: Image
                type: image
              video:
                label: Video
                type: video

  sidebar:
    label: Articles
    width: 1/3
    sections:
      articles:
        label: Articles
        type: pages
        query: page.childrenAndDrafts.sortBy("date", "desc")
        layout: list
        info: "Date: {{ page.date.toDate('d/m/Y') }}"
        template: article

article.yml

title: Article

fields:
  date:
    label: Publication Date
    type: date
    required: true

  tags:
    label: Tags
    type: tags

  text:
    label: Contenu de la page
    type: blocks
    fieldsets:
      text:
        label: Texte
        type: group
        fieldsets:
          - heading
          - text
          - list
      media:
        label: Media
        type: group
        fieldsets:
          - image
          - video

And the hook like what I posted above.