Jump to content
Autofahrn

Using InputfieldPageListSelect in config inputfields

Recommended Posts

Here is a quest for all Fieldtype gurus out there:

I've stumbled over an issue (maybe bug) when using an InputfieldPageListSelect within the config inputfields returned from a fieldtype module. What I want/need to do is processing POST data and store parameters in a different form (associative array for example). To avoid storing the value twice in the database, I simply remove the value from the POST data. This works fine for all fields including the InputfieldPageListSelect, but that particular field continues to add some bogus entry into the field data (JSON object in the fields table). This is basically no big deal, but I guess it is not expected to be there.

I've condensed the issue into a small fieldtype code:

<?php namespace ProcessWire;
/*
 * Fieldtype to diagnose issue with InputfieldPageListSelect and manually managing form data.
 *
 * This Fieldtype collects some private configuration data through the getConfigInputfields API.
 * After submission the parameters are stripped from the POST array and stored within an
 * associative array for this field.
 *
 * For some unknown reason values generated from InputfieldPageListSelect are still written
 * into database, the field's JSON data looks like this:
 *
 *  { "collapsed":0,
 *    "configParam":{
 *      "sometext":"This is some text",
 *      "somecheckbox":1,
 *      "somepage":1068,
 *      "someoption":4
 *      },
 *    "someprefix[somepage]":0     <== this is not expected
 *  }
 *
 * To simplify processing of the POST data, field names are formed to create an associative
 * array already in the POST data like "someprefix[sometext]".
 * The issue persists even if values use a plain name like "someprefix_sometext".
 *
 * Sidenote: The required attribute does not work, may relate to the array type of POST data. Any hint welcome!
 */
class FieldtypeInputRedirect extends Fieldtype {

	public static function getModuleInfo() {
		return array(
			'title' => __('TEST Input Redirection'),
			'version' => 1,
			'summary' => __('TEST Input Redirection to field config'),
			'installs' => 'InputfieldInputRedirect'
			);
	}

	const thePrefix = 'someprefix';
	const configParam = 'configParam';

	// Field definition to simplify testing.
	private static function getCfgFlds() { return [
		'sometext' => [
			'type' => 'InputfieldText',
			'label' => __('Type some Text'),
//			'required' => 1,	// Would be nice but not working
			'columnWidth' => 25,
			],
		'somecheckbox' => [
			'type' => 'InputfieldCheckbox',	// Requires special attention after setting the value
			'label' => __('Toggle it'),
			'columnWidth' => 25,
			],
		'somepage' => [
			'type' => 'InputfieldPageListSelect',
			'label' => __('Point to a Page'),
			'columnWidth' => 25,
			'derefAsPage' => 1,
			'parent_id' => '/',
			],
		'someoption' => [
			'type' => 'InputfieldSelect',
			'label' => __('Pick a Color'),
			'initValue' => 1,
			'defaultValue' => '1',
//			'required' => 1,
			'columnWidth' => 25,
			'options' => [
				1 => 'white',
				2 => 'red',
				3 => 'green',
				4 => 'blue',
				5 => 'black',
				],
			],
		]; }


	public function ___getCompatibleFieldtypes(Field $field) {	return null; } // No compatible fields
	public function sanitizeValue(Page $page, Field $field, $value) { return $value; } // No field, never called yet required
	public function getInputfield(Page $page, Field $field) { return($this->modules->get('InputfieldInputRedirect')); }	// Generate Inputfield

	public function ___getConfigInputfields(Field $field) {

		// Get some PW variables
		$input = $this->wire('input');
		$modules = $this->wire('modules');

		/**
		 * Process submission
		 */
		$configParam = $input->post(self::thePrefix);
		if(isset($configParam))
			{
//			$this->message('Field SET: '.print_r($configParam, true));
			$field->set(self::configParam, $configParam);	// Store parameters to field (and database)
			$input->post->offsetUnset(self::thePrefix);	// Remove array from POST data
			}
		else
			{	// restore parameters from field
			$configParam = $field->get(self::configParam);
			}
	
		/**
		 * Setup Inputfields
		 */
		$inputfields = parent::___getConfigInputfields($field);

		// Create wrapper for our own fields
		$fs = new InputfieldWrapper;
		$fs->skipLabel = InputField::skipLabelHeader;
		$fs->collapsed = false;
		
		// enumerate field configuration and generate fields dynamically
		foreach($this->getCfgFlds() as $configName => $configDef)
			{
			$cfg = $modules->get($configDef['type']);	// Get Inputfield instance
			if($cfg)
				{
				$cfg->attr('id+name', self::thePrefix."[{$configName}]");	// Setup fieldname

				if(isset($configParam[$configName]))	// Initialize value, if already set
					$cfg->value = $configParam[$configName];
				if($configDef['type'] == 'InputfieldCheckbox')	// Special attention to checkboxes
					$cfg->attr('checked', $cfg->value != 0);

				foreach($configDef as $k => $v)	// Setup remaining attributes
					{
					switch($k)
						{
						case 'type':	// Type already handled
							continue;
						case 'options':	// create inputfield options
							$fldOpts = array();
							foreach($v as $kopt => $opt)
								$fldOpts[] = "{$kopt}={$opt}";
							$cfg->set('options', implode("\n", $fldOpts));
							break;
						default:
							$cfg->set($k, $v);
							break;
						}
					}
				$fs->add($cfg);	// Add field to fieldset
				}
			}
		
		$inputfields->prepend($fs);	// Add fieldset to inputfields
		return($inputfields);
	}
}

along with this dummy Inputfield:

<?php namespace ProcessWire;
/*
 * Dummy inputfield for FieldtypeInputRedirect, not actually useful
 */
class InputfieldInputRedirect extends Inputfield {
	public static function getModuleInfo() {
		return array(
			'title' => __('TEST Input Redirection', __FILE__), // Module Title
			'summary' => __('TEST Input Redirection to field config', __FILE__), // Module Summary
			'version' => 1,
			);
	}
	public function ___render() { return '<span>This field is not intended to be used!</span>'; }	// Required to generate field
}

Any hint welcome!.

Edit: PW 3.0.123

Share this post


Link to post
Share on other sites

@Autofahrn I don't really understand the code above well enough to know how to answer your question specifically, but one thing that jumps out to me is that you are interacting with POST data here, and that's something you want to avoid if possible. I looked in InputfieldPageListSelect and it doesn't have any getConfigInputfields() method of its own so I don't think it is adding anything here, instead, that method in InputfieldSelect is what you'd want to look at, particularly the part where it skips out early if the Inputfield isn't connected with a Fieldtype: if($this->hasFieldtype !== false) return $inputfields; . I would also try and use TracyDebugger with those bd() calls after your $cfg->set() to see what you are setting just to be sure. 

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...