Autofahrn Posted February 16, 2019 Share Posted February 16, 2019 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 More sharing options...
ryan Posted March 3, 2019 Share Posted March 3, 2019 @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. 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now