Webylon 3.2 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • 1c
    • exchange
      • catalog
  • auth
  • Booking
  • building
    • company
  • cart
    • shipping
    • steppedcheckout
  • Catalog
    • monument
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • AjaxUniqueTextField
  • AutocompleteTextField
  • ConfirmedPasswordField
  • CreditCardField
  • CurrencyField
  • CurrencyField_Disabled
  • CurrencyField_Readonly
  • EmailField
  • HtmlEditorConfig
  • HtmlEditorField
  • HtmlEditorField_Readonly
  • HtmlEditorField_Toolbar
  • NumericField
  • PasswordField
  • PhoneNumberField
  • UniqueRestrictedTextField
  • UniqueTextField
  1 <?php
  2 /**
  3  * Shows two password-fields, and checks for matching passwords.
  4  * Optionally hides the fields by default and shows
  5  * a link to toggle their visibility.
  6  * 
  7  * @package forms
  8  * @subpackage fields-formattedinput
  9  */
 10 class ConfirmedPasswordField extends FormField {
 11     
 12     /**
 13      * Minimum character length of the password.
 14      *
 15      * @var int
 16      */
 17     public $minLength = null;
 18     
 19     /**
 20      * Maximum character length of the password.
 21      *
 22      * @var int
 23      */
 24     public $maxLength = null;
 25     
 26     /**
 27      * Enforces at least one digit and one alphanumeric
 28      * character (in addition to {$minLength} and {$maxLength}
 29      *
 30      * @var boolean
 31      */
 32     public $requireStrongPassword = false;
 33     
 34     /**
 35      * Allow empty fields in serverside validation
 36      *
 37      * @var boolean
 38      */
 39     public $canBeEmpty = false;
 40     
 41     /**
 42      * If set to TRUE, the "password" and "confirm password"
 43      * formfields will be hidden via CSS and JavaScript by default,
 44      * and triggered by a link. An additional hidden field
 45      * determines if showing the fields has been triggered,
 46      * and just validates/saves the input in this case.
 47      * This behaviour works unobtrusively, without JavaScript enabled
 48      * the fields show, validate and save by default.
 49      * 
 50      * @param boolean $showOnClick
 51      */
 52     protected $showOnClick = false;
 53     
 54     /**
 55      * Title for the link that triggers
 56      * the visibility of password fields.
 57      *
 58      * @var string
 59      */
 60     public $showOnClickTitle;
 61     
 62     /**
 63      * @param string $name
 64      * @param string $title
 65      * @param mixed $value
 66      * @param Form $form
 67      * @param boolean $showOnClick
 68      * @param string $titleConfirmField Alternate title (not localizeable)
 69      */
 70     function __construct($name, $title = null, $value = "", $form = null, $showOnClick = false, $titleConfirmField = null) {
 71         // naming with underscores to prevent values from actually being saved somewhere
 72         $this->children = new FieldSet(
 73             $pf = new PasswordField(
 74                 "{$name}[_Password]", 
 75                 (isset($title)) ? $title : _t('Member.PASSWORD')),
 76             $cpf = new PasswordField(
 77                 "{$name}[_ConfirmPassword]",
 78                 (isset($titleConfirmField)) ? $titleConfirmField : _t('Member.CONFIRMPASSWORD', 'Confirm Password')
 79             )
 80         );
 81         /*$pf->isConfirmedPasswordField = true;*///~VA - валидация только на второе поле
 82         $cpf->isConfirmedPasswordField = true;
 83         
 84         // has to be called in constructor because Field() isn't triggered upon saving the instance
 85         if($showOnClick) {
 86             $this->children->push(new HiddenField("{$name}[_PasswordFieldVisible]"));
 87         }
 88         $this->showOnClick = $showOnClick;
 89         
 90         // we have labels for the subfields
 91         $title = false;
 92         
 93         parent::__construct($name, $title, null, $form);
 94         $this->setValue($value);
 95     }
 96     
 97     function Field() {      
 98         return $this->renderWith($this->fieldTemplates());
 99     }
100         
101     /**
102      * Can be empty is a flag that turns on/off empty field checking.
103      * For example, set this to false (the default) when creating a user account,
104      * and true 
105      */
106     function setCanBeEmpty($value) {
107         $this->canBeEmpty = (bool)$value;
108     }
109     
110     /**
111      * The title on the link which triggers display of the
112      * "password" and "confirm password" formfields.
113      * Only used if {@link setShowOnClick()} is set to TRUE.
114      * 
115      * @param $title
116      */
117     public function setShowOnClickTitle($title) {
118         $this->showOnClickTitle = $title;
119     }
120     
121     /**
122      * @return string
123      */
124     public function getShowOnClickTitle() {
125         return $this->showOnClickTitle;
126     }
127     
128     function setRightTitle($title) {
129         foreach($this->children as $field) {
130             $field->setRightTitle($title);
131         }
132     }
133     
134     /**
135      * @param array: 2 entrie array with the customised title for each of the 2 children.
136      */
137     function setChildrenTitles($titles) {
138         if(is_array($titles)&&count($titles)==2){
139             foreach($this->children as $field) {
140                 if(isset($titles[0])){
141                     $field->setTitle($titles[0]);
142                     array_shift($titles);       
143                 }
144             }
145         }
146     }
147     
148     /**
149      * Value is sometimes an array, and sometimes a single value, so we need to handle both cases
150      */
151     function setValue($value) {
152         if(is_array($value)) {
153             if($value['_Password'] || (!$value['_Password'] && !$this->canBeEmpty)) {
154                 $this->value = $value['_Password'];
155             }
156             if(isset($value['_PasswordFieldVisible'])){
157                 $this->children->fieldByName($this->Name() . '[_PasswordFieldVisible]')->setValue($value['_PasswordFieldVisible']);
158             }
159         } else {
160             if($value || (!$value && !$this->canBeEmpty)) {
161                 $this->value = $value;
162             }
163         }
164         $this->children->fieldByName($this->Name() . '[_Password]')->setValue($this->value);
165         $this->children->fieldByName($this->Name() . '[_ConfirmPassword]')->setValue($this->value);
166     }
167     
168     function jsValidation() {
169         $formID = $this->form->FormName();
170         $jsTests = '';
171         
172         $jsTests .= "
173             // if fields are hidden, reset values and don't validate
174             var containers = $$('.showOnClickContainer', $('#'+fieldName));
175             if(containers.length && !Element.visible(containers[0])) {
176                 passEl.value = null;
177                 confEl.value = null;
178                 return true;
179             }
180         ";
181 
182         $error1 = _t('ConfirmedPasswordField.HAVETOMATCH', 'Passwords have to match.');
183         $jsTests .= "
184             if(passEl.value != confEl.value) {
185                 validationError(confEl, \"$error1\", \"error\");
186                 return false;
187             }
188         ";
189         
190         $error2 = _t('ConfirmedPasswordField.NOEMPTY', 'Passwords can\'t be empty.');
191         if(!$this->canBeEmpty) {
192             $jsTests .= "
193                 if(!passEl.value || !confEl.value) {
194                     validationError(confEl, \"$error2\", \"error\");
195                     return false;
196                 }
197             ";
198         }
199         
200         if(($this->minLength || $this->maxLength)) {
201             if($this->minLength && $this->maxLength) {
202                 $limit = "{{$this->minLength},{$this->maxLength}}";
203                 $errorMsg = sprintf(_t('ConfirmedPasswordField.BETWEEN', 'Passwords must be %s to %s characters long.'), $this->minLength, $this->maxLength);
204             } elseif($this->minLength) {
205                 $limit = "{{$this->minLength}}.*";
206                 $errorMsg = sprintf(_t('ConfirmedPasswordField.ATLEAST', 'Passwords must be at least %s characters long.'), $this->minLength);
207             } elseif($this->maxLength) {
208                 $limit = "{0,{$this->maxLength}}";
209                 $errorMsg = sprintf(_t('ConfirmedPasswordField.MAXIMUM', 'Passwords must be at most %s characters long.'), $this->maxLength);
210             }
211             $limitRegex = '/^.' . $limit . '$/';
212             $jsTests .= "
213             if(passEl.value && !passEl.value.match({$limitRegex})) {
214                 validationError(confEl, \"{$errorMsg}\", \"error\");
215                 return false;
216             }
217             ";
218         }
219         
220         $error3 = _t('ConfirmedPasswordField.LEASTONE', 'Passwords must have at least one digit and one alphanumeric character.');
221         if($this->requireStrongPassword) {
222             $jsTests .= "
223                 if(!passEl.value.match(/^(([a-zA-Z]+\d+)|(\d+[a-zA-Z]+))[a-zA-Z0-9]*$/)) {
224                     validationError(
225                         confEl, 
226                         \"$error3\", 
227                         \"error\"
228                     );
229                     return false;
230                 }
231             ";
232         }
233         
234         $jsFunc =<<<JS
235 Behaviour.register({
236     "#$formID": {
237         validateConfirmedPassword: function(fieldName) {
238             var passEl = _CURRENT_FORM.elements['Password[_Password]'];
239             var confEl = _CURRENT_FORM.elements['Password[_ConfirmPassword]'];
240             $jsTests
241             return true;
242         }
243     }
244 });
245 JS;
246         Requirements :: customScript($jsFunc, 'func_validateConfirmedPassword_' . $formID);
247         
248         //return "\$('$formID').validateConfirmedPassword('$this->name');";
249         return <<<JS
250 if(typeof fromAnOnBlur != 'undefined'){
251     if(fromAnOnBlur.name == '$this->name')
252         $('$formID').validateConfirmedPassword('$this->name');
253 }else{
254     $('$formID').validateConfirmedPassword('$this->name');
255 }
256 JS;
257     }
258 
259     /**
260      * Determines if the field was actually
261      * shown on the clientside - if not,
262      * we don't validate or save it.
263      * 
264      * @return bool
265      */
266     function isSaveable() {
267         $isVisible = $this->children->fieldByName($this->Name() . '[_PasswordFieldVisible]');
268         return (!$this->showOnClick || ($this->showOnClick && $isVisible && $isVisible->Value()));
269     }
270     
271     function validate() {
272         $validator = $this->form->getValidator();
273         $name = $this->name;
274         
275         // if field isn't visible, don't validate
276         if(!$this->isSaveable()) return true; 
277         
278         $passwordField = $this->children->fieldByName($name.'[_Password]');
279         $passwordConfirmField = $this->children->fieldByName($name.'[_ConfirmPassword]');
280         $passwordField->setValue($_POST[$name]['_Password']);
281         $passwordConfirmField->setValue($_POST[$name]['_ConfirmPassword']);
282         
283         $value = $passwordField->Value();
284         
285         // both password-fields should be the same
286         if($value != $passwordConfirmField->Value()) {
287             $validator->validationError($name, _t('Form.VALIDATIONPASSWORDSDONTMATCH',"Passwords don't match"), "validation", false);
288             return false;
289         }
290 
291         if(!$this->canBeEmpty) {
292             // both password-fields shouldn't be empty
293             if(!$value || !$passwordConfirmField->Value()) {
294                 $validator->validationError($name, _t('Form.VALIDATIONPASSWORDSNOTEMPTY', "Passwords can't be empty"), "validation", false);
295                 return false;
296             }
297         }
298             
299         // lengths
300         if(($this->minLength || $this->maxLength)) {
301             if($this->minLength && $this->maxLength) {
302                 $limit = "{{$this->minLength},{$this->maxLength}}";
303                 $errorMsg = sprintf(_t('ConfirmedPasswordField.BETWEEN', 'Passwords must be %s to %s characters long.'), $this->minLength, $this->maxLength);
304             } elseif($this->minLength) {
305                 $limit = "{{$this->minLength}}.*";
306                 $errorMsg = sprintf(_t('ConfirmedPasswordField.ATLEAST', 'Passwords must be at least %s characters long.'), $this->minLength);
307             } elseif($this->maxLength) {
308                 $limit = "{0,{$this->maxLength}}";
309                 $errorMsg = sprintf(_t('ConfirmedPasswordField.MAXIMUM', 'Passwords must be at most %s characters long.'), $this->maxLength);
310             }
311             $limitRegex = '/^.' . $limit . '$/';
312             if(!empty($value) && !preg_match($limitRegex,$value)) {
313                 $validator->validationError('Password', $errorMsg, 
314                     "validation", 
315                     false
316                 );
317             }
318         }
319         
320         if($this->requireStrongPassword) {
321             if(!preg_match('/^(([a-zA-Z]+\d+)|(\d+[a-zA-Z]+))[a-zA-Z0-9]*$/',$value)) {
322                 $validator->validationError(
323                     'Password', 
324                     _t('Form.VALIDATIONSTRONGPASSWORD', "Passwords must have at least one digit and one alphanumeric character."), 
325                     "validation", 
326                     false
327                 );
328                 return false;
329             }
330         }
331         return true;
332     }
333     
334     /**
335      * Only save if field was shown on the client,
336      * and is not empty.
337      *
338      * @param DataObject $record
339      * @return bool
340      */
341     function saveInto(DataObject $record) {
342         if(!$this->isSaveable()) return false;
343         
344         if(!($this->canBeEmpty && !$this->value)) {
345             parent::saveInto($record);
346         }
347     }
348     
349     /**
350      * Makes a pretty readonly field with some stars in it
351      */
352     function performReadonlyTransformation() {
353         $stars = '*****';
354 
355         $field = new ReadonlyField($this->name, $this->title ? $this->title : _t('Member.PASSWORD'), $stars);
356         $field->setForm($this->form);
357         return $field;
358     }
359 }
360 
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -
Webylon 3.2 API Docs API documentation generated by ApiGen 2.8.0