mirror of
https://github.com/processwire/processwire.git
synced 2025-08-17 20:11:46 +02:00
Various minor Inputfield code and phpdoc improvements
This commit is contained in:
@@ -3,6 +3,9 @@
|
||||
/**
|
||||
* An Inputfield for handling "button" buttons
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property string $href URL to link to
|
||||
* @property string $aclass Optional class name(s) for <a> element (if href is used).
|
||||
* @property string $target Link target
|
||||
@@ -17,7 +20,7 @@ class InputfieldButton extends InputfieldSubmit {
|
||||
'summary' => __('Form button element that you can optionally pass an href attribute to.', __FILE__), // Module Summary
|
||||
'version' => 100,
|
||||
'permanent' => true,
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
public function init() {
|
||||
|
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* An Inputfield for handling email addresses
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property int $confirm Specify 1 to make it include a second input for confirmation
|
||||
|
@@ -1,16 +1,41 @@
|
||||
<?php namespace ProcessWire;
|
||||
|
||||
/**
|
||||
* Fieldset Inputfield
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property string|int $defaultValue
|
||||
* @property array|string $options Get or set options, array of [value => label], or use options string.
|
||||
* @property array $optionAttributes
|
||||
* @property bool $valueAddOption If value attr set from API (only) that is not an option, add it as an option? (default=false) 3.0.171+
|
||||
*
|
||||
*/
|
||||
|
||||
class InputfieldFieldset extends InputfieldWrapper {
|
||||
|
||||
/**
|
||||
* Get module info
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public static function getModuleInfo() {
|
||||
return array(
|
||||
'title' => __('Fieldset', __FILE__), // Module Title
|
||||
'summary' => __('Groups one or more fields together in a container', __FILE__), // Module Summary
|
||||
'version' => 101,
|
||||
'permanent' => true,
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function ___render() {
|
||||
// Note the extra "\n" is required in order to prevent InputfieldWrapper from
|
||||
// skipping over an empty fieldset. Empty fieldsets are used by InputfieldRepeater
|
||||
|
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* Inputfield for floating point numbers
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property int $precision Decimals precision
|
||||
|
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* InputfieldForm: An Inputfield for containing form elements
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property string $prependMarkup Optional markup to prepend to the form output
|
||||
@@ -75,7 +75,7 @@ class InputfieldForm extends InputfieldWrapper {
|
||||
'summary' => __('Contains one or more fields in a form', __FILE__), // Module Summary
|
||||
'version' => 107,
|
||||
'permanent' => true,
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
const debug = false; // set to true to enable debug mode for field dependencies
|
||||
@@ -233,6 +233,8 @@ class InputfieldForm extends InputfieldWrapper {
|
||||
}
|
||||
|
||||
if(self::debug) $this->debugNote("showIf selector: $selectorString");
|
||||
|
||||
/** @var Selectors $selectors */
|
||||
$selectors = $this->wire(new Selectors($selectorString));
|
||||
|
||||
// whether we should process $child now or not
|
||||
@@ -387,7 +389,8 @@ class InputfieldForm extends InputfieldWrapper {
|
||||
|
||||
if(strlen($selectorString)) {
|
||||
if(self::debug) $this->debugNote("requiredIf selector: $selectorString");
|
||||
|
||||
|
||||
/** @var Selectors $selectors */
|
||||
$selectors = $this->wire(new Selectors($selectorString));
|
||||
|
||||
foreach($selectors as $selector) {
|
||||
|
@@ -3,6 +3,9 @@
|
||||
/**
|
||||
* An Inputfield for handling HTML “hidden” form inputs
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property bool $renderValueAsInput Render the hidden input, even when in renderValue mode (default=false)
|
||||
* @property string $initValue Initial populated value if value attribute not separately populated (default='')
|
||||
*
|
||||
@@ -18,6 +21,10 @@ class InputfieldHidden extends Inputfield {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->setAttribute('type', 'hidden');
|
||||
@@ -25,10 +32,22 @@ class InputfieldHidden extends Inputfield {
|
||||
$this->initValue = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Render
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function ___render() {
|
||||
return "<input " . $this->getAttributesString() . " />";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render value
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function ___renderValue() {
|
||||
if($this->renderValueAsInput) {
|
||||
return $this->render();
|
||||
@@ -37,12 +56,24 @@ class InputfieldHidden extends Inputfield {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get attributes
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function getAttributes() {
|
||||
$attrs = parent::getAttributes();
|
||||
if(!strlen("$attrs[value]") && $this->initValue) $attrs['value'] = (string) $this->initValue;
|
||||
return $attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Inputfield
|
||||
*
|
||||
* @return InputfieldWrapper
|
||||
*
|
||||
*/
|
||||
public function ___getConfigInputfields() {
|
||||
|
||||
$inputfields = parent::___getConfigInputfields();
|
||||
@@ -54,7 +85,7 @@ class InputfieldHidden extends Inputfield {
|
||||
$inputfields->remove($f);
|
||||
|
||||
/** @var InputfieldText $field */
|
||||
$field = $this->modules->get('InputfieldText');
|
||||
$field = $this->wire()->modules->get('InputfieldText');
|
||||
$field->setAttribute('name', 'initValue');
|
||||
$field->label = $this->_('Value');
|
||||
$field->description = $this->_('Value to be populated in this hidden field.');
|
||||
|
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* Integer Inputfield
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property string $inputType Input type to use, one of "text" or "number"
|
||||
|
@@ -3,6 +3,9 @@
|
||||
/**
|
||||
* Intended just for outputting markup as help or commentary among other Inputfields
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property callable|string|null $markupFunction
|
||||
* @property array $textformatters
|
||||
* @property string $markupText
|
||||
@@ -11,25 +14,49 @@
|
||||
|
||||
class InputfieldMarkup extends InputfieldWrapper {
|
||||
|
||||
/**
|
||||
* Get module info
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public static function getModuleInfo() {
|
||||
return array(
|
||||
'title' => __('Markup', __FILE__),
|
||||
'summary' => __('Contains any other markup and optionally child Inputfields', __FILE__),
|
||||
'version' => 102,
|
||||
'permanent' => true,
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Whether render() has been called from renderValue()
|
||||
*
|
||||
* @var bool
|
||||
*
|
||||
*/
|
||||
protected $renderValueMode = false;
|
||||
|
||||
/**
|
||||
* Init
|
||||
*
|
||||
*/
|
||||
public function init() {
|
||||
$this->set('markupText', '');
|
||||
$this->set('markupFunction', null); // closure or name of function that returns markup, receives $this as arg0.
|
||||
$this->set('textformatters', array());
|
||||
$this->skipLabel = Inputfield::skipLabelBlank;
|
||||
parent::init();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Render ready
|
||||
*
|
||||
* @param Inputfield|null $parent
|
||||
* @param bool $renderValueMode
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
public function renderReady(Inputfield $parent = null, $renderValueMode = false) {
|
||||
$label = $this->getSetting('label');
|
||||
|
||||
@@ -39,8 +66,15 @@ class InputfieldMarkup extends InputfieldWrapper {
|
||||
return parent::renderReady($parent, $renderValueMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function ___render() {
|
||||
|
||||
|
||||
$modules = $this->wire()->modules;
|
||||
$out = '';
|
||||
$value = (string) $this->attr('value');
|
||||
|
||||
@@ -63,7 +97,8 @@ class InputfieldMarkup extends InputfieldWrapper {
|
||||
|
||||
if(wireCount($textformatters)) {
|
||||
foreach($textformatters as $className) {
|
||||
$t = $this->wire()->modules->get($className);
|
||||
/** @var Textformatter $t */
|
||||
$t = $modules->get($className);
|
||||
if(!$t) continue;
|
||||
$t->formatValue($this->wire()->page, $this->wire(new Field()), $out);
|
||||
}
|
||||
@@ -74,7 +109,7 @@ class InputfieldMarkup extends InputfieldWrapper {
|
||||
if($this->getSetting('entityEncodeText') !== false && $textFormat != Inputfield::textFormatNone) {
|
||||
if($textFormat == Inputfield::textFormatBasic) {
|
||||
$description = $this->entityEncode($description, Inputfield::textFormatBasic);
|
||||
$out = "<p class='description'>{$description}</p>$out";
|
||||
$out = "<p class='description'>$description</p>$out";
|
||||
} else if($textFormat == Inputfield::textFormatMarkdown) {
|
||||
$out = "<div class='description'>" . $this->entityEncode($description, Inputfield::textFormatMarkdown) . "</div>$out";
|
||||
}
|
||||
@@ -93,13 +128,25 @@ class InputfieldMarkup extends InputfieldWrapper {
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render value
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function ___renderValue() {
|
||||
$this->renderValueMode = true;
|
||||
$out = $this->render();
|
||||
$this->renderValueMode = false;
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure Inputfield
|
||||
*
|
||||
* @return InputfieldWrapper
|
||||
*
|
||||
*/
|
||||
public function ___getConfigInputfields() {
|
||||
|
||||
$modules = $this->wire()->modules;
|
||||
@@ -119,13 +166,13 @@ class InputfieldMarkup extends InputfieldWrapper {
|
||||
$f->attr('id+name', 'textformatters');
|
||||
$f->label = $this->_('Text Formatters');
|
||||
|
||||
foreach($modules->find("className^=Textformatter") as $textformatter) {
|
||||
$info = $textformatter->getModuleInfo();
|
||||
$f->addOption($textformatter->className(), "$info[title]");
|
||||
foreach($modules->findByPrefix('Textformatter') as $moduleName) {
|
||||
$info = $modules->getModuleInfo($moduleName);
|
||||
$title = $info['title'] ? $info['title'] : $moduleName;
|
||||
$f->addOption($moduleName, $title);
|
||||
}
|
||||
|
||||
$f->attr('value', $this->textformatters);
|
||||
|
||||
$f->description = $this->_('Select the format that your Markup Text is in, or the formatters that you want to be applied to it, in the order you want them applied.');
|
||||
$f->notes = $this->_('If your Markup Text is plain HTML, you may not want to select any Text Formatters.');
|
||||
$inputfields->add($f);
|
||||
|
@@ -3,6 +3,9 @@
|
||||
/**
|
||||
* An Inputfield for handling ProcessWire "name" fields
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property string $sanitizeMethod
|
||||
*
|
||||
*/
|
||||
@@ -14,7 +17,7 @@ class InputfieldName extends InputfieldText {
|
||||
'version' => 100,
|
||||
'summary' => __('Text input validated as a ProcessWire name field', __FILE__), // Module Summary
|
||||
'permanent' => true,
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
@@ -37,9 +40,11 @@ class InputfieldName extends InputfieldText {
|
||||
protected function setAttributeValue($value) {
|
||||
$sanitizeMethod = $this->sanitizeMethod;
|
||||
if($this->isWired()) {
|
||||
$value = call_user_func(array($this->wire('sanitizer'), $sanitizeMethod), $value);
|
||||
$sanitizer = $this->wire()->sanitizer;
|
||||
$value = call_user_func(array($sanitizer, $sanitizeMethod), $value);
|
||||
} else {
|
||||
$value = wire('sanitizer')->$sanitizeMethod($value);
|
||||
$sanitizer = wire()->sanitizer;
|
||||
$value = $sanitizer->$sanitizeMethod($value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
* Sublcasses will want to override the render method, but it's not necessary to override processInput().
|
||||
* Subclasses that select multiple values should implement the InputfieldHasArrayValue interface.
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property string|int $defaultValue
|
||||
@@ -164,8 +164,10 @@ class InputfieldSelect extends Inputfield implements InputfieldHasSelectableOpti
|
||||
*
|
||||
*/
|
||||
public function optionLanguageLabel($language, $key = null, $label = null) {
|
||||
$languages = $this->wire()->languages;
|
||||
if(!$languages) return $this;
|
||||
if(is_string($language) && !ctype_digit("$language")) {
|
||||
$language = $this->wire('languages')->get($language);
|
||||
$language = $languages->get($language);
|
||||
}
|
||||
$languageID = (int) "$language"; // converts Page or string to id
|
||||
if(!isset($this->optionLanguageLabels[$languageID])) {
|
||||
@@ -676,17 +678,20 @@ class InputfieldSelect extends Inputfield implements InputfieldHasSelectableOpti
|
||||
*
|
||||
*/
|
||||
public function renderReady(Inputfield $parent = null, $renderValueMode = false) {
|
||||
if(!empty($this->optionLanguageLabels) && $this->wire('languages') && $this->hasFieldtype === false) {
|
||||
// make option labels use use language where available
|
||||
$language = $this->wire('user')->language;
|
||||
$defaultLanguage = $this->wire('languages')->getDefault();
|
||||
if(!empty($this->optionLanguageLabels[$language->id])) {
|
||||
$labels = $this->optionLanguageLabels[$language->id];
|
||||
foreach($this->options as $key => $defaultLabel) {
|
||||
if(empty($labels[$key])) continue;
|
||||
$this->options[$key] = $labels[$key];
|
||||
if($language->id != $defaultLanguage->id) {
|
||||
$this->optionLanguageLabel($defaultLanguage, $key, $defaultLabel);
|
||||
if(!empty($this->optionLanguageLabels) && $this->hasFieldtype === false) {
|
||||
$languages = $this->wire()->languages;
|
||||
if($languages) {
|
||||
// make option labels use use language where available
|
||||
$language = $this->wire()->user->language;
|
||||
$defaultLanguage = $languages->getDefault();
|
||||
if(!empty($this->optionLanguageLabels[$language->id])) {
|
||||
$labels = $this->optionLanguageLabels[$language->id];
|
||||
foreach($this->options as $key => $defaultLabel) {
|
||||
if(empty($labels[$key])) continue;
|
||||
$this->options[$key] = $labels[$key];
|
||||
if($language->id != $defaultLanguage->id) {
|
||||
$this->optionLanguageLabel($defaultLanguage, $key, $defaultLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -705,12 +710,10 @@ class InputfieldSelect extends Inputfield implements InputfieldHasSelectableOpti
|
||||
$attrs = $this->getAttributes();
|
||||
unset($attrs['value']);
|
||||
|
||||
$out =
|
||||
return
|
||||
"<select " . $this->getAttributesString($attrs) . ">" .
|
||||
$this->renderOptions($this->options) .
|
||||
$this->renderOptions($this->options) .
|
||||
"</select>";
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -722,6 +725,7 @@ class InputfieldSelect extends Inputfield implements InputfieldHasSelectableOpti
|
||||
public function ___renderValue() {
|
||||
|
||||
$out = '';
|
||||
$sanitizer = $this->wire()->sanitizer;
|
||||
|
||||
foreach($this->options as $value => $label) {
|
||||
|
||||
@@ -738,11 +742,13 @@ class InputfieldSelect extends Inputfield implements InputfieldHasSelectableOpti
|
||||
}
|
||||
|
||||
if(strlen($o)) {
|
||||
$out .= "<li>" . $this->wire('sanitizer')->entities($o) . "</li>";
|
||||
$out .= "<li>" . $sanitizer->entities($o) . "</li>";
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen($out)) $out = "<ul class='pw-bullets'>$out</ul>";
|
||||
if(strlen($out)) {
|
||||
$out = "<ul class='pw-bullets'>$out</ul>";
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
@@ -779,10 +785,10 @@ class InputfieldSelect extends Inputfield implements InputfieldHasSelectableOpti
|
||||
|
||||
if($this instanceof InputfieldHasArrayValue) {
|
||||
/** @var InputfieldSelect $this */
|
||||
if(!is_array($value)) $value = array();
|
||||
foreach($value as $k => $v) {
|
||||
if(!$this->isOption($v)) {
|
||||
// $this->message("Removing invalid option: " . wire('sanitizer')->entities($value[$k]), Notice::debug);
|
||||
unset($value[$k]);
|
||||
unset($value[$k]); // remove invalid option
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,8 +811,8 @@ class InputfieldSelect extends Inputfield implements InputfieldHasSelectableOpti
|
||||
*
|
||||
*/
|
||||
public function get($key) {
|
||||
if($key == 'options') return $this->options;
|
||||
if($key == 'optionAttributes') return $this->optionAttributes;
|
||||
if($key === 'options') return $this->options;
|
||||
if($key === 'optionAttributes') return $this->optionAttributes;
|
||||
return parent::get($key);
|
||||
}
|
||||
|
||||
@@ -874,7 +880,7 @@ class InputfieldSelect extends Inputfield implements InputfieldHasSelectableOpti
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(strlen($value) && !$this->isOption($value)) {
|
||||
if(strlen("$value") && !$this->isOption($value)) {
|
||||
$this->addOption($value);
|
||||
}
|
||||
}
|
||||
@@ -901,7 +907,7 @@ class InputfieldSelect extends Inputfield implements InputfieldHasSelectableOpti
|
||||
} else if($value === null || $value === false) {
|
||||
return true;
|
||||
|
||||
} else if($value == "0") {
|
||||
} else if("$value" === "0") {
|
||||
if(!array_key_exists("$value", $this->options)) return true;
|
||||
|
||||
} else {
|
||||
@@ -920,12 +926,15 @@ class InputfieldSelect extends Inputfield implements InputfieldHasSelectableOpti
|
||||
public function ___getConfigInputfields() {
|
||||
|
||||
$inputfields = parent::___getConfigInputfields();
|
||||
$modules = $this->wire()->modules;
|
||||
|
||||
if($this instanceof InputfieldHasArrayValue) {
|
||||
$f = $this->wire('modules')->get('InputfieldTextarea');
|
||||
/** @var InputfieldTextarea $f */
|
||||
$f = $modules->get('InputfieldTextarea');
|
||||
$f->description = $this->_('To have pre-selected default value(s), enter the option values (one per line) below.');
|
||||
} else {
|
||||
$f = $this->wire('modules')->get('InputfieldText');
|
||||
/** @var InputfieldText $f */
|
||||
$f = $modules->get('InputfieldText');
|
||||
$f->description = $this->_('To have a pre-selected default value, enter the option value below.');
|
||||
}
|
||||
$f->attr('name', 'defaultValue');
|
||||
@@ -943,10 +952,10 @@ class InputfieldSelect extends Inputfield implements InputfieldHasSelectableOpti
|
||||
|
||||
// the following configuration specific to non-Fieldtype use of single/multi-selects
|
||||
$isInputfieldSelect = $this->className() == 'InputfieldSelect';
|
||||
/** @var Languages|null $languages */
|
||||
$languages = $this->wire('languages');
|
||||
$languages = $this->wire()->languages;
|
||||
|
||||
$f = $this->wire('modules')->get('InputfieldTextarea');
|
||||
/** @var InputfieldTextarea $f */
|
||||
$f = $modules->get('InputfieldTextarea');
|
||||
$f->attr('name', 'options');
|
||||
$f->label = $this->_('Options');
|
||||
$value = '';
|
||||
|
@@ -1,18 +1,45 @@
|
||||
<?php namespace ProcessWire;
|
||||
|
||||
/**
|
||||
* Select Multiple Inputfield
|
||||
*
|
||||
* An Inputfield for handling multiple selection using HTML `<select multiple>`.
|
||||
* Also a base type for other multiple selection types (checkboxes, asmSelect, etc.)
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property int $size
|
||||
*
|
||||
*/
|
||||
|
||||
class InputfieldSelectMultiple extends InputfieldSelect implements InputfieldHasArrayValue {
|
||||
|
||||
const defaultSize = 10;
|
||||
/**
|
||||
* Default 'size' attribute value
|
||||
*
|
||||
*/
|
||||
const defaultSize = 10;
|
||||
|
||||
/**
|
||||
* Get module info
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public static function getModuleInfo() {
|
||||
return array(
|
||||
'title' => __('Select Multiple', __FILE__), // Module Title
|
||||
'summary' => __('Select multiple items from a list', __FILE__), // Module Summary
|
||||
'version' => 101,
|
||||
'permanent' => true,
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->setAttribute('multiple', 'multiple');
|
||||
@@ -23,6 +50,11 @@ class InputfieldSelectMultiple extends InputfieldSelect implements InputfieldHas
|
||||
* Add options only if they are non-blank
|
||||
*
|
||||
* We don't need blank options in a select multiple since the unselected state involves no selected options
|
||||
*
|
||||
* @param string|int $value
|
||||
* @param string|null $label
|
||||
* @param array|null $attributes
|
||||
* @return InputfieldSelect|InputfieldSelectMultiple|self
|
||||
*
|
||||
*/
|
||||
public function addOption($value, $label = null, array $attributes = null) {
|
||||
@@ -30,11 +62,18 @@ class InputfieldSelectMultiple extends InputfieldSelect implements InputfieldHas
|
||||
return parent::addOption($value, $label, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Inputfield
|
||||
*
|
||||
* @return InputfieldWrapper
|
||||
*
|
||||
*/
|
||||
public function ___getConfigInputfields() {
|
||||
$inputfields = parent::___getConfigInputfields();
|
||||
if($this->className() == 'InputfieldSelectMultiple') {
|
||||
if($this->className() === 'InputfieldSelectMultiple') {
|
||||
// descending classes may null out the 'size' attribute if they don't need it
|
||||
$f = $this->wire('modules')->get('InputfieldInteger');
|
||||
/** @var InputfieldInteger $f */
|
||||
$f = $this->wire()->modules->get('InputfieldInteger');
|
||||
$f->label = $this->_('Size: number of rows visible at once in the select multiple');
|
||||
$f->attr('name', 'size');
|
||||
$f->attr('value', (int) $this->attr('size'));
|
||||
@@ -42,6 +81,4 @@ class InputfieldSelectMultiple extends InputfieldSelect implements InputfieldHas
|
||||
}
|
||||
return $inputfields;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -3,14 +3,27 @@
|
||||
/**
|
||||
* An Inputfield for handling "textarea" form inputs
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property int $rows Number of rows for textarea (default=5)
|
||||
* @property int $contentType Content type, applicable when used with FieldtypeTextarea. See FieldtypeTextarea contentType constants (default=contentTypeUnknown)
|
||||
*
|
||||
*/
|
||||
class InputfieldTextarea extends InputfieldText {
|
||||
|
||||
const defaultRows = 5;
|
||||
/**
|
||||
* Default value for rows attribute
|
||||
*
|
||||
*/
|
||||
const defaultRows = 5;
|
||||
|
||||
/**
|
||||
* Get module info
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public static function getModuleInfo() {
|
||||
return array(
|
||||
'title' => __('Textarea', __FILE__), // Module Title
|
||||
@@ -20,7 +33,10 @@ class InputfieldTextarea extends InputfieldText {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Init Inputfield
|
||||
*
|
||||
*/
|
||||
public function init() {
|
||||
parent::init();
|
||||
$this->setAttribute('rows', self::defaultRows);
|
||||
@@ -70,10 +86,8 @@ class InputfieldTextarea extends InputfieldText {
|
||||
*
|
||||
*/
|
||||
protected function getValueLength($value, $countWords = false) {
|
||||
if(in_array($this->contentType, array(FieldtypeTextarea::contentTypeHTML, FieldtypeTextarea::contentTypeImageHTML))) {
|
||||
$value = strip_tags($value);
|
||||
}
|
||||
$value = $this->wire('sanitizer')->textarea($value, array('stripTags' => false));
|
||||
if($this->isContentTypeHTML()) $value = strip_tags($value);
|
||||
$value = $this->wire()->sanitizer->textarea($value, array('stripTags' => false));
|
||||
return parent::getValueLength($value, $countWords);
|
||||
}
|
||||
|
||||
@@ -89,11 +103,10 @@ class InputfieldTextarea extends InputfieldText {
|
||||
$value = $attrs['value'];
|
||||
unset($attrs['value'], $attrs['size'], $attrs['type']);
|
||||
|
||||
$out =
|
||||
return
|
||||
"<textarea " . $this->getAttributesString($attrs) . ">" .
|
||||
htmlspecialchars($value, ENT_QUOTES, "UTF-8") .
|
||||
"</textarea>";
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,8 +118,10 @@ class InputfieldTextarea extends InputfieldText {
|
||||
*
|
||||
*/
|
||||
protected function setAttributeValue($value) {
|
||||
|
||||
$maxlength = $this->attr('maxlength');
|
||||
$value = (string) $value;
|
||||
|
||||
if($maxlength > 0 && $this->hasFieldtype === false) {
|
||||
$value = $this->wire()->sanitizer->textarea($value, array(
|
||||
'maxLength' => $maxlength,
|
||||
@@ -119,7 +134,9 @@ class InputfieldTextarea extends InputfieldText {
|
||||
$value = str_replace("\r\n", "\n", $value);
|
||||
}
|
||||
}
|
||||
|
||||
if($this->stripTags) $value = strip_tags($value);
|
||||
|
||||
return $this->noTrim ? $value : trim($value);
|
||||
}
|
||||
|
||||
@@ -133,6 +150,7 @@ class InputfieldTextarea extends InputfieldText {
|
||||
public function ___processInput(WireInputData $input) {
|
||||
|
||||
$maxlength = $this->attr('maxlength');
|
||||
|
||||
if($this->hasFieldtype !== false && $maxlength > 0) {
|
||||
// we want to apply our own maxlength logic that doesn't truncate
|
||||
$this->attr('maxlength', 0);
|
||||
@@ -161,26 +179,49 @@ class InputfieldTextarea extends InputfieldText {
|
||||
*
|
||||
*/
|
||||
public function ___renderValue() {
|
||||
if($this->contentType == FieldtypeTextarea::contentTypeHTML) {
|
||||
$out = "<div class='InputfieldTextareaContentTypeHTML'>" .
|
||||
$this->wire('sanitizer')->purify($this->attr('value')) . "</div>";
|
||||
if($this->isContentTypeHTML()) {
|
||||
$out =
|
||||
"<div class='InputfieldTextareaContentTypeHTML'>" .
|
||||
$this->wire()->sanitizer->purify($this->val()) .
|
||||
"</div>";
|
||||
} else {
|
||||
$out = nl2br(htmlentities($this->attr('value'), ENT_QUOTES, "UTF-8"));
|
||||
$out = nl2br(htmlentities($this->val(), ENT_QUOTES, "UTF-8"));
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is current content-type an HTML content-type?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
public function isContentTypeHTML() {
|
||||
$contentTypes = array(
|
||||
FieldtypeTextarea::contentTypeHTML,
|
||||
FieldtypeTextarea::contentTypeImageHTML
|
||||
);
|
||||
return in_array($this->contentType, $contentTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Inputfield
|
||||
*
|
||||
* @return InputfieldWrapper
|
||||
*
|
||||
*/
|
||||
public function ___getConfigInputfields() {
|
||||
|
||||
$inputfields = parent::___getConfigInputfields();
|
||||
$removes = array('size', 'pattern');
|
||||
|
||||
foreach($removes as $name) {
|
||||
$f = $inputfields->getChildByName($name);
|
||||
if($f) $inputfields->remove($f);
|
||||
}
|
||||
|
||||
/** @var InputfieldInteger $field */
|
||||
$field = $this->modules->get('InputfieldInteger');
|
||||
$field = $this->wire()->modules->get('InputfieldInteger');
|
||||
$field->setAttribute('name', 'rows');
|
||||
$field->label = $this->_('Rows');
|
||||
$field->setAttribute('value', $this->attr('rows') > 0 ? $this->attr('rows') : self::defaultRows);
|
||||
@@ -191,7 +232,14 @@ class InputfieldTextarea extends InputfieldText {
|
||||
|
||||
return $inputfields;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get config fields allowed for context
|
||||
*
|
||||
* @param Field $field
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function ___getConfigAllowContext($field) {
|
||||
return array_merge(parent::___getConfigAllowContext($field), array('rows'));
|
||||
}
|
||||
|
@@ -1,9 +1,12 @@
|
||||
<?php namespace ProcessWire;
|
||||
|
||||
/**
|
||||
* Class InputfieldURL
|
||||
* URL Inputfield Module
|
||||
*
|
||||
* An Inputfield for handling input of URLs
|
||||
* An Inputfield for handling input of URLs in ProcessWire forms.
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property int|bool $noRelative Whether relative URLs are disabled
|
||||
* @property int|bool $addRoot Whether to prepend root path
|
||||
@@ -17,10 +20,14 @@ class InputfieldURL extends InputfieldText {
|
||||
return array(
|
||||
'title' => __('URL', __FILE__), // Module Title
|
||||
'summary' => __('URL in valid format', __FILE__), // Module Summary
|
||||
'version' => 102,
|
||||
);
|
||||
'version' => 103,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->setAttribute('type', 'text');
|
||||
@@ -34,44 +41,75 @@ class InputfieldURL extends InputfieldText {
|
||||
$this->set('allowQuotes', 0); // whether to allow quote characters in URLs
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Inputfield
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function ___render() {
|
||||
$rootUrl = $this->config->urls->root;
|
||||
$rootUrl = $this->wire()->config->urls->root;
|
||||
if($this->addRoot && !$this->noRelative && !$this->notes && strlen($rootUrl) > 1) {
|
||||
$this->notes = sprintf($this->_("Start local URLs with \"/\" and leave off the \"%s\" part."), $rootUrl); // Instruction for local URLs displayed when site is running from a subdirectory
|
||||
$this->notes = sprintf(
|
||||
$this->_("Start local URLs with “/” and leave off the “%s” part."), // Instruction for local URLs displayed when site is running from a subdirectory
|
||||
$rootUrl
|
||||
);
|
||||
}
|
||||
return parent::___render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value attribute
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
protected function setAttributeValue($value) {
|
||||
|
||||
if(strlen($value)) {
|
||||
$value = trim($value);
|
||||
$unsanitized = $value;
|
||||
$value = $this->wire('sanitizer')->url($value, array(
|
||||
'allowRelative' => $this->noRelative ? false : true,
|
||||
'allowIDN' => $this->allowIDN ? true : false,
|
||||
'stripQuotes' => $this->allowQuotes ? false : true,
|
||||
));
|
||||
|
||||
if(!$value || $unsanitized != $value && "http://$unsanitized" != $value) {
|
||||
$error = true;
|
||||
if($value && strpos($unsanitized, '%') !== false) {
|
||||
$test = rawurldecode($unsanitized);
|
||||
if($value == $test || $value == "http://$test") $error = false;
|
||||
}
|
||||
if($error) {
|
||||
$this->error($this->name . ': ' . $this->_("Error found - please check that it is a valid URL")); // Error message when invalid URL found
|
||||
}
|
||||
|
||||
} else if($value != $unsanitized && $value == "http://$unsanitized") {
|
||||
$this->message($this->name . ': ' . $this->_("Note that \"http://\" was added")); // Message displayed when http scheme was automatically added to the URL
|
||||
$value = trim((string) $value);
|
||||
$dirty = $value;
|
||||
$label = $this->label ? $this->label : $this->name;
|
||||
|
||||
if(!strlen($dirty)) return '';
|
||||
|
||||
$value = $this->wire()->sanitizer->url($dirty, array(
|
||||
'allowRelative' => $this->noRelative ? false : true,
|
||||
'allowIDN' => $this->allowIDN ? true : false,
|
||||
'stripQuotes' => $this->allowQuotes ? false : true,
|
||||
));
|
||||
|
||||
if(empty($value) || ($dirty !== $value && "http://$dirty" !== $value && "https://$dirty" !== $value)) {
|
||||
$error = true;
|
||||
if(strpos($dirty, '%') !== false) {
|
||||
$test = rawurldecode($dirty);
|
||||
if($value === $test || $value === "http://$test" || $value === "https://$test") $error = false;
|
||||
}
|
||||
if($error) {
|
||||
$this->error("$label - " . $this->_("Error found - please check that it is a valid URL")); // Error message when invalid URL found
|
||||
}
|
||||
|
||||
} else $value = '';
|
||||
} else if($value !== $dirty) {
|
||||
$scheme = '';
|
||||
foreach(array('http', 'https') as $s) {
|
||||
if($value !== "$s://$dirty") continue;
|
||||
$scheme = "$s://";
|
||||
break;
|
||||
}
|
||||
if($scheme) {
|
||||
$this->message("$label - " . sprintf($this->_("Note that %s was added"), $scheme)); // Message displayed when scheme was automatically added to the URL
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Inputfield
|
||||
*
|
||||
* @return InputfieldWrapper
|
||||
*
|
||||
*/
|
||||
public function ___getConfigInputfields() {
|
||||
$inputfields = parent::___getConfigInputfields();
|
||||
$f = $inputfields->get('stripTags');
|
||||
|
Reference in New Issue
Block a user