Support » Plugin: Contact Form 7 » Feature Request: Add an option for listo sources to use keys as values

  • Resolved angarf

    (@angarf)


    I hope title is self explanatory. But for the sake of comprehension:

    Would be very useful if an extra boolean parameter for select, radio, and check tags like “data_keys_as_values” or something similar, with a default of false to keep retrocompatibility, could be used to tell cf7 to use keys of items returned by listo as values of options in selects, radios or checks.

    By the way, very nice plugin!

    • This topic was modified 6 months, 3 weeks ago by angarf.
    • This topic was modified 6 months, 3 weeks ago by angarf.
Viewing 6 replies - 1 through 6 (of 6 total)
  • Plugin Author Takayuki Miyoshi

    (@takayukister)

    Could you show some use cases where it would make it more helpful?

    Well,

    i frequently use cf7 hooks to get submitted data and save it to user metas or external repositories of data. Sometimes the forms have fields that involve long list of options that i dont want to write again and again in the templates: is prone to errors in copy/paste. So i decide to use listo to supply this options to cf7. I enjoy the simplicity of listo, but for my purpouses the list available list is short. No problem, i use the filter listo_list_types of listo to add more lists pointing new lists names in listo to a set of clases loaded with an autoloader that implement Listo interface. The problem is that i also use frequently the pipe syntax for select values. I haven’t found a way to use pipe syntax when setting listo as values resource, so i ended making more hacks to get it work: I need to use wpcf7_add_form_tag and wpcf7_remove_form_tag in a function hooked on wpcf7_init to replace select module. The new module is just a verbatim copy of the standard adding just 3 lines to use a custom option named data_values_as_keys that enable the use of values or keys of listo returned items if it values is true or false respectively. I wish this feature were in cf7 instead the need to do hacks. I have to review any update of cf7 to see if select module is modified. Although im not doing modifications on original code, in practice it is coz i’m totally replacing this module.

    I hope i have explained.

    some code to illustrate:

    – Somewhere in a extension plugin or in a theme:

    ...
    add_action( 'wpcf7_init', 'custom_wpcf7_add_form_tag_select', 9, 0 );
    
    function custom_wpcf7_add_form_tag_select() {
    	wpcf7_remove_form_tag('select');
    	wpcf7_remove_form_tag('select*');
    	wpcf7_add_form_tag( array( 'select', 'select*' ),
    		'custom_wpcf7_select_form_tag_handler',
    		array(
    			'name-attr' => true,
    			'selectable-values' => true,
    		)
    	);
    }
    
    function custom_wpcf7_select_form_tag_handler( $tag ) {
    ...
    ...
    		$valuesAsKeys = $tag->get_option( 'data_values_as_keys', '', true);
    		if ($valuesAsKeys == 'true') {
    			$tag->values = array_merge( $tag->values, array_keys( $data ) );
    		} else {
    			$tag->values = array_merge( $tag->values, array_values( $data ) );
    		}
    ...
    ...

    – Exceprt of custom listo extension plugin

    ...
    ...
    define( 'CUSTOM_LISTO_VERSION', '0.1' );
    define( 'CUSTOM_LISTO_PLUGIN_DIR', dirname( __FILE__ ) );
    define( 'CUSTOM_LISTO_LISTS_DIR', path_join( CUSTOM_LISTO_PLUGIN_DIR, 'lists' ) );
    
    add_filter('listo_list_types','custom_listo_add_custom_types',10,1);
    
    function custom_listo_add_custom_types ( $list_types ) {
    	$lists = array_filter(scandir(CUSTOM_LISTO_LISTS_DIR), function($item) {
    		return (is_file(path_join(CUSTOM_LISTO_LISTS_DIR, $item)) && preg_match('/^Listo_.+\.php$/', $item));
    	});
    	foreach($lists as $list) {
    		$class = substr($list,0,-4); 
    		$type = substr($class,6);
    		$list_types[$type] = $class;
    	}
    	return $list_types;
    }
    
    spl_autoload_register(
    	function($class) {
    		if (substr($class,0,10) != 'Listo_ctm_') {
    			return;
    		}
    		$classPath = path_join( CUSTOM_LISTO_LISTS_DIR, $class . '.php' );
    		if ( file_exists( $classPath ) ) {
    			require_once $classPath;
    		}
    	}
    );
    
    ...

    Inside a lists dir of listo extension plugin would be n files with Listo_cstm_xxxxxxxx.php with a class in each file implementing Listo interface.

    I wish this option in select tag enable this feature avoiding hacks. Maybe would be a hook triggered in modules to give hooked functions a chance to change something, altough it maybe would involve more coupling, i dont know.

    Thanks, in advance and sorry for poor english.

    • This reply was modified 6 months, 3 weeks ago by angarf.
    Plugin Author Takayuki Miyoshi

    (@takayukister)

    Thanks. So if I understand you correctly, the point is making the pipes and Listo output able to work together (yes, it’s difficult to do in the current versions), and getting keys instead of array values is no more than an option of means, not the goal, right?

    Well, i think is more than this. Perhaps, the goal isn’t clear cause i twist a bit cf7 to use it as a kind of ui to edit some data in different kind of data backends, not as a form/email paradigm i admit (not always). One of the use cases is to replace personal profile form in WP desktop. I tend to persist data as ids instead string literal cause many time i have to pass this data by rest or message protocol like AMPQ and ids are shorter. Althoug many times this lists can be served by rest points where keys/value pairs served finally by listo come directly from data repository and updating this data is easier if i don’t have to to implement maps to traslate back strings into ids.

    I know that this use of CF7 could be out of point for many users but i tend to reuse components to avoid too much plugins. CF7 is a very good plugin for form/email paradigm ,but you built it in a way that can be use for much more and i have done it.

    Following the example you use in manual for pipes to hide (in some way) emails, would be nice to use listo instead hardcoded lists. The goal is the same, but using listo one can use dynamic lists based for example on rest resources or db queries.

    For what i do with CF7 and persistance in data repositories i need to twist and hack CF7 a little bit, but for the example i tell before is the same as pipes with selects, checks and radios: Is giving the option to do the same hidding emails but with listo instead hardcoded lists.

    The meaninful part of code is:

    ...
       $valuesAsKeys = $tag->get_option( 'data_values_as_keys', '', true);
    	if ($valuesAsKeys == 'true') {
    		$tag->values = array_merge( $tag->values, array_keys( $data ) );
    	} else {
    		$tag->values = array_merge( $tag->values, array_values( $data ) );
    	}
    ...

    Anyway. Thank you so much for your attention.
    I hope you can continue for many more years keeping this great plugin.

    P.D. I apologize for the ammount of edits of the post.

    • This reply was modified 6 months, 3 weeks ago by angarf.
    • This reply was modified 6 months, 3 weeks ago by angarf.
    • This reply was modified 6 months, 3 weeks ago by angarf.
    • This reply was modified 6 months, 3 weeks ago by angarf.
    • This reply was modified 6 months, 3 weeks ago by angarf.
    • This reply was modified 6 months, 3 weeks ago by angarf.
    • This reply was modified 6 months, 3 weeks ago by angarf.
    Plugin Author Takayuki Miyoshi

    (@takayukister)

    OK. I got the point. But, I don’t think the way you have shown in your first comment is bad or inefficient. There is no problem to add your own form-tag hander as you did. It’s fully customizable. That’s how Contact Form 7 is designed.

    Ok. So i’ll do this way. Thanks.

Viewing 6 replies - 1 through 6 (of 6 total)
  • The topic ‘Feature Request: Add an option for listo sources to use keys as values’ is closed to new replies.