From 75f2b17f30f2ee8ec360d11a9be38eb097a7b66c Mon Sep 17 00:00:00 2001 From: colymba Date: Mon, 7 Oct 2013 14:24:16 +0300 Subject: [PATCH 01/12] FIX gridfield delete alert selector specificity --- javascript/GridField.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/GridField.js b/javascript/GridField.js index 9574a094b..746f6fbf6 100644 --- a/javascript/GridField.js +++ b/javascript/GridField.js @@ -136,7 +136,7 @@ }); // Covers both tabular delete button, and the button on the detail form - $('.ss-gridfield .Actions .action.gridfield-button-delete, .cms-edit-form .Actions button.action.action-delete').entwine({ + $('.ss-gridfield .col-buttons .action.gridfield-button-delete, .cms-edit-form .Actions button.action.action-delete').entwine({ onclick: function(e){ if(!confirm(ss.i18n._t('TABLEFIELD.DELETECONFIRMMESSAGE'))) { e.preventDefault(); From 9288bdc5ea3ff9e33b04878d2de6885e2c2c41a8 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Tue, 8 Oct 2013 11:37:11 +0200 Subject: [PATCH 02/12] Updated Te Reo translations --- javascript/lang/mi_NZ.js | 7 +-- lang/mi.yml | 106 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 3 deletions(-) diff --git a/javascript/lang/mi_NZ.js b/javascript/lang/mi_NZ.js index 8df395b98..c2c284a10 100644 --- a/javascript/lang/mi_NZ.js +++ b/javascript/lang/mi_NZ.js @@ -13,14 +13,14 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { 'UPDATEURL.CONFIRM': 'Kei te hiahia koe kia huri au i te PRO ki:\n\n%s/\n\nPāwhiri Āe kia hurihia te PRO, pāwhiri Whakakore kia waiho:\n\n%s', 'UPDATEURL.CONFIRMURLCHANGED':'Kua hurihia te PRO ki \n"%s"', 'FILEIFRAMEFIELD.DELETEFILE': 'Muku Kōnae', - 'FILEIFRAMEFIELD.UNATTACHFILE': 'Wehe Kōnae', + 'FILEIFRAMEFIELD.UNATTACHFILE': 'Wehetāpiri Kōnae', 'FILEIFRAMEFIELD.DELETEIMAGE': 'Muku Atahanga', 'FILEIFRAMEFIELD.CONFIRMDELETE': 'Kei te tino hiahia muku i tēnei kōnae?', 'LeftAndMain.IncompatBrowserWarning': 'Kāore tō pūtirotiro i te hototahi ki te atanga CMS. Whakamahia Internet Explorer 7+, Google Chrome 10+, Mozilla Firefox 3.5+ rānei.', 'GRIDFIELD.ERRORINTRANSACTION': 'Kua puta mai he hapa i te tiki raraunga mai i te tūmau\n Ngāna anō ā muri atu.', 'UploadField.ConfirmDelete': 'He tika tonu kia tangohia tēnei kōnae i te pūnahakōnae tūmau?', 'UploadField.PHP_MAXFILESIZE': 'Kua hipa te mōrahi_rahikōnae_tukuatu i te kōnae (whakaritenga php.ini)', - 'UploadField.HTML_MAXFILESIZE': 'Kua hipa te MŌRAHI_RAHI_KŌNAE i te kōnae (whakaritenga puka HTML)', + 'UploadField.HTML_MAXFILESIZE': 'Kua hipa te mōrahi_rahi_kōnae i te kōnae (whakaritenga puka HTML)', 'UploadField.ONLYPARTIALUPLOADED': 'Kua tukuna atu he wāhanga anake o te kōnae', 'UploadField.NOFILEUPLOADED': 'Kāore he Kōnae i tukuna atu', 'UploadField.NOTMPFOLDER': 'Kua ngaro tētahi kōpaki rangitahi', @@ -34,6 +34,7 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { 'UploadField.EMPTYRESULT': 'Otinga tukuatu kōnae piako', 'UploadField.LOADING': 'Uta ana...', 'UploadField.Editing': 'Whakatika ana ...', - 'UploadField.Uploaded': 'Kua tukuna atu' + 'UploadField.Uploaded': 'Kua tukuna atu', + 'UploadField.OVERWRITEWARNING': 'Kei te tīari kē tētahi kōnae me te ingoa ōrite' }); } diff --git a/lang/mi.yml b/lang/mi.yml index 8daaafe0d..b8d13ffa1 100644 --- a/lang/mi.yml +++ b/lang/mi.yml @@ -2,6 +2,7 @@ mi: AssetAdmin: ALLOWEDEXTS: 'Ngā toronga ka whakaaetia' NEWFOLDER: KōpakiHōu + SHOWALLOWEDEXTS: 'Whakaaturia mai ngā toronga e whakaaetia ana' AssetTableField: CREATED: 'Tukuatu tuatahi' DIM: Ngā Rahinga @@ -68,6 +69,8 @@ mi: ACCESSALLINTERFACES: 'Uru ki ngā wāhanga CMS katoa' ACCESSALLINTERFACESHELP: 'Ka takahi i ngā tautuhinga uru tauwhāiti ake' SAVE: Tiaki + CMSProfileController: + MENUTITLE: 'Taku Kōtaha' ChangePasswordEmail_ss: CHANGEPASSWORDTEXT1: 'Kua hurihia tō kupuhipa mō' CHANGEPASSWORDTEXT2: 'Ka taea te whakamahi i ēnei taipitopito tuakiri ināianei hei takiuru:' @@ -96,13 +99,30 @@ mi: FOURTH: tuawhā SECOND: tuarua THIRD: tuatoru + CurrencyField: + CURRENCYSYMBOL: $ DataObject: PLURALNAME: 'Ngā Ahanoa Raraunga' SINGULARNAME: 'Ahanoa Raraunga' Date: + DAY: rā + DAYS: ngā rā + HOUR: haora + HOURS: ngā haora + MIN: meneti + MINS: ngā meneti + MONTH: marama + MONTHS: ngā marama + SEC: hēkona + SECS: ngā hēkona TIMEDIFFAGO: '{difference} i mua' TIMEDIFFIN: 'i roto i te {difference}' + YEAR: tau + YEARS: ngā tau + LessThanMinuteAgo: 'iti iho i te meneti kotahi' DateField: + NOTSET: 'kāore i tautuhia' + TODAY: tēnei rā VALIDDATEFORMAT2: 'Tāurua he hōputu rā tika ({format})' VALIDDATEMAXDATE: 'Me tawhito ake tō rā, kia ōrite rānei ki te rā mōrahi ({date}) kua whakaaetia' VALIDDATEMINDATE: 'Me hōu ake tō rā, kia ōrite rānei ki te rā moroiti ({date}) kua whakaaetia' @@ -120,18 +140,37 @@ mi: Enum: ANY: Ko tētahi File: + AviType: 'kōnae ataata AVI' Content: Ngā Ihirangi + CssType: 'kōnae CSS' + DmgType: 'atahanga kōpae Apple' + DocType: 'tuhinga Word' Filename: Ingoa Kōnae + GifType: 'atahanga GIF - he pai mō ngā hoahoa' + GzType: 'kōnae kōpeke GZIP' + HtlType: 'kōnae HTML' + HtmlType: 'kōnae HTML' INVALIDEXTENSION: 'Kāore e whakaaetia te toronga (valid: {extensions})' INVALIDEXTENSIONSHORT: 'Kāore e whakaaetia te toronga' + IcoType: 'atahanga Ata' + JpgType: 'atahanga JPEG - he pai mō ngā whakaahua' + JsType: 'kōnae Javascript' + Mp3Type: 'kōnae ororongo MP3' + MpgType: 'kōnae ataata MPEG' NOFILESIZE: 'He kore ngā paita kei te kōnae' NOVALIDUPLOAD: 'Ehara te kōnae i te tukuatu pono' Name: Ingoa PLURALNAME: Ngā Kōnae + PdfType: 'kōnae Adobe Acrobat PDF' + PngType: 'atahanga PNG - he hōputu pai hei whakamahi whānui noa' SINGULARNAME: Kōnae TOOLARGE: 'He rahi rawa te rahi kōnae, he {size} te rahi mōrahi ka taea' TOOLARGESHORT: 'Ka hipa te {size} i te rahi kōnae' + TiffType: 'Hōputu atatahanga tūtohu ' Title: Taitara + WavType: 'kōnae ororongo WAV' + XlsType: 'ripakaute Excel' + ZipType: 'kōnae kōpeke ZIP' FileIFrameField: ATTACH: 'Āpiti {type}' ATTACHONCESAVED: 'Ka taea te āpiti i ngā {type} ina oti te tiaki tuatahi o te pūkete.' @@ -147,12 +186,17 @@ mi: TITLE: 'Iframe Tukuatu Atahanga' Filesystem: SYNCRESULTS: 'Kua oti te tukutahi: e {createdcount} ngā tūemi i hangaia, e {deletedcount} ngā tūemi i mukua' + Folder: + PLURALNAME: Ngā Kōpaki + SINGULARNAME: Kōpaki ForgotPasswordEmail_ss: HELLO: Kia ora TEXT1: 'Anei tō' TEXT2: 'hono tautuhi kupuhipa anō' TEXT3: mā Form: + FIELDISREQUIRED: 'Ka hiahiatia te {name}' + SubmitBtnLabel: Haere VALIDATIONCREDITNUMBER: 'Tirohia kua tika tō tāuru i te tau kāri nama {number}' VALIDATIONNOTUNIQUE: 'Ehara te uara i tāurua i te ahurei' VALIDATIONPASSWORDSDONTMATCH: 'Kāore ngā kupuhipa i te ōrite' @@ -160,8 +204,10 @@ mi: VALIDATIONSTRONGPASSWORD: 'Kia kotahi tonu te mati, kia tahi hoki te pūāhua retawhika i te iti rawa o ngā kupuhipa' VALIDATOR: Pūwhakamana VALIDCURRENCY: 'Tāurua he moni tika' + CSRF_FAILED_MESSAGE: 'Te āhua nei kua puta he raru hangarau. Pāwhiria te pātene hoki, ka tāmata anō i tō pūtirotiro, ka ngana anō.' FormField: NONE: Kore + Example: 'hei tauira %s' GridAction: DELETE_DESCRIPTION: Muku Delete: Muku @@ -183,6 +229,7 @@ mi: ResetFilter: Tautuhi anō GridFieldAction_Delete: DeletePermissionsFailure: 'Kāore he muku whakaaetanga' + EditPermissionsFailure: 'Kāore ō whakaaetanga kia wetehono pūkete' GridFieldDetailForm: CancelBtn: Whakakore Create: Hanga @@ -190,16 +237,25 @@ mi: DeletePermissionsFailure: 'Kāore he whakaaetanga muku' Deleted: 'Kua mukua %s %s' Save: Tiaki + Saved: 'I tiakina te {name} {link}' GridFieldItemEditView_ss: Go_back: 'Hoki' Group: AddRole: 'Tāpiritia he tūnga mō tēnei rōpū' + Code: 'Waehere Rōpū' + DefaultGroupTitleAdministrators: Ngā Kaiwhakahaere DefaultGroupTitleContentAuthors: 'Ngā Kaituhi Ihirangi' + Description: Whakaahuatanga GroupReminder: 'Mēnā ka kōwhiri koe i tētahi rōpū matua, ka whiwhi tēnei rōpū i ōna tūnga katoa' + Locked: 'Kua maukati?' + NoRoles: 'Kāore i kitea he tūnga' PLURALNAME: Ngā Rōpū + Parent: 'Rōpū Matua' RolesAddEditLink: 'Whakahaere tūnga' SINGULARNAME: Rōpū + Sort: 'Raupapa Kōmaka' has_many_Permissions: Ngā Whakaaetanga + many_many_Members: Ngā Mema GroupImportForm: Help1: '

Kawea mai ngā kaiwhakamahi i te hōputu CSV (ngā uara ka wehea ki te piko). Whakaatu whakamahinga ara atu anō

' Help2: "
\n

Advanced usage

\n
    \n
  • Allowed columns: %s
  • \n
  • Existing groups are matched by their unique Code value, and updated with any new values from the \n imported file
  • \n
  • Group hierarchies can be created by using a ParentCode column.
  • \n
  • Permission codes can be assigned by the PermissionCode column. Existing permission codes are not\n cleared.
  • \n
\n
" @@ -231,6 +287,8 @@ mi: FROMWEB: 'Mai i te tukutuku' FindInFolder: 'Rapu i te Kōpaki' IMAGEALT: 'Tuhinga kē (alt)' + IMAGEALTTEXT: 'Kuputuhi kē (alt) - ka whakaaturia ki te kore e taea te atahanga te whakaatu' + IMAGEALTTEXTDESC: 'Ka whakaaturia ki ngā pūpānui mata ki te kore e taea te atahanga te whakaatu' IMAGEDIMENSIONS: Ngā Rahinga IMAGEHEIGHTPX: Teitei IMAGETITLE: 'Tuhinga taitara (ākiutauta) - mō ngā mōhiohio tāpiri mō te atahanga' @@ -251,6 +309,7 @@ mi: URL: PRO URLNOTANOEMBEDRESOURCE: 'Kāore e taea te huri i te PRO ''{url}'' hei rawa pāpāho.' UpdateMEDIA: 'Whakahōu Pāpāho' + BUTTONADDURL: 'Tāpiri PRO' Image: PLURALNAME: Ngā Kōnae SINGULARNAME: Kōnae @@ -275,6 +334,9 @@ mi: REORGANISATIONSUCCESSFUL: 'Kua momoho te whakaraupapa anō i te rākau pae' SAVEDUP: Kua Tiakina VersionUnknown: tē mōhiotia + ShowAsList: 'whakaaturia hei rārangi' + TooManyPages: 'He nui rawa ngā whārangi' + ValidationError: 'Hapa manatoko' LeftAndMain_Menu_ss: Hello: Kia ora LOGOUT: 'Takiputa' @@ -290,6 +352,7 @@ mi: BUTTONLOGIN: 'Takiuru' BUTTONLOGINOTHER: 'Takiuru hei tangata kē' BUTTONLOSTPASSWORD: 'Kua ngaro i a au taku kupuhipa' + CANTEDIT: 'Kāore ō whakaaetanga kia pēnā' CONFIRMNEWPASSWORD: 'Whakaū Kupuhipa Hōu' CONFIRMPASSWORD: 'Whakaū Kupuhipa' DATEFORMAT: 'Hōputu Rā' @@ -299,6 +362,7 @@ mi: EMPTYNEWPASSWORD: 'Kāore e whakaaetia kia piako te kupuhipa hōu, ngana anō' ENTEREMAIL: 'Tāurua he wāhitau īmēra kia whiwhi i te hono tautuhi kupuhipa anō.' ERRORLOCKEDOUT: 'Kua mono rangitahitia tō pūkete nā te nui rawa o ngā whakamātau hē ki te takiuru. Ngana anō ā te 20 meneti.' + ERRORLOCKEDOUT2: 'Kua monokia rangitahitia tō pūkete nā te nui rawa o ngā ngana takiuru kua rahua. Ngana anō ā muri i te {count} meneti.' ERRORNEWPASSWORD: 'Kua rerekē tō tāuru kupuhipa, whakamātau anō' ERRORPASSWORDNOTMATCH: 'Kāore i te ōrite tō kupuhipa o nāianei, ngana anō' ERRORWRONGCRED: 'Te āhua nei ehara i te wāhitau īmerā tika, i te kuphipa tika rānei. Ngana anō' @@ -326,6 +390,7 @@ mi: db_NumVisit: 'Maha o ngā Toronga' db_Password: Kupuhipa db_PasswordExpiry: 'Rā Mōnehu Kupuhipa' + NoPassword: 'Kāore he kupuhipa i tēnei mema.' MemberAuthenticator: TITLE: 'Īmērā & Kupuhipa' MemberDatetimeOptionsetField: @@ -348,6 +413,7 @@ mi: TWODIGITMONTH: 'Marama matirua (01=Kohitātea)' TWODIGITSECOND: 'Ngā mati hēkona e rua (00 ki te 59)' TWODIGITYEAR: 'Tau matirua' + Toggle: 'Whakaaturia te āwhina whakahōputu' MemberImportForm: Help1: '

Kawea mai ngā kaiwhakamahi i te hōputu CSV (ngā uara ka wehea ki te piko). Whakaatu whakamahinga ara atu anō

' Help2: "
\n

Advanced usage

\n
    \n
  • Allowed columns: %s
  • \n
  • Existing users are matched by their unique Code property, and updated with any new values from\n the imported file.
  • \n
  • Groups can be assigned by the Groups column. Groups are identified by their Code property,\n multiple groups can be separated by comma. Existing group memberships are not cleared.
  • \n
\n
" @@ -355,11 +421,15 @@ mi: ResultDeleted: 'Kua mukua e %d ngā mema' ResultNone: 'Kāore he huringa' ResultUpdated: 'I whakahōutia e {count} mhā mema' + MemberPassword: + PLURALNAME: 'Ngā Kupuhipa Mema' + SINGULARNAME: 'Kupuhipa Mema' MemberTableField: APPLY_FILTER: 'Hoatu Tātari' ModelAdmin: DELETE: Muku DELETEDRECORDS: 'I mukua e {count} ngā pūkete.' + EMPTYBEFOREIMPORT: 'Whakakapi raraunga' IMPORT: 'Kawemai i CSV' IMPORTEDRECORDS: 'I kawea mai e {count} ngā pūkete.' NOCSVFILE: 'Pūtirotiro kia kitea he kōnae CSV hei kawemai' @@ -387,22 +457,30 @@ mi: VALIDATION: 'Ehara te ''{value}'' i te tau, ka taea ngā tau anake ki tēnei āpure' Pagination: Page: Whārangi + View: Tiro Permission: AdminGroup: Kaiwhakahaere CMS_ACCESS_CATEGORY: 'Uru CMS' FULLADMINRIGHTS: 'Ngā motika kaiwhakahaere katoa' FULLADMINRIGHTS_HELP: 'Ka whakapae me te takahi i ērā atu whakaaetanga katoa kua tautapatia.' + PLURALNAME: Ngā Whakaaetanga + SINGULARNAME: Whakaaetanga PermissionCheckboxSetField: AssignedTo: 'kua tautapatia ki "{title}"' FromGroup: 'I tukuna iho i te rōpū "{title}"' FromRole: 'I tukuna iho i te tūnga "{title}"' FromRoleOnGroup: 'i tukuna iho i "%s" i te rōpū "%s"' PermissionRole: + OnlyAdminCanApply: 'Ka taea anake te tono e ngā kaiwhakahaere' PLURALNAME: Ngā Tūnga SINGULARNAME: Tūranga Title: Taitara + PermissionRoleCode: + PLURALNAME: 'Ngā Waehere Tūnga Whakaaetanga' + SINGULARNAME: 'Waehere Tūnga Whakaaetanga' Permissions: PERMISSIONS_CATEGORY: 'Ngā tūnga me ngā whakaaetanga uru' + UserPermissionsIntro: 'Mā te tautapa rōpū ki tēnei kaiwhakamahi e whakarite āna whakaaetanga. Tirohia te wāhanga rōpū mō ngā taipitopito o ngā whakaaetanga o ngā rōpū takitahi.' PhoneNumberField: VALIDATION: 'Tāurua he tau waea tika' RelationComplexTableField_ss: @@ -411,6 +489,7 @@ mi: NOTFOUND: 'Kāore i kitea he tūemi' Security: ALREADYLOGGEDIN: 'Kāore i te whakaaetia kia uru koe ki tēnei whārangi. Mēnā he pūkete anō tōu e taea ai te uru ki tēnā whārangi, ka taea te takiuru anō i raro.' + LOSTPASSWORDHEADER: 'Kupuhipa Ngaro' BUTTONSEND: 'Tukuna mai te hono tautuhi kupuhipa anō' CHANGEPASSWORDBELOW: 'Ka taea te huri i tō kupuhipa i raro' CHANGEPASSWORDHEADER: 'Hurihia tō kupuhipa' @@ -446,6 +525,19 @@ mi: FileFieldLabel: 'Kōnae CSV (Ngā toronga ka whakaaetia: *.csv)' SilverStripeNavigator: Edit: Whakatika + Auto: Aunoa + ChangeViewMode: 'Hurihia te aratau tiro' + Desktop: Papamahi + DualWindowView: 'Matapihi Takirua' + EditView: 'Aratau whakatika' + Mobile: Pūkoro + PreviewState: 'Tūnga Arokite' + PreviewView: 'Aratau arokite' + Responsive: Urupare + SplitView: 'Aratau weherua' + Tablet: Paparorohiko + ViewDeviceWidth: 'Tīpakohia he whānui arokite' + Width: whānui SimpleImageField: NOUPLOAD: 'Kāore He Atahanga Tukuatu' SiteTree: @@ -493,17 +585,31 @@ mi: FROMCOMPUTER: 'Mai i tō rorohiko' FROMCOMPUTERINFO: 'Tīpako mai i ngā kōnae' FROMFILES: 'I ngā kōnae' + HOTLINKINFO: 'Mōhiohio: Ka honoweratia tēnei atahanga. Me whakarite kia whai whakaaetanga koe i te kaihanga pae taketake kia pēnā.' MAXNUMBEROFFILES: 'Kua hipa te mōrahi o ngā kōnae {count}.' MAXNUMBEROFFILESSHORT: 'Ka taea te tukuatu i ngā kōnae {count} anake ' + MAXNUMBEROFFILESONE: 'Ka taea tētahi kōnae kotahi anake te tukuatu' REMOVE: Tango REMOVEERROR: 'Kua rarua te tango kōnae' REMOVEINFO: 'Tangohia tēnei kōane i konei, engari kaua e muku i te pātaka kōnae' STARTALL: 'Tīmata katoa' STARTALLINFO: 'Tīmataria ngā tukuatu katoa' Saved: Kua Tiakina + CHOOSEANOTHERFILE: 'Kōwhiria tētahi kōnae anō' + CHOOSEANOTHERINFO: 'Whakakapia tēnei kōnae ki tētahi atu mai i te pātaka kōnae' + OVERWRITEWARNING: 'Kei te tīari kē tētahi kōnae me te ingoa ōrite' + UPLOADSINTO: 'ka tiaki ki /{path}' Versioned: has_many_Versions: Ngā Putanga + CMSPageHistoryController_versions_ss: + PREVIEW: 'Arokite Paetukutuku' GridFieldEditButton_ss: EDIT: Whakatika + ContentController: + NOTLOGGEDIN: 'kāore i te takiuru' GridFieldItemEditView: Go_back: 'Hoki' + PasswordValidator: + LOWCHARSTRENGTH: 'Whakakahatia tō kupuhipa mā te tāpiri i ētahi o ēnei pūāhua: %s' + PREVPASSWORD: 'Kua whakamahi kētia tēnā kupuhipa i mua, kōwhiria he kupuhipa hou' + TOOSHORT: 'He poto rawa te kupuhipa, me %s pūāhua neke atu te roa' From 93558a6d623824162375792c89ebd59ef36adfc0 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Tue, 8 Oct 2013 12:07:38 +0200 Subject: [PATCH 03/12] Globalization in TreeDropdownField JS --- admin/code/LeftAndMain.php | 2 +- javascript/TreeDropdownField.js | 12 ++++-------- javascript/lang/en_US.js | 6 +++++- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/admin/code/LeftAndMain.php b/admin/code/LeftAndMain.php index ca92f69b0..bc5919855 100644 --- a/admin/code/LeftAndMain.php +++ b/admin/code/LeftAndMain.php @@ -325,11 +325,11 @@ class LeftAndMain extends Controller implements PermissionProvider { FRAMEWORK_ADMIN_DIR . '/thirdparty/chosen/chosen/chosen.jquery.js', FRAMEWORK_ADMIN_DIR . '/thirdparty/jquery-hoverIntent/jquery.hoverIntent.js', FRAMEWORK_ADMIN_DIR . '/javascript/jquery-changetracker/lib/jquery.changetracker.js', + FRAMEWORK_DIR . '/javascript/i18n.js', FRAMEWORK_DIR . '/javascript/TreeDropdownField.js', FRAMEWORK_DIR . '/javascript/DateField.js', FRAMEWORK_DIR . '/javascript/HtmlEditorField.js', FRAMEWORK_DIR . '/javascript/TabSet.js', - FRAMEWORK_DIR . '/javascript/i18n.js', FRAMEWORK_ADMIN_DIR . '/javascript/ssui.core.js', FRAMEWORK_DIR . '/javascript/GridField.js', ) diff --git a/javascript/TreeDropdownField.js b/javascript/TreeDropdownField.js index 7c05f33e4..13042dac0 100644 --- a/javascript/TreeDropdownField.js +++ b/javascript/TreeDropdownField.js @@ -23,9 +23,9 @@ }); var strings = { - 'openlink': 'Open', - 'fieldTitle': '(Choose)', - 'searchFieldTitle': '(Choose or Search)' + 'openlink': ss.i18n._t('TreeDropdownField.OpenLink'), + 'fieldTitle': '(' + ss.i18n._t('TreeDropdownField.FieldTitle') + ')', + 'searchFieldTitle': '(' + ss.i18n._t('TreeDropdownField.SearchFieldTitle') + ')' }; var _clickTestFn = function(e) { @@ -298,11 +298,7 @@ $('.TreeDropdownField.searchable').entwine({ onadd: function() { this._super(); - var title = ss.i18n._t( - 'DropdownField.ENTERTOSEARCH', - 'Press enter to search' - ); - + var title = ss.i18n._t('TreeDropdownField.ENTERTOSEARCH'); this.find('.treedropdownfield-panel').prepend( $('') ); diff --git a/javascript/lang/en_US.js b/javascript/lang/en_US.js index 076f18db6..2d3ec171c 100644 --- a/javascript/lang/en_US.js +++ b/javascript/lang/en_US.js @@ -36,6 +36,10 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { 'UploadField.LOADING': 'Loading ...', 'UploadField.Editing': 'Editing ...', 'UploadField.Uploaded': 'Uploaded', - 'UploadField.OVERWRITEWARNING': 'File with the same name already exists' + 'UploadField.OVERWRITEWARNING': 'File with the same name already exists', + 'TreeDropdownField.ENTERTOSEARCH': 'Press enter to search', + 'TreeDropdownField.OpenLink': 'Open', + 'TreeDropdownField.FieldTitle': 'Choose', + 'TreeDropdownField.SearchFieldTitle': 'Choose or Search' }); } From 36d8a9f62d33836f26fa4f1ee858ffc1ab1e2c70 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Tue, 8 Oct 2013 12:20:10 +0200 Subject: [PATCH 04/12] Chinese translation encoding --- lang/zh.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lang/zh.yml b/lang/zh.yml index 9064823b2..dc8905da9 100644 --- a/lang/zh.yml +++ b/lang/zh.yml @@ -413,8 +413,8 @@ zh: TWODIGITYEAR: '两位数表示的年份' Toggle: '显示格式帮助' MemberImportForm: - Help1: '<p>采用 <em>CSV 格式</em> 导入用户(逗号分隔值)<small><a href="#" class="toggle-advanced">显示高级用法</a></small></p>' - Help2: "<div class=\"advanced\">\n <h4>高级用法</h4>\n <ul>\n <li>允许的栏目:<em>%s</em></li>\n <li>通过独有的 <em>代码</em> 属性对现有用户进行配对并使用导入文件中任何新的值更新他们。</li>\n <li>群组可通过 <em>组别</em> 栏目进行分类。群组通过他们的<em>代码</em> 属性进行识别,\n多个群组可用逗号隔开。现有的群组分配情况不会被清除。</li>\n </ul>\n</div>" + Help1: '

采用 CSV 格式 导入用户(逗号分隔值)显示高级用法

' + Help2: "
\n

高级用法

\n
    \n
  • 允许的栏目:%s
  • \n
  • 通过独有的 代码 属性对现有用户进行配对并使用导入文件中任何新的值更新他们。
  • \n
  • 群组可通过 组别 栏目进行分类。群组通过他们的代码 属性进行识别,\n多个群组可用逗号隔开。现有的群组分配情况不会被清除。
  • \n
\n
" ResultCreated: '已创建 {count} 位成员' ResultDeleted: '已删除 %d 位成员' ResultNone: '无更改' @@ -520,7 +520,7 @@ zh: Users: 用户 SecurityAdmin_MemberImportForm: BtnImport: '从 CSV 导入' - FileFieldLabel: 'CSV 文件 <small>(允许的扩展名:*.csv)</small>' + FileFieldLabel: 'CSV 文件 (允许的扩展名:*.csv)' SilverStripeNavigator: Edit: 编辑 Auto: 自动 From f0ccdeb9fcb1da43c8043bea3f54b8473d5b9d80 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Tue, 8 Oct 2013 21:28:35 +0200 Subject: [PATCH 05/12] Updated Te Reo translation --- javascript/lang/mi_NZ.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/javascript/lang/mi_NZ.js b/javascript/lang/mi_NZ.js index c2c284a10..402610e46 100644 --- a/javascript/lang/mi_NZ.js +++ b/javascript/lang/mi_NZ.js @@ -35,6 +35,10 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { 'UploadField.LOADING': 'Uta ana...', 'UploadField.Editing': 'Whakatika ana ...', 'UploadField.Uploaded': 'Kua tukuna atu', - 'UploadField.OVERWRITEWARNING': 'Kei te tīari kē tētahi kōnae me te ingoa ōrite' + 'UploadField.OVERWRITEWARNING': 'Kei te tīari kē tētahi kōnae me te ingoa ōrite', + 'TreeDropdownField.ENTERTOSEARCH': 'Pēhi tāuru hei rapu', + 'TreeDropdownField.OpenLink': 'Whakatuwhera', + 'TreeDropdownField.FieldTitle': 'Kōwhiri', + 'TreeDropdownField.SearchFieldTitle': 'Kōwhiri ka Rapu rānei' }); } From a3396874933ff8f84b705aff964bc499be2b7e18 Mon Sep 17 00:00:00 2001 From: Andrew Short Date: Wed, 9 Oct 2013 15:02:36 +1100 Subject: [PATCH 06/12] API: Pass extra context information to shortcode handlers. This allows shortcodes to perform more complex actions on the element which contains them. For example, the element reference can be used to add extra classes or attributes to links which provide additional metadata. --- docs/en/reference/shortcodes.md | 5 ++++- parsers/ShortcodeParser.php | 10 ++++++---- tests/parsers/ShortcodeParserTest.php | 18 ++++++++++++++---- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/docs/en/reference/shortcodes.md b/docs/en/reference/shortcodes.md index 362215484..76984bc66 100644 --- a/docs/en/reference/shortcodes.md +++ b/docs/en/reference/shortcodes.md @@ -64,7 +64,10 @@ These parameters are passed to the callback: will not have been parsed, and can optionally be fed back into the parser. - The ShortcodeParser instance used to parse the content. - The shortcode tag name that was matched within the parsed content. - + - An associative array of extra information about the shortcode being parsed. For example, if the shortcode is + is inside an attribute, the `element` key contains a reference to the parent `DOMElement`, and the `node` + key the attribute's `DOMNode`. + ## Example: Google Maps Iframe by Address To demonstrate how easy it is to build custom shortcodes, we'll build one to display diff --git a/parsers/ShortcodeParser.php b/parsers/ShortcodeParser.php index 8388873e7..ed7e659d9 100644 --- a/parsers/ShortcodeParser.php +++ b/parsers/ShortcodeParser.php @@ -68,6 +68,7 @@ class ShortcodeParser { * this will not have been parsed, and can optionally be fed back into the parser. * - The {@link ShortcodeParser} instance used to parse the content. * - The shortcode tag name that was matched within the parsed content. + * - An associative array of extra information about the shortcode being parsed. * * @param string $shortcode The shortcode tag to map to the callback - normally in lowercase_underscore format. * @param callback $callback The callback to replace the shortcode with. @@ -102,9 +103,9 @@ class ShortcodeParser { $this->shortcodes = array(); } - public function callShortcode($tag, $attributes, $content) { + public function callShortcode($tag, $attributes, $content, $extra = array()) { if (!isset($this->shortcodes[$tag])) return false; - return call_user_func($this->shortcodes[$tag], $attributes, $content, $this, $tag); + return call_user_func($this->shortcodes[$tag], $attributes, $content, $this, $tag, $extra); } // -------------------------------------------------------------------------------------------------------------- @@ -332,11 +333,12 @@ class ShortcodeParser { for($i = 0; $i < $attributes->length; $i++) { $node = $attributes->item($i); $tags = $this->extractTags($node->nodeValue); + $extra = array('node' => $node, 'element' => $node->ownerElement); if($tags) { $node->nodeValue = $this->replaceTagsWithText($node->nodeValue, $tags, - function($idx, $tag) use ($parser){ - $content = $parser->callShortcode($tag['open'], $tag['attrs'], $tag['content']); + function($idx, $tag) use ($parser, $extra){ + $content = $parser->callShortcode($tag['open'], $tag['attrs'], $tag['content'], $extra); if ($content === false) { if(ShortcodeParser::$error_behavior == ShortcodeParser::ERROR) { diff --git a/tests/parsers/ShortcodeParserTest.php b/tests/parsers/ShortcodeParserTest.php index a87caff85..1ab935a06 100644 --- a/tests/parsers/ShortcodeParserTest.php +++ b/tests/parsers/ShortcodeParserTest.php @@ -6,6 +6,7 @@ class ShortcodeParserTest extends SapphireTest { protected $arguments, $contents, $tagName, $parser; + protected $extra = array(); public function setUp() { ShortcodeParser::get('test')->register('test_shortcode', array($this, 'shortcodeSaver')); @@ -210,16 +211,25 @@ class ShortcodeParserTest extends SapphireTest { ); } + public function testExtraContext() { + $this->parser->parse('Test'); + + $this->assertInstanceOf('DOMNode', $this->extra['node']); + $this->assertInstanceOf('DOMElement', $this->extra['element']); + $this->assertEquals($this->extra['element']->tagName, 'a'); + } + // ----------------------------------------------------------------------------------------------------------------- /** * Stores the result of a shortcode parse in object properties for easy testing access. */ - public function shortcodeSaver($arguments, $content = null, $parser, $tagName = null) { + public function shortcodeSaver($arguments, $content, $parser, $tagName, $extra) { $this->arguments = $arguments; - $this->contents = $content; - $this->tagName = $tagName; - + $this->contents = $content; + $this->tagName = $tagName; + $this->extra = $extra; + return $content; } From c34167b0ec1bb848457f477be9a1ad8074dcdf55 Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Wed, 9 Oct 2013 10:43:53 +0100 Subject: [PATCH 07/12] Unit test coverage for CMSMenuItem --- admin/tests/CMSMenuItemTest.php | 44 +++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 admin/tests/CMSMenuItemTest.php diff --git a/admin/tests/CMSMenuItemTest.php b/admin/tests/CMSMenuItemTest.php new file mode 100644 index 000000000..d6f61b173 --- /dev/null +++ b/admin/tests/CMSMenuItemTest.php @@ -0,0 +1,44 @@ + 'foo bar', 'disabled' => true, 'data-foo' => ''); + + $this->assertEquals( + 'title="foo bar" disabled="disabled" data-foo="<something>"', + $menuItem->getAttributesHTML($exampleAttributes), + 'Attributes appear correctly when passed as an argument' + ); + + $emptyAttributes = array('empty' => ''); + $this->assertEquals( + '', + $menuItem->getAttributesHTML($emptyAttributes), + 'No attributes are output when argument values are empty' + ); + $this->assertEquals( + '', + $menuItem->getAttributesHTML('some string'), + 'getAttributesHTML() ignores a string argument' + ); + + // Set attributes as class property + $menuItem->setAttributes($exampleAttributes); + $this->assertEquals( + 'title="foo bar" disabled="disabled" data-foo="<something>"', + $menuItem->getAttributesHTML(), + 'Attributes appear correctly when using setAttributes()' + ); + $this->assertEquals( + 'title="foo bar" disabled="disabled" data-foo="<something>"', + $menuItem->getAttributesHTML('foo bar'), + 'getAttributesHTML() ignores a string argument and falls back to class property' + ); + } + +} \ No newline at end of file From ed9f8dcf1f84df4a98267c1be48c9f96c2212e48 Mon Sep 17 00:00:00 2001 From: Andrew Short Date: Wed, 9 Oct 2013 23:27:56 +1100 Subject: [PATCH 08/12] BUG: Fix CMS forms with validation errors responding incorrectly. A new form instance was being constructed for the response, which mean that a lot of the validation information was lost. This fix means that: * Enterered data is correctly persisted. * A validation error notification is displayed. --- admin/code/CMSForm.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/admin/code/CMSForm.php b/admin/code/CMSForm.php index 52dcda0d1..f364ad4ff 100644 --- a/admin/code/CMSForm.php +++ b/admin/code/CMSForm.php @@ -28,9 +28,16 @@ class CMSForm extends Form { protected function getValidationErrorResponse() { $request = $this->getRequest(); $negotiator = $this->getResponseNegotiator(); + if($request->isAjax() && $negotiator) { - $negotiator->setResponse(new SS_HTTPResponse($this)); - return $negotiator->respond($request); + $this->setupFormErrors(); + $result = $this->forTemplate(); + + return $negotiator->respond($request, array( + 'CurrentForm' => function() use($result) { + return $result; + } + )); } else { return parent::getValidationErrorResponse(); } From a63b9c9d5de4e642abdcae16f8e55d6771a48407 Mon Sep 17 00:00:00 2001 From: Andrew Short Date: Wed, 9 Oct 2013 23:28:09 +1100 Subject: [PATCH 09/12] FIX: Fix not switching to the correct tab on validation error. --- admin/javascript/LeftAndMain.EditForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/javascript/LeftAndMain.EditForm.js b/admin/javascript/LeftAndMain.EditForm.js index 8754e7b2f..e2ff393c1 100644 --- a/admin/javascript/LeftAndMain.EditForm.js +++ b/admin/javascript/LeftAndMain.EditForm.js @@ -93,7 +93,7 @@ var firstTabWithErrors = this.find('.message.validation:first').closest('.tab'); $('.cms-container').clearCurrentTabState(); // clear state to avoid override later on this.redraw(); - firstTabWithErrors.closest('.cms-tabset').tabs('select', firstTabWithErrors.attr('id')); + firstTabWithErrors.closest('.ss-tabset').tabs('select', firstTabWithErrors.attr('id')); } this._super(); From a8c9fffed4cb58d611499d68cb8c000759d44d02 Mon Sep 17 00:00:00 2001 From: Daniel Hensby Date: Thu, 10 Oct 2013 10:18:03 +0100 Subject: [PATCH 10/12] Appending to debug.log file Until now debug.log files were loaded into memory, concatenated and then re-written to disk. This is an intensive operation on a large file. I've added the `FILE_APPEND` flag to append to this file instead. --- dev/Debug.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dev/Debug.php b/dev/Debug.php index fc3512bb0..1d3f98f07 100644 --- a/dev/Debug.php +++ b/dev/Debug.php @@ -205,11 +205,16 @@ class Debug { * @param $message string to output */ public static function log($message) { - $file = dirname(__FILE__).'/../../debug.log'; + if (defined('BASE_PATH')) { + $path = BASE_PATH; + } + else { + $path = dirname(__FILE__) . '/../..'; + } + $file = $path . '/debug.log'; $now = date('r'); - $oldcontent = (file_exists($file)) ? file_get_contents($file) : ''; - $content = $oldcontent . "\n\n== $now ==\n$message\n"; - file_put_contents($file, $content); + $content = "\n\n== $now ==\n$message\n"; + file_put_contents($file, $content, FILE_APPEND); } /** From cd225f0fa44994b188d53feec1a581f1d0b56b61 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Thu, 10 Oct 2013 12:05:02 +0200 Subject: [PATCH 11/12] No HTML entities in "Groups" ListboxField (fixes #2513) --- control/Controller.php.orig | 590 ++++++++++++++++++++++++++++++++++++ control/Controller.php.rej | 27 ++ security/Member.php | 6 +- 3 files changed, 622 insertions(+), 1 deletion(-) create mode 100644 control/Controller.php.orig create mode 100644 control/Controller.php.rej diff --git a/control/Controller.php.orig b/control/Controller.php.orig new file mode 100644 index 000000000..8f4ae4234 --- /dev/null +++ b/control/Controller.php.orig @@ -0,0 +1,590 @@ +requestVars() + */ + protected $requestParams; + + /** + * @var string $action The URL part matched on the current controller as + * determined by the "$Action" part of the {@link $url_handlers} definition. + * Should correlate to a public method on this controller. + * Used in {@link render()} and {@link getViewer()} to determine + * action-specific templates. + */ + protected $action; + + /** + * The {@link Session} object for this controller + */ + protected $session; + + /** + * Stack of current controllers. + * Controller::$controller_stack[0] is the current controller. + */ + protected static $controller_stack = array(); + + protected $basicAuthEnabled = true; + + /** + * @var SS_HTTPResponse $response The response object that the controller returns. + * Set in {@link handleRequest()}. + */ + protected $response; + + /** + * Default URL handlers - (Action)/(ID)/(OtherID) + */ + private static $url_handlers = array( + '$Action//$ID/$OtherID' => 'handleAction', + ); + + private static $allowed_actions = array( + 'handleAction', + 'handleIndex', + ); + + /** + * Initialisation function that is run before any action on the controller is called. + * + * @uses BasicAuth::requireLogin() + */ + public function init() { + if($this->basicAuthEnabled) BasicAuth::protect_site_if_necessary(); + + // Directly access the session variable just in case the Group or Member tables don't yet exist + if(Session::get('loggedInAs') && Security::database_is_ready()) { + $member = Member::currentUser(); + if($member) { + if(!headers_sent()) Cookie::set("PastMember", true, 90, null, null, false, true); + DB::query("UPDATE \"Member\" SET \"LastVisited\" = " . DB::getConn()->now() + . " WHERE \"ID\" = $member->ID", null); + } + } + + // This is used to test that subordinate controllers are actually calling parent::init() - a common bug + $this->baseInitCalled = true; + } + + /** + * Returns a link to this controller. Overload with your own Link rules if they exist. + */ + public function Link() { + return get_class($this) .'/'; + } + + /** + * Executes this controller, and return an {@link SS_HTTPResponse} object with the result. + * + * This method first does a few set-up activities: + * - Push this controller ont to the controller stack - + * see {@link Controller::curr()} for information about this. + * - Call {@link init()} + * - Defer to {@link RequestHandler->handleRequest()} to determine which action + * should be executed + * + * Note: $requestParams['executeForm'] support was removed, + * make the following change in your URLs: + * "/?executeForm=FooBar" -> "/FooBar" + * Also make sure "FooBar" is in the $allowed_actions of your controller class. + * + * Note: You should rarely need to overload run() - + * this kind of change is only really appropriate for things like nested + * controllers - {@link ModelAsController} and {@link RootURLController} + * are two examples here. If you want to make more + * orthodox functionality, it's better to overload {@link init()} or {@link index()}. + * + * Important: If you are going to overload handleRequest, + * make sure that you start the method with $this->pushCurrent() + * and end the method with $this->popCurrent(). + * Failure to do this will create weird session errors. + * + * @param $request The {@link SS_HTTPRequest} object that is responsible + * for distributing request parsing. + * @return SS_HTTPResponse The response that this controller produces, + * including HTTP headers such as redirection info + */ + public function handleRequest(SS_HTTPRequest $request, DataModel $model) { + if(!$request) user_error("Controller::handleRequest() not passed a request!", E_USER_ERROR); + + $this->pushCurrent(); + $this->urlParams = $request->allParams(); + $this->request = $request; + $this->response = new SS_HTTPResponse(); + $this->setDataModel($model); + + $this->extend('onBeforeInit'); + + // Init + $this->baseInitCalled = false; + $this->init(); + if(!$this->baseInitCalled) { + user_error("init() method on class '$this->class' doesn't call Controller::init()." + . "Make sure that you have parent::init() included.", E_USER_WARNING); + } + + $this->extend('onAfterInit'); + + // If we had a redirection or something, halt processing. + if($this->response->isFinished()) { + $this->popCurrent(); + return $this->response; + } + + $body = parent::handleRequest($request, $model); + if($body instanceof SS_HTTPResponse) { + if(isset($_REQUEST['debug_request'])) { + Debug::message("Request handler returned SS_HTTPResponse object to $this->class controller;" + . "returning it without modification."); + } + $this->response = $body; + + } else { + if($body instanceof Object && $body->hasMethod('getViewer')) { + if(isset($_REQUEST['debug_request'])) { + Debug::message("Request handler $body->class object to $this->class controller;" + . "rendering with template returned by $body->class::getViewer()"); + } + $body = $body->getViewer($request->latestParam('Action'))->process($body); + } + + $this->response->setBody($body); + } + + + ContentNegotiator::process($this->response); + HTTP::add_cache_headers($this->response); + + $this->popCurrent(); + return $this->response; + } + + /** + * Controller's default action handler. It will call the method named in $Action, if that method exists. + * If $Action isn't given, it will use "index" as a default. + */ + protected function handleAction($request, $action) { + foreach($request->latestParams() as $k => $v) { + if($v || !isset($this->urlParams[$k])) $this->urlParams[$k] = $v; + } + + $this->action = $action; + $this->requestParams = $request->requestVars(); + + if($this->hasMethod($action)) { + $result = parent::handleAction($request, $action); + + // If the action returns an array, customise with it before rendering the template. + if(is_array($result)) { + return $this->getViewer($action)->process($this->customise($result)); + } else { + return $result; + } + } else { + return $this->getViewer($action)->process($this); + } + } + + public function setURLParams($urlParams) { + $this->urlParams = $urlParams; + } + + /** + * @return array The parameters extracted from the URL by the {@link Director}. + */ + public function getURLParams() { + return $this->urlParams; + } + + /** + * Returns the SS_HTTPResponse object that this controller is building up. + * Can be used to set the status code and headers + */ + public function getResponse() { + return $this->response; + } + + protected $baseInitCalled = false; + + /** + * Return the object that is going to own a form that's being processed, and handle its execution. + * Note that the result needn't be an actual controller object. + */ + public function getFormOwner() { + // Get the appropraite ocntroller: sometimes we want to get a form from another controller + if(isset($this->requestParams['formController'])) { + $formController = Director::getControllerForURL($this->requestParams['formController']); + + while(is_a($formController, 'NestedController')) { + $formController = $formController->getNestedController(); + } + return $formController; + + } else { + return $this; + } + } + + /** + * This is the default action handler used if a method doesn't exist. + * It will process the controller object with the template returned by {@link getViewer()} + */ + public function defaultAction($action) { + return $this->getViewer($action)->process($this); + } + + /** + * Returns the action that is being executed on this controller. + */ + public function getAction() { + return $this->action; + } + + /** + * Return an SSViewer object to process the data + * @return SSViewer The viewer identified being the default handler for this Controller/Action combination + */ + public function getViewer($action) { + // Hard-coded templates + if(isset($this->templates[$action]) && $this->templates[$action]) { + $templates = $this->templates[$action]; + + } else if(isset($this->templates['index']) && $this->templates['index']) { + $templates = $this->templates['index']; + + } else if($this->template) { + $templates = $this->template; + } else { + // Add action-specific templates for inheritance chain + $templates = array(); + $parentClass = $this->class; + if($action && $action != 'index') { + $parentClass = $this->class; + while($parentClass != "Controller") { + $templates[] = strtok($parentClass,'_') . '_' . $action; + $parentClass = get_parent_class($parentClass); + } + } + // Add controller templates for inheritance chain + $parentClass = $this->class; + while($parentClass != "Controller") { + $templates[] = strtok($parentClass,'_'); + $parentClass = get_parent_class($parentClass); + } + + $templates[] = 'Controller'; + + // remove duplicates + $templates = array_unique($templates); + } + + return new SSViewer($templates); + } + + public function hasAction($action) { + return parent::hasAction($action) || $this->hasActionTemplate($action); + } + + /** + * Removes all the "action" part of the current URL and returns the result. + * If no action parameter is present, returns the full URL + * @static + * @return String + */ + public function removeAction($fullURL, $action = null) { + if (!$action) $action = $this->getAction(); //default to current action + $returnURL = $fullURL; + + if (($pos = strpos($fullURL, $action)) !== false) { + $returnURL = substr($fullURL,0,$pos); + } + + return $returnURL; + } + + /** + * Return the class that defines the given action, so that we know where to check allowed_actions. + * Overrides RequestHandler to also look at defined templates + */ + protected function definingClassForAction($action) { + $definingClass = parent::definingClassForAction($action); + if($definingClass) return $definingClass; + + $class = get_class($this); + while($class != 'RequestHandler') { + $templateName = strtok($class, '_') . '_' . $action; + if(SSViewer::hasTemplate($templateName)) return $class; + + $class = get_parent_class($class); + } + } + + /** + * Returns TRUE if this controller has a template that is specifically designed to handle a specific action. + * + * @param string $action + * @return bool + */ + public function hasActionTemplate($action) { + if(isset($this->templates[$action])) return true; + + $parentClass = $this->class; + $templates = array(); + + while($parentClass != 'Controller') { + $templates[] = strtok($parentClass, '_') . '_' . $action; + $parentClass = get_parent_class($parentClass); + } + + return SSViewer::hasTemplate($templates); + } + + /** + * Render the current controller with the templates determined + * by {@link getViewer()}. + * + * @param array $params Key-value array for custom template variables (Optional) + * @return string Parsed template content + */ + public function render($params = null) { + $template = $this->getViewer($this->getAction()); + + // if the object is already customised (e.g. through Controller->run()), use it + $obj = ($this->customisedObj) ? $this->customisedObj : $this; + + if($params) $obj = $this->customise($params); + + return $template->process($obj); + } + + /** + * Call this to disable site-wide basic authentication for a specific contoller. + * This must be called before Controller::init(). That is, you must call it in your controller's + * init method before it calls parent::init(). + */ + public function disableBasicAuth() { + $this->basicAuthEnabled = false; + } + + /** + * Returns the current controller + * @returns Controller + */ + public static function curr() { + if(Controller::$controller_stack) { + return Controller::$controller_stack[0]; + } else { + user_error("No current controller available", E_USER_WARNING); + } + } + + /** + * Tests whether we have a currently active controller or not + * @return boolean True if there is at least 1 controller in the stack. + */ + public static function has_curr() { + return Controller::$controller_stack ? true : false; + } + + /** + * Returns true if the member is allowed to do the given action. + * @param perm The permission to be checked, such as 'View'. + * @param member The member whose permissions need checking. Defaults to the currently logged + * in user. + * @return boolean + */ + public function can($perm, $member = null) { + if(!$member) $member = Member::currentUser(); + if(is_array($perm)) { + $perm = array_map(array($this, 'can'), $perm, array_fill(0, count($perm), $member)); + return min($perm); + } + if($this->hasMethod($methodName = 'can' . $perm)) { + return $this->$methodName($member); + } else { + return true; + } + } + + //--------------------------------------------------------------------------------------------------------------- + + /** + * Pushes this controller onto the stack of current controllers. + * This means that any redirection, session setting, or other things that rely on Controller::curr() will now + * write to this controller object. + */ + public function pushCurrent() { + array_unshift(self::$controller_stack, $this); + // Create a new session object + if(!$this->session) { + if(isset(self::$controller_stack[1])) { + $this->session = self::$controller_stack[1]->getSession(); + } else { + $this->session = new Session(null); + } + } + } + + /** + * Pop this controller off the top of the stack. + */ + public function popCurrent() { + if($this === self::$controller_stack[0]) { + array_shift(self::$controller_stack); + } else { + user_error("popCurrent called on $this->class controller, but it wasn't at the top of the stack", + E_USER_WARNING); + } + } + + /** + * Redirect to the given URL. + * + * @return SS_HTTPResponse + */ + public function redirect($url, $code=302) { + if(!$this->response) $this->response = new SS_HTTPResponse(); + + if($this->response->getHeader('Location') && $this->response->getHeader('Location') != $url) { + user_error("Already directed to " . $this->response->getHeader('Location') + . "; now trying to direct to $url", E_USER_WARNING); + return; + } + + // Attach site-root to relative links, if they have a slash in them + if($url=="" || $url[0]=='?' || (substr($url,0,4) != "http" && $url[0] != "/" && strpos($url,'/') !== false)) { + $url = Director::baseURL() . $url; + } + + return $this->response->redirect($url, $code); + } + + /** + * Redirect back. Uses either the HTTP_REFERER or a manually set request-variable called "BackURL". + * This variable is needed in scenarios where not HTTP-Referer is sent ( + * e.g when calling a page by location.href in IE). + * If none of the two variables is available, it will redirect to the base + * URL (see {@link Director::baseURL()}). + * @uses redirect() + */ + public function redirectBack() { + // Don't cache the redirect back ever + HTTP::set_cache_age(0); + + $url = null; + + // In edge-cases, this will be called outside of a handleRequest() context; in that case, + // redirect to the homepage - don't break into the global state at this stage because we'll + // be calling from a test context or something else where the global state is inappropraite + if($this->request) { + if($this->request->requestVar('BackURL')) { + $url = $this->request->requestVar('BackURL'); + } else if($this->request->getHeader('Referer')) { + $url = $this->request->getHeader('Referer'); + } + } + + if(!$url) $url = Director::baseURL(); + + // absolute redirection URLs not located on this site may cause phishing + if(Director::is_site_url($url)) { + return $this->redirect($url); + } else { + return false; + } + + } + + /** + * Tests whether a redirection has been requested. + * @return string If redirect() has been called, it will return the URL redirected to. Otherwise, it will + * return null; + */ + public function redirectedTo() { + return $this->response && $this->response->getHeader('Location'); + } + + /** + * Get the Session object representing this Controller's session + * @return Session + */ + public function getSession() { + return $this->session; + } + + /** + * Set the Session object. + */ + public function setSession(Session $session) { + $this->session = $session; + } + + /** + * Joins two or more link segments together, putting a slash between them if necessary. + * Use this for building the results of {@link Link()} methods. + * If either of the links have query strings, + * then they will be combined and put at the end of the resulting url. + * + * Caution: All parameters are expected to be URI-encoded already. + * + * @param String + * @return String + */ + public static function join_links() { + $args = func_get_args(); + $result = ""; + $queryargs = array(); + $fragmentIdentifier = null; + + foreach($args as $arg) { + // Find fragment identifier - keep the last one + if(strpos($arg,'#') !== false) { + list($arg, $fragmentIdentifier) = explode('#',$arg,2); + } + // Find querystrings + if(strpos($arg,'?') !== false) { + list($arg, $suffix) = explode('?',$arg,2); + parse_str($suffix, $localargs); + $queryargs = array_merge($queryargs, $localargs); + } + if((is_string($arg) && $arg) || is_numeric($arg)) { + $arg = (string)$arg; + if($result && substr($result,-1) != '/' && $arg[0] != '/') $result .= "/$arg"; + else $result .= (substr($result, -1) == '/' && $arg[0] == '/') ? ltrim($arg, '/') : $arg; + } + } + + if($queryargs) $result .= '?' . http_build_query($queryargs); + + if($fragmentIdentifier) $result .= "#$fragmentIdentifier"; + + return $result; + } + + public static function get_template_global_variables() { + return array( + 'CurrentPage' => 'curr', + ); + } +} + + diff --git a/control/Controller.php.rej b/control/Controller.php.rej new file mode 100644 index 000000000..a0bf20658 --- /dev/null +++ b/control/Controller.php.rej @@ -0,0 +1,27 @@ +*************** +*** 72,82 **** + if($this->basicAuthEnabled) BasicAuth::protect_site_if_necessary(); + + // Directly access the session variable just in case the Group or Member tables don't yet exist +- if(Session::get('loggedInAs') && Security::database_is_ready()) { +- $member = Member::currentUser(); +- if($member) { +- DB::query("UPDATE \"Member\" SET \"LastVisited\" = " . DB::getConn()->now() +- . " WHERE \"ID\" = $member->ID", null); + } + } + +--- 79,91 ---- + if($this->basicAuthEnabled) BasicAuth::protect_site_if_necessary(); + + // Directly access the session variable just in case the Group or Member tables don't yet exist ++ if($this->config()->log_last_visited) { ++ if(Session::get('loggedInAs') && Security::database_is_ready()) { ++ $member = Member::currentUser(); ++ if($member) { ++ DB::query("UPDATE \"Member\" SET \"LastVisited\" = " . DB::getConn()->now() ++ . " WHERE \"ID\" = $member->ID", null); ++ } + } + } + diff --git a/security/Member.php b/security/Member.php index 07defd2a6..6022b0ab2 100644 --- a/security/Member.php +++ b/security/Member.php @@ -1199,7 +1199,11 @@ class Member extends DataObject implements TemplateGlobalProvider { $fields->removeByName('Groups'); if(Permission::check('EDIT_PERMISSIONS')) { - $groupsMap = Group::get()->map('ID', 'Breadcrumbs')->toArray(); + $groupsMap = array(); + foreach(Group::get() as $group) { + // Listboxfield values are escaped, use ASCII char instead of » + $groupsMap[$group->ID] = $group->getBreadcrumbs(' > '); + } asort($groupsMap); $fields->addFieldToTab('Root.Main', ListboxField::create('DirectGroups', singleton('Group')->i18n_plural_name()) From f6035505c1ec12ce1f93b9f3136aa2b513fd1001 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Thu, 10 Oct 2013 12:11:17 +0200 Subject: [PATCH 12/12] Removed accidental artifacts --- control/Controller.php.orig | 590 ------------------------------------ control/Controller.php.rej | 27 -- 2 files changed, 617 deletions(-) delete mode 100644 control/Controller.php.orig delete mode 100644 control/Controller.php.rej diff --git a/control/Controller.php.orig b/control/Controller.php.orig deleted file mode 100644 index 8f4ae4234..000000000 --- a/control/Controller.php.orig +++ /dev/null @@ -1,590 +0,0 @@ -requestVars() - */ - protected $requestParams; - - /** - * @var string $action The URL part matched on the current controller as - * determined by the "$Action" part of the {@link $url_handlers} definition. - * Should correlate to a public method on this controller. - * Used in {@link render()} and {@link getViewer()} to determine - * action-specific templates. - */ - protected $action; - - /** - * The {@link Session} object for this controller - */ - protected $session; - - /** - * Stack of current controllers. - * Controller::$controller_stack[0] is the current controller. - */ - protected static $controller_stack = array(); - - protected $basicAuthEnabled = true; - - /** - * @var SS_HTTPResponse $response The response object that the controller returns. - * Set in {@link handleRequest()}. - */ - protected $response; - - /** - * Default URL handlers - (Action)/(ID)/(OtherID) - */ - private static $url_handlers = array( - '$Action//$ID/$OtherID' => 'handleAction', - ); - - private static $allowed_actions = array( - 'handleAction', - 'handleIndex', - ); - - /** - * Initialisation function that is run before any action on the controller is called. - * - * @uses BasicAuth::requireLogin() - */ - public function init() { - if($this->basicAuthEnabled) BasicAuth::protect_site_if_necessary(); - - // Directly access the session variable just in case the Group or Member tables don't yet exist - if(Session::get('loggedInAs') && Security::database_is_ready()) { - $member = Member::currentUser(); - if($member) { - if(!headers_sent()) Cookie::set("PastMember", true, 90, null, null, false, true); - DB::query("UPDATE \"Member\" SET \"LastVisited\" = " . DB::getConn()->now() - . " WHERE \"ID\" = $member->ID", null); - } - } - - // This is used to test that subordinate controllers are actually calling parent::init() - a common bug - $this->baseInitCalled = true; - } - - /** - * Returns a link to this controller. Overload with your own Link rules if they exist. - */ - public function Link() { - return get_class($this) .'/'; - } - - /** - * Executes this controller, and return an {@link SS_HTTPResponse} object with the result. - * - * This method first does a few set-up activities: - * - Push this controller ont to the controller stack - - * see {@link Controller::curr()} for information about this. - * - Call {@link init()} - * - Defer to {@link RequestHandler->handleRequest()} to determine which action - * should be executed - * - * Note: $requestParams['executeForm'] support was removed, - * make the following change in your URLs: - * "/?executeForm=FooBar" -> "/FooBar" - * Also make sure "FooBar" is in the $allowed_actions of your controller class. - * - * Note: You should rarely need to overload run() - - * this kind of change is only really appropriate for things like nested - * controllers - {@link ModelAsController} and {@link RootURLController} - * are two examples here. If you want to make more - * orthodox functionality, it's better to overload {@link init()} or {@link index()}. - * - * Important: If you are going to overload handleRequest, - * make sure that you start the method with $this->pushCurrent() - * and end the method with $this->popCurrent(). - * Failure to do this will create weird session errors. - * - * @param $request The {@link SS_HTTPRequest} object that is responsible - * for distributing request parsing. - * @return SS_HTTPResponse The response that this controller produces, - * including HTTP headers such as redirection info - */ - public function handleRequest(SS_HTTPRequest $request, DataModel $model) { - if(!$request) user_error("Controller::handleRequest() not passed a request!", E_USER_ERROR); - - $this->pushCurrent(); - $this->urlParams = $request->allParams(); - $this->request = $request; - $this->response = new SS_HTTPResponse(); - $this->setDataModel($model); - - $this->extend('onBeforeInit'); - - // Init - $this->baseInitCalled = false; - $this->init(); - if(!$this->baseInitCalled) { - user_error("init() method on class '$this->class' doesn't call Controller::init()." - . "Make sure that you have parent::init() included.", E_USER_WARNING); - } - - $this->extend('onAfterInit'); - - // If we had a redirection or something, halt processing. - if($this->response->isFinished()) { - $this->popCurrent(); - return $this->response; - } - - $body = parent::handleRequest($request, $model); - if($body instanceof SS_HTTPResponse) { - if(isset($_REQUEST['debug_request'])) { - Debug::message("Request handler returned SS_HTTPResponse object to $this->class controller;" - . "returning it without modification."); - } - $this->response = $body; - - } else { - if($body instanceof Object && $body->hasMethod('getViewer')) { - if(isset($_REQUEST['debug_request'])) { - Debug::message("Request handler $body->class object to $this->class controller;" - . "rendering with template returned by $body->class::getViewer()"); - } - $body = $body->getViewer($request->latestParam('Action'))->process($body); - } - - $this->response->setBody($body); - } - - - ContentNegotiator::process($this->response); - HTTP::add_cache_headers($this->response); - - $this->popCurrent(); - return $this->response; - } - - /** - * Controller's default action handler. It will call the method named in $Action, if that method exists. - * If $Action isn't given, it will use "index" as a default. - */ - protected function handleAction($request, $action) { - foreach($request->latestParams() as $k => $v) { - if($v || !isset($this->urlParams[$k])) $this->urlParams[$k] = $v; - } - - $this->action = $action; - $this->requestParams = $request->requestVars(); - - if($this->hasMethod($action)) { - $result = parent::handleAction($request, $action); - - // If the action returns an array, customise with it before rendering the template. - if(is_array($result)) { - return $this->getViewer($action)->process($this->customise($result)); - } else { - return $result; - } - } else { - return $this->getViewer($action)->process($this); - } - } - - public function setURLParams($urlParams) { - $this->urlParams = $urlParams; - } - - /** - * @return array The parameters extracted from the URL by the {@link Director}. - */ - public function getURLParams() { - return $this->urlParams; - } - - /** - * Returns the SS_HTTPResponse object that this controller is building up. - * Can be used to set the status code and headers - */ - public function getResponse() { - return $this->response; - } - - protected $baseInitCalled = false; - - /** - * Return the object that is going to own a form that's being processed, and handle its execution. - * Note that the result needn't be an actual controller object. - */ - public function getFormOwner() { - // Get the appropraite ocntroller: sometimes we want to get a form from another controller - if(isset($this->requestParams['formController'])) { - $formController = Director::getControllerForURL($this->requestParams['formController']); - - while(is_a($formController, 'NestedController')) { - $formController = $formController->getNestedController(); - } - return $formController; - - } else { - return $this; - } - } - - /** - * This is the default action handler used if a method doesn't exist. - * It will process the controller object with the template returned by {@link getViewer()} - */ - public function defaultAction($action) { - return $this->getViewer($action)->process($this); - } - - /** - * Returns the action that is being executed on this controller. - */ - public function getAction() { - return $this->action; - } - - /** - * Return an SSViewer object to process the data - * @return SSViewer The viewer identified being the default handler for this Controller/Action combination - */ - public function getViewer($action) { - // Hard-coded templates - if(isset($this->templates[$action]) && $this->templates[$action]) { - $templates = $this->templates[$action]; - - } else if(isset($this->templates['index']) && $this->templates['index']) { - $templates = $this->templates['index']; - - } else if($this->template) { - $templates = $this->template; - } else { - // Add action-specific templates for inheritance chain - $templates = array(); - $parentClass = $this->class; - if($action && $action != 'index') { - $parentClass = $this->class; - while($parentClass != "Controller") { - $templates[] = strtok($parentClass,'_') . '_' . $action; - $parentClass = get_parent_class($parentClass); - } - } - // Add controller templates for inheritance chain - $parentClass = $this->class; - while($parentClass != "Controller") { - $templates[] = strtok($parentClass,'_'); - $parentClass = get_parent_class($parentClass); - } - - $templates[] = 'Controller'; - - // remove duplicates - $templates = array_unique($templates); - } - - return new SSViewer($templates); - } - - public function hasAction($action) { - return parent::hasAction($action) || $this->hasActionTemplate($action); - } - - /** - * Removes all the "action" part of the current URL and returns the result. - * If no action parameter is present, returns the full URL - * @static - * @return String - */ - public function removeAction($fullURL, $action = null) { - if (!$action) $action = $this->getAction(); //default to current action - $returnURL = $fullURL; - - if (($pos = strpos($fullURL, $action)) !== false) { - $returnURL = substr($fullURL,0,$pos); - } - - return $returnURL; - } - - /** - * Return the class that defines the given action, so that we know where to check allowed_actions. - * Overrides RequestHandler to also look at defined templates - */ - protected function definingClassForAction($action) { - $definingClass = parent::definingClassForAction($action); - if($definingClass) return $definingClass; - - $class = get_class($this); - while($class != 'RequestHandler') { - $templateName = strtok($class, '_') . '_' . $action; - if(SSViewer::hasTemplate($templateName)) return $class; - - $class = get_parent_class($class); - } - } - - /** - * Returns TRUE if this controller has a template that is specifically designed to handle a specific action. - * - * @param string $action - * @return bool - */ - public function hasActionTemplate($action) { - if(isset($this->templates[$action])) return true; - - $parentClass = $this->class; - $templates = array(); - - while($parentClass != 'Controller') { - $templates[] = strtok($parentClass, '_') . '_' . $action; - $parentClass = get_parent_class($parentClass); - } - - return SSViewer::hasTemplate($templates); - } - - /** - * Render the current controller with the templates determined - * by {@link getViewer()}. - * - * @param array $params Key-value array for custom template variables (Optional) - * @return string Parsed template content - */ - public function render($params = null) { - $template = $this->getViewer($this->getAction()); - - // if the object is already customised (e.g. through Controller->run()), use it - $obj = ($this->customisedObj) ? $this->customisedObj : $this; - - if($params) $obj = $this->customise($params); - - return $template->process($obj); - } - - /** - * Call this to disable site-wide basic authentication for a specific contoller. - * This must be called before Controller::init(). That is, you must call it in your controller's - * init method before it calls parent::init(). - */ - public function disableBasicAuth() { - $this->basicAuthEnabled = false; - } - - /** - * Returns the current controller - * @returns Controller - */ - public static function curr() { - if(Controller::$controller_stack) { - return Controller::$controller_stack[0]; - } else { - user_error("No current controller available", E_USER_WARNING); - } - } - - /** - * Tests whether we have a currently active controller or not - * @return boolean True if there is at least 1 controller in the stack. - */ - public static function has_curr() { - return Controller::$controller_stack ? true : false; - } - - /** - * Returns true if the member is allowed to do the given action. - * @param perm The permission to be checked, such as 'View'. - * @param member The member whose permissions need checking. Defaults to the currently logged - * in user. - * @return boolean - */ - public function can($perm, $member = null) { - if(!$member) $member = Member::currentUser(); - if(is_array($perm)) { - $perm = array_map(array($this, 'can'), $perm, array_fill(0, count($perm), $member)); - return min($perm); - } - if($this->hasMethod($methodName = 'can' . $perm)) { - return $this->$methodName($member); - } else { - return true; - } - } - - //--------------------------------------------------------------------------------------------------------------- - - /** - * Pushes this controller onto the stack of current controllers. - * This means that any redirection, session setting, or other things that rely on Controller::curr() will now - * write to this controller object. - */ - public function pushCurrent() { - array_unshift(self::$controller_stack, $this); - // Create a new session object - if(!$this->session) { - if(isset(self::$controller_stack[1])) { - $this->session = self::$controller_stack[1]->getSession(); - } else { - $this->session = new Session(null); - } - } - } - - /** - * Pop this controller off the top of the stack. - */ - public function popCurrent() { - if($this === self::$controller_stack[0]) { - array_shift(self::$controller_stack); - } else { - user_error("popCurrent called on $this->class controller, but it wasn't at the top of the stack", - E_USER_WARNING); - } - } - - /** - * Redirect to the given URL. - * - * @return SS_HTTPResponse - */ - public function redirect($url, $code=302) { - if(!$this->response) $this->response = new SS_HTTPResponse(); - - if($this->response->getHeader('Location') && $this->response->getHeader('Location') != $url) { - user_error("Already directed to " . $this->response->getHeader('Location') - . "; now trying to direct to $url", E_USER_WARNING); - return; - } - - // Attach site-root to relative links, if they have a slash in them - if($url=="" || $url[0]=='?' || (substr($url,0,4) != "http" && $url[0] != "/" && strpos($url,'/') !== false)) { - $url = Director::baseURL() . $url; - } - - return $this->response->redirect($url, $code); - } - - /** - * Redirect back. Uses either the HTTP_REFERER or a manually set request-variable called "BackURL". - * This variable is needed in scenarios where not HTTP-Referer is sent ( - * e.g when calling a page by location.href in IE). - * If none of the two variables is available, it will redirect to the base - * URL (see {@link Director::baseURL()}). - * @uses redirect() - */ - public function redirectBack() { - // Don't cache the redirect back ever - HTTP::set_cache_age(0); - - $url = null; - - // In edge-cases, this will be called outside of a handleRequest() context; in that case, - // redirect to the homepage - don't break into the global state at this stage because we'll - // be calling from a test context or something else where the global state is inappropraite - if($this->request) { - if($this->request->requestVar('BackURL')) { - $url = $this->request->requestVar('BackURL'); - } else if($this->request->getHeader('Referer')) { - $url = $this->request->getHeader('Referer'); - } - } - - if(!$url) $url = Director::baseURL(); - - // absolute redirection URLs not located on this site may cause phishing - if(Director::is_site_url($url)) { - return $this->redirect($url); - } else { - return false; - } - - } - - /** - * Tests whether a redirection has been requested. - * @return string If redirect() has been called, it will return the URL redirected to. Otherwise, it will - * return null; - */ - public function redirectedTo() { - return $this->response && $this->response->getHeader('Location'); - } - - /** - * Get the Session object representing this Controller's session - * @return Session - */ - public function getSession() { - return $this->session; - } - - /** - * Set the Session object. - */ - public function setSession(Session $session) { - $this->session = $session; - } - - /** - * Joins two or more link segments together, putting a slash between them if necessary. - * Use this for building the results of {@link Link()} methods. - * If either of the links have query strings, - * then they will be combined and put at the end of the resulting url. - * - * Caution: All parameters are expected to be URI-encoded already. - * - * @param String - * @return String - */ - public static function join_links() { - $args = func_get_args(); - $result = ""; - $queryargs = array(); - $fragmentIdentifier = null; - - foreach($args as $arg) { - // Find fragment identifier - keep the last one - if(strpos($arg,'#') !== false) { - list($arg, $fragmentIdentifier) = explode('#',$arg,2); - } - // Find querystrings - if(strpos($arg,'?') !== false) { - list($arg, $suffix) = explode('?',$arg,2); - parse_str($suffix, $localargs); - $queryargs = array_merge($queryargs, $localargs); - } - if((is_string($arg) && $arg) || is_numeric($arg)) { - $arg = (string)$arg; - if($result && substr($result,-1) != '/' && $arg[0] != '/') $result .= "/$arg"; - else $result .= (substr($result, -1) == '/' && $arg[0] == '/') ? ltrim($arg, '/') : $arg; - } - } - - if($queryargs) $result .= '?' . http_build_query($queryargs); - - if($fragmentIdentifier) $result .= "#$fragmentIdentifier"; - - return $result; - } - - public static function get_template_global_variables() { - return array( - 'CurrentPage' => 'curr', - ); - } -} - - diff --git a/control/Controller.php.rej b/control/Controller.php.rej deleted file mode 100644 index a0bf20658..000000000 --- a/control/Controller.php.rej +++ /dev/null @@ -1,27 +0,0 @@ -*************** -*** 72,82 **** - if($this->basicAuthEnabled) BasicAuth::protect_site_if_necessary(); - - // Directly access the session variable just in case the Group or Member tables don't yet exist -- if(Session::get('loggedInAs') && Security::database_is_ready()) { -- $member = Member::currentUser(); -- if($member) { -- DB::query("UPDATE \"Member\" SET \"LastVisited\" = " . DB::getConn()->now() -- . " WHERE \"ID\" = $member->ID", null); - } - } - ---- 79,91 ---- - if($this->basicAuthEnabled) BasicAuth::protect_site_if_necessary(); - - // Directly access the session variable just in case the Group or Member tables don't yet exist -+ if($this->config()->log_last_visited) { -+ if(Session::get('loggedInAs') && Security::database_is_ready()) { -+ $member = Member::currentUser(); -+ if($member) { -+ DB::query("UPDATE \"Member\" SET \"LastVisited\" = " . DB::getConn()->now() -+ . " WHERE \"ID\" = $member->ID", null); -+ } - } - } -