From 4a26d7626fab80d164355afc2ad2b3585e5c7b2e Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Fri, 25 Aug 2017 10:33:43 -0400 Subject: [PATCH] Improve extendability of FieldtypeFieldsetOpen for FieldtypeFieldsetGroup --- .../Fieldtype/FieldtypeFieldsetOpen.module | 130 ++++++++++++++---- .../InputfieldPage/InputfieldPage.module | 4 +- 2 files changed, 104 insertions(+), 30 deletions(-) diff --git a/wire/modules/Fieldtype/FieldtypeFieldsetOpen.module b/wire/modules/Fieldtype/FieldtypeFieldsetOpen.module index 8b15a463..b674a0e6 100644 --- a/wire/modules/Fieldtype/FieldtypeFieldsetOpen.module +++ b/wire/modules/Fieldtype/FieldtypeFieldsetOpen.module @@ -27,7 +27,7 @@ class FieldtypeFieldsetOpen extends Fieldtype { public static function getModuleInfo() { return array( 'title' => 'Fieldset (Open)', - 'version' => 100, + 'version' => 101, 'summary' => 'Open a fieldset to group fields. Should be followed by a Fieldset (Close) after one or more fields.', 'permanent' => true, ); @@ -47,14 +47,23 @@ class FieldtypeFieldsetOpen extends Fieldtype { */ public function init() { if(!self::$hooked && ($this->process == 'ProcessField' || $this->process = 'ProcessTemplate')) { - $this->addHook('ProcessField::fieldAdded', $this, 'hookFieldAdded'); - $this->addHook('ProcessField::fieldDeleted', $this, 'hookFieldDeleted'); - $this->addHook('ProcessTemplate::fieldAdded', $this, 'hookTemplateFieldAdded'); - $this->addHook('ProcessTemplate::fieldRemoved', $this, 'hookTemplateFieldRemoved'); + $this->addProcessHooks(); } self::$hooked = true; } + /** + * Add hooks to ProcessField or ProcessTemplate, called only when applicable + * + */ + protected function addProcessHooks() { + $this->addHook('ProcessField::fieldAdded', $this, 'hookFieldAdded'); + $this->addHook('ProcessField::fieldDeleted', $this, 'hookFieldDeleted'); + $this->addHook('ProcessField::allowFieldInTemplate', $this, 'hookAllowFieldInTemplate'); + $this->addHook('ProcessTemplate::fieldAdded', $this, 'hookTemplateFieldAdded'); + $this->addHook('ProcessTemplate::fieldRemoved', $this, 'hookTemplateFieldRemoved'); + } + public function sanitizeValue(Page $page, Field $field, $value) { return null; } @@ -100,33 +109,74 @@ class FieldtypeFieldsetOpen extends Fieldtype { /** * For hooks to share in determining if this is a field they want to operate on + * + * @param Field $field + * @return bool * */ protected function isFieldset(Field $field) { return $field->type instanceof FieldtypeFieldsetOpen && !($field->type instanceof FieldtypeFieldsetClose); } + /** + * Get the Field that closes/terminates the given Fieldset field + * + * @param Field $field + * @param bool $createIfNotExists Create it if it doesn't already exist? + * @return null|Field of type FieldtypeFieldsetClose + * + */ + public function getFieldsetCloseField(Field $field, $createIfNotExists = false) { + + if(!$this->isFieldset($field)) return; + + $name = $field->name . self::fieldsetCloseIdentifier; + $closer = $this->wire('fields')->get($name); + + if(!$closer) { + $closeFieldID = (int) $field->get('closeFieldID'); + if($closeFieldID) { + $closer = $this->wire('fields')->get($closeFieldID); + } + } + + if(!$closer && $createIfNotExists) { + $closer = $this->wire(new Field()); + $closer->type = $this->wire(new FieldtypeFieldsetClose()); + $closer->name = $name; + $closer->label = "Close an open fieldset"; + $closer->description = + "This field was added automatically to accompany fieldset '$field'. " . + "It should be placed in your template/fieldgroup wherever you want the fieldset to end."; + $closer->set('openFieldID', $field->id); + $closer->save(); + } + + if($closer && !$field->get('closeFieldID')) { + $field->set('closeFieldID', $closer->id); + $field->save(); + } + + return $closer; + } + /** * Hook executed when field is added via ProcessField + * + * @param HookEvent $event * */ public function hookFieldAdded($event) { - $field = $event->arguments[0]; if(!$this->isFieldset($field)) return; - - $closer = $this->wire(new Field()); - $closer->type = $this->wire(new FieldtypeFieldsetClose()); - $closer->name = $field->name . self::fieldsetCloseIdentifier; - $closer->label = "Close an open fieldset"; - $closer->description = "This field was added automatically to accompany fieldset '$field'. It should be placed in your template/fieldgroup wherever you want the fieldset to end."; - $closer->save(); - + $closer = $this->getFieldsetCloseField($field, true); $this->message("Also added field '$closer', to accompany '$field'"); } /** * Hook executed when field is deleted via ProcessField + * + * @param HookEvent $event * */ public function hookFieldDeleted($event) { @@ -134,39 +184,61 @@ class FieldtypeFieldsetOpen extends Fieldtype { $field = $event->arguments[0]; if(!$this->isFieldset($field)) return; - $closer = $this->wire('fields')->get($field->name . self::fieldsetCloseIdentifier); - if(!$closer) return; - - $this->wire('fields')->delete($closer); - $this->message("Delete also issued for field '$closer'"); + $closer = $this->getFieldsetCloseField($field); + + if($closer) { + $this->wire('fields')->delete($closer); + $this->message("Delete also issued for field '$closer'"); + } } /** * Hook executed when field is added to a template via ProcessTemplate + * + * @param HookEvent $event * */ public function hookTemplateFieldAdded($event) { + /** @var Field $field */ + /** @var Template $template */ list($field, $template) = $event->arguments; if(!$this->isFieldset($field)) return; - $closer = $this->wire('fields')->get($field->name . self::fieldsetCloseIdentifier); + $closer = $this->getFieldsetCloseField($field); if(!$closer) return; - $template->fieldgroup->add($closer); - $this->message("Also added field '$closer', which should be placed where you want to close fieldset '$field'"); + if(!$template->fieldgroup->hasField($closer)) { + $template->fieldgroup->add($closer); + $this->message("Also added field '$closer', which should be placed where you want to close fieldset '$field'"); + } } /** * Hook executed when field is removed from a template via ProcessTemplate + * + * @param HookEvent $event * */ public function hookTemplateFieldRemoved($event) { list($field, $template) = $event->arguments; if(!$this->isFieldset($field)) return; - $closer = $this->wire('fields')->get($field->name . self::fieldsetCloseIdentifier); + $closer = $this->getFieldsetCloseField($field); if(!$closer) return; $template->fieldgroup->remove($closer); $this->message("Also removed '$closer', which accompanies '$field'"); } + /** + * Hook to ProcessField::allowFieldInTemplate + * + * @param HookEvent $event + * + */ + public function hookAllowFieldInTemplate(HookEvent $event) { + /** @var Field $field */ + // $field = $event->arguments(0); + /** @var Template $template */ + // $template = $event->arguments(1); + } + /** * Hook called by Fields::save() after a field using this type has been renamed * @@ -184,12 +256,12 @@ class FieldtypeFieldsetOpen extends Fieldtype { if($this instanceof FieldtypeFieldsetClose) return; // rename the _END field to match this one $fields = $this->wire('fields'); - $endField = $fields->get($field->name . self::fieldsetCloseIdentifier); - if(!$endField) { - $endField = $fields->get($prevName . self::fieldsetCloseIdentifier); - if($endField) { - $endField->name = $field->name . self::fieldsetCloseIdentifier; - $fields->save($endField); + $closer = $this->getFieldsetCloseField($field); + if(!$closer) { + $closer = $fields->get($prevName . self::fieldsetCloseIdentifier); + if($closer) { + $closer->name = $field->name . self::fieldsetCloseIdentifier; + $fields->save($closer); } } parent::___renamedField($field, $prevName); diff --git a/wire/modules/Inputfield/InputfieldPage/InputfieldPage.module b/wire/modules/Inputfield/InputfieldPage/InputfieldPage.module index a69f24eb..5fc877b1 100644 --- a/wire/modules/Inputfield/InputfieldPage/InputfieldPage.module +++ b/wire/modules/Inputfield/InputfieldPage/InputfieldPage.module @@ -1052,11 +1052,13 @@ class InputfieldPage extends Inputfield implements ConfigurableModule { $field = $this->modules->get('InputfieldMarkup'); $field->attr('name', '_findPagesCode'); $field->collapsed = Inputfield::collapsedYes; + $if = "\$event->object->" . + ($this->name ? "hasField == '$this->name'" : "name == 'your_field_name'"); $field->value = '

' . sprintf($this->_('Add the following hook to a %s file and modify per your needs. The hook should find and return selectable pages in a PageArray.'), '/site/ready.php') . "

" . 
 				"\$wire->addHookAfter('InputfieldPage::getSelectablePages', function(\$event) {" .
-				"\n  if(\$event->object->hasField == '$this->name') {" . 
+				"\n  if($if) {" . 
 				"\n    \$event->return = \$event->pages->find('your selector here');" . 
 				"\n  }" . 
 				"\n});" .