diff --git a/wire/modules/Inputfield/InputfieldButton.module b/wire/modules/Inputfield/InputfieldButton.module index 1afa744f..2969c430 100644 --- a/wire/modules/Inputfield/InputfieldButton.module +++ b/wire/modules/Inputfield/InputfieldButton.module @@ -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 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() { diff --git a/wire/modules/Inputfield/InputfieldEmail.module b/wire/modules/Inputfield/InputfieldEmail.module index 0a046031..6ee8d879 100644 --- a/wire/modules/Inputfield/InputfieldEmail.module +++ b/wire/modules/Inputfield/InputfieldEmail.module @@ -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 diff --git a/wire/modules/Inputfield/InputfieldFieldset.module b/wire/modules/Inputfield/InputfieldFieldset.module index 24c5571a..6eabd0b5 100644 --- a/wire/modules/Inputfield/InputfieldFieldset.module +++ b/wire/modules/Inputfield/InputfieldFieldset.module @@ -1,16 +1,41 @@ 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 diff --git a/wire/modules/Inputfield/InputfieldFloat.module b/wire/modules/Inputfield/InputfieldFloat.module index f5416ee9..93979a21 100644 --- a/wire/modules/Inputfield/InputfieldFloat.module +++ b/wire/modules/Inputfield/InputfieldFloat.module @@ -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 diff --git a/wire/modules/Inputfield/InputfieldForm.module b/wire/modules/Inputfield/InputfieldForm.module index 7c49a105..cebb555b 100644 --- a/wire/modules/Inputfield/InputfieldForm.module +++ b/wire/modules/Inputfield/InputfieldForm.module @@ -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) { diff --git a/wire/modules/Inputfield/InputfieldHidden.module b/wire/modules/Inputfield/InputfieldHidden.module index 0642f3a6..5a31c3fc 100644 --- a/wire/modules/Inputfield/InputfieldHidden.module +++ b/wire/modules/Inputfield/InputfieldHidden.module @@ -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 "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.'); diff --git a/wire/modules/Inputfield/InputfieldInteger.module b/wire/modules/Inputfield/InputfieldInteger.module index ecc4f379..205ace03 100644 --- a/wire/modules/Inputfield/InputfieldInteger.module +++ b/wire/modules/Inputfield/InputfieldInteger.module @@ -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" diff --git a/wire/modules/Inputfield/InputfieldMarkup.module b/wire/modules/Inputfield/InputfieldMarkup.module index aa6a1fb0..21aef816 100644 --- a/wire/modules/Inputfield/InputfieldMarkup.module +++ b/wire/modules/Inputfield/InputfieldMarkup.module @@ -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 = "

{$description}

$out"; + $out = "

$description

$out"; } else if($textFormat == Inputfield::textFormatMarkdown) { $out = "
" . $this->entityEncode($description, Inputfield::textFormatMarkdown) . "
$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); diff --git a/wire/modules/Inputfield/InputfieldName.module b/wire/modules/Inputfield/InputfieldName.module index 6e747273..a8d2997b 100644 --- a/wire/modules/Inputfield/InputfieldName.module +++ b/wire/modules/Inputfield/InputfieldName.module @@ -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; } diff --git a/wire/modules/Inputfield/InputfieldSelect.module b/wire/modules/Inputfield/InputfieldSelect.module index a4ed7c6a..25190e2e 100644 --- a/wire/modules/Inputfield/InputfieldSelect.module +++ b/wire/modules/Inputfield/InputfieldSelect.module @@ -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 ""; - - 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 .= "
  • " . $this->wire('sanitizer')->entities($o) . "
  • "; + $out .= "
  • " . $sanitizer->entities($o) . "
  • "; } } - if(strlen($out)) $out = ""; + if(strlen($out)) { + $out = ""; + } 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 = ''; diff --git a/wire/modules/Inputfield/InputfieldSelectMultiple.module b/wire/modules/Inputfield/InputfieldSelectMultiple.module index e4840949..37e16fba 100644 --- a/wire/modules/Inputfield/InputfieldSelectMultiple.module +++ b/wire/modules/Inputfield/InputfieldSelectMultiple.module @@ -1,18 +1,45 @@ `. + * 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; } - - } diff --git a/wire/modules/Inputfield/InputfieldTextarea.module b/wire/modules/Inputfield/InputfieldTextarea.module index 289539d1..bff42c15 100644 --- a/wire/modules/Inputfield/InputfieldTextarea.module +++ b/wire/modules/Inputfield/InputfieldTextarea.module @@ -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 ""; - 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 = "
    " . - $this->wire('sanitizer')->purify($this->attr('value')) . "
    "; + if($this->isContentTypeHTML()) { + $out = + "
    " . + $this->wire()->sanitizer->purify($this->val()) . + "
    "; } 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')); } diff --git a/wire/modules/Inputfield/InputfieldURL.module b/wire/modules/Inputfield/InputfieldURL.module index 3f31afdc..52ee962b 100644 --- a/wire/modules/Inputfield/InputfieldURL.module +++ b/wire/modules/Inputfield/InputfieldURL.module @@ -1,9 +1,12 @@ __('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');