Recent Topics

1 Jun 22, 2017 11:29    

This topic deals with the request for plugin-per-user settings as per http://forums.b2evolution.net/plugin-development-opportunities

From @fplanque]

@achillis Yes, we'll be checking on how to make that work for plugin-per-user settings as shown on your screenshot above.

Of you have another place where it doesn't work, please be so kind and screenshot it.

Settings:

1) Plugin Settings (/admin.php?ctrl=widgets) ..................................................................... result (Passed)
2) Collection Plugin Settings (/admin.php?ctrl=coll_settings&tab=plugins) ....................... result (Failed)
3) User Plugin Settings (/admin.php?ctrl=user&user_tab=advanced) ................................ result (Failed)
4) Message Plugin Settings (/admin.php?ctrl=msgsettings&tab=renderers) ...................... result (Failed)
5) Widget Settings (/admin.php?ctrl=plugins&action=edit_settings) .................................. result (Failed)
6) Skin Settings (/admin.php?ctrl=coll_settings&tab=skin) ................................................. result (Failed)

See Screen shots to follow

2 Jun 22, 2017 11:41

<?php
/**
 * -----------------------------------------------------------------------------------------
 * This file provides a skeleton to create a new {@link http://b2evolution.net/ b2evolution}
 * plugin quickly.
 * See also:
 *  - {@link http://b2evolution.net/man/creating-plugin}
 *  - {@link http://doc.b2evolution.net/stable/plugins/Plugin.html}
 * (Delete this first paragraph, of course)
 * -----------------------------------------------------------------------------------------
 *
 * This file implements the Foo Plugin for {@link http://b2evolution.net/}.
 *
 * @license GNU GPL v2 - {@link http://b2evolution.net/about/gnu-gpl-license}
 *
 * @copyright (c)2010 by Your NAME - {@link http://example.com/}.
 *
 * @package plugins
 *
 * @author Your NAME
 */
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );


/**
 * Foo Plugin
 *
 * Your description
 *
 * @package plugins
 */
class development_plugin extends Plugin
{
	/**
	 * Variables below MUST be overriden by plugin implementations,
	 * either in the subclass declaration or in the subclass constructor.
	 */
	/**
	 * Human readable plugin name.
	 */
	var $name = 'Plugin Name';
	/**
	 * Code, if this is a renderer or pingback plugin.
	 */
	var $code = 'devplugin';
	var $priority = 50;
	var $version = '0.1-dev';
	var $author = 'http://example.com/';
	var $help_url = '';

	/**
	 * Group of the plugin, e.g. "widget", "rendering", "antispam"
	 */
	var $group = 'Test';


	/**
	 * Init: This gets called after a plugin has been registered/instantiated.
	 */
	function PluginInit( & $params )
	{
		$this->short_desc = $this->T_('Short description');
		$this->long_desc = $this->T_('Longer description. You may also remove this.');
	}


	/**
	 * Define the GLOBAL settings of the plugin here. These can then be edited in the backoffice in System > Plugins.
	 *
	 * @param array Associative array of parameters (since v1.9).
	 *    'for_editing': true, if the settings get queried for editing;
	 *                   false, if they get queried for instantiating {@link Plugin::$Settings}.
	 * @return array see {@link Plugin::GetDefaultSettings()}.
	 * The array to be returned should define the names of the settings as keys (max length is 30 chars)
	 * and assign an array with the following keys to them (only 'label' is required):
	 */
	function GetDefaultSettings( & $params )
	{
		global $app_version;
		
		return array(
		
				'section_test_start' => array(
					'layout' => 'begin_fieldset',
					'label'  => T_('Dynamic Settings')
				),
			
			'sample_sets' => array(
				'label' => T_('Dynamic Settings'),
				'note' => T_('Click to add another set'),
				'type' => version_compare( $app_version, '6.6.5', '>' ) ? 'array:array:string' : 'array',
				'max_count' => 10,
			
				'entries' => array(
					'disabled' => array(
						'label' => T_('Disabled'),
						'defaultvalue' => 0,
						'type' => 'checkbox',
						'note' => T_('Check to disable this something.'),
					),
			
					'sample_text' => array(
						'label' => T_('Something else'),
						'note' => T_('Some thing to note ').' '.sprintf( T_('E.g. &laquo;%s&raquo;'), 'FooBar' ),
						'size' => 30,
					),
			
					'sample_options' => array(
						'label' => $this->T_('Some options'),
						'type'  => 'select',
						'options' => array(
							'none' => $this->T_('None'),
							'foo' => $this->T_('Foo'),
							'bar' => $this->T_('Bar')
						),
						'note' => $this->T_('A note of something'),
					),
			
					'sample_checkbox' => array(
						'label' => T_('Checkbox'),
						'note' => T_('A Note about this checkbox'),
						'type'  => 'checkbox',
					),
			
					'sample_group' => array(
						'label' => T_('Groups'),
						'type' => 'select_group',
						'note' => T_('The group note.'),
						'allow_none' => true,
					),
				),
			),
		
				'section_test_end' => array(
					'layout' => 'end_fieldset',
				),
		
		);
	}


	/**
	 * Define the PER-USER settings of the plugin here. These can then be edited by each user.
	 *
	 * @see Plugin::GetDefaultSettings()
	 * @param array Associative array of parameters.
	 *    'for_editing': true, if the settings get queried for editing;
	 *                   false, if they get queried for instantiating
	 * @return array See {@link Plugin::GetDefaultSettings()}.
	 */
	function GetDefaultUserSettings( & $params )
	{
		global $app_version;
		
		return array(
		
				'section_test_start' => array(
					'layout' => 'begin_fieldset',
					'label'  => T_('Dynamic Settings')
				),
			
			'sample_sets' => array(
				'label' => T_('Dynamic Settings'),
				'note' => T_('Click to add another set'),
				'type' => version_compare( $app_version, '6.6.5', '>' ) ? 'array:array:string' : 'array',
				'max_count' => 10,
			
				'entries' => array(
					'disabled' => array(
						'label' => T_('Disabled'),
						'defaultvalue' => 0,
						'type' => 'checkbox',
						'note' => T_('Check to disable this something.'),
					),
			
					'sample_text' => array(
						'label' => T_('Something else'),
						'note' => T_('Some thing to note ').' '.sprintf( T_('E.g. &laquo;%s&raquo;'), 'FooBar' ),
						'size' => 30,
					),
			
					'sample_options' => array(
						'label' => $this->T_('Some options'),
						'type'  => 'select',
						'options' => array(
							'none' => $this->T_('None'),
							'foo' => $this->T_('Foo'),
							'bar' => $this->T_('Bar')
						),
						'note' => $this->T_('A note of something'),
					),
			
					'sample_checkbox' => array(
						'label' => T_('Checkbox'),
						'note' => T_('A Note about this checkbox'),
						'type'  => 'checkbox',
					),
			
					'sample_group' => array(
						'label' => T_('Groups'),
						'type' => 'select_group',
						'note' => T_('The group note.'),
						'allow_none' => true,
					),
				),
			),
		
				'section_test_end' => array(
					'layout' => 'end_fieldset',
				),
		
		);
	}

	
	
		/**
	 * Define here default custom settings that are to be made available
	 *     in the backoffice for collections, private messages and newsletters.
	 *
	 * @param array Associative array of parameters.
	 * @return array See {@link Plugin::get_custom_setting_definitions()}.
	 */
	function get_custom_setting_definitions( & $params )
	{
		global $app_version;
		
		return array(
		
				'section_test_start' => array(
					'layout' => 'begin_fieldset',
					'label'  => T_('Dynamic Settings')
				),
			
			'sample_sets' => array(
				'label' => T_('Dynamic Settings'),
				'note' => T_('Click to add another set'),
				'type' => version_compare( $app_version, '6.6.5', '>' ) ? 'array:array:string' : 'array',
				'max_count' => 10,
			
				'entries' => array(
					'disabled' => array(
						'label' => T_('Disabled'),
						'defaultvalue' => 0,
						'type' => 'checkbox',
						'note' => T_('Check to disable this something.'),
					),
			
					'sample_text' => array(
						'label' => T_('Something else'),
						'note' => T_('Some thing to note ').' '.sprintf( T_('E.g. &laquo;%s&raquo;'), 'FooBar' ),
						'size' => 30,
					),
			
					'sample_options' => array(
						'label' => $this->T_('Some options'),
						'type'  => 'select',
						'options' => array(
							'none' => $this->T_('None'),
							'foo' => $this->T_('Foo'),
							'bar' => $this->T_('Bar')
						),
						'note' => $this->T_('A note of something'),
					),
			
					'sample_checkbox' => array(
						'label' => T_('Checkbox'),
						'note' => T_('A Note about this checkbox'),
						'type'  => 'checkbox',
					),
			
					'sample_group' => array(
						'label' => T_('Groups'),
						'type' => 'select_group',
						'note' => T_('The group note.'),
						'allow_none' => true,
					),
				),
			),
		
				'section_test_end' => array(
					'layout' => 'end_fieldset',
				),
		
		);
	}	
	
	/**
	 * Define here default collection/blog settings that are to be made available in the backoffice.
	 *
	 * @param array Associative array of parameters.
	 * @return array See {@link Plugin::get_coll_setting_definitions()}.
	 */
	function get_coll_setting_definitions( & $params )

	{
		global $app_version;
		
		return array(
		
				'section_test_start' => array(
					'layout' => 'begin_fieldset',
					'label'  => T_('Dynamic Settings')
				),
			
			'sample_sets' => array(
				'label' => T_('Dynamic Settings'),
				'note' => T_('Click to add another set'),
				'type' => version_compare( $app_version, '6.6.5', '>' ) ? 'array:array:string' : 'array',
				'max_count' => 10,
			
				'entries' => array(
					'disabled' => array(
						'label' => T_('Disabled'),
						'defaultvalue' => 0,
						'type' => 'checkbox',
						'note' => T_('Check to disable this something.'),
					),
			
					'sample_text' => array(
						'label' => T_('Something else'),
						'note' => T_('Some thing to note ').' '.sprintf( T_('E.g. &laquo;%s&raquo;'), 'FooBar' ),
						'size' => 30,
					),
			
					'sample_options' => array(
						'label' => $this->T_('Some options'),
						'type'  => 'select',
						'options' => array(
							'none' => $this->T_('None'),
							'foo' => $this->T_('Foo'),
							'bar' => $this->T_('Bar')
						),
						'note' => $this->T_('A note of something'),
					),
			
					'sample_checkbox' => array(
						'label' => T_('Checkbox'),
						'note' => T_('A Note about this checkbox'),
						'type'  => 'checkbox',
					),
			
					'sample_group' => array(
						'label' => T_('Groups'),
						'type' => 'select_group',
						'note' => T_('The group note.'),
						'allow_none' => true,
					),
				),
			),
		
				'section_test_end' => array(
					'layout' => 'end_fieldset',
				),
		
		);
	}
	/**
	 * Param definitions when added as a widget.
	 *
	 * Plugins used as widget need to implement the SkinTag hook.
	 *
	 * @return array
	 */
	function get_widget_param_definitions( $params )
	{
		global $app_version;
		
		return array(
		
				'section_test_start' => array(
					'layout' => 'begin_fieldset',
					'label'  => T_('Dynamic Settings')
				),
			
			'sample_sets' => array(
				'label' => T_('Dynamic Settings'),
				'note' => T_('Click to add another set'),
				'type' => version_compare( $app_version, '6.6.5', '>' ) ? 'array:array:string' : 'array',
				'max_count' => 10,
			
				'entries' => array(
					'disabled' => array(
						'label' => T_('Disabled'),
						'defaultvalue' => 0,
						'type' => 'checkbox',
						'note' => T_('Check to disable this something.'),
					),
			
					'sample_text' => array(
						'label' => T_('Something else'),
						'note' => T_('Some thing to note ').' '.sprintf( T_('E.g. &laquo;%s&raquo;'), 'FooBar' ),
						'size' => 30,
					),
			
					'sample_options' => array(
						'label' => $this->T_('Some options'),
						'type'  => 'select',
						'options' => array(
							'none' => $this->T_('None'),
							'foo' => $this->T_('Foo'),
							'bar' => $this->T_('Bar')
						),
						'note' => $this->T_('A note of something'),
					),
			
					'sample_checkbox' => array(
						'label' => T_('Checkbox'),
						'note' => T_('A Note about this checkbox'),
						'type'  => 'checkbox',
					),
			
					'sample_group' => array(
						'label' => T_('Groups'),
						'type' => 'select_group',
						'note' => T_('The group note.'),
						'allow_none' => true,
					),
				),
			),
		
				'section_test_end' => array(
					'layout' => 'end_fieldset',
				),
		
		);
	}


	// If you use hooks, that are not present in b2evo 1.8, you should also add
	// a GetDependencies() function and require the b2evo version your Plugin needs.
	// See http://doc.b2evolution.net/stable/plugins/Plugin.html#methodGetDependencies


	// Add the methods to hook into here...
	// See http://doc.b2evolution.net/stable/plugins/Plugin.html
	
	
	function SkinTag( & $params )
	{
		
		
		
		return true;
		
	}
	
	
	
	
}
?>


Attachments:

4 Jul 07, 2017 11:37

@mgsolipa looking at https://github.com/b2evolution/b2evolution/commit/9a1fceb8dbc77f10ec25c382aa23bfb497a51b12

I am not sure if this is correct or incorrect behavior;

When developing a plugin both settings needs to be specified. If Global settings are not defined then it breaks. This is because with Widgets it looks for Settings and not param_settings? if the user does not specify matching sets with GetDefaultSettings together with get_widget_param_definitions the following result with widget type settings:

function GetDefaultSettings( & $params )
	{ 
		global $app_version;
		
		return array(
		
			
			'sample_sets' => array(
				'label' => T_('Dynamic Settings'),
				'note' => T_('Click to add another set'),
				'type' => version_compare( $app_version, '6.6.5', '>' ) ? 'array:array:string' : 'array',
),
)
}

function get_widget_param_definitions( $params )
	{ 
		global $app_version;
		
		return array(
		
			
			
			'sample_sets' => array(
				'label' => T_('Dynamic Settings'),
				'note' => T_('Click to add another set'),
				'type' => version_compare( $app_version, '6.6.5', '>' ) ? 'array:array:string' : 'array',
),
)
}

then the following error occurs.

Fatal error: Uncaught Error: Call to a member function get() on null in /Users/macbookpro/Dropbox/XAMPP/Development/inc/plugins/_plugin.funcs.php:739 Stack trace: #0 /Users/macbookpro/Dropbox/XAMPP/Development/inc/plugins/_plugin.funcs.php(586): get_plugin_settings_node_by_path(Object(development_plugin), 'Widget', Array, true) #1 /Users/macbookpro/Dropbox/XAMPP/Development/htsrv/async.php(250): _set_setting_by_path(Object(development_plugin), 'Widget', 'sample_sets[2]', Array) #2 {main} thrown in /Users/macbookpro/Dropbox/XAMPP/Development/inc/plugins/_plugin.funcs.php on line 739

6 Jul 07, 2017 15:57

inc/_core/ui/forms/_form.class.php in function file_select_delete( event_object ) and function file_select_add( fieldName, root, path )

The solution is to wrap the square brackets with

fieldName = fieldName.replace(/(\[|\])/g, "\\\\$1");

function file_select_add( fieldName, root, path )
						{
							// check if value is already present
							
							fieldName = fieldName.replace(/(\[|\])/g, "\\\\$1");
							var inputField = jQuery( "input#" + fieldName );
							var values = inputField.val().split( "'.$field_params['value_separator'].'" );

							// Add new item
							jQuery.ajax({
								type: "GET",
								url: "'.get_htsrv_url().'anon_async.php",
								data: {
										"action": "get_file_select_item",
										"field_name": fieldName,
										"root": root,
										"path": path,
										"params": '.json_encode( $script_params ).'
									},
								success: function( result )
									{
										result = jQuery.parseJSON( ajax_debug_clear( result) );
										var fieldName = result.fieldName;
										var fieldValue = result.fieldValue;
										var inputField = jQuery( "input#" + fieldName );
										var wrapper = jQuery( "div[name=" + fieldName + "].file_select_wrapper" );
										var maxLength = wrapper.data( "maxLength" );
										var overflowMode = wrapper.data( "overflowMode" );
										var addButton = jQuery( "button", wrapper );
										var items = jQuery( ".file_select_item:not(button)", wrapper );
										var lastItem = items.last();

										var newItem = jQuery( atob( result.item ) );

										if( fsel_replace )
										{
											var item = jQuery( fsel_obj ).closest( ".file_select_item" );
											newItem.insertAfter( item );
											file_select_delete( item );
										}
										else
										{
											// Attach new item
											// check if adding item will result to an overflow
											if( items.length >= maxLength )
											{ // remove extra item first depending on overflow mode
												if( overflowMode == "queue" )
												{
													file_select_delete( items.first() );
												}
												else if( overflowMode == "stack" )
												{
													file_select_delete( items.last() );
												}

												items = jQuery( ".file_select_item:not(button)", wrapper );
												lastItem = items.last();
											}

											if( lastItem.length )
											{ // attachment already exists, add to the last
												newItem.insertAfter( lastItem );
											}
											else
											{ // no attachments yet
												wrapper.prepend( newItem );
											}
										}

										newItem.find( "span.remove_file_icon" ).replaceWith(\''.$remove_icon.'\'); // replace unlink icon with skin specific icon saved earlier
										newItem.find( "span.edit_file_icon" ).replaceWith(\''.$edit_icon.'\'); // replace unlink icon with skin specific icon saved earlier

										items = jQuery( ".file_select_item:not(button)", wrapper );
										lastItem = items.last();

										// Toggle add button
										addButton.html( items.length === 0 ? "'./* TRANS: verb */ T_('Select').'" : \''.get_icon( 'new' ).' '.T_('Add').'\' );
										if( maxLength > items.length )
										{
											addButton.show();
										}
										else
										{
											addButton.hide();
										}

										// append field value
										var values = inputField.val();
										values = values ? ( inputField.val().split( "'.$field_params['value_separator'].'" ) ) : [];
										values.push( fieldValue );
										inputField.val( values.join( "'.$field_params['value_separator'].'" ) );

										// Trigger change so bozo validator will pickup the change
										inputField.trigger( "change" );

										// close modal if single item select
										if( maxLength == 1 )
										{
											closeModalWindow();
										}
									}
							});

							return false;
						}

						function file_select_delete( event_object )
						{
							var wrapper = jQuery( event_object ).closest( ".file_select_wrapper" );
							var item = jQuery( event_object ).closest( ".file_select_item" );
							var fieldName = wrapper.attr( "name" );
							var fieldValue = item.data( "itemValue" ).toString(); // converted to string because it will later be compared to array of strings
							var maxLength = wrapper.data( "maxLength" );
							var addButton = jQuery( "button", wrapper );

							// Remove file select item
							item.remove();

							var items = jQuery( ".file_select_item:not(button)", wrapper );
							var lastItem = items.last();

							// Toggle add button
							addButton.html( items.length === 0 ? "'./* TRANS: verb */ T_('Select').'" : \''.get_icon( 'new' ).' '.T_('Add').'\' );
							if( maxLength > items.length )
							{
								addButton.show();
							}
							else
							{
								addButton.hide();
							}

							// Change input value
							fieldName = fieldName.replace(/(\[|\])/g, "\\\\$1");
							var inputField = jQuery( "input#" + fieldName );
							var values = inputField.val().split( "'.$field_params['value_separator'].'" );
							var index =  values.indexOf( fieldValue );
							if( index != -1 )
							{
								values.splice( index, 1 );
							}
							inputField.val( values.join( "'.$field_params['value_separator'].'" ) );
							inputField.trigger( "change" );

							return false;
						}


Form is loading...