diff --git a/_config/requestprocessors.yml b/_config/requestprocessors.yml new file mode 100644 index 000000000..1e9310bd3 --- /dev/null +++ b/_config/requestprocessors.yml @@ -0,0 +1,8 @@ +--- +Name: requestprocessors +--- +Injector: + RequestProcessor: + properties: + filters: + - '%$VersionedRequestFilter' diff --git a/admin/code/AdminRootController.php b/admin/code/AdminRootController.php index 765500c03..77a394ce6 100644 --- a/admin/code/AdminRootController.php +++ b/admin/code/AdminRootController.php @@ -1,5 +1,9 @@ * - * @package cms - * @subpackage batchaction + * @package framework + * @subpackage admin */ abstract class CMSBatchAction extends Object { diff --git a/admin/code/CMSBatchActionHandler.php b/admin/code/CMSBatchActionHandler.php index d3229e694..a8854e662 100644 --- a/admin/code/CMSBatchActionHandler.php +++ b/admin/code/CMSBatchActionHandler.php @@ -3,8 +3,8 @@ /** * Special request handler for admin/batchaction * - * @package cms - * @subpackage batchaction + * @package framework + * @subpackage admin */ class CMSBatchActionHandler extends RequestHandler { diff --git a/admin/code/CMSForm.php b/admin/code/CMSForm.php index a03d51178..39641a95c 100644 --- a/admin/code/CMSForm.php +++ b/admin/code/CMSForm.php @@ -1,6 +1,11 @@ setCurrentPageID(Member::currentUserID()); $form = parent::getEditForm($id, $fields); - if($form instanceof SS_HTTPResponse) return $form; + if($form instanceof SS_HTTPResponse) { + return $form; + } + $form->Fields()->removeByName('LastVisited'); $form->Fields()->push(new HiddenField('ID', null, Member::currentUserID())); $form->Actions()->push( @@ -32,11 +40,21 @@ class CMSProfileController extends LeftAndMain { ->setAttribute('data-icon', 'accept') ->setUseButtonTag(true) ); + $form->Actions()->removeByName('action_delete'); - $form->setValidator(new Member_Validator()); $form->setTemplate('Form'); $form->setAttribute('data-pjax-fragment', null); - if($form->Fields()->hasTabset()) $form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet'); + + if($member = Member::currentUser()) { + $form->setValidator($member->getValidator()); + } else { + $form->setValidator(Injector::inst()->get('Member')->getValidator()); + } + + if($form->Fields()->hasTabset()) { + $form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet'); + } + $form->addExtraClass('member-profile-form root-form cms-edit-form cms-panel-padded center'); return $form; diff --git a/admin/code/GroupImportForm.php b/admin/code/GroupImportForm.php index e4271f002..a544e8373 100644 --- a/admin/code/GroupImportForm.php +++ b/admin/code/GroupImportForm.php @@ -1,10 +1,11 @@ getRecord($id); - if($record && !$record->canView()) return Security::permissionFailure($this); + + if($record && !$record->canView()) { + return Security::permissionFailure($this); + } $memberList = GridField::create( 'Members', @@ -70,7 +75,16 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider { ->addComponent(new GridFieldButtonRow('after')) ->addComponent(new GridFieldExportButton('buttons-after-left')) )->addExtraClass("members_grid"); - $memberListConfig->getComponentByType('GridFieldDetailForm')->setValidator(new Member_Validator()); + + if($record && method_exists($record, 'getValidator')) { + $validator = $record->getValidator(); + } else { + $validator = Injector::inst()->get('Member')->getValidator(); + } + + $memberListConfig + ->getComponentByType('GridFieldDetailForm') + ->setValidator($validator); $groupList = GridField::create( 'Groups', diff --git a/admin/css/ie7.css b/admin/css/ie7.css index 0375b8db6..d783e44af 100644 --- a/admin/css/ie7.css +++ b/admin/css/ie7.css @@ -20,8 +20,8 @@ .ss-gridfield-button-filter.ss-ui-button.hover-alike { background-color: #338DC1; background-position: -16px 6px; filter: none; } .ss-gridfield-button-reset.ss-ui-button { background: #e6e6e6 url(../images/filter-icons.png) no-repeat 8px 5px; filter: none; } -.ss-gridfield-button-reset.ss-ui-button.filtered:hover { background: red url(../images/filter-icons.png) no-repeat 8px -17px; filter: none; } -.ss-gridfield-button-reset.ss-ui-button.filtered:active { background: #e60000 url(../images/filter-icons.png) no-repeat 9px -16px; filter: none; } +.ss-gridfield-button-reset.ss-ui-button.filtered:hover { background: #d81b21 url(../images/filter-icons.png) no-repeat 8px -17px; filter: none; } +.ss-gridfield-button-reset.ss-ui-button.filtered:active { background: #c1181e url(../images/filter-icons.png) no-repeat 9px -16px; filter: none; } .cms table.ss-gridfield-table tr td { border-right: 1px solid #9a9a9a; } .cms table.ss-gridfield-table tr th { border-right: 1px solid #9a9a9a; } diff --git a/admin/css/ie8.css b/admin/css/ie8.css index 569c11ab2..b2253cb85 100644 --- a/admin/css/ie8.css +++ b/admin/css/ie8.css @@ -20,8 +20,8 @@ .ss-gridfield-button-filter.ss-ui-button.hover-alike { background-color: #338DC1; background-position: -16px 6px; filter: none; } .ss-gridfield-button-reset.ss-ui-button { background: #e6e6e6 url(../images/filter-icons.png) no-repeat 8px 5px; filter: none; } -.ss-gridfield-button-reset.ss-ui-button.filtered:hover { background: red url(../images/filter-icons.png) no-repeat 8px -17px; filter: none; } -.ss-gridfield-button-reset.ss-ui-button.filtered:active { background: #e60000 url(../images/filter-icons.png) no-repeat 9px -16px; filter: none; } +.ss-gridfield-button-reset.ss-ui-button.filtered:hover { background: #d81b21 url(../images/filter-icons.png) no-repeat 8px -17px; filter: none; } +.ss-gridfield-button-reset.ss-ui-button.filtered:active { background: #c1181e url(../images/filter-icons.png) no-repeat 9px -16px; filter: none; } .cms table.ss-gridfield-table tr td { border-right: 1px solid #9a9a9a; } .cms table.ss-gridfield-table tr th { border-right: 1px solid #9a9a9a; } diff --git a/admin/css/screen.css b/admin/css/screen.css index 522e24a62..140fde63a 100644 --- a/admin/css/screen.css +++ b/admin/css/screen.css @@ -217,7 +217,9 @@ form.small .field input.text, form.small .field textarea, form.small .field sele .cms .ss-ui-button.ss-ui-action-constructive { text-shadow: none; font-weight: bold; color: white; border-color: #1f9433; border-bottom-color: #166a24; background-color: #1f9433; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjAlIiB4Mj0iNTAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzkzYmU0MiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzFmOTQzMyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #93be42), color-stop(100%, #1f9433)); background: -webkit-linear-gradient(#93be42, #1f9433); background: -moz-linear-gradient(#93be42, #1f9433); background: -o-linear-gradient(#93be42, #1f9433); background: linear-gradient(#93be42, #1f9433); text-shadow: #1c872f 0 -1px -1px; } .cms .ss-ui-button.ss-ui-action-constructive.ui-state-hover, .cms .ss-ui-button.ss-ui-action-constructive:hover { border-color: #166a24; background-color: #1f9433; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjAlIiB4Mj0iNTAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2E0Y2EzYSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzIzYTkzYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #a4ca3a), color-stop(100%, #23a93a)); background: -webkit-linear-gradient(#a4ca3a, #23a93a); background: -moz-linear-gradient(#a4ca3a, #23a93a); background: -o-linear-gradient(#a4ca3a, #23a93a); background: linear-gradient(#a4ca3a, #23a93a); } .cms .ss-ui-button.ss-ui-action-constructive:active, .cms .ss-ui-button.ss-ui-action-constructive:focus, .cms .ss-ui-button.ss-ui-action-constructive.ui-state-active, .cms .ss-ui-button.ss-ui-action-constructive.ui-state-focus { background-color: #1d8c30; -webkit-box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); -moz-box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); } -.cms .ss-ui-button.ss-ui-action-destructive { color: red; background-color: #e6e6e6; } +.cms .ss-ui-button.ss-ui-action-destructive { color: #fff; text-shadow: none; border-color: #980c10; border-bottom-color: #69080b; background-color: #d81b21; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjAlIiB4Mj0iNTAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2YzM2Y0NCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2Q4MWIyMSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #f33f44), color-stop(100%, #d81b21)); background: -webkit-linear-gradient(#f33f44, #d81b21); background: -moz-linear-gradient(#f33f44, #d81b21); background: -o-linear-gradient(#f33f44, #d81b21); background: linear-gradient(#f33f44, #d81b21); text-shadow: #ca191f 0 -1px -1px; } +.cms .ss-ui-button.ss-ui-action-destructive.ui-state-hover, .cms .ss-ui-button.ss-ui-action-destructive:hover { border-color: #69080b; background-color: #d81b21; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjAlIiB4Mj0iNTAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2Y5MzQzYSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2U0MjgyZSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #f9343a), color-stop(100%, #e4282e)); background: -webkit-linear-gradient(#f9343a, #e4282e); background: -moz-linear-gradient(#f9343a, #e4282e); background: -o-linear-gradient(#f9343a, #e4282e); background: linear-gradient(#f9343a, #e4282e); } +.cms .ss-ui-button.ss-ui-action-destructive:active, .cms .ss-ui-button.ss-ui-action-destructive:focus, .cms .ss-ui-button.ss-ui-action-destructive.ui-state-active, .cms .ss-ui-button.ss-ui-action-destructive.ui-state-focus { background-color: #cf1a20; -webkit-box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); -moz-box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); } .cms .ss-ui-button.ss-ui-button-small .ui-button-text { font-size: 10px; } .cms .ss-ui-button.ui-state-highlight { background-color: #e6e6e6; border: 1px solid #708284; } .cms .ss-ui-button.ss-ui-action-minor { background: none; border: 0; color: #393939; text-decoration: underline; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } @@ -437,6 +439,7 @@ body.cms { overflow: hidden; } /** -------------------------------------------- Actions -------------------------------------------- */ .cms-content-actions, .cms-preview-controls { margin: 0; padding: 12px 12px; z-index: 0; border-top: 1px solid #cacacc; -webkit-box-shadow: 1px 0 0 #eceff1, rgba(248, 248, 248, 0.9) 0 1px 0px inset, rgba(201, 205, 206, 0.8) 0 0 1px; -moz-box-shadow: 1px 0 0 #eceff1, rgba(248, 248, 248, 0.9) 0 1px 0px inset, rgba(201, 205, 206, 0.8) 0 0 1px; box-shadow: 1px 0 0 #eceff1, rgba(248, 248, 248, 0.9) 0 1px 0px inset, rgba(201, 205, 206, 0.8) 0 0 1px; height: 28px; background-color: #eceff1; } +.cms-content-actions .ss-ui-action-destructive, .cms-preview-controls .ss-ui-action-destructive { float: right; margin-left: 8px; } /** -------------------------------------------- Messages -------------------------------------------- */ .message { display: block; clear: both; margin: 0 0 8px; padding: 10px 12px; font-weight: normal; border: 1px #ccc solid; background: #fff; background: rgba(255, 255, 255, 0.5); text-shadow: none; -webkit-border-radius: 3px 3px 3px 3px; -moz-border-radius: 3px 3px 3px 3px; -ms-border-radius: 3px 3px 3px 3px; -o-border-radius: 3px 3px 3px 3px; border-radius: 3px 3px 3px 3px; } @@ -513,10 +516,10 @@ body.cms { overflow: hidden; } .cms-content-tools .field { /* Fields are more compressed in the sidebar compared to the main content editing window so the below alters the internal spacing of the fields so we can move that spacing to between the form fields rather than padding */ } .cms-content-tools .field label { float: none; width: auto; font-size: 11px; padding: 0 8px 4px 0; } .cms-content-tools .field .middleColumn { margin: 0; } -.cms-content-tools .field .description { margin-left: 0; } .cms-content-tools .field input.text, .cms-content-tools .field select, .cms-content-tools .field textarea { padding: 5px; font-size: 11px; } .cms-content-tools .field.checkbox { padding: 0 0 8px; } .cms-content-tools .field.checkbox input { margin: 2px 0; } +.cms-content-tools .field .description { margin-left: 0; } .cms-content-tools .fieldgroup .fieldgroup-field { padding: 0; } .cms-content-tools .fieldgroup .fieldgroup-field .field { margin: 0; padding: 0; } .cms-content-tools table { margin: 8px -4px; } diff --git a/admin/scss/_forms.scss b/admin/scss/_forms.scss index 1c479ef20..9f17487ca 100644 --- a/admin/scss/_forms.scss +++ b/admin/scss/_forms.scss @@ -434,8 +434,34 @@ form.small .field, .field.small { /* destructive */ &.ss-ui-action-destructive { - color: $color-button-destructive; - background-color: $color-button-generic; + color: #fff; + text-shadow:none; + border-color: $color-button-destructive-border; + border-bottom-color: darken($color-button-destructive-border, 10%); + background-color: $color-button-destructive; + @include background( + linear-gradient(color-stops( + scale-color(lighten($color-button-destructive, 10%), $red:50%), + $color-button-destructive + )) + ); + @include text-shadow(darken($color-button-destructive, 3%) 0 -1px -1px); + + &.ui-state-hover, &:hover { + border-color: darken($color-button-destructive-border, 10%); + background-color: $color-button-destructive; + @include background( + linear-gradient(color-stops( + scale-color(saturate(lighten($color-button-destructive, 10%), 10%), $red:60%), + lighten($color-button-destructive, 5%) + )) + ); + } + + &:active, &:focus, &.ui-state-active, &.ui-state-focus { + background-color: darken($color-button-destructive, 2%); + @include box-shadow(inset 0 1px 3px rgb(23, 24, 26), 0 1px 0 rgba(255, 255, 255, .6)); + } } &.ss-ui-button-small { diff --git a/admin/scss/_style.scss b/admin/scss/_style.scss index 943b9b6f1..bd8a85353 100644 --- a/admin/scss/_style.scss +++ b/admin/scss/_style.scss @@ -426,6 +426,11 @@ body.cms { $color-shadow-light 0 0 1px); height: 28px; background-color: $tab-panel-texture-color; + + .ss-ui-action-destructive { + float: right; + margin-left: 8px; + } } diff --git a/admin/scss/themes/_default.scss b/admin/scss/themes/_default.scss index 53a2e6308..b1d860e23 100644 --- a/admin/scss/themes/_default.scss +++ b/admin/scss/themes/_default.scss @@ -56,7 +56,8 @@ $color-button-highlight-border: #708284 !default; $color-button-constructive: #1F9433 !default; $color-button-constructive-border: #1F9433 !default; -$color-button-destructive: #f00 !default; +$color-button-destructive: #d81b21 !default; +$color-button-destructive-border: #980c10 !default; $color-button-disabled: #eeeded !default; diff --git a/control/Session.php b/control/Session.php index a4aaf0b89..0610d4fb1 100644 --- a/control/Session.php +++ b/control/Session.php @@ -614,6 +614,6 @@ class Session { */ public static function get_timeout() { Deprecation::notice('3.2', 'Use the "Session.timeout" config setting instead'); - return Config::inst()->update('Session', 'timeout'); + return Config::inst()->get('Session', 'timeout'); } } diff --git a/control/VersionedRequestFilter.php b/control/VersionedRequestFilter.php new file mode 100644 index 000000000..c6158cc4f --- /dev/null +++ b/control/VersionedRequestFilter.php @@ -0,0 +1,17 @@ +has_extension($class, $requiredExtension)) + * @param string $classOrExtension if 1 argument supplied, the class name of the extension to check for; if 2 supplied, the class name to test + * @param string $requiredExtension used only if 2 arguments supplied */ - public static function has_extension($requiredExtension) { - $class = get_called_class(); + public static function has_extension($classOrExtension, $requiredExtension = null) { + //BC support + if(func_num_args() > 1){ + $class = $classOrExtension; + $requiredExtension = $requiredExtension; + } + else { + $class = get_called_class(); + $requiredExtension = $classOrExtension; + } $requiredExtension = strtolower($requiredExtension); $extensions = Config::inst()->get($class, 'extensions'); diff --git a/css/GridField.css b/css/GridField.css index 43ab08fd1..0a0b8c62b 100644 --- a/css/GridField.css +++ b/css/GridField.css @@ -30,10 +30,10 @@ Used in side panels and action tabs .cms .ss-gridfield .ss-gridfield-buttonrow { font-size: 14.4px; } .cms .ss-gridfield .grid-levelup { text-indent: -9999em; margin-bottom: 6px; } .cms .ss-gridfield .grid-levelup a.list-parent-link { background: transparent url(../images/gridfield-level-up.png) no-repeat 0 0; display: block; } -.cms .ss-gridfield .add-existing-autocompleter { width: 500px; } -.cms .ss-gridfield .add-existing-autocompleter span { display: -moz-inline-stack; display: inline-block; vertical-align: top; *vertical-align: auto; zoom: 1; *display: inline; } -.cms .ss-gridfield .add-existing-autocompleter input.relation-search { width: 270px; margin-bottom: 12px; } -.cms .ss-gridfield .grid-csv-button, .cms .ss-gridfield .grid-print-button { font-size: 12px; margin-bottom: 0; display: -moz-inline-stack; display: inline-block; vertical-align: middle; *vertical-align: auto; zoom: 1; *display: inline; } +.cms .ss-gridfield .add-existing-autocompleter span { float: left; display: -moz-inline-stack; display: inline-block; vertical-align: top; *vertical-align: auto; zoom: 1; *display: inline; } +.cms .ss-gridfield .add-existing-autocompleter input.relation-search { width: 270px; height: 32px; margin-bottom: 12px; border-top-right-radius: 0; border-bottom-right-radius: 0; } +.cms .ss-gridfield .add-existing-autocompleter button#action_gridfield_relationadd { height: 32px; margin-left: 0; border-top-left-radius: 0; border-bottom-left-radius: 0; border-left: none; } +.cms .ss-gridfield .grid-csv-button, .cms .ss-gridfield .grid-print-button { margin-bottom: 0; font-size: 12px; display: -moz-inline-stack; display: inline-block; vertical-align: middle; *vertical-align: auto; zoom: 1; *display: inline; } .cms table.ss-gridfield-table { display: table; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; padding: 0; border-collapse: separate; border-bottom: 0 none; width: 100%; } .cms table.ss-gridfield-table thead { color: #323e46; background: transparent; } .cms table.ss-gridfield-table thead tr.filter-header .fieldgroup { max-width: 512px; } diff --git a/dev/Debug.php b/dev/Debug.php index 1d3f98f07..c17d68c82 100644 --- a/dev/Debug.php +++ b/dev/Debug.php @@ -23,19 +23,7 @@ * @subpackage dev */ class Debug { - - /** - * @config - * @var string Email address to send error notifications - */ - private static $send_errors_to; - - /** - * @config - * @var string Email address to send warning notifications - */ - private static $send_warnings_to; - + /** * @config * @var String indicating the file where errors are logged. @@ -262,18 +250,6 @@ class Debug { if(error_reporting() == 0) return; ini_set('display_errors', 0); - if(Config::inst()->get('Debug', 'send_warnings_to')) { - return self::emailError( - Config::inst()->get('Debug', 'send_warnings_to'), - $errno, - $errstr, - $errfile, - $errline, - $errcontext, - "Warning" - ); - } - // Send out the error details to the logger for writing SS_Log::log( array( @@ -286,10 +262,6 @@ class Debug { SS_Log::WARN ); - if(Config::inst()->get('Debug', 'log_errors_to')) { - self::log_error_if_necessary( $errno, $errstr, $errfile, $errline, $errcontext, "Warning"); - } - if(Director::isDev()) { return self::showError($errno, $errstr, $errfile, $errline, $errcontext, "Warning"); } else { @@ -310,13 +282,6 @@ class Debug { */ public static function fatalHandler($errno, $errstr, $errfile, $errline, $errcontext) { ini_set('display_errors', 0); - - if(Config::inst()->get('Debug', 'send_errors_to')) { - self::emailError( - Config::inst()->get('Debug', 'send_errors_to'), $errno, - $errstr, $errfile, $errline, $errcontext, "Error" - ); - } // Send out the error details to the logger for writing SS_Log::log( @@ -330,10 +295,6 @@ class Debug { SS_Log::ERR ); - if(Config::inst()->get('Debug', 'log_errors_to')) { - self::log_error_if_necessary( $errno, $errstr, $errfile, $errline, $errcontext, "Error"); - } - if(Director::isDev() || Director::is_cli()) { return self::showError($errno, $errstr, $errfile, $errline, $errcontext, "Error"); } else { diff --git a/dev/install/install.php5 b/dev/install/install.php5 index 02cf81343..f1419f2ae 100755 --- a/dev/install/install.php5 +++ b/dev/install/install.php5 @@ -653,7 +653,7 @@ class InstallRequirements { // special case for display_errors, check the original value before // it was changed at the start of this script. - if($settingName = 'display_errors') { + if($settingName == 'display_errors') { global $originalDisplayErrorsValue; $val = $originalDisplayErrorsValue; } else { diff --git a/docs/en/topics/i18n.md b/docs/en/topics/i18n.md index 79041d528..3f9ef98d5 100644 --- a/docs/en/topics/i18n.md +++ b/docs/en/topics/i18n.md @@ -212,6 +212,17 @@ the PHP version of the function. // Using injection to add variables into the translated strings (note that $Name and $Greeting must be available in the current template scope). <%t Header.Greeting "Hello {name} {greeting}" name=$Name greeting=$Greeting %> + +#### Caching in Template Files with locale switching + +When caching a `<% loop %>` or `<% with %>` with `<%t params %>`. It is important to add the Locale to the cache key otherwise it won't pick up locale changes. + + ::::ss + <% cached 'MyIdentifier', $CurrentLocale %> + <% loop $Students %> + $Name + <% end_loop %> + <% end_cached %> ## Collecting text diff --git a/email/Email.php b/email/Email.php index 6aa8c4811..e3645434a 100644 --- a/email/Email.php +++ b/email/Email.php @@ -181,6 +181,7 @@ class Email extends ViewableData { 'filename' => $filename, 'mimetype' => $mimetype, ); + return $this; } public function setBounceHandlerURL($bounceHandlerURL) { @@ -195,6 +196,7 @@ class Email extends ViewableData { } else { user_error("Could not attach '$absoluteFileName' to email. File does not exist.", E_USER_NOTICE); } + return $this; } public function Subject() { @@ -223,26 +225,32 @@ class Email extends ViewableData { public function setSubject($val) { $this->subject = $val; + return $this; } public function setBody($val) { $this->body = $val; + return $this; } public function setTo($val) { $this->to = $val; + return $this; } public function setFrom($val) { $this->from = $val; + return $this; } public function setCc($val) { $this->cc = $val; + return $this; } public function setBcc($val) { $this->bcc = $val; + return $this; } /** @@ -251,6 +259,7 @@ class Email extends ViewableData { */ public function replyTo($email) { $this->addCustomHeader('Reply-To', $email); + return $this; } /** @@ -267,6 +276,7 @@ class Email extends ViewableData { if(isset($this->customHeaders[$headerName])) $this->customHeaders[$headerName] .= ", " . $headerValue; else $this->customHeaders[$headerName] = $headerValue; } + return $this; } public function BaseURL() { @@ -295,6 +305,7 @@ class Email extends ViewableData { */ public function setTemplate($template) { $this->ss_template = $template; + return $this; } /** @@ -340,6 +351,8 @@ class Email extends ViewableData { $this->template_data = $this->customise($data); } $this->parseVariables_done = false; + + return $this; } /** @@ -375,6 +388,8 @@ class Email extends ViewableData { $this->body = HTTP::absoluteURLs($fullBody); } Config::inst()->update('SSViewer', 'source_file_comments', $origState); + + return $this; } /** diff --git a/forms/ConfirmedPasswordField.php b/forms/ConfirmedPasswordField.php index 7082881be..c8202b394 100644 --- a/forms/ConfirmedPasswordField.php +++ b/forms/ConfirmedPasswordField.php @@ -251,8 +251,12 @@ class ConfirmedPasswordField extends FormField { // If $data is a DataObject, don't use the value, since it's a hashed value if ($data && $data instanceof DataObject) $value = ''; + //store this for later + $oldValue = $this->value; + if(is_array($value)) { - if($value['_Password'] || (!$value['_Password'] && !$this->canBeEmpty)) { + //only set the value if it's valid! + if($this->validate(RequiredFields::create())) { $this->value = $value['_Password']; } @@ -266,11 +270,14 @@ class ConfirmedPasswordField extends FormField { } } - $this->children->fieldByName($this->getName() . '[_Password]') - ->setValue($this->value); + //looking up field by name is expensive, so lets check it needs to change + if ($oldValue != $this->value) { + $this->children->fieldByName($this->getName() . '[_Password]') + ->setValue($this->value); - $this->children->fieldByName($this->getName() . '[_ConfirmPassword]') - ->setValue($this->value); + $this->children->fieldByName($this->getName() . '[_ConfirmPassword]') + ->setValue($this->value); + } return $this; } @@ -359,7 +366,9 @@ class ConfirmedPasswordField extends FormField { } $limitRegex = '/^.' . $limit . '$/'; if(!empty($value) && !preg_match($limitRegex,$value)) { - $validator->validationError('Password', $errorMsg, + $validator->validationError( + $name, + $errorMsg, "validation", false ); @@ -369,7 +378,7 @@ class ConfirmedPasswordField extends FormField { if($this->requireStrongPassword) { if(!preg_match('/^(([a-zA-Z]+\d+)|(\d+[a-zA-Z]+))[a-zA-Z0-9]*$/',$value)) { $validator->validationError( - 'Password', + $name, _t('Form.VALIDATIONSTRONGPASSWORD', "Passwords must have at least one digit and one alphanumeric character"), "validation", diff --git a/forms/RequiredFields.php b/forms/RequiredFields.php index 1e3adbd08..960a2bcde 100644 --- a/forms/RequiredFields.php +++ b/forms/RequiredFields.php @@ -1,10 +1,12 @@ required = array(); + return $this; } @@ -50,7 +55,9 @@ class RequiredFields extends Validator { * Debug helper */ public function debug() { - if(!is_array($this->required)) return false; + if(!is_array($this->required)) { + return false; + } $result = "