ProcessWire - Konfigurierbare Module: Unterschied zwischen den Versionen

Aus Wikizone
Wechseln zu: Navigation, Suche
Zeile 128: Zeile 128:
 
  https://processwire.com/talk/topic/29098-how-should-getmoduleconfiginputfields-be-declared/
 
  https://processwire.com/talk/topic/29098-how-should-getmoduleconfiginputfields-be-declared/
  
Should getModuleConfigInputfields() be declared in a module as static or not? Also, I am confused that som modules use an array as the parameter whereas others use an InputfieldWrapper.
+
Diese Funktion wurde schon bei den ersten Modulen eingesetzt. Sie ist noch aus Gründen der Kompatibilität vorhanden. Wenn man ältere Module anpassen möchte ist es gut etwas über diese Funktion zu wissen.
 +
 
 +
'''Should getModuleConfigInputfields() be declared in a module as static or not?'''
 +
 
 +
Also, I am confused that som modules use an array as the parameter whereas others use an InputfieldWrapper.
  
 
For example, WireMailSmtp has  
 
For example, WireMailSmtp has  
Zeile 145: Zeile 149:
  
 
The static method is the old/original way from when ProcessWire first was released (13 years ago), and it was used primarily so that one could configure a module without booting up an instance of the module. Later on (like ~8 years ago?), the Modules class was upgraded so that it could instantiate the module without initializing it, which made the static option obsolete. The only reason ProcessWire still recognizes it is for backwards compatibility, or if it happens to be preferred by the module developer for one reason or another.
 
The static method is the old/original way from when ProcessWire first was released (13 years ago), and it was used primarily so that one could configure a module without booting up an instance of the module. Later on (like ~8 years ago?), the Modules class was upgraded so that it could instantiate the module without initializing it, which made the static option obsolete. The only reason ProcessWire still recognizes it is for backwards compatibility, or if it happens to be preferred by the module developer for one reason or another.
 +
 +
Value Attribut setzen
 +
 +
Damit Werte richtig gespeichert werden muss man im Gegensatz zu den moderneren Funktionen das Value Attribut setzen. Ryan setzt i.d.R. im Konstruktor des Moduls die Default Werte.
 +
 +
Beispiel aus dem alten LoginRegister Modul (plus ein Textfeld)
 +
 +
<syntaxhighlight lang="php">
 +
const defaultRoleName = 'login-register';
 +
 +
/**
 +
* Construct and establish default settings
 +
*
 +
*/
 +
public function __construct() {
 +
$this->set('renderStyles', true);
 +
$this->set('renderScripts', true);
 +
$this->set('registerRoles', array(self::defaultRoleName));
 +
$this->set('registerFields', array('name', 'email', 'pass'));
 +
$this->set('profileFields', array('name', 'pass'));
 +
$this->set('features', array('login', 'register', 'profile'));
 +
$this->set('adminEmail','test@tester.de');
 +
 +
parent::__construct();
 +
}
 +
 +
/**
 +
* Module configuration
 +
*
 +
* @param InputfieldWrapper $inputfields
 +
*
 +
*/
 +
public function getModuleConfigInputfields(InputfieldWrapper $inputfields) {
 +
 +
$hasForgot = $this->modules->isInstalled('ProcessForgotPassword');
 +
 +
 +
/** @var InputfieldEmail $f  */
 +
 +
$f = $this->wire('modules')->get('InputfieldText');
 +
$f->label = 'Admin Email';
 +
$f->icon = 'user';
 +
$f->attr('name', 'adminEmail');
 +
$f->attr('value',$this->adminEmail);
 +
//$f->required = 1;
 +
$f->description = _('Used for messages such as new user registrations.');
 +
$inputfields->add($f);
 +
 +
 +
 +
/** @var InputfieldCheckboxes $f */
 +
$f = $this->modules->get('InputfieldCheckboxes');
 +
$f->attr('name', 'features');
 +
$f->label = $this->_('Features to use');
 +
$f->icon = 'sliders';
 +
$f->addOption('login', $this->_('Login form'));
 +
$f->addOption('register', $this->_('New user registration form'));
 +
$f->addOption('profile', $this->_('Edit profile form (for logged-in users)'));
 +
$f->addOption('login-email', $this->_('Use email address for login rather than user name'));
 +
$f->addOption('forgot', $this->_('Forgot password reset') . ($hasForgot ? '' : '*'));
 +
$f->addOption('registered-email', $this->_('Send email to admin if new user had registered.'));
 +
$f->attr('value', $this->features);
 +
if(!$hasForgot) $f->notes =
 +
$this->_('*Requires core “ProcessForgotPassword” module') . ' - [' .
 +
$this->_('Click to install') . '](./installConfirm?name=ProcessForgotPassword)';
 +
$inputfields->add($f);
 +
 +
 +
/** @var InputfieldAsmSelect $f */
 +
$f = $this->modules->get('InputfieldAsmSelect');
 +
$f->attr('name', 'registerFields');
 +
$f->label = $this->_('Registration form fields');
 +
$f->description =
 +
$this->_('If you do not see all the fields you need, add them to the “user” template first and then come back here.') . ' ' .
 +
$this->_('Only standard fields may be used on the front-end (no files, repeaters, richtext, multi-value, combined fields, etc.).');
 +
$f->showIf = 'features=register';
 +
$f->icon = 'address-book-o';
 +
foreach($this->wire('templates')->get('user')->fieldgroup as $field) {
 +
if($field->name == 'roles') continue;
 +
$label = $field->getLabel();
 +
if($field->name == 'email' || $field->name == 'pass') $label .= ' ' . $this->_('(required)');
 +
$f->addOption($field->name, $label);
 +
}
 +
$f2 = clone $f;
 +
$value = $this->registerFields;
 +
if(!in_array('email', $value)) $value[] = 'email';
 +
if(!in_array('pass', $value)) $value[] = 'pass';
 +
$f->attr('value', $value);
 +
$inputfields->add($f);
 +
 +
/** @var InputfieldAsmSelect $f2 */
 +
$f2->attr('name', 'profileFields');
 +
$f2->label = $this->_('Profile form fields');
 +
$f2->showIf = 'features=profile';
 +
$f2->icon = 'address-card-o';
 +
$value = $this->profileFields;
 +
if(!in_array('email', $value)) $value[] = 'email';
 +
if(!in_array('pass', $value)) $value[] = 'pass';
 +
$f2->attr('value', $value);
 +
$inputfields->add($f2);
 +
 +
/** @var InputfieldCheckboxes $f */
 +
$f = $this->modules->get('InputfieldCheckboxes');
 +
$f->attr('name', 'registerRoles');
 +
$f->label = $this->_('Roles to add to newly registered users');
 +
$f->notes = $this->_('The “guest” role is assumed. Roles with page-edit permission are not shown.');
 +
$f->showIf = 'features=register';
 +
$f->icon = 'gears';
 +
$value = array();
 +
foreach($this->wire('roles') as $role) {
 +
if($role->name == 'guest' || $role->name == 'superuser') continue;
 +
if($role->hasPermission('page-edit')) continue;
 +
$option = "$role->name:$role->id";
 +
$f->addOption($option, $role->name);
 +
if(in_array($option, $this->registerRoles) || in_array($role->name, $this->registerRoles)) $value[] = $option;
 +
}
 +
$f->attr('value', $value);
 +
$inputfields->add($f);
 +
 +
/** @var InputfieldMarkup $f */
 +
$f = $this->modules->get('InputfieldMarkup');
 +
$f->attr('name', '_docs');
 +
$f->label = $this->_('How to use + documentation');
 +
$f->icon = 'bookmark-o';
 +
$f->collapsed = Inputfield::collapsedYes;
 +
if($this->wire('adminTheme') instanceof AdminThemeFramework) {
 +
$f->value = $this->wire('sanitizer')->entitiesMarkdown(file_get_contents(__DIR__ . '/README.md'), true);
 +
} else {
 +
$f->description =
 +
$this->_('Place the following where you want the login/register/profile output to go in your template file.') . ' ' .
 +
$this->_('It should ideally be placed in a main/bodycopy area.');
 +
$f->value = '<pre><code>&lt;?php echo $modules->get("LoginRegister")->execute(); ?&gt;</code></pre>';
 +
$f->notes = sprintf(
 +
$this->_('See the [full documentation](%s) for more details.'),
 +
'https://github.com/ryancramerdesign/LoginRegister/blob/master/README.md'
 +
);
 +
}
 +
$inputfields->add($f);
 +
 +
return $inputfields;
 +
}
 +
 +
</syntaxhighlight>

Version vom 25. Juni 2024, 06:27 Uhr

Ab ProcessWire 2.5.5. kann man Module mit Konfigurationsmöglichkeiten einfacher erstellen. Die Konfigurationsoptionen lagert man in eine extra Datei aus.

https://processwire.com/blog/posts/new-module-configuration-options/
https://processwire.com/api/ref/modules/save-config/

Beispiel Modul "Test" (gibt eine Meldung im Admin bei jeder Seitenladen aus)

  • Datei mit dem Namen und Klasse [Modulname]Config erstellen
  • Klasse extends ModulConfig
  • Default Werte über getDefaults() Funktion definieren
  • Inputfelder über getInputfields() Funktion definieren

Test.php

class Test extends WireData implements Module {
  public static function getModuleInfo() {
    return array(
     'title' => 'Module Test',
     'version' => 1,
     'summary' => 'Module for testing/demo purposes.',
     'autoload' => 'template=admin',
    );
  }
  public function ready() {
    if($this->fullname && !count($this->input->post)) {
      $msg = "Hi $this->fullname! ";
      $msg .= "Your age: $this->age. ";
      $msg .= "Favorite color: $this->color.";
      $this->message($msg);
    }
  }
}

TestConfig.php

class TestConfig extends ModuleConfig {
  public function getDefaults() {
    return array(
      'fullname' => '',
      'color' => 'blue',
      'age' => 40,
    );
  }
  public function getInputfields() {
    $inputfields = parent::getInputfields();

    $f = $this->modules->get('InputfieldText');
    $f->attr('name', 'fullname');
    $f->label = 'Full Name';
    $f->required = true;
    $inputfields->add($f);

    $f = $this->modules->get('InputfieldSelect');
    $f->attr('name', 'color');
    $f->label = 'Favorite Color';
    $f->options = array(
      'red' => 'Red',
      'green' => 'Green',
      'blue' => 'Blue'
    );
    $inputfields->add($f);

    $f = $this->modules->get('InputfieldInteger');
    $f->attr('name', 'age');
    $f->label = 'Your Age';
    $inputfields->add($f);

    return $inputfields;
  }
}


Tipps für das Konfigurieren von Modulen

Es gibt verschiedene Möglichkeiten Module zu konfigurieren. Außerdem ältere Funktionen die manchmal eingesetzt werden.

Old School Storing

In alten Versionen von ProcessWire hat man es so gemacht:

class MyFooBar implements Module, ConfigurableModule {

  public static function getModuleInfo() { /* you know what's here */ }

  public function __construct() {
    // set your default values for config variables
    $this->set('foo', ''); 
    $this->set('bar', 0); 
  }

  public function init() {
    // note that PW populates the actual values for your config vars, 'foo' and 'bar'
    // before this init() function is called, but after __construct is called. That's why 
    // we set the defaults in __construct. Once you get to this init(), your config is 
    // now populated, and likewise available for this non-static function below: 
  }
  
  public function getConfig() {
    // you can name this function whatever you want, since it's not part of any interface
    // this is the stuff you would usually have in your static getModuleConfigInputfields
    // see how we can pull the values from $this->foo rather than $data['foo']; 
    $inputfields = new InputfieldWrapper();

    $f = $this->modules->get('InputfieldText');
    $f->attr('name', 'foo');
    $f->attr('value', $this->foo);
    $f->label = 'Foo';
    $inputfields->add($f);

    $f = $this->modules->get('InputfieldInteger');
    $f->attr('name', 'bar');
    $f->attr('value', $this->bar); 
    $f->label = 'Bar';
    $inputfields->add($f);

    return $inputfields;
  }

  public static function getModuleConfigInputfields(array $data) {
    // note we don't actually need $data in this pattern
    $module = wire('modules')->get('MyFooBar'); 
    return $module->getConfig();
  }
}

Die Funktion getModuleConfigInputfields()

https://processwire.com/talk/topic/29098-how-should-getmoduleconfiginputfields-be-declared/

Diese Funktion wurde schon bei den ersten Modulen eingesetzt. Sie ist noch aus Gründen der Kompatibilität vorhanden. Wenn man ältere Module anpassen möchte ist es gut etwas über diese Funktion zu wissen.

Should getModuleConfigInputfields() be declared in a module as static or not?

Also, I am confused that som modules use an array as the parameter whereas others use an InputfieldWrapper.

For example, WireMailSmtp has

static public function getModuleConfigInputfields(array $data)

whereas WireMailRouter has

public function getModuleConfigInputfields(InputfieldWrapper $inputfields)

I am trying to build a module that allows certain configs to be set outside the modules themselves (to allow non-superuser access), so I need to call the getModuleConfigInputfields() method, but without knowing what parameter to supply. If it is an array, I can use getConfig(), but otherwise what. And why do different modules do it differently anyway?

Ryans Antwort:

The Modules class supports a lot of different options for this, and it figures out which you are using automatically according to how you've defined it. The one that I prefer to use is your second example, that is not static and has the InputfieldWrapper $inputfields as the argument.

The static method is the old/original way from when ProcessWire first was released (13 years ago), and it was used primarily so that one could configure a module without booting up an instance of the module. Later on (like ~8 years ago?), the Modules class was upgraded so that it could instantiate the module without initializing it, which made the static option obsolete. The only reason ProcessWire still recognizes it is for backwards compatibility, or if it happens to be preferred by the module developer for one reason or another.

Value Attribut setzen

Damit Werte richtig gespeichert werden muss man im Gegensatz zu den moderneren Funktionen das Value Attribut setzen. Ryan setzt i.d.R. im Konstruktor des Moduls die Default Werte.

Beispiel aus dem alten LoginRegister Modul (plus ein Textfeld)

	const defaultRoleName = 'login-register';

	/**
	 * Construct and establish default settings
	 *
	 */
	public function __construct() {
		$this->set('renderStyles', true);
		$this->set('renderScripts', true);
		$this->set('registerRoles', array(self::defaultRoleName));
		$this->set('registerFields', array('name', 'email', 'pass'));
		$this->set('profileFields', array('name', 'pass'));
		$this->set('features', array('login', 'register', 'profile'));
		$this->set('adminEmail','test@tester.de');
			
		parent::__construct();
	}

	/**
	 * Module configuration
	 * 
	 * @param InputfieldWrapper $inputfields
	 * 
	 */
	public function getModuleConfigInputfields(InputfieldWrapper $inputfields) {

		$hasForgot = $this->modules->isInstalled('ProcessForgotPassword'); 
		

		/** @var InputfieldEmail $f  */

		$f = $this->wire('modules')->get('InputfieldText');
		$f->label = 'Admin Email';
		$f->icon = 'user';
		$f->attr('name', 'adminEmail');
		$f->attr('value',$this->adminEmail);
		//$f->required = 1;
		$f->description = _('Used for messages such as new user registrations.');
		$inputfields->add($f);



		/** @var InputfieldCheckboxes $f */
		$f = $this->modules->get('InputfieldCheckboxes'); 
		$f->attr('name', 'features'); 
		$f->label = $this->_('Features to use'); 
		$f->icon = 'sliders';
		$f->addOption('login', $this->_('Login form')); 
		$f->addOption('register', $this->_('New user registration form')); 
		$f->addOption('profile', $this->_('Edit profile form (for logged-in users)'));
		$f->addOption('login-email', $this->_('Use email address for login rather than user name'));
		$f->addOption('forgot', $this->_('Forgot password reset') . ($hasForgot ? '' : '*')); 
		$f->addOption('registered-email', $this->_('Send email to admin if new user had registered.')); 
		$f->attr('value', $this->features);
		if(!$hasForgot) $f->notes = 
			$this->_('*Requires core “ProcessForgotPassword” module') . ' - [' .
			$this->_('Click to install') . '](./installConfirm?name=ProcessForgotPassword)';
		$inputfields->add($f); 


		/** @var InputfieldAsmSelect $f */
		$f = $this->modules->get('InputfieldAsmSelect'); 
		$f->attr('name', 'registerFields'); 
		$f->label = $this->_('Registration form fields'); 
		$f->description = 
			$this->_('If you do not see all the fields you need, add them to the “user” template first and then come back here.') . ' ' . 
			$this->_('Only standard fields may be used on the front-end (no files, repeaters, richtext, multi-value, combined fields, etc.).');
		$f->showIf = 'features=register';
		$f->icon = 'address-book-o';
		foreach($this->wire('templates')->get('user')->fieldgroup as $field) {
			if($field->name == 'roles') continue;
			$label = $field->getLabel();
			if($field->name == 'email' || $field->name == 'pass') $label .= ' ' . $this->_('(required)'); 
			$f->addOption($field->name, $label);
		}
		$f2 = clone $f;
		$value = $this->registerFields;
		if(!in_array('email', $value)) $value[] = 'email';
		if(!in_array('pass', $value)) $value[] = 'pass';
		$f->attr('value', $value); 
		$inputfields->add($f);
	
		/** @var InputfieldAsmSelect $f2 */
		$f2->attr('name', 'profileFields');
		$f2->label = $this->_('Profile form fields');
		$f2->showIf = 'features=profile';
		$f2->icon = 'address-card-o';
		$value = $this->profileFields;
		if(!in_array('email', $value)) $value[] = 'email';
		if(!in_array('pass', $value)) $value[] = 'pass';
		$f2->attr('value', $value); 
		$inputfields->add($f2);
	
		/** @var InputfieldCheckboxes $f */
		$f = $this->modules->get('InputfieldCheckboxes'); 
		$f->attr('name', 'registerRoles'); 
		$f->label = $this->_('Roles to add to newly registered users'); 
		$f->notes = $this->_('The “guest” role is assumed. Roles with page-edit permission are not shown.'); 
		$f->showIf = 'features=register';
		$f->icon = 'gears';
		$value = array();
		foreach($this->wire('roles') as $role) {
			if($role->name == 'guest' || $role->name == 'superuser') continue; 
			if($role->hasPermission('page-edit')) continue; 
			$option = "$role->name:$role->id";
			$f->addOption($option, $role->name); 
			if(in_array($option, $this->registerRoles) || in_array($role->name, $this->registerRoles)) $value[] = $option;
		}
		$f->attr('value', $value); 
		$inputfields->add($f); 
	
		/** @var InputfieldMarkup $f */
		$f = $this->modules->get('InputfieldMarkup'); 
		$f->attr('name', '_docs');
		$f->label = $this->_('How to use + documentation'); 
		$f->icon = 'bookmark-o';
		$f->collapsed = Inputfield::collapsedYes;
		if($this->wire('adminTheme') instanceof AdminThemeFramework) {
			$f->value = $this->wire('sanitizer')->entitiesMarkdown(file_get_contents(__DIR__ . '/README.md'), true);
		} else {
			$f->description = 
				$this->_('Place the following where you want the login/register/profile output to go in your template file.') . ' ' . 
				$this->_('It should ideally be placed in a main/bodycopy area.'); 
			$f->value = '<pre><code>&lt;?php echo $modules->get("LoginRegister")->execute(); ?&gt;</code></pre>';
			$f->notes = sprintf(
				$this->_('See the [full documentation](%s) for more details.'), 
				'https://github.com/ryancramerdesign/LoginRegister/blob/master/README.md'
			);
		}
		$inputfields->add($f);

		return $inputfields;
	}