Skip to content

[5.x] Add a creating-entry hook to allow default values to be set #8643

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: 5.x
Choose a base branch
from

Conversation

ryanmitchell
Copy link
Contributor

@ryanmitchell ryanmitchell commented Aug 29, 2023

This PR fires a creating-entry hook on the 'create' screen of the CP, allowing you to programatically set default values for fields.

You can see this has been asked for in a few places, e.g. statamic/ideas#964, https://discord.com/channels/489818810157891584/489818810157891586/1146021950112665682

You can then add a listener like follows:

EntriesController::hook('creating-entry', function ($entry) {
  $entry->set('title', 'This value was set in the listener');
});

Which lets you modify the default values:
Screenshot 2023-08-29 at 13 53 14

Obviously titles can have their default values in other ways, but where this becomes really useful is when you want to have default replicator or grid values.

Copy link
Member

@jasonvarga jasonvarga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On line 267, the event is already being dispatched:

$blueprint = $collection->entryBlueprint($request->blueprint);

The entryBlueprint method can accept an entry as the second argument. So, maybe we can make the entry earlier and pass it into that, rather than manually dispatching the event again.

$entry = Entry::make()->collection($collection);
$blueprint = $collection->entryBlueprint($request->blueprint, $entry);
//...
$values = $entry->values()->all();

@ryanmitchell
Copy link
Contributor Author

That was what I tried to do originally, but the event fires without the entry parameter being set.
I think maybe from the Entry policy?

@jasonvarga
Copy link
Member

Oh yeah there's code in there to intentionally not fire the event. Bah.

@radermacher
Copy link

Any chance this PR or a solution for this topic (pre-filling of fields, replicator fields in our case, based on blueprints) will be part of the core?

Currently we apply this PR as an patch to our code base after every cms update.
This approach is currently working for us, but It feels like an hack.

Thanks again @ryanmitchell for this PR and solution!

@jasonvarga
Copy link
Member

In it's current state, I don't think it'll get merged. But I'm leaving this open temporarily as a reminder to think about a permanent solution.

@ryanmitchell
Copy link
Contributor Author

You can achieve almost the same thing by applying a default value to your replicator field in the blueprint... eg.

          -
            handle: replicator_field
            field:
              collapse: false
              previews: true
              fullscreen: true
              sets:
                new_set_group:
                  display: 'New Set Group'
                  instructions: null
                  icon: null
                  sets:
                    test_set_1:
                      display: 'Test set 1'
                      instructions: null
                      icon: null
                      fields:
                        -
                          handle: title
                          field:
                            input_type: text
                            antlers: false
                            type: text
                            display: Title
                            icon: text
                            localizable: false
                            listable: hidden
                            instructions_position: above
                            visibility: visible
                            hide_display: false
                    test_set_2:
                      display: 'Test set 2'
                      instructions: null
                      icon: null
                      fields:
                        -
                          handle: title
                          field:
                            input_type: text
                            antlers: false
                            type: text
                            display: Title
                            icon: text
                            localizable: false
                            listable: hidden
                            instructions_position: above
                            visibility: visible
                            hide_display: false
                    replicator_in_replicator:
                      display: 'Replicator in replicator'
                      instructions: null
                      icon: null
                      fields:
                        -
                          handle: replicator_field
                          field:
                            collapse: false
                            previews: true
                            fullscreen: true
                            sets:
                              new_set_group:
                                display: 'New Set Group'
                                instructions: null
                                icon: null
                                sets:
                                  new_set:
                                    display: 'New Set'
                                    instructions: null
                                    icon: null
                                    fields:
                                      -
                                        handle: text
                                        field:
                                          input_type: text
                                          antlers: false
                                          type: text
                                          display: Text
                                          icon: text
                                          localizable: false
                                          listable: hidden
                                          instructions_position: above
                                          visibility: visible
                                          hide_display: false
                            type: replicator
                            display: 'Replicator Field'
                            icon: replicator
                            localizable: false
                            listable: hidden
                            instructions_position: above
                            visibility: visible
                            hide_display: false
              type: replicator
              display: 'Replicator Field'
              icon: replicator
              localizable: false
              listable: hidden
              instructions_position: above
              visibility: visible
              hide_display: false
              default:
                -
                  id: lkhwp0kp
                  title: Ryan
                  type: test_set_1
                  enabled: true
                -
                  id: lki12mr5
                  replicator_field:
                    -
                      id: lki12nxn
                      text: text
                      type: new_set
                      enabled: true
                  type: replicator_in_replicator
                  enabled: true

Obviously the event lets you apply use non-fixed values, eg if you were pulling from an API. So it would be good to come up with a solution that allows for that.

@radermacher
Copy link

Thanks @ryanmitchell 🙏
Your solution works like in your example. Sadly it doesn't work with imported replicator fields, which we use to prevent duplicated field configs in blueprints. Default values could be set in the shared fieldset but couldn't be set/overwritten per blueprint. We need the latter.

So we hope @jasonvarga and team find a mergeable solution.
Until then, we will work with an applied patch after every Statamic update 😬

@jasonvarga
Copy link
Member

jasonvarga commented Oct 5, 2023

Until then, we will work with an applied patch after every Statamic update 😬

You can use a composer patch to automate it.

@radermacher
Copy link

Until then, we will work with an applied patch after every Statamic update 😬

You can use a composer patch to automate it.

Awesome! Thank you @jasonvarga, I didn't know about this solution to apply patches!

@ryanmitchell
Copy link
Contributor Author

What about using a hook for this? You could pass the blank entry to it and let it be amended?

@ryanmitchell ryanmitchell changed the title [4.x] Fire EntryBlueprintFound before creating [5.x] Fire EntryBlueprintFound before creating Oct 8, 2024
@ryanmitchell ryanmitchell changed the base branch from 4.x to 5.x October 8, 2024 12:39
@ryanmitchell
Copy link
Contributor Author

@jasonvarga I've updated this to use a hook instead of an event. Does this sit any better with you?

@daun
Copy link
Contributor

daun commented Apr 7, 2025

Just chiming in to say that this works great in its current state. Wouldn't mind to see it merged :) We're using it to define a random seed that needs to be present on first save.

// app/Providers/AppServiceProvider.php

EntriesController::hook('creating-entry', function ($entry) {
  $entry->set('rand', random_int(1, 9999));
});

@ryanmitchell ryanmitchell changed the title [5.x] Fire EntryBlueprintFound before creating [5.x] Add a creating-entry hook to allow default values to be set Apr 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants