In my panel, I am allowing the creation of pages along with their respective subpages. Within the parent pages, I have a structure field that enables the selection of subpages from all the existing ones. This approach is essential for sorting and displaying the subpages according to the specific preferences of my client.
Recently, the client expressed a need to duplicate these parent pages in order to create private “hidden versions” with minor content modifications, meant for internal sharing purposes.
On duplicating, new versions of the pages and its subpages are generated, resulting in new slugs as desired. However, an issue arises with the structure field of these new duplicates, as the links in the structure field still point to the original subpages instead of the duplicated ones, which I assume is logical from a technical standpoint.
I’m seeking a solution or alternative that would allow the new structure links to point to the newly duplicated subpages.
If there is a straightforward approach or any suggestions on this topic, I would greatly appreciate it!
Thanks for the answer.
So far, I managed to access the field in question in the structure that needs to be updated.
What I am not sure about is how to alter it so it reflects the new duplicated page url structure:
// Update structure field on duplicate
'page.duplicate:after' => function ($duplicatePage, $originalPage) {
$projects = $duplicatePage->projects()->toStructure()->toArray();
foreach ($projects as &$project) {
$project['project'] = '' // Do something here
}
$duplicatePage->update([
'projects' => $projects,
]);
},
So let’s say the original structure field value points to:
../pages/projects+project-one+subproject
It needs to point to:
../pages/projects+project-one-copy+subproject
Any idea on how can I do that dynamically so it updates on each of the items in the structure field?
A bit more of progress, but now the values show empty.
// Update structure field on duplicate
'page.duplicate:after' => function ($duplicatePage, $originalPage) {
$projects = $duplicatePage->projects()->toStructure()->toArray(); // Get the projects structure field
foreach ($projects as &$project) {
$originalProjectName = $project['project']; // Get the original project name
$duplicatedProjectPage = $duplicatePage->children()->find($originalProjectName); // Find the corresponding project page in the duplicated page
$project['project'] = $duplicatedProjectPage->id(); // Assign the new project page object
}
$duplicatePage->update([
'projects' => $projects, // Update the projects structure field
]);
},
Please find below the yaml for the ‘project’ field structure – which is the field I need to update on duplicating the page. The structure field in question is so extense that I prefered to simply share the important content related to this issue.
You didn’t answer my second question: And what does the project subfield store? The id or the UUID (don’t know what Kirby version you are using and if you are using UUIDs or not)
Sorry, I thought I answered by sharing the yaml code.
I am using Kirby 3.5.4 and by ‘what does the project subfield store’ what do you mean exactly?
Here’s the updated code with the yaml encoding and the store of the id as array.
// Update structure field on duplicate
'page.duplicate:after' => function ($duplicatePage, $originalPage) {
$projects = $duplicatePage->projects()->toStructure()->toArray(); // Get the projects structure field
foreach ($projects as &$project) {
$originalProjectName = $project['project']; // Get the original project name
$duplicatedProjectPage = $duplicatePage->children()->find($originalProjectName); // Find the corresponding project page in the duplicated page
$project['project'] = [$duplicatedProjectPage->id()]; // Assign the new project page object
}
$duplicatePage->update([
'projects' => Yaml::encode($projects),
]);
},
If I, for example, do something like $project['project'] = $duplicatePage->find('standard-project')->id(); to test, that would work, and turn each of the project values to point to that specific project.
Oh, okay!
I’ve tried basename($project['project'])but I get ‘Argument #1 ($path) must be of type string, array given’ error. Do you know how I could achieve it? It’s getting pretty close now.
Ok, thanks. I really appreciate the time you put helping me out!
Unfortunately, I get ‘Call to a member function id() on null’ now after trying your snippet.