diff --git a/contrib/smarty/plugins/block.render.php b/contrib/smarty/plugins/block.render.php index 5244ec90c2084139fdce62eba80a57cd80b9a144..23e6b8a72652fae47919f4732cf21282329eb9b5 100644 --- a/contrib/smarty/plugins/block.render.php +++ b/contrib/smarty/plugins/block.render.php @@ -37,7 +37,7 @@ function smarty_block_render ($params, $text) echo '<div style="color:blue;">'.$acl.(isset($params['aclName']) ? ' ['.$params['aclName'].']' : '').'</div>'; } - /* Read / Write*/ + /* Read / Write */ if (preg_match('/w/i', $acl)) { return $text; } diff --git a/html/main.php b/html/main.php index df5cd95a6c81a61d59f0337c60804a2ab4c3a806..aa345adc65b7fbd30d56130760f5cbf60bfdf12a 100644 --- a/html/main.php +++ b/html/main.php @@ -180,7 +180,6 @@ $smarty->assign("date", date("l, dS F Y H:i:s O")); $lang = session::global_get('lang'); $smarty->assign('lang', preg_replace('/_.*$/', '', $lang)); $smarty->assign('rtl', Language::isRTL($lang)); -$smarty->assign('must', '<span class="must">*</span>'); if (isset($plugin_index)) { $plug = "?plug=$plugin_index"; } else { diff --git a/html/setup.php b/html/setup.php index f9ef8a8af5a2831fe48fec79f51d62e0f4b1a280..cd115681d1cf8e78b8c7755380f185f5eb092c42 100644 --- a/html/setup.php +++ b/html/setup.php @@ -89,7 +89,6 @@ Language::init($lang); $smarty->assign('lang', preg_replace('/_.*$/', '', $lang)); $smarty->assign('rtl', Language::isRTL($lang)); -$smarty->assign('must', '<span class="must">*</span>'); /* Minimal config */ if (!session::global_is_set('config')) { diff --git a/html/themes/breezy/less/plugin.less b/html/themes/breezy/less/plugin.less index adf358033ccf6875a4b4060396e289a552c25e03..41c7ee6f750ef46f93103c500c9a220f436344de 100644 --- a/html/themes/breezy/less/plugin.less +++ b/html/themes/breezy/less/plugin.less @@ -214,6 +214,31 @@ html.rtl .plugin-section.invisible { display: none; } +html.ltr .plugin-section, +html.rtl .plugin-section { + &.nonreadable { + display: none; + } + > div > table > tbody > tr { + &.nonreadable { + display: none; + } + &.nonwritable.subattribute { + display: none; + } + &.nonwritable .subattribute { + display: none; + } + &.nonwritable input:disabled { + color: @text-color; + } + &.required > td > label::after { + content: "*"; + color: @warning-red-color; + } + } +} + fieldset.plugin-section.critical legend span, .plugin-section.critical > span.legend { font-weight: bold; diff --git a/html/themes/breezy/less/style.less b/html/themes/breezy/less/style.less index 81a5e7c06d87cbe250242ae0d3913f70caa31d7b..6b909d7a30b5b57ffce90ae7747361cbccb7279f 100644 --- a/html/themes/breezy/less/style.less +++ b/html/themes/breezy/less/style.less @@ -115,10 +115,6 @@ hr { height: 1px; } -.must { - color: @warning-red-color; -} - img.center { text-align: center; vertical-align: middle; diff --git a/html/themes/breezy/plugin.css b/html/themes/breezy/plugin.css index 857e4b3f31928180c6e2cd90df3ea4522dd4f012..c98c5a7813fcfc6e871c4cef325f52d0d3ff4e3a 100644 --- a/html/themes/breezy/plugin.css +++ b/html/themes/breezy/plugin.css @@ -197,6 +197,31 @@ html.ltr .plugin-section.invisible, html.rtl .plugin-section.invisible { display: none; } +html.ltr .plugin-section.nonreadable, +html.rtl .plugin-section.nonreadable { + display: none; +} +html.ltr .plugin-section > div > table > tbody > tr.nonreadable, +html.rtl .plugin-section > div > table > tbody > tr.nonreadable { + display: none; +} +html.ltr .plugin-section > div > table > tbody > tr.nonwritable.subattribute, +html.rtl .plugin-section > div > table > tbody > tr.nonwritable.subattribute { + display: none; +} +html.ltr .plugin-section > div > table > tbody > tr.nonwritable .subattribute, +html.rtl .plugin-section > div > table > tbody > tr.nonwritable .subattribute { + display: none; +} +html.ltr .plugin-section > div > table > tbody > tr.nonwritable input:disabled, +html.rtl .plugin-section > div > table > tbody > tr.nonwritable input:disabled { + color: #31363b; +} +html.ltr .plugin-section > div > table > tbody > tr.required > td > label::after, +html.rtl .plugin-section > div > table > tbody > tr.required > td > label::after { + content: "*"; + color: #dd0000; +} fieldset.plugin-section.critical legend span, .plugin-section.critical > span.legend { font-weight: bold; diff --git a/html/themes/breezy/style.css b/html/themes/breezy/style.css index 71a0edea79a3122f3fc99469a32aca815acd6317..884baf83eab63f5ba40d82aff874b6cba967553e 100644 --- a/html/themes/breezy/style.css +++ b/html/themes/breezy/style.css @@ -110,9 +110,6 @@ hr { background-color: #c0c2c3; height: 1px; } -.must { - color: #dd0000; -} img.center { text-align: center; vertical-align: middle; diff --git a/html/themes/legacy/style.css b/html/themes/legacy/style.css index 4b55e0cb83a4e27afa82354f36b6542217644c4f..caf7aa415f257005ade0c66f496d971802eebf0f 100644 --- a/html/themes/legacy/style.css +++ b/html/themes/legacy/style.css @@ -112,7 +112,9 @@ background-color: #aaa; height: 1px; } -.must { +html.ltr .plugin-section > div > table > tbody > tr.required > td > label::after, +html.rtl .plugin-section > div > table > tbody > tr.required > td > label::after { +content: "*"; color: red; font-family: arial,helvetica,sans-serif; } diff --git a/ihtml/themes/breezy/simpleplugin_section.tpl b/ihtml/themes/breezy/simpleplugin_section.tpl index 0c9b525010bbf53f6717842dbdfdb8906449f241..4909f228e95a2e9f95a1b8f983f7f0f8fc5077eb 100644 --- a/ihtml/themes/breezy/simpleplugin_section.tpl +++ b/ihtml/themes/breezy/simpleplugin_section.tpl @@ -3,7 +3,12 @@ <div> <table> {foreach from=$attributes item=attribute key=id} - <tr> + <tr class=" + {if $attribute.subattribute}subattribute{/if} + {if $attribute.required}required{/if} + {if !$attribute.readable}nonreadable{/if} + {if !$attribute.writable}nonwritable{/if} + "> <td title="{$attribute.description|escape}"><label for="{$attribute.htmlid}">{eval var=$attribute.label}</label></td> <td>{eval var=$attribute.input}</td> </tr> diff --git a/include/class_standAlonePage.inc b/include/class_standAlonePage.inc index 43b22792a31ef079ac176f9d70510247bc0e051f..201e3728a5411a5d7c6cba377acd7dcabdd9229f 100644 --- a/include/class_standAlonePage.inc +++ b/include/class_standAlonePage.inc @@ -163,7 +163,6 @@ class standAlonePage $lang = session::global_get('lang'); $smarty->assign('lang', preg_replace('/_.*$/', '', $lang)); $smarty->assign('rtl', Language::isRTL($lang)); - $smarty->assign('must', '<span class="must">*</span>'); $smarty->assign('usePrototype', 'FALSE'); $smarty->assign('CSRFtoken', CSRFProtection::getToken()); diff --git a/include/class_template.inc b/include/class_template.inc index bbe6875cf1cf9aceb915b7a7ce1ee19b64582ec9..17e9616e2e2b979a4d9e5f088b2e852900b73fbf 100644 --- a/include/class_template.inc +++ b/include/class_template.inc @@ -285,7 +285,9 @@ class template // We assign ACLs so that attributes can use them in their template code $smarty->assign($plugin->attributesAccess[$attr]->getAcl().'ACL', $plugin->aclGetPermissions($plugin->attributesAccess[$attr]->getAcl())); } - $plugin->attributesAccess[$attr]->renderAttribute($attributesRendered, FALSE); + $readable = $plugin->attrIsReadable($attr); + $writable = $plugin->attrIsWriteable($attr); + $plugin->attributesAccess[$attr]->renderAttribute($attributesRendered, FALSE, $readable, $writable); } $smarty->assign('section', $this->tabObject->by_name[$class]); diff --git a/include/simpleplugin/attributes/class_CompositeAttribute.inc b/include/simpleplugin/attributes/class_CompositeAttribute.inc index 4d4a3a211489b9a4c0862b5b481496e8dc763ee3..e8408a3d77938ad6add057f4ce3ffebb1f71e600 100644 --- a/include/simpleplugin/attributes/class_CompositeAttribute.inc +++ b/include/simpleplugin/attributes/class_CompositeAttribute.inc @@ -229,15 +229,15 @@ class CompositeAttribute extends Attribute unset($attribute); } - function renderAttribute (array &$attributes, bool $readOnly) + function renderAttribute (array &$attributes, bool $readOnly, bool $readable, bool $writable) { if ($this->visible) { if ($this->linearRendering) { - parent::renderAttribute($attributes, $readOnly); + parent::renderAttribute($attributes, $readOnly, $readable, $writable); } else { foreach ($this->attributes as &$attribute) { $attribute->setDisabled($this->disabled); - $attribute->renderAttribute($attributes, $readOnly); + $attribute->renderAttribute($attributes, $readOnly, $readable, $writable); } unset($attribute); } diff --git a/include/simpleplugin/attributes/class_FileAttribute.inc b/include/simpleplugin/attributes/class_FileAttribute.inc index 0d760894f4723900a94847d964854d8f74abf1c8..0be6a09e8900b0fb92c4a48273e64b6541dca6ee 100644 --- a/include/simpleplugin/attributes/class_FileAttribute.inc +++ b/include/simpleplugin/attributes/class_FileAttribute.inc @@ -206,12 +206,12 @@ class FileDownloadAttribute extends FileAttribute return $ids; } - function renderAttribute (array &$attributes, bool $readOnly) + function renderAttribute (array &$attributes, bool $readOnly, bool $readable, bool $writable) { if ($this->upload === FALSE) { - parent::renderAttribute($attributes, FALSE); + parent::renderAttribute($attributes, FALSE, $readable, $writable); } else { - parent::renderAttribute($attributes, $readOnly); + parent::renderAttribute($attributes, $readOnly, $readable, $writable); } } } diff --git a/include/simpleplugin/attributes/class_MailsAttribute.inc b/include/simpleplugin/attributes/class_MailsAttribute.inc index ec456257c9d0d4491cccb2c55091d3ff9676c15b..8ce42552247d6178ed5d16e3d13769083b5183d8 100644 --- a/include/simpleplugin/attributes/class_MailsAttribute.inc +++ b/include/simpleplugin/attributes/class_MailsAttribute.inc @@ -97,18 +97,18 @@ class MailsAttribute extends DialogAttribute $id = $this->getHtmlId(); $buttons = $this->renderInputField( 'submit', 'add'.$id, - ['value' => '{msgPool type=addButton}'] + ['value' => '{msgPool type=addButton}', 'class' => 'subattribute'] ); $buttons .= $this->renderInputField( 'submit', 'add'.$id.'_dialog', [ - 'class' => 'dialog', + 'class' => 'dialog subattribute', 'value' => '{msgPool type=addButton} (from list)' ] ); $buttons .= $this->renderInputField( 'submit', 'del'.$id, - ['value' => '{msgPool type=delButton}'] + ['value' => '{msgPool type=delButton}', 'class' => 'subattribute'] ); return $buttons; } diff --git a/include/simpleplugin/attributes/class_SelectAttribute.inc b/include/simpleplugin/attributes/class_SelectAttribute.inc index c1117839df771c38bbe356b6319ce44ba307ccf3..16be00530ed8215024501fc52db4756c1955e240 100644 --- a/include/simpleplugin/attributes/class_SelectAttribute.inc +++ b/include/simpleplugin/attributes/class_SelectAttribute.inc @@ -193,6 +193,9 @@ class SelectAttribute extends Attribute $js = $this->managedAttributesJS(); $display .= 'onChange="javascript:'.htmlentities($js, ENT_COMPAT, 'UTF-8').'"'; } + if ($this->isSubAttribute) { + $display .= 'class="subattribute" '; + } $display .= '>'; $display .= '{html_options values=$'.$id.'_choices output=$'.$id.'_outputs selected=$'.$id.'_selected}'; $display .= '</select>'; diff --git a/include/simpleplugin/attributes/class_SetAttribute.inc b/include/simpleplugin/attributes/class_SetAttribute.inc index 8b4a62241812d9007bad2a99d8c57fee96094941..ae6478572430cf586f3155ee02cb3639381f60ef 100644 --- a/include/simpleplugin/attributes/class_SetAttribute.inc +++ b/include/simpleplugin/attributes/class_SetAttribute.inc @@ -227,26 +227,28 @@ class SetAttribute extends Attribute } } - function renderAttribute (array &$attributes, bool $readOnly) + function renderAttribute (array &$attributes, bool $readOnly, bool $readable, bool $writable) { if ($this->attribute === FALSE) { - return parent::renderAttribute($attributes, $readOnly); + return parent::renderAttribute($attributes, $readOnly, $readable, $writable); } if ($this->visible) { $this->attribute->setDisabled($this->disabled); if ($this->linearRendering || $readOnly) { - parent::renderAttribute($attributes, $readOnly); + parent::renderAttribute($attributes, $readOnly, $readable, $writable); } else { $attributes[$this->getLdapName()] = [ 'htmlid' => $this->getForHtmlId(), - 'label' => '{literal}'.$this->getLabel().'{/literal}'.($this->isRequired() ? '{$must}' : ''), + 'label' => '{literal}'.$this->getLabel().'{/literal}', 'description' => ($this->isRequired() ? sprintf(_("%s (required)"), $this->getDescription()) : $this->getDescription()), 'input' => $this->renderAcl($this->renderOnlyFormInput()), 'subattribute' => $this->isSubAttribute, 'required' => $this->isRequired(), + 'readable' => $readable, + 'writable' => $writable, ]; $this->handleEditingValue(); - $this->attribute->renderAttribute($attributes, $readOnly); + $this->attribute->renderAttribute($attributes, $readOnly, $acl); $attributes[$this->getLdapName().'_buttons'] = [ 'htmlid' => 'add'.$this->getHtmlId(), 'label' => '', @@ -254,6 +256,8 @@ class SetAttribute extends Attribute 'input' => $this->renderAcl($this->renderButtons()), 'subattribute' => TRUE, 'required' => FALSE, + 'readable' => $readable, + 'writable' => $writable, ]; } } @@ -289,8 +293,8 @@ class SetAttribute extends Attribute function renderButtons () { $id = $this->getHtmlId(); - $buttons = $this->renderInputField('submit', 'add'.$id, ['value' => '{msgPool type=addButton}', 'formnovalidate' => 'formnovalidate']); - $buttons .= $this->renderInputField('submit', 'del'.$id, ['value' => '{msgPool type=delButton}', 'formnovalidate' => 'formnovalidate']); + $buttons = $this->renderInputField('submit', 'add'.$id, ['value' => '{msgPool type=addButton}', 'formnovalidate' => 'formnovalidate', 'class' => 'subattribute']); + $buttons .= $this->renderInputField('submit', 'del'.$id, ['value' => '{msgPool type=delButton}', 'formnovalidate' => 'formnovalidate', 'class' => 'subattribute']); return $buttons; } @@ -667,7 +671,7 @@ class OrderedArrayAttribute extends SetAttribute function renderButtons () { $id = $this->getHtmlId(); - $buttons = $this->renderInputField('submit', 'add'.$id, ['value' => '{msgPool type=addButton}', 'formnovalidate' => 'formnovalidate']); + $buttons = $this->renderInputField('submit', 'add'.$id, ['value' => '{msgPool type=addButton}', 'formnovalidate' => 'formnovalidate', 'class' => 'subattribute']); return $buttons; } } diff --git a/include/simpleplugin/class_Attribute.inc b/include/simpleplugin/class_Attribute.inc index 65161d69a54a90be238cb4521d5804387ea00a0b..828cc735a7976cc006608f2e71ad11519ca5f078 100644 --- a/include/simpleplugin/class_Attribute.inc +++ b/include/simpleplugin/class_Attribute.inc @@ -583,8 +583,12 @@ class Attribute * \param array &$attributes the attributes array * * \param bool $readOnly should we show text or input + * + * \param bool $readable ACL read + * + * \param bool $writable ACL write */ - function renderAttribute (array &$attributes, bool $readOnly) + function renderAttribute (array &$attributes, bool $readOnly, bool $readable, bool $writable) { if ($this->visible) { if ($readOnly) { @@ -607,11 +611,13 @@ class Attribute } $attributes[$this->getLdapName()] = [ 'htmlid' => $this->getForHtmlId(), - 'label' => '{literal}'.$this->getLabel().'{/literal}'.($this->isRequired() ? '{$must}' : ''), + 'label' => '{literal}'.$this->getLabel().'{/literal}', 'description' => ($this->isRequired() ? sprintf(_("%s (required)"), $this->getDescription()) : $this->getDescription()), 'input' => $input, 'subattribute' => $this->isSubAttribute, 'required' => $this->isRequired(), + 'readable' => $readable, + 'writable' => $writable, ]; } } @@ -824,7 +830,7 @@ class FakeAttribute extends Attribute $this->setInLdap(FALSE); } - function renderAttribute (array &$attributes, bool $readOnly) + function renderAttribute (array &$attributes, bool $readOnly, bool $readable, bool $writable) { $attributes[$this->getLdapName()] = $this->getValue(); } diff --git a/include/simpleplugin/class_dialogAttributes.inc b/include/simpleplugin/class_dialogAttributes.inc index 45877e45d3209cbae9230de2a5e1733f0fc9f5df..dd5f3f57bd128bf259085f7d5edbcb1cab9d25c8 100644 --- a/include/simpleplugin/class_dialogAttributes.inc +++ b/include/simpleplugin/class_dialogAttributes.inc @@ -200,13 +200,14 @@ abstract class DialogAttribute extends SetAttribute if ($this->isTemplate()) { $buttons .= $this->renderInputField( 'text', $id, - ['value' => $this->editingValue] + ['value' => $this->editingValue, 'class' => 'subattribute'] ); $buttons .= $this->renderInputField( 'submit', 'add'.$id, [ 'value' => '{msgPool type=addButton}', - 'formnovalidate' => 'formnovalidate' + 'formnovalidate' => 'formnovalidate', + 'class' => 'subattribute', ] ); $dialogButtonValue = _('Add (dialog)'); @@ -214,16 +215,17 @@ abstract class DialogAttribute extends SetAttribute $buttons .= $this->renderInputField( 'submit', 'add'.$id.'_dialog', [ - 'class' => 'dialog', + 'class' => 'dialog subattribute', 'value' => $dialogButtonValue, - 'formnovalidate' => 'formnovalidate' + 'formnovalidate' => 'formnovalidate', ] ); $buttons .= $this->renderInputField( 'submit', 'del'.$id, [ 'value' => '{msgPool type=delButton}', - 'formnovalidate' => 'formnovalidate' + 'formnovalidate' => 'formnovalidate', + 'class' => 'subattribute', ] ); return $buttons; @@ -294,7 +296,7 @@ abstract class DialogOrderedArrayAttribute extends OrderedArrayAttribute return $this->renderInputField( 'submit', 'add'.$id.'_dialog', [ - 'class' => 'dialog', + 'class' => 'dialog subattribute', 'value' => '{msgPool type=addButton}', 'formnovalidate' => 'formnovalidate' ] diff --git a/include/simpleplugin/class_simplePlugin.inc b/include/simpleplugin/class_simplePlugin.inc index 940604f8362a407d465741d07effc93c168e513b..a1f0164d77fec3d5556735178e2717ddd6206a92 100644 --- a/include/simpleplugin/class_simplePlugin.inc +++ b/include/simpleplugin/class_simplePlugin.inc @@ -785,6 +785,21 @@ class simplePlugin implements SimpleTab return $display; } + /*! \brief Check if logged in user have enough right to read this attribute value + * + * \param mixed $attr Attribute object or name (in this case it will be fetched from attributesAccess) + */ + function attrIsReadable ($attr): bool + { + if (!is_object($attr)) { + $attr = $this->attributesAccess[$attr]; + } + if ($attr->getLdapName() == 'base') { + return TRUE; + } + return $this->acl_is_readable($attr->getAcl()); + } + /*! \brief Check if logged in user have enough right to write this attribute value * * \param mixed $attr Attribute object or name (in this case it will be fetched from attributesAccess) @@ -852,20 +867,29 @@ class simplePlugin implements SimpleTab } $smarty->assign("section", $legend); $smarty->assign("sectionId", $section); + $sectionClasses = ''; if (isset($sectionInfo['class'])) { - $smarty->assign("sectionClasses", ' '.join(' ', $sectionInfo['class'])); - } else { - $smarty->assign("sectionClasses", ''); + $sectionClasses .= ' '.join(' ', $sectionInfo['class']); } - $attributes = []; + $attributes = []; + $readableSection = FALSE; foreach ($sectionInfo['attrs'] as $attr) { if ($attr->getAclInfo() !== FALSE) { // We assign ACLs so that attributes can use them in their template code - $smarty->assign($attr->getAcl()."ACL", $this->aclGetPermissions($attr->getAcl(), NULL, $this->acl_skip_write())); + $smarty->assign($attr->getAcl().'ACL', $this->aclGetPermissions($attr->getAcl(), NULL, $this->acl_skip_write())); + } + $readable = $this->attrIsReadable($attr); + $writable = $this->attrIsWriteable($attr); + if (!$readableSection && ($readable || $writable)) { + $readableSection = TRUE; } - $attr->renderAttribute($attributes, $readOnly); + $attr->renderAttribute($attributes, $readOnly, $readable, $writable); + } + $smarty->assign('attributes', $attributes); + if (!$readableSection) { + $sectionClasses .= ' nonreadable'; } - $smarty->assign("attributes", $attributes); + $smarty->assign('sectionClasses', $sectionClasses); // We fetch each section with the section template if (isset($sectionInfo['template'])) { $displaySection = $smarty->fetch($sectionInfo['template']); @@ -923,7 +947,7 @@ class simplePlugin implements SimpleTab /*! \brief Can we write the attribute */ function acl_is_writeable ($attribute, bool $skipWrite = FALSE): bool { - return preg_match('/w/', $this->aclGetPermissions($attribute, NULL, $skipWrite)); + return (strpos($this->aclGetPermissions($attribute, NULL, $skipWrite), 'w') !== FALSE); } /*! @@ -933,7 +957,7 @@ class simplePlugin implements SimpleTab */ function acl_is_readable ($attribute): bool { - return preg_match('/r/', $this->aclGetPermissions($attribute)); + return (strpos($this->aclGetPermissions($attribute), 'r') !== FALSE); } /*! @@ -943,7 +967,7 @@ class simplePlugin implements SimpleTab */ function acl_is_createable (string $base = NULL): bool { - return preg_match('/c/', $this->aclGetPermissions('0', $base)); + return (strpos($this->aclGetPermissions('0', $base), 'c') !== FALSE); } /*! @@ -953,7 +977,7 @@ class simplePlugin implements SimpleTab */ function acl_is_removeable (string $base = NULL): bool { - return preg_match('/d/', $this->aclGetPermissions('0', $base)); + return (strpos($this->aclGetPermissions('0', $base), 'd') !== FALSE); } /*! @@ -963,7 +987,7 @@ class simplePlugin implements SimpleTab */ function acl_is_moveable (string $base = NULL): bool { - return preg_match('/m/', $this->aclGetPermissions('0', $base)); + return (strpos($this->aclGetPermissions('0', $base), 'm') !== FALSE); } /*! \brief Get the acl permissions for an attribute or the plugin itself */ diff --git a/plugins/personal/generic/class_UserPasswordAttribute.inc b/plugins/personal/generic/class_UserPasswordAttribute.inc index 607d2b59646c796d22247498cce688f99dfcf14e..7b73efaa96a729f415b5c87f35ca1c67c9271aef 100644 --- a/plugins/personal/generic/class_UserPasswordAttribute.inc +++ b/plugins/personal/generic/class_UserPasswordAttribute.inc @@ -88,12 +88,12 @@ class UserPasswordAttribute extends CompositeAttribute } /* We need to handle method select disabling manually */ - function renderAttribute (array &$attributes, bool $readOnly) + function renderAttribute (array &$attributes, bool $readOnly, bool $readable, bool $writable) { global $config; if ($this->visible) { if ($this->linearRendering) { - parent::renderAttribute($attributes, $readOnly); + parent::renderAttribute($attributes, $readOnly, $readable, $writable); } else { foreach ($this->attributes as $key => &$attribute) { if (is_object($this->plugin) && $this->plugin->is_template && ($key == 2)) { @@ -105,7 +105,7 @@ class UserPasswordAttribute extends CompositeAttribute } else { $attribute->setDisabled($this->disabled); } - $attribute->renderAttribute($attributes, $readOnly); + $attribute->renderAttribute($attributes, $readOnly, $readable, $writable); } unset($attribute); }