Jump to content

Emptying / resetting all fields for a recently cloned page?


theoretic
 Share

Recommended Posts

Hi friends! And thanks for ProcessWire!

Content managers I work with like to create new pages by cloning the old ones. No bad in general, but they frequently forget to check and clean up all the content they copy, especially the multilanguage fields. So I decided to make a hook which should wipe all data fields of a recently created clone immediately after it has been created.

Hooking such event is a piece of cake (thanks Processwire!) but cleaning all data fields appears to be a tricky business. Of course I've read this topic but it appears to be irrelevant in my case.

My hook is basically like this:

$wire->addHookAfter("Pages::cloned", function($event) {
	$clonePage = $event->arguments(1);
	$clonePage->of(false);
	//$clonePage->fields = $clonePage->fields->makeNew(); //fails
	// ...some more tricks including iterating through all data fields...
	$clonePage->of(true);
	$clonePage->save();
}

Will be grateful for any possible advice )

Link to comment
Share on other sites

Reading this, I am asking myself:

A clone followed by a data wipe is nothing more than creating an empty new page with the same template, right? Why don't you disallow clone for these templates (possibly for your client's role only) and instruct your users to use "new" instead?

  • Like 2
Link to comment
Share on other sites

Ha! I could tell my users to do that, but unfortunately they would not respond positively. The reason I'm interested in this thread is that I will soon need to:

  • Clone a page (same template)
  • Retain some field values
  • Remove remaining values
  • Populate 2 field values based on certain conditions
  • Position the clone in the page tree based on said conditions

I think just somehow iterating through the KNOWN field names/values and doing the work is the way to go, but it's always good to hear about any efficiencies that others my be aware of.

Link to comment
Share on other sites

Thanks for your interest friends! After some attempts I decided to this the hard way. Here's my working code:

$wire->addHookAfter("Pages::cloned", function($event) {

	$clonePage = $event->arguments(1);
	$clonePage->of(false);

	$languages = \ProcessWire\wire('languages');
	$emptyLanguageValues = [];
	foreach($languages as $language) $emptyLanguageValues[$language->name] = '';

	foreach( $clonePage->fields as $field ){

		switch(true){

			case $field->type instanceof \ProcessWire\FieldtypePageTitleLanguage:
			case $field->type instanceof \ProcessWire\FieldtypeTextLanguage:
			case $field->type instanceof \ProcessWire\FieldtypeTextareaLanguage:
				$clonePage->{$field->name}->setLanguageValues($emptyLanguageValues);
			break;

			case $field->type instanceof \ProcessWire\FieldtypeInteger:
			case $field->type instanceof \ProcessWire\FieldtypeFloat:
				$clonePage->{$field->name} = NULL;
			break;

			case $field->type instanceof \ProcessWire\FieldtypeFile:
			case $field->type instanceof \ProcessWire\FieldtypeImage:
				$clonePage->$field->deleteAll();
			break;

			case $field->type instanceof \ProcessWire\FieldtypePage:
				$clonePage->{$field->name}->removeAll();
			break;
		}

	}

	$clonePage->save();
	$clonePage->of(true);

});

This example covers the most used types of data fields. It was enough for me, and it can be extended to include more data fields.

By the way, I suppose that it could be a good idea to have a possibility to turn data copy on/off while cloning. But it's in PW core so I don't dare to change this.

 

Link to comment
Share on other sites

16 hours ago, poljpocket said:

A clone followed by a data wipe is nothing more than creating an empty new page with the same template, right? Why don't you disallow clone for these templates (possibly for your client's role only) and instruct your users to use "new" instead?

Good point. I think you could hook BEFORE Pages::clone and do exactly that instead of instructing the users to so manually.

Note that you need the $event->replace = true; flag so that the original clone process does not kick in after your new page has been created. Something like this (untested):

<?php
$wire->addHookBefore('Pages::clone', function($event) {
  $page = $event->arguments('page');
  if($page->template != 'your-template') return;
  $p = new Page();
  $p->template = $page->template;
  $p->parent = $page->parent;
  $p->title = $page->title;
  $p->save();
  $event->replace = true; // should not be necessary but just to be sure
  wire()->session->redirect($p->editUrl());
});

Of course that would mean that any clone would wipe all data. But you could add a checkbox to that page that disables the hook and therefore would work as a normal clone.

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...