mirror of
https://github.com/processwire/processwire.git
synced 2025-08-27 00:25:05 +02:00
Upgrade Inputfield and InputfieldWrapper base classes to support new getting, setting, and traversal methods. Plus a new $inputfields->new() method that lets you create a new Inputfield and add it to the wrapper in one step.
This commit is contained in:
@@ -45,6 +45,10 @@
|
||||
* @property mixed $value HTML 'value' attribute for the Inputfield. #pw-group-attribute-properties
|
||||
* @property string $class HTML 'class' attribute for the Inputfield. #pw-group-attribute-properties
|
||||
*
|
||||
* @method string|Inputfield name($name = null) Get or set the name attribute. @since 3.0.110 #pw-group-attribute-methods
|
||||
* @method string|Inputfield id($id = null) Get or set the id attribute. @since 3.0.110 #pw-group-attribute-methods
|
||||
* @method string|Inputfield class($class = null) Get class attribute or add a class to the class attribute. @since 3.0.110 #pw-group-attribute-methods
|
||||
*
|
||||
* LABELS & CONTENT
|
||||
* ================
|
||||
* @property string $label Primary label text that appears above the input. #pw-group-labels
|
||||
@@ -56,6 +60,15 @@
|
||||
* @property string|null $prependMarkup Optional markup to prepend to the Inputfield content container. #pw-group-other
|
||||
* @property string|null $appendMarkup Optional markup to append to the Inputfield content container. #pw-group-other
|
||||
*
|
||||
* @method string|Inputfield label($label = null) Get or set the 'label' property via method. @since 3.0.110 #pw-group-labels
|
||||
* @method string|Inputfield description($description = null) Get or set the 'description' property via method. @since 3.0.110 #pw-group-labels
|
||||
* @method string|Inputfield notes($notes = null) Get or set the 'notes' property via method. @since 3.0.110 #pw-group-labels
|
||||
* @method string|Inputfield icon($icon = null) Get or set the 'icon' property via method. @since 3.0.110 #pw-group-labels
|
||||
* @method string|Inputfield requiredLabel($requiredLabel = null) Get or set the 'requiredLabel' property via method. @since 3.0.110 #pw-group-labels
|
||||
* @method string|Inputfield head($head = null) Get or set the 'head' property via method. @since 3.0.110 #pw-group-labels
|
||||
* @method string|Inputfield prependMarkup($markup = null) Get or set the 'prependMarkup' property via method. @since 3.0.110 #pw-group-labels
|
||||
* @method string|Inputfield appendMarkup($markup = null) Get or set the 'appendMarkup' property via method. @since 3.0.110 #pw-group-labels
|
||||
*
|
||||
* APPEARANCE
|
||||
* ==========
|
||||
* @property int $collapsed Whether the field is collapsed or visible, using one of the "collapsed" constants. #pw-group-appearance
|
||||
@@ -63,6 +76,12 @@
|
||||
* @property int $columnWidth Width of column for this Inputfield 10-100 percent. 0 is assumed to be 100 (default). #pw-group-appearance
|
||||
* @property int $skipLabel Skip display of the label? See the "skipLabel" constants for options. #pw-group-appearance
|
||||
*
|
||||
* @method int|Inputfield collapsed($collapsed = null) Get or set collapsed property via method. @since 3.0.110 #pw-group-appearance
|
||||
* @method string|Inputfield showIf($showIf = null) Get or set showIf selector property via method. @since 3.0.110 #pw-group-appearance
|
||||
* @method int|Inputfield columnWidth($columnWidth = null) Get or set columnWidth property via method. @since 3.0.110 #pw-group-appearance
|
||||
* @method int|Inputfield skipLabel($skipLabel = null) Get or set the skipLabel constant property via method. @since 3.0.110 #pw-group-appearance
|
||||
*
|
||||
*
|
||||
* SETTINGS & BEHAVIOR
|
||||
* ===================
|
||||
* @property int|bool $required Set to true (or 1) to make input required, or false (or 0) to make not required (default=0). #pw-group-behavior
|
||||
@@ -78,6 +97,14 @@
|
||||
* @property string $wrapClass Optional class name (CSS) to apply to the HTML element wrapping the Inputfield. #pw-group-other
|
||||
* @property string $headerClass Optional class name (CSS) to apply to the InputfieldHeader element #pw-group-other
|
||||
* @property string $contentClass Optional class name (CSS) to apply to the InputfieldContent element #pw-group-other
|
||||
*
|
||||
* @method string|Inputfield required($required = null) Get or set required state. @since 3.0.110 #pw-group-behavior
|
||||
* @method string|Inputfield requiredIf($requiredIf = null) Get or set required-if selector. @since 3.0.110 #pw-group-behavior
|
||||
*
|
||||
* @method string|Inputfield wrapClass($class = null) Get wrapper class attribute or add a class to it. @since 3.0.110 #pw-group-other
|
||||
* @method string|Inputfield headerClass($class = null) Get header class attribute or add a class to it. @since 3.0.110 #pw-group-other
|
||||
* @method string|Inputfield contentClass($class = null) Get content class attribute or add a class to it. @since 3.0.110 #pw-group-other
|
||||
*
|
||||
*
|
||||
* HOOKABLE METHODS
|
||||
* ================
|
||||
@@ -305,7 +332,7 @@ abstract class Inputfield extends WireData implements Module {
|
||||
|
||||
self::$numInstances++;
|
||||
|
||||
$this->set('label', ''); // primary clikable label
|
||||
$this->set('label', ''); // primary clickable label
|
||||
$this->set('description', ''); // descriptive copy, below label
|
||||
$this->set('icon', ''); // optional icon name to accompany label
|
||||
$this->set('notes', ''); // highlighted descriptive copy, below output of input field
|
||||
@@ -321,6 +348,8 @@ abstract class Inputfield extends WireData implements Module {
|
||||
$this->set('contentClass', ''); // optional class to apply to InputfieldContent wrapper
|
||||
$this->set('textFormat', self::textFormatBasic); // format applied to description and notes
|
||||
$this->set('renderValueFlags', 0); // see renderValue* constants, applicable to renderValue mode only
|
||||
$this->set('prependMarkup', '');
|
||||
$this->set('appendMarkup', '');
|
||||
|
||||
// default ID attribute if no 'id' attribute set
|
||||
$this->defaultID = $this->className() . self::$numInstances;
|
||||
@@ -463,6 +492,9 @@ abstract class Inputfield extends WireData implements Module {
|
||||
*
|
||||
*/
|
||||
public function setParent(InputfieldWrapper $parent) {
|
||||
if($this->parent && $this->parent instanceof InputfieldWrapper && $this->parent !== $parent) {
|
||||
$this->parent->remove($this);
|
||||
}
|
||||
$this->parent = $parent;
|
||||
return $this;
|
||||
}
|
||||
@@ -497,6 +529,47 @@ abstract class Inputfield extends WireData implements Module {
|
||||
return $parents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set parent of Inputfield
|
||||
*
|
||||
* This convenience method performs the same thing as getParent() and setParent().
|
||||
*
|
||||
* To get parent, specify no arguments. It will return null if no parent assigned, or an
|
||||
* InputfieldWrapper instance of the parent.
|
||||
*
|
||||
* To set parent, specify an InputfieldWrapper for the $parent argument. The return value
|
||||
* is the current Inputfield for fluent interface.
|
||||
*
|
||||
* #pw-group-traversal
|
||||
*
|
||||
* @param null|InputfieldWrapper $parent
|
||||
* @return null|Inputfield|InputfieldWrapper
|
||||
* @since 3.0.110
|
||||
*
|
||||
*/
|
||||
public function parent($parent = null) {
|
||||
if($parent === null) {
|
||||
return $this->getParent();
|
||||
} else {
|
||||
return $this->setParent($parent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of all parents of this Inputfield
|
||||
*
|
||||
* This is identical to and an alias of the getParents() method.
|
||||
*
|
||||
* #pw-group-traversal
|
||||
*
|
||||
* @return array
|
||||
* @since 3.0.110
|
||||
*
|
||||
*/
|
||||
public function parents() {
|
||||
return $this->getParents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root parent InputfieldWrapper element (farthest parent, commonly InputfieldForm)
|
||||
*
|
||||
@@ -715,6 +788,39 @@ abstract class Inputfield extends WireData implements Module {
|
||||
return $this->setAttribute('value', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* If method call resulted in no handler, this hookable method is called.
|
||||
*
|
||||
* We use this to allow for attributes and properties to be set via method, useful primarily
|
||||
* for fluent interface calls.
|
||||
*
|
||||
* #pw-internal
|
||||
*
|
||||
* @param string $method Requested method name
|
||||
* @param array $arguments Arguments provided
|
||||
* @return null|mixed Return value of method (if applicable)
|
||||
* @throws WireException
|
||||
* @since 3.0.110
|
||||
*
|
||||
*/
|
||||
protected function ___callUnknown($method, $arguments) {
|
||||
$arg = isset($arguments[0]) ? $arguments[0] : null;
|
||||
if(isset($this->attributes[$method])) {
|
||||
// get or set an attribute
|
||||
return $arg === null ? $this->getAttribute($method) : $this->setAttribute($method, $arg);
|
||||
} else if(($value = $this->getSetting($method)) !== null) {
|
||||
// get or set a setting
|
||||
if($arg === null) return $value;
|
||||
if(stripos($method, 'class') !== false) {
|
||||
// i.e. class, wrapClass, contentClass, etc.
|
||||
return $this->addClass($arg, $method);
|
||||
} else {
|
||||
return $this->set($method, $arg);
|
||||
}
|
||||
}
|
||||
return parent::___callUnknown($method, $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all attributes specified for this Inputfield
|
||||
*
|
||||
|
@@ -24,6 +24,7 @@
|
||||
* @property InputfieldsArray|null $children Inputfield instances that are direct children of this InputfieldWrapper. #pw-group-properties
|
||||
*
|
||||
* @method string renderInputfield(Inputfield $inputfield, $renderValueMode = false) #pw-group-output
|
||||
* @method Inputfield new($typeName, $name = '', $label = '', array $settings = array()) #pw-group-manipulation
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -185,23 +186,87 @@ class InputfieldWrapper extends Inputfield implements \Countable, \IteratorAggre
|
||||
/**
|
||||
* Add an Inputfield item as a child (also accepts array definition)
|
||||
*
|
||||
* Since 3.0.110: If given a string value, it is assumed to be an Inputfield type that you
|
||||
* want to add. In that case, it will create the Inputfield and return it instead of $this.
|
||||
*
|
||||
* #pw-group-manipulation
|
||||
*
|
||||
* @param Inputfield|array $item
|
||||
* @return $this
|
||||
* @param Inputfield|array|string $item
|
||||
* @return Inputfield|InputfieldWrapper|$this
|
||||
* @see InputfieldWrapper::import()
|
||||
*
|
||||
*/
|
||||
public function add($item) {
|
||||
if(is_array($item)) {
|
||||
if(is_string($item)) {
|
||||
return $this->___new($item);
|
||||
} else if(is_array($item)) {
|
||||
$this->importArray($item);
|
||||
} else {
|
||||
$item->setParent($this);
|
||||
$this->children->add($item);
|
||||
$item->setParent($this);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Inputfield, add it to this InputfieldWrapper, and return the new Inputfield
|
||||
*
|
||||
* - Only the $typeName argument is required.
|
||||
* - You may optionally substitute the $settings argument for the $name or $label arguments.
|
||||
* - You may optionally substitute Inputfield “description” property for $settings argument.
|
||||
*
|
||||
* #pw-group-manipulation
|
||||
*
|
||||
* @param string $typeName Inputfield type, i.e. “InputfieldCheckbox” or just “checkbox” for short.
|
||||
* @param string|array $name Name of input (or substitute $settings here).
|
||||
* @param string|array $label Label for input (or substitute $settings here).
|
||||
* @param array|string $settings Settings to add to Inputfield (optional). Or if string, assumed to be “description”.
|
||||
* @return Inputfield|InputfieldSelect|InputfieldWrapper An Inputfield instance ready to populate with additional properties/attributes.
|
||||
* @throws WireException If you request an unknown Inputfield type
|
||||
* @since 3.0.110
|
||||
*
|
||||
*/
|
||||
public function ___new($typeName, $name = '', $label = '', $settings = array()) {
|
||||
|
||||
if(is_array($name)) {
|
||||
$settings = $name;
|
||||
$name = '';
|
||||
} else if(is_array($label)) {
|
||||
$settings = $label;
|
||||
$label = '';
|
||||
}
|
||||
|
||||
if(strpos($typeName, 'Inputfield') !== 0) {
|
||||
$typeName = "Inputfield" . ucfirst($typeName);
|
||||
}
|
||||
|
||||
/** @var Inputfield|InputfieldSelect|InputfieldWrapper $inputfield */
|
||||
$inputfield = $this->wire('modules')->getModule($typeName);
|
||||
|
||||
if(!$inputfield && wireClassExists($typeName)) {
|
||||
$inputfield = $this->wire(new $typeName());
|
||||
}
|
||||
|
||||
if(!$inputfield || !$inputfield instanceof Inputfield) {
|
||||
throw new WireException("Unknown Inputfield type: $typeName");
|
||||
}
|
||||
|
||||
if(strlen($name)) $inputfield->attr('name', $name);
|
||||
if(strlen($label)) $inputfield->label = $label;
|
||||
|
||||
if(is_array($settings)) {
|
||||
foreach($settings as $key => $value) {
|
||||
$inputfield->set($key, $value);
|
||||
}
|
||||
} else if(is_string($settings)) {
|
||||
$inputfield->description = $settings;
|
||||
}
|
||||
|
||||
$this->add($inputfield);
|
||||
|
||||
return $inputfield;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the given Inputfield items as children
|
||||
*
|
||||
@@ -941,6 +1006,61 @@ class InputfieldWrapper extends Inputfield implements \Countable, \IteratorAggre
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an Inputfield below this one that has the given name
|
||||
*
|
||||
* This is an alternative to the `getChildByName()` method, with more options for when you need it.
|
||||
* For instance, it can also accept a selector string or numeric index for the $name argument, and you
|
||||
* can optionally disable the $recursive behavior.
|
||||
*
|
||||
* #pw-group-retrieval-and-traversal
|
||||
*
|
||||
* @param string|int $name Name or selector string of child to find, omit for first child, or specify zero-based index of child to return.
|
||||
* @param bool $recursive Find child recursively? Looks for child in this wrapper, and all other wrappers below it. (default=true)
|
||||
* @return Inputfield|null Returns Inputfield instance if found, or null if not.
|
||||
* @since 3.0.110
|
||||
*
|
||||
*/
|
||||
public function child($name = '', $recursive = true) {
|
||||
$child = null;
|
||||
|
||||
if(!$this->children->count()) {
|
||||
// no child possible
|
||||
|
||||
} else if(empty($name)) {
|
||||
// first child
|
||||
$child = $this->children->first();
|
||||
|
||||
} else if(is_int($name)) {
|
||||
// number index
|
||||
$child = $this->children->eq($name);
|
||||
|
||||
} else if($this->wire('sanitizer')->name($name) === $name) {
|
||||
// child by name
|
||||
$wrappers = array();
|
||||
foreach($this->children as $f) {
|
||||
if($f->getAttribute('name') === $name) {
|
||||
$child = $f;
|
||||
break;
|
||||
} else if($recursive && $f instanceof InputfieldWrapper) {
|
||||
$wrappers[] = $f;
|
||||
}
|
||||
}
|
||||
if(!$child && $recursive && count($wrappers)) {
|
||||
foreach($wrappers as $wrapper) {
|
||||
$child = $wrapper->child($name, $recursive);
|
||||
if($child) break;
|
||||
}
|
||||
}
|
||||
|
||||
} else if(Selectors::stringHasSelector($name)) {
|
||||
// first child matching selector string
|
||||
$child = $this->children("$name, limit=1")->first();
|
||||
}
|
||||
|
||||
return $child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all children Inputfields (alias of children method)
|
||||
*
|
||||
|
Reference in New Issue
Block a user