From e917c93d764ecda9c385b1898975bbf5b4eee1cd Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Mon, 29 Jan 2018 09:16:03 -0500 Subject: [PATCH] Fix issue processwire/processwire-issues where clone of page having FieldsetPage field was not cloning the FieldsetPage portion of it --- wire/core/Page.php | 1 + wire/core/PagesEditor.php | 38 +++++++++++++------ .../FieldtypeFieldsetPage.module | 13 +++++++ 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/wire/core/Page.php b/wire/core/Page.php index eeca57d4..94d37663 100644 --- a/wire/core/Page.php +++ b/wire/core/Page.php @@ -75,6 +75,7 @@ * @property PageRender $render May be used for field markup rendering like $page->render->title. #pw-advanced * @property bool $loaderCache Whether or not pages loaded as a result of this one may be cached by PagesLoaderCache. #pw-internal * + * @property Page|null $_cloning Internal runtime use, contains Page being cloned (source), when this Page is the new copy (target). #pw-internal * @property bool|null $_hasAutogenName Internal runtime use, set by Pages class when page as auto-generated name. #pw-internal * @property bool|null $_forceSaveParents Internal runtime/debugging use, force a page to refresh its pages_parents DB entries on save(). #pw-internal * diff --git a/wire/core/PagesEditor.php b/wire/core/PagesEditor.php index a19fdfa7..afcdc6ad 100644 --- a/wire/core/PagesEditor.php +++ b/wire/core/PagesEditor.php @@ -15,12 +15,12 @@ class PagesEditor extends Wire { /** * Are we currently cloning a page? * - * This is true only when the clone() method is currently in progress. + * This is greater than 0 only when the clone() method is currently in progress. * - * @var bool + * @var int * */ - protected $cloning = false; + protected $cloning = 0; /** * Name for autogenerated page names when fields to generate name aren't populated @@ -44,9 +44,16 @@ class PagesEditor extends Wire { $this->addHookAfter('Fieldtype::sleepValue', $this, 'hookFieldtypeSleepValueStripMB4'); } } - - public function isCloning() { - return $this->cloning; + + /** + * Are we currently in a page clone? + * + * @param bool $getDepth Get depth (int) rather than state (bool)? + * @return bool|int + * + */ + public function isCloning($getDepth = false) { + return $getDepth ? $this->cloning : $this->cloning > 0; } /** @@ -1101,7 +1108,7 @@ class PagesEditor extends Wire { } /** - * Clone an entire page, it's assets and children and return it. + * Clone an entire page (including fields, file assets, and optionally children) and return it. * * @param Page $page Page that you want to clone * @param Page $parent New parent, if different (default=same parent) @@ -1149,6 +1156,7 @@ class PagesEditor extends Wire { // clone in memory $copy = clone $page; + $copy->setQuietly('_cloning', $page); $copy->id = isset($options['forceID']) ? (int) $options['forceID'] : 0; $copy->setIsNew(true); $copy->name = $name; @@ -1185,19 +1193,23 @@ class PagesEditor extends Wire { $o = $copy->outputFormatting; $copy->setOutputFormatting(false); $this->pages->cloneReady($page, $copy); + $this->cloning++; + $options['ignoreFamily'] = true; // skip family checks during clone try { - $this->cloning = true; - $options['ignoreFamily'] = true; // skip family checks during clone $this->pages->save($copy, $options); } catch(\Exception $e) { - $this->cloning = false; + $this->cloning--; + $copy->setQuietly('_cloning', null); throw $e; } - $this->cloning = false; + $this->cloning--; $copy->setOutputFormatting($o); // check to make sure the clone has worked so far - if(!$copy->id || $copy->id == $page->id) return $this->pages->newNullPage(); + if(!$copy->id || $copy->id == $page->id) { + $copy->setQuietly('_cloning', null); + return $this->pages->newNullPage(); + } // copy $page's files over to new page if(PagefilesManager::hasFiles($page)) { @@ -1234,9 +1246,11 @@ class PagesEditor extends Wire { } } + $copy->setQuietly('_cloning', null); $copy->resetTrackChanges(); $this->pages->cloned($page, $copy); $this->pages->debugLog('clone', "page=$page, parent=$parent", $copy); + $copy->setTrackChanges(false); return $copy; } diff --git a/wire/modules/Fieldtype/FieldtypeRepeater/FieldtypeFieldsetPage.module b/wire/modules/Fieldtype/FieldtypeRepeater/FieldtypeFieldsetPage.module index 1c7ed77a..53e4ec33 100644 --- a/wire/modules/Fieldtype/FieldtypeRepeater/FieldtypeFieldsetPage.module +++ b/wire/modules/Fieldtype/FieldtypeRepeater/FieldtypeFieldsetPage.module @@ -363,6 +363,19 @@ class FieldtypeFieldsetPage extends FieldtypeRepeater implements ConfigurableMod public function ___savePageField(Page $page, Field $field) { if(!$page->id || !$field->id) return false; + + if($page->get('_cloning') instanceof Page) { + // $page is being cloned, so lets also clone the FieldsetPage + $source = $page->get('_cloning')->get($field->name); + if(!$source->id) return false; + $target = $this->wire('pages')->clone($source, null, false, array( + 'uncacheAll' => false, + 'set' => array('name' => self::repeaterPageNamePrefix . $page->id) + )); + if(!$target->id) return false; + $page->set($field->name, $target); + } + $value = $page->get($field->name); if(!$value instanceof Page) return false;