Jump to content

Using InputfieldPageListSelect in config inputfields


Autofahrn
 Share

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

Link to comment
Share on other sites

  • 3 weeks later...

@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
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...