diff --git a/.travis.yml b/.travis.yml index 9d99600ac..9fd8794df 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,8 @@ matrix: env: DB=MYSQL BEHAT_TEST=1 before_script: +# Until http://pecl.php.net/package/imagick is working again +# - printf "\n" | pecl install imagick - composer self-update || true - phpenv rehash - git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support diff --git a/_config/routes.yml b/_config/routes.yml index 77971cd7c..3c149a440 100644 --- a/_config/routes.yml +++ b/_config/routes.yml @@ -15,6 +15,7 @@ After: Director: rules: 'Security//$Action/$ID/$OtherID': 'Security' + 'CMSSecurity//$Action/$ID/$OtherID': 'CMSSecurity' 'dev': 'DevelopmentAdmin' 'interactive': 'SapphireREPL' 'InstallerTest//$Action/$ID/$OtherID': 'InstallerTest' diff --git a/admin/code/ModelAdmin.php b/admin/code/ModelAdmin.php index 3f35a7d2e..037e9d6af 100644 --- a/admin/code/ModelAdmin.php +++ b/admin/code/ModelAdmin.php @@ -212,7 +212,7 @@ abstract class ModelAdmin extends LeftAndMain { $params = $this->getRequest()->requestVar('q'); if(is_array($params)) { - $params = array_map('trim', $params); + $params = ArrayLib::array_map_recursive('trim', $params); } $list = $context->getResults($params); diff --git a/admin/javascript/LeftAndMain.ActionTabSet.js b/admin/javascript/LeftAndMain.ActionTabSet.js index 0806be353..dbbf3da22 100644 --- a/admin/javascript/LeftAndMain.ActionTabSet.js +++ b/admin/javascript/LeftAndMain.ActionTabSet.js @@ -28,7 +28,7 @@ // Remove all bound events. // This guards against an edge case where the click handlers are not unbound // because the panel is still open when the ajax edit form reloads. - var frame = $('.cms').find('iframe'); + var frame = $('.cms-container').find('iframe'); frame.each(function(index, iframe){ $(iframe).contents().off('click.ss-ui-action-tabset'); }); @@ -58,7 +58,7 @@ * Note: Should be called by a click event attached to 'this' */ attachCloseHandler: function(event, ui) { - var that = this, frame = $('.cms').find('iframe'), closeHandler; + var that = this, frame = $('.cms-container').find('iframe'), closeHandler; // Create a handler for the click event so we can close tabs // and easily remove the event once done @@ -74,7 +74,7 @@ that.tabs('option', 'active', false); // close tabs // remove click event from objects it is bound to (iframe's and document) - frame = $('.cms').find('iframe'); + frame = $('.cms-container').find('iframe'); frame.each(function(index, iframe){ $(iframe).contents().off('click.ss-ui-action-tabset', closeHandler); }); diff --git a/admin/javascript/LeftAndMain.EditForm.js b/admin/javascript/LeftAndMain.EditForm.js index 79414bfc6..a9ee20fd9 100644 --- a/admin/javascript/LeftAndMain.EditForm.js +++ b/admin/javascript/LeftAndMain.EditForm.js @@ -278,21 +278,23 @@ sessionData = hasSessionStorage ? window.sessionStorage.getItem(this.attr('id')) : null, sessionStates = sessionData ? JSON.parse(sessionData) : false, elementID, - tabbed = this.find('.ss-tabset'), + tabbed = (this.find('.ss-tabset').length !== 0), activeTab, elementTab, toggleComposite, scrollY; if(hasSessionStorage && sessionStates.length > 0){ - $.each(sessionStates, function(i, sessionState) { if(self.is('#' + sessionState.id)){ elementID = $('#' + sessionState.selected); } }); + // If the element IDs saved in session states don't match up to anything in this particular form + // that probably means we haven't encountered this form yet, so focus on the first input if($(elementID).length < 1){ + this.focusFirstInput(); return; } @@ -330,14 +332,18 @@ } } else { - // If there is no focus data attribute set, focus input on first form element. Exclude elements which - // specifically opt-out of this behaviour via "data-skip-autofocus". - // This opt-out is useful if the first visible field is shown far down a scrollable area, - // for example for the pagination input field after a long GridField listing. - // Skip if an element in the form is already focused. - - this.find(':input:not(:submit)[data-skip-autofocus!="true"]').filter(':visible:first').focus(); + // If session storage is not supported or there is nothing stored yet, focus on the first input + this.focusFirstInput(); } + }, + /** + * Skip if an element in the form is already focused. Exclude elements which specifically + * opt-out of this behaviour via "data-skip-autofocus". This opt-out is useful if the + * first visible field is shown far down a scrollable area, for example for the pagination + * input field after a long GridField listing. + */ + focusFirstInput: function() { + this.find(':input:not(:submit)[data-skip-autofocus!="true"]').filter(':visible:first').focus(); } }); diff --git a/admin/javascript/LeftAndMain.Tree.js b/admin/javascript/LeftAndMain.Tree.js index b7ecd5d56..4a01ce9bb 100644 --- a/admin/javascript/LeftAndMain.Tree.js +++ b/admin/javascript/LeftAndMain.Tree.js @@ -105,7 +105,10 @@ SiblingIDs: siblingIDs }, success: function() { - $('.cms-edit-form :input[name=ParentID]').val(newParentID); + // We only need to update the ParentID if the current page we're on is the page being moved + if ($('.cms-edit-form :input[name=ID]').val() == nodeID) { + $('.cms-edit-form :input[name=ParentID]').val(newParentID); + } self.updateNodesFromServer([nodeID]); }, statusCode: { diff --git a/admin/javascript/lang/eo.js b/admin/javascript/lang/eo.js index 81eb6d2ea..f46611198 100644 --- a/admin/javascript/lang/eo.js +++ b/admin/javascript/lang/eo.js @@ -4,13 +4,13 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); } else { ss.i18n.addDictionary('eo', { - "CMSMAIN.SELECTONEPAGE": "Please select at least one page", - "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", - "CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", - "CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", - "CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.", - "CMSMAIN.BATCH_RESTORE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to restore to stage?\n\nChildren of archived pages will be restored to the root level, unless those pages are also being restored.", - "CMSMAIN.BATCH_DELETELIVE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete these pages from live?", + "CMSMAIN.SELECTONEPAGE": "Bonvole elektu almenaŭ 1 paĝon.", + "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas malpublikigi?", + "CMSMAIN.BATCH_PUBLISH_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas publikigi?", + "CMSMAIN.BATCH_DELETE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas forigi?", + "CMSMAIN.BATCH_ARCHIVE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈu vi vere volas enarĥivigi tiujn paĝojn?\n\nTiuj paĝoj kaj ĉiuj idaj paĝoj estos malpublikigitaj kaj senditaj al la arĥivo.", + "CMSMAIN.BATCH_RESTORE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈu vi vere volas restaŭri al stadio?\n\nIdoj de enarĥivigitaj paĝoj estos restaŭritaj al la radika nivelo, escepte se tiuj paĝoj ankaŭ estos restaŭritaj.", + "CMSMAIN.BATCH_DELETELIVE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas forigi tiujn paĝojn el la publika stadio?", "LeftAndMain.CONFIRMUNSAVED": "Ĉu vi vere volas navigi for de ĉi tiu paĝo?\n\nAVERTO: Viaj ŝanĝoj ne estas konservitaj.\n\nPremu je Akcepti por daŭrigi, aŭ Nuligi por resti ĉe la aktuala paĝo.", "LeftAndMain.CONFIRMUNSAVEDSHORT": "AVERTO: Viaj ŝanĝoj ne estas konservitaj.", "SecurityAdmin.BATCHACTIONSDELETECONFIRM": "Ĉu vi vere volas forigi %s grupojn?", diff --git a/admin/javascript/lang/src/eo.js b/admin/javascript/lang/src/eo.js index bcea526f6..1a69993f4 100644 --- a/admin/javascript/lang/src/eo.js +++ b/admin/javascript/lang/src/eo.js @@ -1,11 +1,11 @@ { - "CMSMAIN.SELECTONEPAGE": "Please select at least one page", - "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", - "CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", - "CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", - "CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.", - "CMSMAIN.BATCH_RESTORE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to restore to stage?\n\nChildren of archived pages will be restored to the root level, unless those pages are also being restored.", - "CMSMAIN.BATCH_DELETELIVE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete these pages from live?", + "CMSMAIN.SELECTONEPAGE": "Bonvole elektu almenaŭ 1 paĝon.", + "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas malpublikigi?", + "CMSMAIN.BATCH_PUBLISH_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas publikigi?", + "CMSMAIN.BATCH_DELETE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas forigi?", + "CMSMAIN.BATCH_ARCHIVE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈu vi vere volas enarĥivigi tiujn paĝojn?\n\nTiuj paĝoj kaj ĉiuj idaj paĝoj estos malpublikigitaj kaj senditaj al la arĥivo.", + "CMSMAIN.BATCH_RESTORE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈu vi vere volas restaŭri al stadio?\n\nIdoj de enarĥivigitaj paĝoj estos restaŭritaj al la radika nivelo, escepte se tiuj paĝoj ankaŭ estos restaŭritaj.", + "CMSMAIN.BATCH_DELETELIVE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas forigi tiujn paĝojn el la publika stadio?", "LeftAndMain.CONFIRMUNSAVED": "Ĉu vi vere volas navigi for de ĉi tiu paĝo?\n\nAVERTO: Viaj ŝanĝoj ne estas konservitaj.\n\nPremu je Akcepti por daŭrigi, aŭ Nuligi por resti ĉe la aktuala paĝo.", "LeftAndMain.CONFIRMUNSAVEDSHORT": "AVERTO: Viaj ŝanĝoj ne estas konservitaj.", "SecurityAdmin.BATCHACTIONSDELETECONFIRM": "Ĉu vi vere volas forigi %s grupojn?", diff --git a/admin/javascript/lang/src/zh.js b/admin/javascript/lang/src/zh.js index 686b667d3..c61a5628e 100644 --- a/admin/javascript/lang/src/zh.js +++ b/admin/javascript/lang/src/zh.js @@ -1,8 +1,8 @@ { - "CMSMAIN.SELECTONEPAGE": "Please select at least one page", - "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", - "CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", - "CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", + "CMSMAIN.SELECTONEPAGE": "请至少选择一个页面", + "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "您已选了{num}个页面。\n\n是否确定要取消发布", + "CMSMAIN.BATCH_PUBLISH_PROMPT": "您已选了{num}个页面。\n\n是否确定要发布?", + "CMSMAIN.BATCH_DELETE_PROMPT": "您已选了{num}个页面。\n\n是否确定要删除?", "CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.", "CMSMAIN.BATCH_RESTORE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to restore to stage?\n\nChildren of archived pages will be restored to the root level, unless those pages are also being restored.", "CMSMAIN.BATCH_DELETELIVE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete these pages from live?", diff --git a/admin/javascript/lang/zh.js b/admin/javascript/lang/zh.js index f55fd2a3e..bea2e3a73 100644 --- a/admin/javascript/lang/zh.js +++ b/admin/javascript/lang/zh.js @@ -4,10 +4,10 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); } else { ss.i18n.addDictionary('zh', { - "CMSMAIN.SELECTONEPAGE": "Please select at least one page", - "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", - "CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", - "CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", + "CMSMAIN.SELECTONEPAGE": "请至少选择一个页面", + "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "您已选了{num}个页面。\n\n是否确定要取消发布", + "CMSMAIN.BATCH_PUBLISH_PROMPT": "您已选了{num}个页面。\n\n是否确定要发布?", + "CMSMAIN.BATCH_DELETE_PROMPT": "您已选了{num}个页面。\n\n是否确定要删除?", "CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.", "CMSMAIN.BATCH_RESTORE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to restore to stage?\n\nChildren of archived pages will be restored to the root level, unless those pages are also being restored.", "CMSMAIN.BATCH_DELETELIVE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete these pages from live?", diff --git a/control/Controller.php b/control/Controller.php index cb704f0e0..26bdff851 100644 --- a/control/Controller.php +++ b/control/Controller.php @@ -119,6 +119,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider { $this->pushCurrent(); $this->urlParams = $request->allParams(); $this->setRequest($request); + $this->getResponse(); $this->setDataModel($model); $this->extend('onBeforeInit'); @@ -394,7 +395,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider { /** * Returns the current controller - * @returns Controller + * @return Controller */ public static function curr() { if(Controller::$controller_stack) { diff --git a/control/HTTP.php b/control/HTTP.php index e03903ac8..b3bdc816d 100644 --- a/control/HTTP.php +++ b/control/HTTP.php @@ -448,8 +448,14 @@ class HTTP { // Now that we've generated them, either output them or attach them to the SS_HTTPResponse as appropriate foreach($responseHeaders as $k => $v) { - if($body) $body->addHeader($k, $v); - else if(!headers_sent()) header("$k: $v"); + if($body) { + // Set the header now if it's not already set. + if ($body->getHeader($k) === null) { + $body->addHeader($k, $v); + } + } elseif(!headers_sent()) { + header("$k: $v"); + } } } diff --git a/core/ArrayLib.php b/core/ArrayLib.php index e51eed23e..e582be118 100644 --- a/core/ArrayLib.php +++ b/core/ArrayLib.php @@ -163,6 +163,23 @@ class ArrayLib { return false; } + /** + * Similar to array_map, but recurses when arrays are encountered. + * + * Actually only one array argument is supported. + * + * @param $f callback to apply + * @param $array array + * @return array + */ + public static function array_map_recursive($f, $array) { + $applyOrRecurse = function($v) use($f) { + return is_array($v) ? ArrayLib::array_map_recursive($f, $v) : call_user_func($f, $v); + }; + + return array_map($applyOrRecurse, $array); + } + /** * Recursively merges two or more arrays. * diff --git a/core/ClassInfo.php b/core/ClassInfo.php index af166f77a..f990237b9 100644 --- a/core/ClassInfo.php +++ b/core/ClassInfo.php @@ -301,22 +301,30 @@ class ClassInfo { * @return string */ public static function table_for_object_field($candidateClass, $fieldName) { - if(!$candidateClass || !$fieldName || !is_subclass_of($candidateClass, 'DataObject')) { + if(!$candidateClass + || !$fieldName + || !class_exists($candidateClass) + || !is_subclass_of($candidateClass, 'DataObject') + ) { return null; } //normalise class name $candidateClass = self::class_name($candidateClass); - $exists = self::exists($candidateClass); - while($candidateClass && $candidateClass != 'DataObject' && $exists) { - if(DataObject::has_own_table($candidateClass)) { - $inst = singleton($candidateClass); + // Short circuit for fixed fields + $fixed = DataObject::config()->fixed_fields; + if($exists && isset($fixed[$fieldName])) { + return self::baseDataClass($candidateClass); + } - if($inst->hasOwnTableDatabaseField($fieldName)) { - break; - } + // Find regular field + while($candidateClass && $candidateClass != 'DataObject' && $exists) { + if( DataObject::has_own_table($candidateClass) + && DataObject::has_own_table_database_field($candidateClass, $fieldName) + ) { + break; } $candidateClass = get_parent_class($candidateClass); diff --git a/core/Object.php b/core/Object.php index 04dcc6905..6c9d17f84 100755 --- a/core/Object.php +++ b/core/Object.php @@ -457,13 +457,17 @@ abstract class Object { } $extensionClass = $matches[1]; if(!class_exists($extensionClass)) { - user_error(sprintf('Object::add_extension() - Can\'t find extension class for "%s"', $extensionClass), - E_USER_ERROR); + user_error( + sprintf('Object::add_extension() - Can\'t find extension class for "%s"', $extensionClass), + E_USER_ERROR + ); } if(!is_subclass_of($extensionClass, 'Extension')) { - user_error(sprintf('Object::add_extension() - Extension "%s" is not a subclass of Extension', - $extensionClass), E_USER_ERROR); + user_error( + sprintf('Object::add_extension() - Extension "%s" is not a subclass of Extension', $extensionClass), + E_USER_ERROR + ); } // unset some caches diff --git a/core/PaginatedList.php b/core/PaginatedList.php index 932ff2137..a31c3de76 100644 --- a/core/PaginatedList.php +++ b/core/PaginatedList.php @@ -434,6 +434,13 @@ class PaginatedList extends SS_ListDecorator { } } + /** + * Returns the total number of items in the list + */ + public function TotalItems() { + return $this->getTotalItems(); + } + /** * Set the request object for this list * diff --git a/docs/en/00_Getting_Started/03_Environment_Management.md b/docs/en/00_Getting_Started/03_Environment_Management.md index e915a003b..781631a6f 100644 --- a/docs/en/00_Getting_Started/03_Environment_Management.md +++ b/docs/en/00_Getting_Started/03_Environment_Management.md @@ -69,7 +69,8 @@ This is my `_ss_environment.php` file. I have it placed in `/var`, as each of th :::php '); @@ -106,7 +107,7 @@ This is my `_ss_environment.php` file. I have it placed in `/var`, as each of th | Name | Description | | ---- | ----------- | | `TEMP_FOLDER` | Absolute file path to store temporary files such as cached templates or the class manifest. Needs to be writeable by the webserver user. Defaults to *silverstripe-cache* in the webroot, and falls back to *sys_get_temp_dir()*. See *getTempFolder()* in *framework/core/TempPath.php*.| -| `SS_DATABASE_CLASS` | The database class to use, MySQLDatabase, MSSQLDatabase, etc. defaults to MySQLDatabase.| +| `SS_DATABASE_CLASS` | The database class to use, MySQLPDODatabase, MySQLDatabase, MSSQLDatabase, etc. defaults to MySQLDatabase.| | `SS_DATABASE_SERVER`| The database server to use, defaulting to localhost.| | `SS_DATABASE_USERNAME`| The database username (mandatory).| | `SS_DATABASE_PASSWORD`| The database password (mandatory).| diff --git a/docs/en/02_Developer_Guides/00_Model/05_Extending_DataObjects.md b/docs/en/02_Developer_Guides/00_Model/05_Extending_DataObjects.md index cb30afb4f..11f6a45b2 100644 --- a/docs/en/02_Developer_Guides/00_Model/05_Extending_DataObjects.md +++ b/docs/en/02_Developer_Guides/00_Model/05_Extending_DataObjects.md @@ -3,7 +3,7 @@ summary: Modify the data model without using subclasses. # Extending DataObjects -You can add properties and methods to existing [api:DataObjects]s like [api:Member] without hacking core code or sub +You can add properties and methods to existing [api:DataObject]s like [api:Member] without hacking core code or sub classing by using [api:DataExtension]. See the [Extending SilverStripe](../extending) guide for more information on [api:DataExtension]. diff --git a/docs/en/02_Developer_Guides/01_Templates/09_Casting.md b/docs/en/02_Developer_Guides/01_Templates/09_Casting.md index d93a85581..8c6298a5b 100644 --- a/docs/en/02_Developer_Guides/01_Templates/09_Casting.md +++ b/docs/en/02_Developer_Guides/01_Templates/09_Casting.md @@ -1,4 +1,4 @@ -title: Formating, Modifying and Casting Variables +title: Formatting, Modifying and Casting Variables summary: Information on casting, security, modifying data before it's displayed to the user and how to format data within the template. # Formatting and Casting diff --git a/docs/en/02_Developer_Guides/01_Templates/How_Tos/01_Navigation_Menu.md b/docs/en/02_Developer_Guides/01_Templates/How_Tos/01_Navigation_Menu.md index 7330c689a..eb555312d 100644 --- a/docs/en/02_Developer_Guides/01_Templates/How_Tos/01_Navigation_Menu.md +++ b/docs/en/02_Developer_Guides/01_Templates/How_Tos/01_Navigation_Menu.md @@ -17,11 +17,11 @@ top level menu with a nested second level using the `Menu` loop and a `Children` <% if $LinkOrSection == section %> <% if $Children %> -
  • <% end_if %> <% end_if %>
  • @@ -31,4 +31,4 @@ top level menu with a nested second level using the `Menu` loop and a `Children` ## Related * [Template Syntax](../syntax) -* [Common Variables](../common_variables) \ No newline at end of file +* [Common Variables](../common_variables) diff --git a/docs/en/02_Developer_Guides/03_Forms/Field_types/04_GridField.md b/docs/en/02_Developer_Guides/03_Forms/Field_types/04_GridField.md index 377526c14..c16718fb1 100644 --- a/docs/en/02_Developer_Guides/03_Forms/Field_types/04_GridField.md +++ b/docs/en/02_Developer_Guides/03_Forms/Field_types/04_GridField.md @@ -67,7 +67,7 @@ the `getConfig()` method on `GridField`. $fields = parent::getCMSFields(); $fields->addFieldToTab('Root.Pages', - $grid = GridField('Pages', 'All pages', SiteTree::get()) + $grid = new GridField('Pages', 'All pages', SiteTree::get()) ); // GridField configuration diff --git a/docs/en/02_Developer_Guides/05_Extending/00_Modules.md b/docs/en/02_Developer_Guides/05_Extending/00_Modules.md index 62478a282..75f955dbd 100644 --- a/docs/en/02_Developer_Guides/05_Extending/00_Modules.md +++ b/docs/en/02_Developer_Guides/05_Extending/00_Modules.md @@ -101,6 +101,51 @@ operate in other structures, paths to static files such as CSS or JavaScript won See the [How to Publish a SilverStripe Module](how_tos/publish_a_module) for details on how to publish your SilverStripe modules with the community +## Module Standard + +The SilverStripe module standard defines a set of conventions that high-quality SilverStripe modules should follow. It’s a bit like PSR for SilverStripe CMS. Suggested improvements can be raised as pull requests. + +### Coding Guidelines + + * Declaration of level of support is provided for each module (either via README.md or composer) including the below. + * Level of support provided. + * Supporting user(s) and/or organisation(s). + * Complies to a well defined module directory structure and coding standards: + * templates (for ss templates) + * code (for php files) + * tests (for php test files) and + * _config (for yml config) + * The module is a Composer package. + * All Composer dependencies are bound to a single major release (e.g. ^3.1 not >=3.1). + * There is a level of test coverage. + * A clear public API documented in the docblock tags. + * Recommend the use of [PSR-1](http://www.php-fig.org/psr/psr-1/) and [PSR-2](http://www.php-fig.org/psr/psr-2/). + * .gitattributes will be used to exclude non-essential files from the distribution. At a minimum tests, docs, and IDE/dev-tool config should be excluded. + +### Documentation Guidelines + +Documentation will use the following format: + + * README.md provides: + * Links or badges to CI and code quality tools. + * A short summary of the module, end-user. + * Installation instructions + * Testing/development instructions and a link to contrib instructions. + * How to report security vulnerabilities. Note that PSR-9 / PSR-10 may be recommended once released. + * Security, license, links to more detailed docs. + * CONTRIBUTING.md explaining terms of contribution. + * A changelog CHANGELOG.md (may link to other more detailed docs or GitHub releases if you want). + * Has a licence (LICENSE.md file) - for SilverStripe supported this needs to be BSD. + * Detailed documentation in /docs/en as a nested set of GitHub-compatible Markdown files. + * Links and image references are relative, and are able to be followed in viewers such as GitHub. + * Markdown may include non-visible comments or meta-data. + +Documentation will cover: + + * Installation + * Configuration + * Usage guides for key features; screenshots are recommended. + * A committers guide, covering PR-merging and release guidelines. ## Related diff --git a/docs/en/02_Developer_Guides/05_Extending/01_Extensions.md b/docs/en/02_Developer_Guides/05_Extending/01_Extensions.md index e1205aa33..b72e9c01c 100644 --- a/docs/en/02_Developer_Guides/05_Extending/01_Extensions.md +++ b/docs/en/02_Developer_Guides/05_Extending/01_Extensions.md @@ -23,7 +23,7 @@ the [api:Extension] class for non DataObject subclasses (such as [api:Controller public function SayHi() { // $this->owner refers to the original instance. In this case a `Member`. - return "Hi ". $this->owner->Name; + return "Hi " . $this->owner->Name; } } @@ -80,7 +80,7 @@ $has_one etc. public function SayHi() { // $this->owner refers to the original instance. In this case a `Member`. - return "Hi ". $this->owner->Name; + return "Hi " . $this->owner->Name; } } diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/05_Typography.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/05_Typography.md index 3c53ceb09..f86635b0b 100644 --- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/05_Typography.md +++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/05_Typography.md @@ -7,7 +7,7 @@ SilverStripe lets you customize the style of content in the CMS. This is done by `editor.css` in either your theme or in your `mysite` folder. This is set through :::php - HtmlEditorConfig::get('cms')->setOption('ContentCSS', project() . '/css/editor.css'); + HtmlEditorConfig::get('cms')->setOption('content_css', project() . '/css/editor.css'); Will load the `mysite/css/editor.css` file. diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/06_Javascript_Development.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/06_Javascript_Development.md index 5f846c393..ce4cffd3f 100644 --- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/06_Javascript_Development.md +++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/06_Javascript_Development.md @@ -250,7 +250,7 @@ Ready](http://docs.jquery.com/How_jQuery_Works#Launching_Code_on_Document_Ready) jQuery supports automatically reapplying event handlers when new DOM elements get inserted, mostly through Ajax calls. This "binding" saves you from reapplying this step manually. -Caution: Only applies to certain events, see the [jQuery.on() documentation](http://api.jquery.com/on/). +Caution: Only applies to certain events, see the [jQuery.on() documentation](http://api.jquery.com/on/#direct-and-delegated-events). Example: Add a 'loading' classname to all pressed buttons @@ -261,14 +261,11 @@ Example: Add a 'loading' classname to all pressed buttons }); // binding, applies to any inserted elements as well - $('input[[type=submit]]').on(function() { + $('.cms-container').on('click', 'input[[type=submit]]', function() { $(this).addClass('loading'); }); -See [jQuery FAQ: Why do my events stop working after an AJAX -request](http://docs.jquery.com/Frequently_Asked_Questions#Why_do_my_events_stop_working_after_an_AJAX_request.3F). - ### Assume Element Collections jQuery is based around collections of DOM elements, the library functions typically handle multiple elements (where it diff --git a/docs/en/04_Changelogs/3.1.15.md b/docs/en/04_Changelogs/3.1.15.md new file mode 100644 index 000000000..2110b4190 --- /dev/null +++ b/docs/en/04_Changelogs/3.1.15.md @@ -0,0 +1,13 @@ +# 3.1.15 + +This release resolves issues with compatibility with PHP 5.3.3 introduced in 3.1.14 + + + +## Change Log + +### Bugfixes + + * 2015-09-17 [e64d73c](https://github.com/silverstripe/silverstripe-framework/commit/e64d73c1f741399412b6015f6602ed707b2e9778) Fix ClassInfo::table_for_object_field (Damian Mooyman) + * 2015-09-09 [06cc185](https://github.com/silverstripe/silverstripe-framework/commit/06cc18526a1f63b8bb16809e23f2eb17ade7a85e) UploadField error when attempting to attach non-existent file IDs (Loz Calver) + * 2015-09-07 [96d20bc](https://github.com/silverstripe/silverstripe-framework/commit/96d20bc1809c731e3e78b7c5248282c8771f3097) Fix missing framework/admin/tests (Damian Mooyman) diff --git a/docs/en/04_Changelogs/3.2.0.md b/docs/en/04_Changelogs/3.2.0.md index dad837b06..b40fe1dcc 100644 --- a/docs/en/04_Changelogs/3.2.0.md +++ b/docs/en/04_Changelogs/3.2.0.md @@ -3,8 +3,8 @@ ## Contents * [Major Changes](#major-changes) -* [Removed API](#deprecated-classesmethods-removed) -* [New API](#new-and-changed-api) +* [Deprecated classes/methods](#deprecated-classesmethods-removed) +* [New and changed API](#new-and-changed-api) * [Bugfixes](#bugfixes) * [Upgrading Notes](#upgrading-notes) @@ -183,6 +183,32 @@ The following functionality deprecated in 3.0 has been removed: ## Upgrading Notes +### Enable PDO + +Although this is not a mandatory upgrade step, the new `[api:PDOConnector]` class offers improved database +performance and security, and should be integrated into any project using 3.2. + +In order to update your connector you can do so in one of two ways, depending on whether or not +your project is using `_ss_environment.php` to configure your database, or via `mysite/_config.php` + +If using `_ss_environment.php`: + + + :::php + define('SS_DATABASE_CLASS', 'MySQLPDODatabase'); + + +If using `mysite/_config.php`: + + + :::php + global $databaseConfig; + $databaseConfig = array( + "type" => "MySQLPDODatabase" + // other config settings + ); + + ### Disable `LastVisited` and `NumVisits` counter These fields were deprecated in 3.1 due to performance concerns, and should be disabled unless required by @@ -788,3 +814,163 @@ In order to remove the new "archive" action and restore the old "delete" action enabled_legacy_actions: - CMSBatchAction_Delete + + +## Change Log + +### API Changes + + * 2015-08-03 [f2c39aa](https://github.com/silverstripe/silverstripe-framework/commit/f2c39aac200f50157d9163b825ea7a7dd1f7aa18) batch restore action (Damian Mooyman) + * 2015-08-03 [e22b653](https://github.com/silverstripe/silverstripe-cms/commit/e22b653e06207bfdc0b36ac7a9e6be250e10bde8) batch restore action (Damian Mooyman) + * 2015-07-10 [a6677b1](https://github.com/silverstripe/silverstripe-cms/commit/a6677b1653cf338d66b8b6d1e4d5b14d66250c0e) respect custom attributes on OptionsetField and CheckboxSetField (Damian Mooyman) + * 2015-07-10 [560f9a6](https://github.com/silverstripe/silverstripe-framework/commit/560f9a6e39df4f09dfe4bed5978f6dcddc0bb299) respect custom attributes on OptionsetField and CheckboxSetField (Damian Mooyman) + * 2015-06-15 [f3e1472](https://github.com/silverstripe/silverstripe-cms/commit/f3e1472493b15758c67bb2c8814bc28765eac401) Revert DataObject::validate to 3.1 method signature (protected) (Damian Mooyman) + * 2015-06-15 [58cc3da](https://github.com/silverstripe/silverstripe-framework/commit/58cc3da8d8005d6a367d88fb7c5d41c96dd8946f) Revert DataObject::validate to 3.1 method signature (protected) (Damian Mooyman) + * 2015-06-13 [e766658](https://github.com/silverstripe/silverstripe-framework/commit/e766658ee3b9e70988b79d99d75124857f2a7ccc) Allow HTTP Cache Headers to be customized (Jeremy Shipman) + * 2015-06-12 [8389260](https://github.com/silverstripe/silverstripe-framework/commit/838926085cac00ec65ee5aecb67e6102ea8b6f20) and renamed image functions (Jonathon Menz) + * 2015-06-09 [914d734](https://github.com/silverstripe/silverstripe-framework/commit/914d734df004947eb869de2abb6fb2fc463be574) Disable deprecation notices by default (Damian Mooyman) + * 2015-06-09 [a8ace75](https://github.com/silverstripe/silverstripe-framework/commit/a8ace7534194b5e1a636c96eca4607d08726dfeb) Support for multiple HTMLEditorConfig per page (Damian Mooyman) + * 2015-05-14 [b169823](https://github.com/silverstripe/silverstripe-cms/commit/b169823a00fed190bcd55054339baa3bc818cd75) Deprecate delete in favour of archive (Damian Mooyman) + * 2015-05-14 [a72bd16](https://github.com/silverstripe/silverstripe-framework/commit/a72bd16f420915d4ef2301ee1bec3dcfe2ed2305) Deprecate delete in favour of archive (Damian Mooyman) + * 2015-04-30 [c5e0c8f](https://github.com/silverstripe/silverstripe-cms/commit/c5e0c8f007c814e82f2c7f84b1fb4eacbcf5ab4d) Enable tree filter highlighting (Damian Mooyman) + * 2015-04-30 [8863797](https://github.com/silverstripe/silverstripe-framework/commit/8863797b76fd1f81d9e9f4900fc6c387966554da) Enable tree filter highlighting (Damian Mooyman) + * 2015-04-29 [e8d6f15](https://github.com/silverstripe/silverstripe-framework/commit/e8d6f15f2883b765bf17bb7027013ebd2a79cf9c) Use mysql buffered statements (Damian Mooyman) + * 2015-04-09 [e91606e](https://github.com/silverstripe/silverstripe-framework/commit/e91606e4943a1725d51f5c0f7bf80165995bc814) Introduce $FromEnd variable for iterators (Damian Mooyman) + * 2015-03-31 [95c162e](https://github.com/silverstripe/silverstripe-framework/commit/95c162ef0d645a2af9ad355ef195ab426a881fd4) Security better respects BackURL on login (Damian Mooyman) + * 2015-03-04 [9367fd2](https://github.com/silverstripe/silverstripe-framework/commit/9367fd2456a1f3f535f55249f9d6d5a2d7399af9) enable PaginatedList to be disabled by setting page length to 0 (Damian Mooyman) + * 2015-01-14 [5d4c2c4](https://github.com/silverstripe/silverstripe-framework/commit/5d4c2c4b34e1a0d544ce1b39a8d6fd74420025d4) Adding default_classes to FormField (Daniel Hensby) + * 2015-01-14 [6d00027](https://github.com/silverstripe/silverstripe-framework/commit/6d0002780dc89af91354979cba4d09d2cf8946da) Adding default_classes to Form (Daniel Hensby) + * 2014-09-25 [e478009](https://github.com/silverstripe/silverstripe-framework/commit/e47800917a5482b1dce455f4fbcb564ff73d7576) Mailer can be configured to use different encoding mechanisms, and added support for unicode quoted-string encoding (Damian Mooyman) + * 2014-09-25 [29e3347](https://github.com/silverstripe/silverstripe-framework/commit/29e33475621fd9e4be20ecdea45d017bbd4f65f8) Convert::html2raw no longer wraps text automatically (Damian Mooyman) + * 2014-09-24 [5631553](https://github.com/silverstripe/silverstripe-framework/commit/563155391f02dca5017dfc2a967eb1e93f0f1014) Cookies set via Cookie::set() are now HTTP only by default (Sean Harvey) + * 2014-09-15 [062ad8e](https://github.com/silverstripe/silverstripe-framework/commit/062ad8e6850efa4a1b8895bd361cb93079685cfa) Allow parameterised joins / subselects (Damian Mooyman) + * 2014-08-15 [2ba1c46](https://github.com/silverstripe/silverstripe-cms/commit/2ba1c46bc86b3c8fdea723e6b936ede4806314be) broken link hihglighting to write to database. (Mateusz Uzdowski) + * 2014-08-13 [784e292](https://github.com/silverstripe/silverstripe-framework/commit/784e292d4e57b82c372f3db2edbbc6e0e067d4d3) Add a getter for customisedObject property. (Mateusz Uzdowski) + * 2014-08-09 [18d6c53](https://github.com/silverstripe/silverstripe-cms/commit/18d6c538a7d8865dca44f4e37d88b54dc30c20e6) Extract siteconfig out to an external module. (Will Rossiter) + * 2014-08-04 [1759d5d](https://github.com/silverstripe/silverstripe-framework/commit/1759d5d017068693b20f82ac7009004fd0163375) Use "number" HTML5 type for NumericField by default (Sean Harvey) + * 2014-07-29 [26a0e91](https://github.com/silverstripe/silverstripe-framework/commit/26a0e915536f067c5c5429ffa5224f3cff37b886) SS_Filterable, SS_Limitable and SS_Sortable now explicitly extend SS_List (Damian Mooyman) + * 2014-04-22 [d16db2d](https://github.com/silverstripe/silverstripe-framework/commit/d16db2d4f4b2fbd65722f40305fbc075edf72eb1) tinymce editor no longer transforms paragraphs with margin-left into blockquotes (Damian Mooyman) + * 2014-04-16 [5f7ebd3](https://github.com/silverstripe/silverstripe-framework/commit/5f7ebd3c235d663b5ad5c0fbcd3d393d2e893306) UploadField: move replaceFile to the front end config (Devlin) + * 2014-04-10 [5b55361](https://github.com/silverstripe/silverstripe-framework/commit/5b553616dc2438b3ad7803e2765bd37b0d1d8736) DateTime.Ago better infers significance of date units. (Damian Mooyman) + * 2014-04-09 [2e73dcb](https://github.com/silverstripe/silverstripe-framework/commit/2e73dcb8912223abb88354e09b13aafa902af8af) Remove swf,html,htm,xhtml,xml as default allowed upload able file types (Damian Mooyman) + * 2014-04-04 [bf4e9eb](https://github.com/silverstripe/silverstripe-framework/commit/bf4e9eb0443c00e1e8a06d0db5636edd627d55eb) Singleton method allowing type inference (Damian Mooyman) + * 2014-02-11 [6906c9b](https://github.com/silverstripe/silverstripe-framework/commit/6906c9bd1a5535e6e2674c26446f4fd6d81e8490) Removed auto-detection for i18n date/time formats (Ingo Schommer) + * 2014-01-17 [973b967](https://github.com/silverstripe/silverstripe-framework/commit/973b967e6b9ce68e0e03b97ae49f28a155a28c6e) Adding chaining to i18nTextCollector::write() (Daniel Hensby) + * 2014-01-02 [791ee71](https://github.com/silverstripe/silverstripe-framework/commit/791ee7171b20ffd66f2d6d0c18589adfc22b6680) Prevent large images from repeatedly crashing PHP on resize (Loz Calver) + * 2013-12-23 [5fff5af](https://github.com/silverstripe/silverstripe-framework/commit/5fff5afb478381a23e6b8b5b9079ae1fe5724fdd) moved useTestTheme to base Sapphire test class so that it can be used elsewhere (eg CMS test) (micmania1) + * 2013-12-19 [6fc9db6](https://github.com/silverstripe/silverstripe-framework/commit/6fc9db6f0e87fe935ccb46daff880158453ad04b) DataObject::validate() visibility changed to public (issue #1659) (Sean Harvey) + * 2013-11-26 [b88a095](https://github.com/silverstripe/silverstripe-framework/commit/b88a0955a5b314cc57573ec573f9839ec9d17f7a) Support string descriptors for unique indexes in Versioned (Fred Condo) + * 2013-10-17 [fee54c7](https://github.com/silverstripe/silverstripe-framework/commit/fee54c75f05d7bbc2b7c221c3150d201e1fffb59) Change DropdownField::getSource() to not return the emptyString value. (Nathan J. Brauer) + * 2013-10-17 [1c983bc](https://github.com/silverstripe/silverstripe-framework/commit/1c983bc16d7479c2c9bac3984e36545dc4a301e8) LookupField::Field now returns an HTMLText instance. (Will Rossiter) + * 2013-10-16 [52f6581](https://github.com/silverstripe/silverstripe-framework/commit/52f6581ecf1d09f8c368e2de15e4a64e69ff4a40) Better declaration of DataObject field change levels. (Damian Mooyman) + * 2013-10-10 [b6b3cd9](https://github.com/silverstripe/silverstripe-framework/commit/b6b3cd98891e0f6134c77225e76147d8721d0129) GridState_Data values can have default values specified during retrieval. (Damian Mooyman) + * 2013-10-09 [b367dd6](https://github.com/silverstripe/silverstripe-framework/commit/b367dd6237e56cc88744befa98e6c8f2cdd503f2) Removed Member.LastVisited and Member.NumVisits (Ingo Schommer) + * 2013-09-27 [c7f656c](https://github.com/silverstripe/silverstripe-framework/commit/c7f656cd0051a051bca2e60011c52ff812596d8a) Removed "PastMember" cookie and template getter (Ingo Schommer) + * 2013-08-08 [4385264](https://github.com/silverstripe/silverstripe-framework/commit/4385264aa9da453d3a9fcf28d92c61ef31d928f2) Make GridFieldConfig objects decoratable (unclecheese) + * 2013-07-10 [7c60c73](https://github.com/silverstripe/silverstripe-framework/commit/7c60c73dbb2559cc5950eb40efa640e04bde2d17) Polymorphic has_one behaviour (Damian Mooyman) + * 2013-06-30 [47147eb](https://github.com/silverstripe/silverstripe-framework/commit/47147eb3dfc39a13da9ff9b9644c0ce0375bd669) delete simplepie from framework thirdparty (carlos barberis) + * 2013-06-20 [a395c53](https://github.com/silverstripe/silverstripe-cms/commit/a395c5322fc1965b775be50149a38cdff36cca59) Move of codebase to parameterised query database abstraction layer (Damian Mooyman) + * 2013-06-20 [d8e9af8](https://github.com/silverstripe/silverstripe-framework/commit/d8e9af8af8d59b3ee16f404f2f2b0a528d503022) Database abstraction layer. Ticket #7429 (Damian Mooyman) + * 2013-05-31 [0c4ec47](https://github.com/silverstripe/silverstripe-framework/commit/0c4ec4708bcbb8fb09a1bb9acf75639077cbaaa9) Using $HolderID for form field container templates (Ingo Schommer) + * 2013-05-25 [ca87b8b](https://github.com/silverstripe/silverstripe-framework/commit/ca87b8b79496a78454d63c225f1f4f38fa55a150) Form Field ID attribute should follow HTML specification (Will Rossiter) + * 2013-05-22 [cb1f95e](https://github.com/silverstripe/silverstripe-framework/commit/cb1f95e51eff1ce762456e0fa6b7eca38ccc3198) Remove AjaxUniqueTextField, since its operation is very limited (#1947) (Ingo Schommer) + * 2013-01-29 [957469d](https://github.com/silverstripe/silverstripe-framework/commit/957469d770c555d5461ea476906fbaa64ac2bc02) Removed auto-routing of controller name (Ingo Schommer) + * 2013-01-17 [56346a5](https://github.com/silverstripe/silverstripe-cms/commit/56346a50bf161a2a840517cf8bf5d38cf8174103) moved reports API to separate module (Will Rossiter) + +### Features and Enhancements + + * 2015-06-02 [a9d22f1](https://github.com/silverstripe/silverstripe-framework/commit/a9d22f1fbf6e499ac0cc7f12e3f389015a07834d) Files can be uploaded directly in the 'Insert Link' form (scott1702) + * 2015-05-29 [44b1ff1](https://github.com/silverstripe/silverstripe-framework/commit/44b1ff193106e55aa754f64ddab28146f8857290) Configurable file version prefix (Jonathon Menz) + * 2015-05-11 [ce5a8f2](https://github.com/silverstripe/silverstripe-framework/commit/ce5a8f2b415d4c4f0680f5adece2686f0a490f48) Cookie names with dots are now handled more gracefully (Daniel Hensby) + * 2015-03-31 [ae8dbe3](https://github.com/silverstripe/silverstripe-framework/commit/ae8dbe309b797a20a91088351d70486cf3dfea79) - Added maximum upload file size by type (Turnerj) + * 2015-03-24 [16f0e7b](https://github.com/silverstripe/silverstripe-framework/commit/16f0e7b0d3f1b25af325c224ea4111303b50785b) ViewableData_Debugger implements __toString (Daniel Hensby) + * 2015-03-03 [835ee69](https://github.com/silverstripe/silverstripe-framework/commit/835ee69339fbfca0c477c3717cc12c1c1e7737e0) Only validate DataObject model definitions during a build (Loz Calver) + * 2015-02-24 [8ee9130](https://github.com/silverstripe/silverstripe-framework/commit/8ee9130bcf10339c3eed54e10aa55f297ec89efd) CMS site tree status icons (Jonathon Menz) + * 2015-02-08 [5f31983](https://github.com/silverstripe/silverstripe-framework/commit/5f31983ded7a7a08586a74a9b5ff594d84a8a11c) updateAttributes hook in FormField (Ingo Schommer) + * 2015-01-23 [3f1805b](https://github.com/silverstripe/silverstripe-framework/commit/3f1805bfd2934bdf2a489fdd00b5c21308cf9837) Support multiple many_manys between the same classes (closes #1377) (Josh) + * 2014-12-15 [6ad8f7c](https://github.com/silverstripe/silverstripe-framework/commit/6ad8f7c3dd1d4b18d9982ac33e709dac6436a664) Subject line for email links in HtmlEditorField (Loz Calver) + * 2014-11-12 [41ea83b](https://github.com/silverstripe/silverstripe-framework/commit/41ea83b3374d026da9575f5256a02bdcfbb82059) add validation to form field subclasses (Stevie Mayhew) + * 2014-10-17 [dc7bc46](https://github.com/silverstripe/silverstripe-framework/commit/dc7bc4673e6860938519bb7cb9fba9e3835fd5de) Text - Limit characters to closest word (Anton Smith) + * 2014-10-03 [23fc498](https://github.com/silverstripe/silverstripe-framework/commit/23fc498c275db92ba182be3bf13e672b20866ba3) Allow 'null' limit for database queries (closes #3487) (Loz Calver) + * 2014-05-04 [3b9056f](https://github.com/silverstripe/silverstripe-framework/commit/3b9056fc014d1a9432aa1142174904ac6c1f8e08) Cookie_Backend for managing cookie state (Daniel Hensby) + * 2013-10-17 [e8287cd](https://github.com/silverstripe/silverstripe-framework/commit/e8287cd2f56952345be65e98fb732476b8c0b481) Hook for `Member::registerFailedLogin` (Thomas Speak) + * 2013-08-23 [7d7c754](https://github.com/silverstripe/silverstripe-cms/commit/7d7c75414c338bfd906f7e63eccaccff913951ef) Track broken anchors (Russell Michell) + * 2013-06-05 [60333f6](https://github.com/silverstripe/silverstripe-framework/commit/60333f68ee3557ce9ecef1984c988a08c2fe6b51) UploadField lists all files, shows path info (Ingo Schommer) + * 2013-06-03 [2a91d27](https://github.com/silverstripe/silverstripe-framework/commit/2a91d27ccb15ea4bb2e8501b7735f977a206d83b) use Injector pattern to create ValidationResult in validate (Will Morgan) + * 2013-05-25 [736bde8](https://github.com/silverstripe/silverstripe-framework/commit/736bde8fe578a8702e72e801996b9cc2c989b9c2) Add Convert::raw2htmlid() (Will Rossiter) + * 2013-03-26 [64349fe](https://github.com/silverstripe/silverstripe-framework/commit/64349fefb5fdc2c8a189a49d72e6a68a6c95afbc) Allow setting of ASSETS_DIR in _ss_environment.php (Loz Calver) + +### Bugfixes + + * 2015-10-06 [df805af](https://github.com/silverstripe/silverstripe-framework/commit/df805af67bda15888d17f49817903bf136561773) Imagick tests compare image dimensions rather than image hashes (Damian Mooyman) + * 2015-10-05 [ad42f80](https://github.com/silverstripe/silverstripe-framework/commit/ad42f802c4a621916a352c3a7c5d4f849b896c3e) Fix duplicate HolderID on TreeDropdownField (Damian Mooyman) + * 2015-10-05 [6c117cd](https://github.com/silverstripe/silverstripe-framework/commit/6c117cd62960670239c5a6f6b3832c819e21332a) fix imagick interface and add to travis (Damian Mooyman) + * 2015-09-30 [cb55a0a](https://github.com/silverstripe/silverstripe-framework/commit/cb55a0a621494873a04c697ecd326bb7a4d02173) GridFieldSortableHeader incorrectly reporting fields as sortable (Loz Calver) + * 2015-09-29 [666ce26](https://github.com/silverstripe/silverstripe-framework/commit/666ce269292521288eef8aeac4af30378f775576) Permission::checkMember() use of undefined variable $codes (Manuel Teuber) + * 2015-09-23 [8f0f647](https://github.com/silverstripe/silverstripe-framework/commit/8f0f6475daa6cb32a33089ef60f18d5f4f8735ed) Issues with field focus in edit forms (fixes #4621) (Loz Calver) + * 2015-09-23 [052aba1](https://github.com/silverstripe/silverstripe-cms/commit/052aba17acee51a276e42bcc0bd5a26b4cc2ae58) Incorrect field IDs breaking SiteTree settings toggles (fixes #1280) (Loz Calver) + * 2015-09-22 [0d89a13](https://github.com/silverstripe/silverstripe-framework/commit/0d89a13c2d02dc08d8ff14884b12f22b2f1cf4f2) GridFieldDetailForm failing to save many_many relations (Loz Calver) + * 2015-09-14 [81ca74b](https://github.com/silverstripe/silverstripe-framework/commit/81ca74bc30cb8f128c48672fd9807943c924145d) #103 (David Alexander) + * 2015-09-10 [6056e9c](https://github.com/silverstripe/silverstripe-framework/commit/6056e9cb1bc4f8073aef07b83f7417edbe7f2ac4) Editing existing file links in HtmlEditorField was broken (Loz Calver) + * 2015-08-31 [e86b45b](https://github.com/silverstripe/silverstripe-framework/commit/e86b45bf5db663b03e006a132e04afba37ee4bf3) Remove html5 number field due to insufficient localisation support (Damian Mooyman) + * 2015-08-24 [f7c1983](https://github.com/silverstripe/silverstripe-framework/commit/f7c19830d663ee05d81f7fa504b1ef043b8361fe) Fix JS error on clicking collapsed panel (Damian Mooyman) + * 2015-08-24 [6c17397](https://github.com/silverstripe/silverstripe-cms/commit/6c173973229acc198cb467ee369bab5af96b7f13) block adding children from archived pages (Damian Mooyman) + * 2015-08-21 [0f81d5e](https://github.com/silverstripe/silverstripe-framework/commit/0f81d5ece57a50c0daaf0d86c2faa977f323663b) Fix bulk actions making sitetree unclickable (Damian Mooyman) + * 2015-08-09 [cf9d2d1](https://github.com/silverstripe/silverstripe-framework/commit/cf9d2d12ac7fc6a2509ee70f8e6f304b3b232019) Fix duplicate primary key crash on duplicate (Damian Mooyman) + * 2015-08-07 [1f0602d](https://github.com/silverstripe/silverstripe-framework/commit/1f0602d42fd9e1c0a4268f3a51aa7f483100a935) Fixed regression from ClassInfo case-sensitivity fix. (Sam Minnee) + * 2015-07-30 [66ca540](https://github.com/silverstripe/silverstripe-framework/commit/66ca5405d0cb8116e5cdf5f886b96d321b20477c) Fix change detection on browser back button (Damian Mooyman) + * 2015-07-30 [97b226a](https://github.com/silverstripe/silverstripe-framework/commit/97b226abe023bbc059633cd944ff04c281a675a8) Fix semver violation in create_table_options (Damian Mooyman) + * 2015-07-27 [aa286ef](https://github.com/silverstripe/silverstripe-framework/commit/aa286ef7d77d78cde1aaedb2eca5b3c07803366b) Missing thumbnails and inconsistencies (Jonathon Menz) + * 2015-07-23 [10b2fdc](https://github.com/silverstripe/silverstripe-cms/commit/10b2fdc3181310ec3ca75361852deca57ccbbe4c) ContentController::getViewer() not returning all found templates (fixes #1244) (Loz Calver) + * 2015-07-22 [b7480b9](https://github.com/silverstripe/silverstripe-framework/commit/b7480b92a9c734058135a3259a1c4432c6bb474d) Hide 'Logged Passwords' tab in member CMS fields (fixes #4422) (Loz Calver) + * 2015-07-05 [a5b3083](https://github.com/silverstripe/silverstripe-framework/commit/a5b3083dccaedf6a78a5bfd5ecfc5d12ca7cdfba) memory exhaustion in MySQLStatement->bind() (micmania1) + * 2015-07-01 [3b90fef](https://github.com/silverstripe/silverstripe-cms/commit/3b90fef04f914aa6d4a43322771ea1d6b3329af2) fix behat tests (Damian Mooyman) + * 2015-06-24 [3507ddb](https://github.com/silverstripe/silverstripe-framework/commit/3507ddb0e8f85cb2a2cb20595590b1c89cc27c67) MemberPassword history removed with with Members (Daniel Hensby) + * 2015-06-19 [a58e595](https://github.com/silverstripe/silverstripe-framework/commit/a58e59565b7b092451b084643d58ddb6ccfbee31) docs not included in composer package installs (through export-ignore git attribute) (Sam Minnee) + * 2015-06-16 [ce3b5a5](https://github.com/silverstripe/silverstripe-framework/commit/ce3b5a5ace556f65a23348ed6e7bd50dd639f9e0) Fix major segfault on PDOConnector after any DDL (Damian Mooyman) + * 2015-06-09 [24a268a](https://github.com/silverstripe/silverstripe-framework/commit/24a268a12b5ade6e513694e6e7d826f5f0759ee2) Image test cleanup (Jonathon Menz) + * 2015-06-09 [07c21e2](https://github.com/silverstripe/silverstripe-framework/commit/07c21e28805236807387b984e988f62043728620) Fix deletion of orphaned versioned records when a parent _versions table has been deleted (Damian Mooyman) + * 2015-06-08 [acf19b7](https://github.com/silverstripe/silverstripe-framework/commit/acf19b72e2a6fb52527a788b1ed87f552e57f314) Fix false values for many_many_ExtraFields not being saved (Damian Mooyman) + * 2015-06-04 [a819bcf](https://github.com/silverstripe/silverstripe-cms/commit/a819bcfc97a6594787cea738bda2596787ab673f) explicitly call get functions for site tree checks (Stevie Mayhew) + * 2015-05-22 [68d8df4](https://github.com/silverstripe/silverstripe-framework/commit/68d8df4e04556b3f9ad63a6d8cff84e63f972d66) DropdownField didn't consider disabled items (Loz Calver) + * 2015-05-11 [9e8a5c9](https://github.com/silverstripe/silverstripe-framework/commit/9e8a5c9ba557298eed319744d3cc5689483063ab) remove validation type constraint from form fields for 3.2 release (Stevie Mayhew) + * 2015-04-02 [dd0e2dc](https://github.com/silverstripe/silverstripe-framework/commit/dd0e2dc36200e3931923693c2b9dc978aea99825) Image_Cached exists method doesnt check for positive ID (Daniel Hensby) + * 2015-02-14 [bee642a](https://github.com/silverstripe/silverstripe-framework/commit/bee642a6b9de946f507b73f07412d4ee2127fe45) make class loader classExists check interface_exists as per docs (Daniel Hensby) + * 2015-02-13 [66391ab](https://github.com/silverstripe/silverstripe-framework/commit/66391ab57ad49c2a40bad59fc1fc9e1f12e39d97) Imported namespaces now correctly used to determine class inheritance (Daniel Hensby) + * 2015-02-08 [6212b4b](https://github.com/silverstripe/silverstripe-framework/commit/6212b4bd4bd9adcc79042ffffe88144796239b57) Versioned not ignoring obsolete fields (Benjamin R. White) + * 2015-01-30 [e724d6f](https://github.com/silverstripe/silverstripe-framework/commit/e724d6f578af8878226665f189c596276e4b1536) notice level error when value is not set on CreditCardField (Will Rossiter) + * 2015-01-07 [cee7adc](https://github.com/silverstripe/silverstripe-framework/commit/cee7adc12c9a05f14e956f8ff23f06c43e337b5f) . Placeholder isn't completely translated (Elvinas L) + * 2014-12-15 [c358ac6](https://github.com/silverstripe/silverstripe-framework/commit/c358ac6496a837e86e5b0ab97fcc56ae8a78a250) How to folder on forms (Cam Findlay) + * 2014-12-08 [bdb3b7f](https://github.com/silverstripe/silverstripe-framework/commit/bdb3b7f085d9ddc1152a98cc93418bcfd10d63d5) Feedback to name the fields section to "field types" to make it clearer what the section is about. (Cam Findlay) + * 2014-12-08 [aba9667](https://github.com/silverstripe/silverstripe-framework/commit/aba966729ac7570435fc33227e3ca88f4e4d955f) use GFMD code blocks to fix code formatting consistency. (Cam Findlay) + * 2014-11-03 [51337ac](https://github.com/silverstripe/silverstripe-framework/commit/51337acda91a68d0d353c521fb4541531dfa82bc) Image backend ignoring config. (Michael Strong) + * 2014-10-26 [ec0c259](https://github.com/silverstripe/silverstripe-framework/commit/ec0c259c17cd3b1df6235378692ed8b6a7630dfc) Reinstate tab and form focus states (fixes CMS #732 and #817) (Naomi Guyer) + * 2014-09-26 [db0cad4](https://github.com/silverstripe/silverstripe-framework/commit/db0cad461670a11f9ba27f979812be4d70ab37c9) ErrorControlChain now supports exception handling (Damian Mooyman) + * 2014-09-01 [c140459](https://github.com/silverstripe/silverstripe-framework/commit/c140459ac624738630ac8bec6a665fa3040e2e54) Fix versioned (Damian Mooyman) + * 2014-09-01 [3644110](https://github.com/silverstripe/silverstripe-framework/commit/364411034947b78d9077caf91ad215ae79d2afba) Ensure that columns are unique within a gridfield (Will Rossiter) + * 2014-08-01 [b0239f4](https://github.com/silverstripe/silverstripe-framework/commit/b0239f43302110f250d6121a518c5119a76d1fca) Fix PDOConnector issues (Damian Mooyman) + * 2014-07-25 [81c0a34](https://github.com/silverstripe/silverstripe-framework/commit/81c0a3499bea4aa4191011616e2cbaf9ed075748) Remove caching of statements due to risk of instability (Damian Mooyman) + * 2014-07-14 [0433ba1](https://github.com/silverstripe/silverstripe-framework/commit/0433ba1642efdd32c5667c12cc3ef7f2f5e7db04) Revert some changes to ManyManyList (Damian Mooyman) + * 2014-05-22 [3213630](https://github.com/silverstripe/silverstripe-framework/commit/32136305be887fe3118f078c3f73df569c86ca53) fix listview not working with IE9 (Igor) + * 2014-05-09 [8335de4](https://github.com/silverstripe/silverstripe-framework/commit/8335de49b3dacd614819af5f7ce12157bb38d6b9) remove redundant DB name switch in TestRunner (Will Morgan) + * 2014-05-02 [9cbfd14](https://github.com/silverstripe/silverstripe-framework/commit/9cbfd14d9d75628bdfd97a31ab571b5ad597b5eb) TemplateManifest prevent cache collision (Will Morgan) + * 2014-04-29 [5dd0583](https://github.com/silverstripe/silverstripe-cms/commit/5dd058338af08dd3ee5956e7a7c66c30160f6cd4) Fix encoding of SearchForm::getSearchQuery (Damian Mooyman) + * 2014-04-08 [438fe02](https://github.com/silverstripe/silverstripe-framework/commit/438fe02116365569893f3370d08c4b1f20f0b19e) change action variable source to getViewer (Will Morgan) + * 2014-03-27 [cf5d524](https://github.com/silverstripe/silverstripe-framework/commit/cf5d524235b82c3f13a0643333ffcd140788da14) Fix regressions from #2206 in hasValue and dbObject (Damian Mooyman) + * 2014-03-25 [4b87b2e](https://github.com/silverstripe/silverstripe-cms/commit/4b87b2e2e6ab1aac546d707f79ce00dc17ca07f8) Fix ContentControllerTest (Damian Mooyman) + * 2014-02-28 [ab52b67](https://github.com/silverstripe/silverstripe-framework/commit/ab52b677aac5caae974928642aee42cc76f54f65) Log out current member when forgotten password (Daniel Hensby) + * 2014-02-20 [f6b72a2](https://github.com/silverstripe/silverstripe-framework/commit/f6b72a20919c77615d222f28adaa735ff0f0a49b) Fixed regression in ContentController template selection. (Sam Minnee) + * 2014-02-14 [d0a4fc2](https://github.com/silverstripe/silverstripe-cms/commit/d0a4fc206542242362a753414bd28366c9c1a84e) Fix failover to index template in ContentController::getViewer() (Sam Minnee) + * 2014-02-03 [cd213ab](https://github.com/silverstripe/silverstripe-framework/commit/cd213ab4884958d45cccaaf75cde15c0c525584b) Fixed handing of false values in GridState_Data (Damian Mooyman) + * 2014-01-31 [6df276c](https://github.com/silverstripe/silverstripe-framework/commit/6df276c843621ca07da3ace5be681cef82dc1ae3) GridState_Data doesn't hold falsey values (Daniel Hensby) + * 2013-10-30 [4102cc6](https://github.com/silverstripe/silverstripe-framework/commit/4102cc64a07992639ea8e9fa91ad55f3c771e430) Issues with CMSForm not consistently respecting new form naming scheme. (Damian Mooyman) + * 2013-10-22 [8534982](https://github.com/silverstripe/silverstripe-framework/commit/85349820e4da838236064681d72405737850b438) Debug error handler breaks error_get_last (Damian Mooyman) + * 2013-10-19 [ab10c2e](https://github.com/silverstripe/silverstripe-framework/commit/ab10c2ecdc8522d11becb59fe7020ab0526d59e9) An enum field in the search panel model admin misses an option to not filter on that field (Nico Haase) + * 2013-10-17 [d22ca62](https://github.com/silverstripe/silverstripe-framework/commit/d22ca62c6f324548b7c494c84b39a4197e7a5f35) FailedLoginCount reset (Thomas Speak) + * 2013-10-02 [fb5bb64](https://github.com/silverstripe/silverstripe-framework/commit/fb5bb646fe2734464ef3fd500765146cdd63dbeb) Fixed cross-platform issues with test cases and file utilities (Damian Mooyman) + * 2013-05-30 [c7468ca](https://github.com/silverstripe/silverstripe-framework/commit/c7468caeb67ad680ef748621348b0d82e2fed992) Generate Form::FormName() through (Will Rossiter) + * 2013-05-25 [831a507](https://github.com/silverstripe/silverstripe-framework/commit/831a507c90b8a4560742e86ecb5defd6fe1e259d) Update references to ID values from 79c9433 (Will Rossiter) + * 2013-05-17 [3728907](https://github.com/silverstripe/silverstripe-framework/commit/372890703ca96abfa8695277c1851c0b8ca52428) allow children to be accessed via template (Will Morgan) + * 2013-01-23 [60c4d99](https://github.com/silverstripe/silverstripe-framework/commit/60c4d999d8a5892132ef3e29d47d8ced410c7061) PHPUnit latest not working with composer installed builds (Hamish Friedlander) + * 2012-12-13 [31255fc](https://github.com/silverstripe/silverstripe-framework/commit/31255fc8f0b03cd70ef3dc50c206c943b07c4c01) Set visibility on login form methods to public. (Justin Martin) + * 2012-12-11 [379b561](https://github.com/silverstripe/silverstripe-framework/commit/379b561cdbd599134196cd7801087f725d8fa993) RSSFeed now sets the Content-Type on the current HTTPResponse (Simon Welsh) diff --git a/docs/en/04_Changelogs/rc/3.2.0-rc2.md b/docs/en/04_Changelogs/rc/3.2.0-rc2.md new file mode 100644 index 000000000..12478d756 --- /dev/null +++ b/docs/en/04_Changelogs/rc/3.2.0-rc2.md @@ -0,0 +1,33 @@ +# 3.2.0-rc2 + +See [3.2.0](/changelogs/3.2.0) changelog for more information on what is new in 3.2 + + + +## Change Log + +### Security + + * 2015-09-07 [d8fd64c](https://github.com/silverstripe/silverstripe-framework/commit/d8fd64c3e25dbf500615ecbbe9580e234e1730d4) Fix XSS in install.php (Damian Mooyman) - See [ss-2015-016](http://www.silverstripe.org/software/download/security-releases/ss-2015-016) + * 2015-09-07 [7192932](https://github.com/silverstripe/silverstripe-framework/commit/7192932022510d830d1fc2373a9edb80fee24f48) Fix insecure returnURL in DatabaseAdmin (Damian Mooyman) - See [ss-2015-015](http://www.silverstripe.org/software/download/security-releases/ss-2015-015) + * 2015-09-07 [7367cf5](https://github.com/silverstripe/silverstripe-framework/commit/7367cf54c4069a8e296fafb511fb28e27a8efd7e) Prevent possible Privilege escalation (Damian Mooyman) - See [ss-2015-020](http://www.silverstripe.org/software/download/security-releases/ss-2015-020) + +### Bugfixes + + * 2015-10-06 [df805af](https://github.com/silverstripe/silverstripe-framework/commit/df805af67bda15888d17f49817903bf136561773) Imagick tests compare image dimensions rather than image hashes (Damian Mooyman) + * 2015-10-05 [ad42f80](https://github.com/silverstripe/silverstripe-framework/commit/ad42f802c4a621916a352c3a7c5d4f849b896c3e) Fix duplicate HolderID on TreeDropdownField (Damian Mooyman) + * 2015-10-05 [6c117cd](https://github.com/silverstripe/silverstripe-framework/commit/6c117cd62960670239c5a6f6b3832c819e21332a) fix imagick interface and add to travis (Damian Mooyman) + * 2015-09-30 [cb55a0a](https://github.com/silverstripe/silverstripe-framework/commit/cb55a0a621494873a04c697ecd326bb7a4d02173) GridFieldSortableHeader incorrectly reporting fields as sortable (Loz Calver) + * 2015-09-23 [8f0f647](https://github.com/silverstripe/silverstripe-framework/commit/8f0f6475daa6cb32a33089ef60f18d5f4f8735ed) Issues with field focus in edit forms (fixes #4621) (Loz Calver) + * 2015-09-23 [052aba1](https://github.com/silverstripe/silverstripe-cms/commit/052aba17acee51a276e42bcc0bd5a26b4cc2ae58) Incorrect field IDs breaking SiteTree settings toggles (fixes #1280) (Loz Calver) + * 2015-09-22 [0d89a13](https://github.com/silverstripe/silverstripe-framework/commit/0d89a13c2d02dc08d8ff14884b12f22b2f1cf4f2) GridFieldDetailForm failing to save many_many relations (Loz Calver) + * 2015-09-14 [81ca74b](https://github.com/silverstripe/silverstripe-framework/commit/81ca74bc30cb8f128c48672fd9807943c924145d) #103 (David Alexander) + * 2015-09-10 [6056e9c](https://github.com/silverstripe/silverstripe-framework/commit/6056e9cb1bc4f8073aef07b83f7417edbe7f2ac4) Editing existing file links in HtmlEditorField was broken (Loz Calver) + * 2015-09-09 [06cc185](https://github.com/silverstripe/silverstripe-framework/commit/06cc18526a1f63b8bb16809e23f2eb17ade7a85e) UploadField error when attempting to attach non-existent file IDs (Loz Calver) + * 2015-09-07 [45b22c7](https://github.com/silverstripe/silverstripe-framework/commit/45b22c788eeb5d7501844ceb19395cc4e15e61b6) Fix missing framework/admin/tests (Damian Mooyman) + * 2015-09-07 [96d20bc](https://github.com/silverstripe/silverstripe-framework/commit/96d20bc1809c731e3e78b7c5248282c8771f3097) Fix missing framework/admin/tests (Damian Mooyman) + * 2015-08-31 [e86b45b](https://github.com/silverstripe/silverstripe-framework/commit/e86b45bf5db663b03e006a132e04afba37ee4bf3) Remove html5 number field due to insufficient localisation support (Damian Mooyman) + * 2015-08-27 [899eb0b](https://github.com/silverstripe/silverstripe-framework/commit/899eb0b235859c843890c790e99c03f4fd4b825c) Use complete fieldlist for extracting data (Daniel Hensby) + * 2015-08-26 [2d4b743](https://github.com/silverstripe/silverstripe-framework/commit/2d4b743090935e7c10bd95e00398df7bfb5763af) Members can access their own profiles in CMS (Daniel Hensby) + * 2015-08-26 [0943b3b](https://github.com/silverstripe/silverstripe-framework/commit/0943b3b1a06e6c9130500532fd979c720b65c761) Recursion errors when sorting objects with circular dependencies (fixes #4464) (Loz Calver) + * 2015-08-20 [fc212e0](https://github.com/silverstripe/silverstripe-framework/commit/fc212e030c474d966ffb1821423ddcb3ae361b72) Fix illegalExtensions breaking tests. (Damian Mooyman) diff --git a/docs/en/05_Contributing/01_Code.md b/docs/en/05_Contributing/01_Code.md index 99e70f276..b8998a851 100644 --- a/docs/en/05_Contributing/01_Code.md +++ b/docs/en/05_Contributing/01_Code.md @@ -1,7 +1,7 @@ title: Contributing Code summary: Fix bugs and add new features to help make SilverStripe better. -# Contributing Code - Submiting Bugfixes and Enhancements +# Contributing Code - Submitting Bugfixes and Enhancements SilverStripe will never be finished, and we need your help to keep making it better. If you're a developer a great way to get involved is to contribute patches to our modules and core codebase, fixing bugs or adding features. diff --git a/docs/en/05_Contributing/06_Core_committers.md b/docs/en/05_Contributing/06_Core_committers.md index afc6ff2d5..3c1fa808f 100644 --- a/docs/en/05_Contributing/06_Core_committers.md +++ b/docs/en/05_Contributing/06_Core_committers.md @@ -6,6 +6,7 @@ The core committers team is reviewed approximately annually, new members are add * [Daniel Hensby](https://github.com/dhensby) * [Hamish Friedlander](https://github.com/hafriedlander) * [Ingo Schommer](https://github.com/chillu) +* [Jono Menz](https://github.com/jonom) * [Loz Calver](https://github.com/kinglozzer) * [Sam Minnée](https://github.com/sminnee) * [Sean Harvey](https://github.com/halkyon/) diff --git a/forms/CompositeField.php b/forms/CompositeField.php index 4b5f8bf3d..c7bb0eabf 100644 --- a/forms/CompositeField.php +++ b/forms/CompositeField.php @@ -222,6 +222,9 @@ class CompositeField extends FormField { return $ret; } + /** + * @uses FieldList->insertAfter() + */ public function insertAfter($insertAfter, $field) { $ret = $this->children->insertAfter($insertAfter, $field); $this->sequentialSet = null; diff --git a/forms/DropdownField.php b/forms/DropdownField.php index bc9f9ad46..60902a019 100644 --- a/forms/DropdownField.php +++ b/forms/DropdownField.php @@ -348,7 +348,9 @@ class DropdownField extends FormField { */ public function castedCopy($classOrCopy) { $field = parent::castedCopy($classOrCopy); - $field->setHasEmptyDefault($this->getHasEmptyDefault()); + if($field->hasMethod('setHasEmptyDefault')) { + $field->setHasEmptyDefault($this->getHasEmptyDefault()); + } return $field; } } diff --git a/forms/FieldList.php b/forms/FieldList.php index 55188ece3..4f27a11ea 100644 --- a/forms/FieldList.php +++ b/forms/FieldList.php @@ -312,7 +312,7 @@ class FieldList extends ArrayList { * Returns a named field. * You can use dot syntax to get fields from child composite fields * - * @todo Implement similiarly to dataFieldByName() to support nested sets - or merge with dataFields() + * @todo Implement similarly to dataFieldByName() to support nested sets - or merge with dataFields() */ public function fieldByName($name) { $name = $this->rewriteTabPath($name); @@ -356,6 +356,7 @@ class FieldList extends ArrayList { * * @param string $name Name of the field to insert before * @param FormField $item The form field to insert + * @return FormField|false */ public function insertBefore($name, $item) { // Backwards compatibility for order of arguments @@ -385,6 +386,7 @@ class FieldList extends ArrayList { * * @param string $name Name of the field to insert after * @param FormField $item The form field to insert + * @return FormField|false */ public function insertAfter($name, $item) { // Backwards compatibility for order of arguments diff --git a/forms/HtmlEditorField.php b/forms/HtmlEditorField.php index 53313cb56..e20aca007 100644 --- a/forms/HtmlEditorField.php +++ b/forms/HtmlEditorField.php @@ -315,7 +315,7 @@ class HtmlEditorField_Toolbar extends RequestHandler { $description = new LiteralField('URLDescription', '
    ' . $URLDescription . '
    '), $remoteURL = new TextField('RemoteURL', 'http://'), new LiteralField('addURLImage', - '') ); diff --git a/forms/InlineFormAction.php b/forms/InlineFormAction.php index 4e8984876..9e5066750 100644 --- a/forms/InlineFormAction.php +++ b/forms/InlineFormAction.php @@ -20,7 +20,7 @@ class InlineFormAction extends FormField { */ public function __construct($action, $title = "", $extraClass = '') { $this->extraClass = ' '.$extraClass; - parent::__construct($action, $title, null, null); + parent::__construct($action, $title); } public function performReadonlyTransformation() { @@ -39,7 +39,8 @@ class InlineFormAction extends FormField { return DBField::create_field( 'HTMLText', - FormField::create('input', array( + FormField::create_tag('input', array( + 'type' => 'submit', 'name' => sprintf('action_%s', $this->getName()), 'value' => $this->title, 'id' => $this->ID(), diff --git a/forms/TabSet.php b/forms/TabSet.php index a551830dd..44b4a50fc 100644 --- a/forms/TabSet.php +++ b/forms/TabSet.php @@ -114,7 +114,10 @@ class TabSet extends CompositeField { } /** - * Returns the named tab + * Returns a named field. + * + * @param string $name Name of the field you want to find. Allows for dot notation. + * @return FormField|null */ public function fieldByName($name) { if(strpos($name,'.') !== false) list($name, $remainder) = explode('.',$name,2); @@ -135,6 +138,8 @@ class TabSet extends CompositeField { } } } + + return null; } /** @@ -148,22 +153,24 @@ class TabSet extends CompositeField { /** * Inserts a field before a particular field in a FieldList. * - * @param FormField $item The form field to insert - * @param string $name Name of the field to insert before + * @param string $insertBefore Name of the field to insert before + * @param FormField $field The form field to insert + * @return FormField|null */ public function insertBefore($insertBefore, $field) { - parent::insertBefore($insertBefore, $field); if($field instanceof Tab) $field->setTabSet($this); - $this->sequentialSet = null; + return parent::insertBefore($insertBefore, $field); } + /** + * Inserts a field after a particular field in a FieldList. + * + * @param string $insertAfter Name of the field to insert after + * @param FormField $field The form field to insert + * @return FormField|null + */ public function insertAfter($insertAfter, $field) { - parent::insertAfter($insertAfter, $field); if($field instanceof Tab) $field->setTabSet($this); - $this->sequentialSet = null; - } - - public function removeByName( $tabName, $dataFieldOnly = false ) { - parent::removeByName( $tabName, $dataFieldOnly ); + return parent::insertAfter($insertAfter, $field); } } diff --git a/forms/gridfield/GridField.php b/forms/gridfield/GridField.php index c18115514..ca9fa7f61 100644 --- a/forms/gridfield/GridField.php +++ b/forms/gridfield/GridField.php @@ -149,7 +149,7 @@ class GridField extends FormField { return $this->modelClassName; } - if($this->list && method_exists($this->list, 'dataClass')) { + if($this->list && $this->list->hasMethod('dataClass')) { $class = $this->list->dataClass(); if($class) { diff --git a/forms/gridfield/GridFieldSortableHeader.php b/forms/gridfield/GridFieldSortableHeader.php index 67af41e73..cc9ec49e3 100644 --- a/forms/gridfield/GridFieldSortableHeader.php +++ b/forms/gridfield/GridFieldSortableHeader.php @@ -114,8 +114,8 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM } elseif(method_exists($tmpItem, 'hasMethod') && $tmpItem->hasMethod($methodName)) { // The part is a relation name, so get the object/list from it $tmpItem = $tmpItem->$methodName(); - } elseif($tmpItem instanceof DataObject && $tmpItem->hasField($methodName)) { - // Else, if we've found a field at the end of the chain, we can sort on it. + } elseif($tmpItem instanceof DataObject && $tmpItem->hasDatabaseField($methodName)) { + // Else, if we've found a database field at the end of the chain, we can sort on it. // If a method is applied further to this field (E.g. 'Cost.Currency') then don't try to sort. $allowSort = $idx === sizeof($parts) - 1; break; @@ -150,7 +150,7 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM && $gridField->getConfig()->getComponentByType('GridFieldFilterHeader')){ $field = new LiteralField($fieldName, - ''); + ''); } else { $field = new LiteralField($fieldName, '' . $title . ''); } diff --git a/javascript/GridField.js b/javascript/GridField.js index f67467351..15ca522c0 100644 --- a/javascript/GridField.js +++ b/javascript/GridField.js @@ -55,7 +55,7 @@ content = ''; self.addClass('show-filter').find('.filter-header').show(); } else { - content = ''; + content = ''; self.removeClass('show-filter').find('.filter-header').hide(); } diff --git a/javascript/HtmlEditorField.js b/javascript/HtmlEditorField.js index f711ebf58..91b2e3223 100644 --- a/javascript/HtmlEditorField.js +++ b/javascript/HtmlEditorField.js @@ -845,9 +845,11 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE; } else if(el.is(':radio')) { el.val([selected]).change(); } else if(fieldName == 'file') { - // Can't rely on fieldName, ad UploadFields have different naming convention - el = $('#' + fieldName); - + // UploadField inputs have a slightly different naming convention + el = this.find(':input[name="' + fieldName + '[Uploads][]"]'); + // We need the UploadField "field", not just the input + el = el.parents('.ss-uploadfield'); + // We have to wait for the UploadField to initialise (function attach(el, selected) { if( ! el.getConfig()) { diff --git a/javascript/UploadField_downloadtemplate.js b/javascript/UploadField_downloadtemplate.js index 006edd1ef..9e9381ac8 100644 --- a/javascript/UploadField_downloadtemplate.js +++ b/javascript/UploadField_downloadtemplate.js @@ -27,7 +27,7 @@ window.tmpl.cache['ss-uploadfield-downloadtemplate'] = tmpl( '' + '{% if (file.error) { %}' + '
    ' + - '
    ' + + '
    ' + '
    ' + '{% } else { %}' + '
    {% print(file.buttons, true); %}
    ' + diff --git a/javascript/UploadField_uploadtemplate.js b/javascript/UploadField_uploadtemplate.js index 942774317..9a05193f9 100644 --- a/javascript/UploadField_uploadtemplate.js +++ b/javascript/UploadField_uploadtemplate.js @@ -17,14 +17,14 @@ window.tmpl.cache['ss-uploadfield-uploadtemplate'] = tmpl( '{% if (!file.error) { %}' + '
    ' + '{% if (!o.options.autoUpload) { %}' + - '
    ' + + '
    ' + '{% } %}' + '{% } %}' + '
    ' + - '' + + '' + '
    ' + '
    ' + - '' + + '' + '
    ' + '' + '' + diff --git a/lang/cs.yml b/lang/cs.yml index adbd61569..710dff459 100644 --- a/lang/cs.yml +++ b/lang/cs.yml @@ -260,6 +260,7 @@ cs: many_many_Members: Členové GroupImportForm: Help1: '

    Import jedné nebo více skupin v CSV formátu (čárkou-oddělené hodnoty). Zobrazit rozšířené použití

    ' + Help2: '

    Pokročilé použití

    ' ResultCreated: 'Vytvořeno {count} skupin' ResultDeleted: 'Smazáno %d skupin' ResultUpdated: 'Aktualizováno %d skupin' @@ -291,6 +292,8 @@ cs: FROMWEB: 'Z webu' FindInFolder: 'Hledat ve složce' IMAGEALT: 'Alternativní text (alt)' + IMAGEALTTEXT: 'Alternativní text (alt) - ukáže se, když obrázek nemúže být zobrazen' + IMAGEALTTEXTDESC: 'Zobrazeno na obrazovce, anebo když obrázek nemůže být zobrazen' IMAGEDIMENSIONS: Rozměry IMAGEHEIGHTPX: Výška IMAGETITLE: 'Titul text (tooltip) - další informace o obrázku' @@ -325,7 +328,11 @@ cs: DELETED: Smazáno. DropdownBatchActionsDefault: Akcie HELP: Nápověda + PAGETYPE: 'Typ stránky:' PERMAGAIN: 'Byli jste odhlášeni z CMS. Pokud se chcete znovu přihlásit, zadejte níže své uživatelské jméno a heslo.' + PERMALREADY: 'Omlouvám se, ale nemůžete vstoupit do této části CMS. Pokud se chcete přihlásit jako někdo jiný, udělejte tak níže.' + PERMDEFAULT: 'Musíte být přihlášen/a k přístup do oblasti administrace, zadejte vaše přihlošovací údaje dole, prosím.' + PLEASESAVE: 'Uložte stránku, prosím. Tato stránka nemůže být aktualizována, protože ještě nebyla uložena.' PreviewButton: Náhled REORGANISATIONSUCCESSFUL: 'Strom webu reorganizován úspěšně.' SAVEDUP: Uloženo. @@ -413,6 +420,7 @@ cs: Toggle: 'Ukázat nápovědu formátování' MemberImportForm: Help1: '

    Import členů v CSV formátu (čárkou-oddělené hodnoty). Zobrazit rozšířené použití

    ' + Help2: '

    Pokročilé použití

    ' ResultCreated: 'Vytvořeno {count} členů' ResultDeleted: 'Smazáno %d členů' ResultNone: 'Žádné změny' diff --git a/lang/en.yml b/lang/en.yml index 43fa53474..d483b5c02 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -292,8 +292,8 @@ en: FROMWEB: 'From the web' FindInFolder: 'Find in Folder' IMAGEALT: 'Alternative text (alt)' - IMAGEALTTEXT: 'Alternative text (alt) - shown if image cannot be displayed' - IMAGEALTTEXTDESC: 'Shown to screen readers or if image can not be displayed' + IMAGEALTTEXT: 'Alternative text (alt) - shown if image can''t be displayed' + IMAGEALTTEXTDESC: 'Shown to screen readers or if image can''t be displayed' IMAGEDIMENSIONS: Dimensions IMAGEHEIGHTPX: Height IMAGETITLE: 'Title text (tooltip) - for additional information about the image' @@ -328,11 +328,11 @@ en: DELETED: Deleted. DropdownBatchActionsDefault: Actions HELP: Help - PAGETYPE: 'Page type: ' + PAGETYPE: 'Page type' PERMAGAIN: 'You have been logged out of the CMS. If you would like to log in again, enter a username and password below.' PERMALREADY: 'I''m sorry, but you can''t access that part of the CMS. If you want to log in as someone else, do so below.' PERMDEFAULT: 'You must be logged in to access the administration area; please enter your credentials below.' - PLEASESAVE: 'Please Save Page: This page could not be upated because it hasn''t been saved yet.' + PLEASESAVE: 'Please Save Page: This page could not be updated because it hasn''t been saved yet.' PreviewButton: Preview REORGANISATIONSUCCESSFUL: 'Reorganised the site tree successfully.' SAVEDUP: Saved. diff --git a/lang/eo.yml b/lang/eo.yml index 14ca046e4..fbe1f4ba2 100644 --- a/lang/eo.yml +++ b/lang/eo.yml @@ -260,6 +260,7 @@ eo: many_many_Members: Membroj GroupImportForm: Help1: '

    Importi unu aŭ pliaj grupojn en formato CSV (perkome disigitaj valoroj values). Vidigi spertulan uzadon

    ' + Help2: '

    Speciala uzado

    ' ResultCreated: 'Kreiĝis {count} grupoj' ResultDeleted: 'Forigis %d grupojn' ResultUpdated: 'Aktualigis %d grupojn' @@ -326,15 +327,20 @@ eo: DropdownBatchActionsDefault: Agoj HELP: Helpo PERMAGAIN: 'Vin adiaŭis la CMS. Se vi volas denove saluti, enigu salutnomon kaj pasvorton malsupre.' + PERMALREADY: 'Bedaŭrinde vi ne povas aliri tiun parton de la CMS. Se vi volas ensaluti kiel aliulo, faru tion sube.' + PERMDEFAULT: 'Necesas ensaluti por aliri la administran zonon; bonvolu enigi viajn akreditaĵoj sube.' PreviewButton: Antaŭvido REORGANISATIONSUCCESSFUL: 'Sukcese reorganizis la retejan arbon.' SAVEDUP: Konservita. ShowAsList: 'vidigi kiel liston' TooManyPages: 'Tro da paĝoj' ValidationError: 'Validiga eraro' + VersionUnknown: nekonata LeftAndMain_Menu_ss: Hello: Saluton LOGOUT: 'Elsaluti' + ListboxField: + SOURCE_VALIDATION: 'Bonvolu elekti valoron el la listo donita. %s ne estas valida agordo' LoginAttempt: Email: 'Retadreso' IP: 'IP-Adreso' @@ -410,6 +416,7 @@ eo: Toggle: 'Vidigi aranĝa helpo' MemberImportForm: Help1: '

    Importi membrojn en CSV-formato (diskomaj valoroj ). Vidigi spertulan uzadon

    ' + Help2: '

    Speciala uzado

    ' ResultCreated: 'Krei {count} membrojn' ResultDeleted: 'Forigis %d membrojn' ResultNone: 'Neniu ŝanĝo' @@ -539,6 +546,8 @@ eo: Print: Presi TableListField_PageControls_ss: OF: de + TextField: + VALIDATEMAXLENGTH: 'La longo de la valoro por {name} devas ne superi {maxLength} signojn' TimeField: VALIDATEFORMAT: 'Bonvole enigu validan horan formaton ({format})' ToggleField: diff --git a/lang/fa_IR.yml b/lang/fa_IR.yml index 41a900443..08e128d9c 100644 --- a/lang/fa_IR.yml +++ b/lang/fa_IR.yml @@ -4,12 +4,18 @@ fa_IR: AssetTableField: DIM: ابعاد FILENAME: نام فايل + FOLDER: پوشه LASTEDIT: 'آخرین تغییرات' OWNER: دارنده SIZE: 'حجم' TITLE: عنوان TYPE: 'نوع' URL: نشانی + AssetUploadField: + EDITALL: 'ویرایش همه' + EDITINFO: 'ویرایش فایل‌ها' + FILES: فایل‌ها + TOTAL: مجموع BBCodeParser: ALIGNEMENT: جاگذاری ALIGNEMENTEXAMPLE: 'به راست' @@ -26,13 +32,29 @@ fa_IR: UNDERLINEEXAMPLE: زیرخط Boolean: ANY: هر + NOANSWER: 'خیر' + YESANSWER: 'بله' + CMSLoadingScreen_ss: + LOADING: بارگذاری... CMSMain: SAVE: نگاهداری + CMSMemberLoginForm: + BUTTONFORGOTPASSWORD: 'رمز عبور را فراموش کرده‌اید؟' + BUTTONLOGOUT: 'خروج' + CMSPageHistoryController_versions_ss: + PREVIEW: 'پیش‌نمایش وب‌سایت' + CMSProfileController: + MENUTITLE: 'پروفایل من' + CMSSecurity: + SUCCESS: موفقیت ChangePasswordEmail_ss: CHANGEPASSWORDTEXT1: 'شما گذرواژه تان را دگرگون کردید برای' EMAIL: ايميل HELLO: درود PASSWORD: كلمه عبور + CheckboxField: + NOANSWER: 'خیر' + YESANSWER: 'بله' ConfirmedPasswordField: SHOWONCLICKTITLE: 'تغيير كلمه عبور' CreditCardField: @@ -40,36 +62,76 @@ fa_IR: FOURTH: چهارم SECOND: دوم THIRD: سوم + CurrencyField: + CURRENCYSYMBOL: ﷼ DataObject: PLURALNAME: 'داده های اشیاء' SINGULARNAME: 'داده اشیاء' + Date: + DAY: روز + DAYS: روز + HOUR: ساعت + HOURS: ساعت + LessThanMinuteAgo: 'کمتر از یک دقیقه' + MIN: دقیقه + MINS: دقیقه + MONTH: ماه + MONTHS: ماه + SEC: ثانیه + SECS: ثانیه + TIMEDIFFAGO: '{difference} پیش' + TIMEDIFFIN: 'در {difference}' + YEAR: سال + YEARS: سال DateField: TODAY: امروز DropdownField: CHOOSE: (گزینش) + Enum: + ANY: هر File: + AviType: 'فایل ویدیو AVI' Content: محتوا + CssType: 'فایل CSS' Filename: نام پرونده + HtlType: 'فایل HTML' + HtmlType: 'فایل HTML' Name: نام PLURALNAME: فايل ها SINGULARNAME: فايل Title: عنوان + Folder: + PLURALNAME: پوشه‌ها + SINGULARNAME: پوشه ForgotPasswordEmail_ss: HELLO: درود TEXT3: برای Form: + SubmitBtnLabel: برو VALIDATIONPASSWORDSDONTMATCH: 'گذرواژه‌ها همانند هم نیستند' VALIDATIONPASSWORDSNOTEMPTY: 'گذرواژه نباید تهی باشد' FormField: NONE: هیچ کدام + GridAction: + DELETE_DESCRIPTION: حذف + Delete: حذف + GridField: + Find: بگرد + ResetFilter: از نو + GridFieldEditButton_ss: + EDIT: ویرایش + GridFieldItemEditView: + Go_back: 'بازگشت' Group: Code: 'كد گروه' DefaultGroupTitleAdministrators: مدیران کل DefaultGroupTitleContentAuthors: 'نویسندگان مطالب' Description: توضحیات Locked: 'بسته شده است؟' + PLURALNAME: گروه‌ها Parent: 'گروه مادر' RolesAddEditLink: 'اضافه/ویرایش وظیفه' + SINGULARNAME: گروه Sort: 'تربیت چیدن' has_many_Permissions: مجوز‌ها many_many_Members: اعضاء @@ -77,8 +139,11 @@ fa_IR: ResultDeleted: 'گروه %d حذف شد' ResultUpdated: 'گروه %d بروز شد' HtmlEditorField: + ADDURL: 'افزودن URL' + BUTTONINSERT: وارد کردن BUTTONINSERTLINK: 'گذاشتن پیوند' BUTTONREMOVELINK: 'برداشتن پیوند' + BUTTONUpdate: به روزرسانی CSSCLASS: 'جاگیری / الگو' EMAIL: 'پست الکترونیک' FILE: پرونده @@ -94,11 +159,25 @@ fa_IR: LINKTO: 'پیوند به' PAGE: برگ URL: نشانی + Image: + PLURALNAME: فایل‌ها + SINGULARNAME: فايل + Image_Cached: + PLURALNAME: فایل‌ها + SINGULARNAME: فايل LeftAndMain: + DELETED: حذف شده HELP: کمک PERMAGAIN: 'شما از سیستم مدیریت محتوا خارج شده اید.اگر میخواهید دوباره وارد شوید نام کاربری و رمز عبور خود را در قسمت زیر وارد کنید' + PreviewButton: پیش‌نمایش + SAVEDUP: ذخیره شده + LeftAndMain_Menu_ss: + Hello: درود + LOGOUT: 'خروج' LoginAttempt: - Email: 'آدرس های ایمیل' + Email: 'نشانی ای‌میل' + IP: 'نشانی IP' + Status: وضعیت Member: BUTTONCHANGEPASSWORD: 'تغییر رمز عبور' BUTTONLOGIN: 'ورود' @@ -116,20 +195,41 @@ fa_IR: SUBJECTPASSWORDCHANGED: 'گذرواژه شما دگرگون شد' SUBJECTPASSWORDRESET: 'پیوند ازنوسازی گذرواژه شما' SURNAME: نام خانوادگی + TIMEFORMAT: 'قالب زمان' YOUROLDPASSWORD: 'رمز عبور قدیمی' belongs_many_many_Groups: گروه‌ها db_LockedOutUntil: 'بسته شده تا ' + db_Password: رمز عبور db_PasswordExpiry: 'تاریخ از میان رفتن گذرواژه' + MemberDatetimeOptionsetField: + Preview: پیش‌نمایش MemberImportForm: ResultDeleted: 'کاربر %d حذف شد' ResultNone: 'تغییری ایجاد نشد' ModelAdmin: DELETE: حذف + ModelAdmin_Tools_ss: + FILTER: پالایش + IMPORT: وارد کردن + ModelSidebar_ss: + IMPORT_TAB_HEADER: وارد کردن + SEARCHLISTINGS: جستجو + MoneyField: + FIELDLABELAMOUNT: مقدار + FIELDLABELCURRENCY: واحد پول NullableField: IsNullLabel: 'خالی است' + Pagination: + Page: صفحه + View: نمایش Permission: AdminGroup: مدیر کل + CMS_ACCESS_CATEGORY: 'دسترسی CMS' FULLADMINRIGHTS: 'توانایی‌های کامل مدیریتی:' + PermissionRole: + PLURALNAME: وظایف + SINGULARNAME: وظیفه + Title: عنوان Permissions: PERMISSIONS_CATEGORY: 'مجوز دسترسی ها و وظایف' PhoneNumberField: @@ -142,14 +242,29 @@ fa_IR: SecurityAdmin: APPLY_ROLES: 'اعمال وظایف به گروه' MEMBERS: کاربران + MENUTITLE: امنیت NEWGROUP: 'گروه تازه' ROLES: وظایف TABROLES: وظایف + Users: کاربران SecurityAdmin_MemberImportForm: BtnImport: 'وارد کردن' + SilverStripeNavigator: + Edit: ویرایش + Mobile: موبایل + Tablet: تبلت + Width: پهنا SiteTree: TABMAIN: اصلی + TableListField: + Print: چاپ ToggleField: MORE: بیشتر + UploadField: + DOEDIT: ذخیره + Dimensions: ابعاد + EDIT: ویرایش + REMOVE: حذف + Saved: ذخیره شده Versioned: has_many_Versions: نسخه ها diff --git a/lang/lt.yml b/lang/lt.yml index 994b01641..1725617f3 100644 --- a/lang/lt.yml +++ b/lang/lt.yml @@ -260,6 +260,7 @@ lt: many_many_Members: Vartotojai GroupImportForm: Help1: '

    Importuoti vieną ar kelias grupes CSV formatu (kableliu atskirtos reikšmės). Rodyti detalesnį aprašymą

    ' + Help2: '

    Detalesnis aprašymas

    ' ResultCreated: 'Sukurta {count} grupių' ResultDeleted: 'Ištrinta %d grupių' ResultUpdated: 'Atnaujinta %d grupių' @@ -291,6 +292,8 @@ lt: FROMWEB: 'Iš interneto' FindInFolder: 'Rasti kataloge' IMAGEALT: 'Alternatyvus tekstas (alt)' + IMAGEALTTEXT: 'Alternatyvus tekstas (alt) - rodomas, jeigu nepavyko parodyti paveikslėlio' + IMAGEALTTEXTDESC: 'Rodomas, jeigu nepavyko parodyti paveikslėlio' IMAGEDIMENSIONS: Matmenys IMAGEHEIGHTPX: Aukštis IMAGETITLE: 'Pavadinimo tekstas (tooltip) - papildomai informacijai apie paveikslėlį' @@ -325,9 +328,11 @@ lt: DELETED: Ištrinta. DropdownBatchActionsDefault: Veiksmai HELP: Pagalba + PAGETYPE: 'Puslapio tipas:' PERMAGAIN: 'Jūs atsijungėte. Norėdami vėl prisijungti, įveskite savo duomenis į žemiau esančius laukelius.' PERMALREADY: 'Deja, bet Jūs negalite patekti į šią TVS dalį. Jeigu norite prisijungti kitu vartotoju, tai atlikite žemiau.' PERMDEFAULT: 'Jūs turite būti prisijungę, norėdami pasiekti administravimo zoną; prašome suvesti prisijungimo duomenis į žemiau esančius laukelius.' + PLEASESAVE: 'Prašome išsaugoti puslapį: Šis puslapis negali būti atnaujintas, nes jis dar nėra išsaugotas.' PreviewButton: Peržiūra REORGANISATIONSUCCESSFUL: 'Puslapių medis pertvarkytas sėkmingai.' SAVEDUP: Išsaugota. @@ -415,6 +420,7 @@ lt: Toggle: 'Rodyti formatavimo aprašymą' MemberImportForm: Help1: '

    Importuoti vartotojus CSV formatu (kableliu atskirtos reikšmės). Rodyti detalesnį aprašymą

    ' + Help2: '

    Detalesnis aprašymas

    ' ResultCreated: 'Sukurta {count} vartotojų' ResultDeleted: 'Ištrinta %d vartotojų' ResultNone: 'Nėra jokių pakeitimų' diff --git a/lang/sk.yml b/lang/sk.yml index 930f95f65..f46181354 100644 --- a/lang/sk.yml +++ b/lang/sk.yml @@ -260,6 +260,7 @@ sk: many_many_Members: Členovia GroupImportForm: Help1: 'Importovať jednu alebo viac skupín v CSV formáte (čiarkov oddelené hodnoty). Zobraziť pokročilé použitie' + Help2: '

    Pokročilé použitie

    ' ResultCreated: 'Vytvorených {count} skupín' ResultDeleted: 'Zmazané %d skupiny' ResultUpdated: 'Aktualizované %d skupiny' @@ -291,6 +292,8 @@ sk: FROMWEB: 'Z webu' FindInFolder: 'Vyhľadať v priečinku' IMAGEALT: 'Atlernatívny text (alt)' + IMAGEALTTEXT: 'Atlernatívny text (alt) - zobrazí sa ak obrázok nemože byť zobrazený ' + IMAGEALTTEXTDESC: 'Zobrazí sa na obrazovke, ak obrázok nemôže byť zobrazený' IMAGEDIMENSIONS: Rozmery IMAGEHEIGHTPX: Výška IMAGETITLE: 'Text titulky (tooltip) - pre doplňujúce informácie o obrázku' @@ -325,7 +328,11 @@ sk: DELETED: Zmazané. DropdownBatchActionsDefault: Akcie HELP: Pomoc + PAGETYPE: 'Typ stránky:' PERMAGAIN: 'Boli ste odhlásený' + PERMALREADY: 'Je mi ľúto, ale nemáte prístup k tejto časti CMS. Ak sa chcete prihlásiť ako niekto iný, urobte tak nižšie' + PERMDEFAULT: 'Musíte byť prihlásený/á k prístupu do oblasti administrácie, zadajte vaše prihlasovacie údaje dole, prosím.' + PLEASESAVE: 'Uložte stránku, prosím. Táto stránka nemôže byť aktualizovaná, pretože eště nebola uložená.' PreviewButton: Náhľad REORGANISATIONSUCCESSFUL: 'Strom webu bol reorganizovaný úspešne.' SAVEDUP: Uložené. @@ -413,6 +420,7 @@ sk: Toggle: 'Ukázať nápovedu formátovania' MemberImportForm: Help1: 'Importovať členov v CSV formáte (čiarkov oddelené hodnoty). Zobraziť pokročile použitie' + Help2: '

    Pokročilé použitie

    ' ResultCreated: 'Vytvorených {count} členov' ResultDeleted: 'Zmazaných %d členov' ResultNone: 'Žiadne zmeny' diff --git a/lang/tr.yml b/lang/tr.yml index 39acb814b..7a564d58a 100644 --- a/lang/tr.yml +++ b/lang/tr.yml @@ -47,6 +47,8 @@ tr: ERRORNOTREC: 'Kullanıcı adı / şifre hatalı' Boolean: ANY: Herhangi + NOANSWER: 'Hayır' + YESANSWER: 'Evet' CMSMain: ACCESSALLINTERFACES: 'Tüm İYS arayüzlerine erişim' SAVE: Kaydet @@ -56,6 +58,9 @@ tr: EMAIL: E-Posta HELLO: Merhaba PASSWORD: Parola + CheckboxField: + NOANSWER: 'Hayır' + YESANSWER: 'Evet' ConfirmedPasswordField: SHOWONCLICKTITLE: 'Parola Değiştir' CreditCardField: @@ -87,6 +92,7 @@ tr: TEXT2: 'şifre sıfırlama linki' TEXT3: için Form: + SubmitBtnLabel: Başla VALIDATIONNOTUNIQUE: 'Girilen değer benzersiz olmalıdır' VALIDATIONPASSWORDSDONTMATCH: 'Şifre tekrarı hatalı' VALIDATIONPASSWORDSNOTEMPTY: 'Şifreler boş geçilemez' diff --git a/lang/zh.yml b/lang/zh.yml index 37ac3a870..7ef8121f2 100644 --- a/lang/zh.yml +++ b/lang/zh.yml @@ -60,6 +60,8 @@ zh: ERRORNOTREC: '那个用户名 / 密码无法被辨认' Boolean: ANY: 任何 + NOANSWER: '不是' + YESANSWER: '是' CMSLoadingScreen_ss: LOADING: 正在载入…… REQUIREJS: 'CMS 要求您启用 JavaScript。' @@ -68,16 +70,35 @@ zh: ACCESSALLINTERFACES: '对所有 CMS 部分的访问' ACCESSALLINTERFACESHELP: '支配更多的特殊访问设置' SAVE: 保存 + CMSMemberLoginForm: + BUTTONFORGOTPASSWORD: '忘记密码?' + BUTTONLOGIN: '重新登录' + BUTTONLOGOUT: '登出' + PASSWORDEXPIRED: '

    您的密码已过期。 请选择一个新的。' CMSPageHistoryController_versions_ss: PREVIEW: '网站预览' CMSProfileController: MENUTITLE: '我的个人资料' + CMSSecurity: + INVALIDUSER: '

    用户已无效。 请在此继续重新进行身份验证' + LoginMessage: '

    如果您有任何未保存的工作,你可以重新登录以回到你未保存的地方。

    ' + SUCCESS: 成功 + SUCCESSCONTENT: '

    登录成功。如果您没有自动重定向点击此处

    ' + TimedOutTitleAnonymous: '你的登陆超时已过期。' + TimedOutTitleMember: '你好{name}!
    你的登陆超时已过期。' ChangePasswordEmail_ss: CHANGEPASSWORDTEXT1: '您的密码已更改为:' CHANGEPASSWORDTEXT2: '现在,您可以使用下列证书来登录了:' EMAIL: 电子邮件 HELLO: 您好 PASSWORD: 密码 + CheckboxField: + NOANSWER: '不是' + YESANSWER: '是' + CheckboxFieldSetField: + SOURCE_VALIDATION: '请选择列表内提供的选项。{value}不是一个有效的选项' + CheckboxSetField: + SOURCE_VALIDATION: '请选择列表内提供的选项。''{value}''不是一个有效的选项' ConfirmedPasswordField: ATLEAST: '密码长度必须至少 {min} 个字符。' BETWEEN: '密码长度必须含 {min} 到 {max} 个字符。' @@ -124,6 +145,7 @@ zh: DropdownField: CHOOSE: (选择) CHOOSESEARCH: '(选择或搜索)' + SOURCE_VALIDATION: '请选择列表内提供的选项。{value}不是一个有效的选项' EmailField: VALIDATION: '请输入一个电子邮件地址' Enum: @@ -171,6 +193,7 @@ zh: TEXT2: '密码重设链接' TEXT3: 为 Form: + CSRF_FAILED_MESSAGE: '似乎是一个技术问题。请点击返回按钮,刷新浏览器,然后再试一次。' FIELDISREQUIRED: '{name} 为必填' SubmitBtnLabel: 前往 VALIDATIONCREDITNUMBER: '请确保您输入了正确的 {number} 信用卡号码' @@ -244,6 +267,8 @@ zh: HtmlEditorField: ADDURL: '添加网址' ADJUSTDETAILSDIMENSIONS: '详情 &amp; 体积' + ANCHORSCANNOTACCESSPAGE: '您不允许访问该页面的内容。' + ANCHORSPAGENOTFOUND: '无法找到该页面。' ANCHORVALUE: 固定 BUTTONADDURL: '添加网址' BUTTONINSERT: 插入 @@ -282,6 +307,7 @@ zh: LINKOPENNEWWIN: '在新窗口中打开链接?' LINKTO: '链接到' PAGE: 页面 + SUBJECT: '电子邮件标题' URL: 网址 URLNOTANOEMBEDRESOURCE: '''{url}'' 该网址无法转换成媒体来源。' UpdateMEDIA: '更新媒体' @@ -299,15 +325,19 @@ zh: DropdownBatchActionsDefault: 动作 HELP: 帮助 PERMAGAIN: '您已经退出 CMS。如果您想再次登录,请在下面输入用户名和密码。' + PERMALREADY: '抱歉,您不能访问这一部分的后台管理。如果您想以不同的身份登录,请在下面进行操作。' PreviewButton: 预览 REORGANISATIONSUCCESSFUL: '重新组织网站地图已成功' SAVEDUP: 已保存。 ShowAsList: '以列表方式展示' TooManyPages: '页面数目过多' ValidationError: '验证错误' + VersionUnknown: 未知 LeftAndMain_Menu_ss: Hello: 您好 LOGOUT: '退出' + ListboxField: + SOURCE_VALIDATION: '请选择列表内提供的选项。%s不是一个有效的选项' LoginAttempt: Email: '电子邮件地址' IP: 'IP 地址' @@ -340,6 +370,7 @@ zh: NEWPASSWORD: '新密码' NoPassword: '该成员无密码' PASSWORD: 密码 + PASSWORDEXPIRED: '您的密码已过期。 请选择一个新的。' PLURALNAME: 成员 REMEMBERME: '下次记住我?' SINGULARNAME: 成员 @@ -445,6 +476,7 @@ zh: SINGULARNAME: 角色 Title: 标题 PermissionRoleCode: + PLURALNAME: '权限角色代码' PermsError: '无法为代码 "%s"分配特权权限(要求具备 ADMIN 访问)' SINGULARNAME: '权限角色代码' Permissions: @@ -510,6 +542,8 @@ zh: Print: 打印 TableListField_PageControls_ss: OF: 的 + TextField: + VALIDATEMAXLENGTH: '{name} 的长度必须至多{maxLength} 个字符。' TimeField: VALIDATEFORMAT: '请输入有效的时间格式 ({format})' ToggleField: diff --git a/model/DataObject.php b/model/DataObject.php index 58c7a6c1b..35c2b2f46 100644 --- a/model/DataObject.php +++ b/model/DataObject.php @@ -1763,10 +1763,8 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity return $this->unsavedRelations[$componentName]; } - $result = ManyManyList::create( - $componentClass, $table, $componentField, $parentField, - $this->manyManyExtraFieldsForComponent($componentName) - ); + $extraFields = $this->manyManyExtraFieldsForComponent($componentName) ?: array(); + $result = ManyManyList::create($componentClass, $table, $componentField, $parentField, $extraFields); if($this->model) $result->setDataModel($this->model); diff --git a/model/connect/MySQLSchemaManager.php b/model/connect/MySQLSchemaManager.php index 5881e2426..85157de58 100644 --- a/model/connect/MySQLSchemaManager.php +++ b/model/connect/MySQLSchemaManager.php @@ -125,9 +125,16 @@ class MySQLSchemaManager extends DBSchemaManager { } public function checkAndRepairTable($tableName) { + // Flag to ensure we only send the warning about PDO + native mode once + static $pdo_warning_sent = false; + // If running PDO and not in emulated mode, check table will fail if($this->database->getConnector() instanceof PDOConnector && !PDOConnector::is_emulate_prepare()) { - $this->alterationMessage('CHECK TABLE command disabled for PDO in native mode', 'notice'); + if (!$pdo_warning_sent) { + $this->alterationMessage('CHECK TABLE command disabled for PDO in native mode', 'notice'); + $pdo_warning_sent = true; + } + return true; } diff --git a/model/fieldtypes/Enum.php b/model/fieldtypes/Enum.php index 7801f77ad..09c9647c5 100644 --- a/model/fieldtypes/Enum.php +++ b/model/fieldtypes/Enum.php @@ -163,7 +163,7 @@ class Enum extends StringField { */ public function setEnum($enum) { if(!is_array($enum)) { - $enum = preg_split("/ *, */", trim($enum)); + $enum = preg_split("/\s*,\s*/", trim($enum, ", \t\n\r\0\x0B")); } $this->enum = $enum; return $this; diff --git a/search/filters/FulltextFilter.php b/search/filters/FulltextFilter.php index 43c6b75a6..233a63f70 100755 --- a/search/filters/FulltextFilter.php +++ b/search/filters/FulltextFilter.php @@ -58,12 +58,12 @@ class FulltextFilter extends SearchFilter { if(is_array($indexes) && array_key_exists($this->getName(), $indexes)) { $index = $indexes[$this->getName()]; if(is_array($index) && array_key_exists("value", $index)) { - return $index['value']; + return $this->prepareColumns($index['value']); } else { // Parse a fulltext string (eg. fulltext ("ColumnA", "ColumnB")) to figure out which columns // we need to search. if(preg_match('/^fulltext\s+\((.+)\)$/i', $index, $matches)) { - return $matches[1]; + return $this->prepareColumns($matches[1]); } else { throw new Exception("Invalid fulltext index format for '" . $this->getName() . "' on '" . $this->model . "'"); @@ -74,4 +74,19 @@ class FulltextFilter extends SearchFilter { return parent::getDbName(); } + /** + * Adds table identifier to the every column. + * Columns must have table identifier to prevent duplicate column name error. + * + * @return string + */ + protected function prepareColumns($columns) { + $cols = preg_split('/"?\s*,\s*"?/', trim($columns, '(") ')); + $class = ClassInfo::table_for_object_field($this->model, current($cols)); + $cols = array_map(function($col) use ($class) { + return sprintf('"%s"."%s"', $class, $col); + }, $cols); + return implode(',', $cols); + } + } diff --git a/security/Permission.php b/security/Permission.php index 96890de94..c2c6a9e18 100644 --- a/security/Permission.php +++ b/security/Permission.php @@ -199,7 +199,7 @@ class Permission extends DataObject implements TemplateGlobalProvider { // Code filters $codeParams = is_array($code) ? $code : array($code); - $codeClause = DB::placeholders($codes); + $codeClause = DB::placeholders($codeParams); $adminParams = (self::$admin_implies_all) ? array('ADMIN') : array(); $adminClause = (self::$admin_implies_all) ? ", ?" : ''; diff --git a/templates/AssetUploadField.ss b/templates/AssetUploadField.ss index b314abbff..b2ac977e1 100644 --- a/templates/AssetUploadField.ss +++ b/templates/AssetUploadField.ss @@ -21,7 +21,7 @@
    - @@ -39,4 +39,4 @@
    - + \ No newline at end of file diff --git a/templates/Includes/HtmlEditorField_viewfile.ss b/templates/Includes/HtmlEditorField_viewfile.ss index 0e5f42590..c69b346db 100644 --- a/templates/Includes/HtmlEditorField_viewfile.ss +++ b/templates/Includes/HtmlEditorField_viewfile.ss @@ -23,12 +23,12 @@
    -
    - <% end_if %> - <% if $canDelete %> - + <% end_if %> <% if $UploadField.canAttachExisting %> - <% end_if %> diff --git a/templates/UploadField.ss b/templates/UploadField.ss index 12b43da96..7fb889a8f 100644 --- a/templates/UploadField.ss +++ b/templates/UploadField.ss @@ -57,11 +57,11 @@ <% end_if %> <% if $canAttachExisting %> - + <% end_if %> <% if $canUpload %> <% if not $autoUpload %> - + <% end_if %> <% end_if %>
    diff --git a/templates/forms/TreeDropdownField.ss b/templates/forms/TreeDropdownField.ss index 09ee0e3ed..ed4eaa4a8 100644 --- a/templates/forms/TreeDropdownField.ss +++ b/templates/forms/TreeDropdownField.ss @@ -1,5 +1,4 @@ -
    assertEmpty($response->getHeader('Cache-Control')); HTTP::set_cache_age(30); - HTTP::add_cache_headers($response); + HTTP::add_cache_headers($response); $this->assertNotEmpty($response->getHeader('Cache-Control')); + // Ensure max-age is zero for development. Config::inst()->update('Director', 'environment_type', 'dev'); + $response = new SS_HTTPResponse($body, 200); HTTP::add_cache_headers($response); $this->assertContains('max-age=0', $response->getHeader('Cache-Control')); + // Ensure max-age setting is respected in production. Config::inst()->update('Director', 'environment_type', 'live'); + $response = new SS_HTTPResponse($body, 200); HTTP::add_cache_headers($response); $this->assertContains('max-age=30', explode(', ', $response->getHeader('Cache-Control'))); $this->assertNotContains('max-age=0', $response->getHeader('Cache-Control')); + + // Still "live": Ensure header's aren't overridden if already set (using purposefully different values). + $headers = array( + 'Vary' => '*', + 'Pragma' => 'no-cache', + 'Cache-Control' => 'max-age=0, no-cache, no-store', + ); + $response = new SS_HTTPResponse($body, 200); + foreach($headers as $name => $value) { + $response->addHeader($name, $value); + } + HTTP::add_cache_headers($response); + foreach($headers as $name => $value) { + $this->assertEquals($value, $response->getHeader($name)); + } } /** diff --git a/tests/core/ArrayLibTest.php b/tests/core/ArrayLibTest.php index da79a3672..f335c849a 100644 --- a/tests/core/ArrayLibTest.php +++ b/tests/core/ArrayLibTest.php @@ -48,6 +48,29 @@ class ArrayLibTest extends SapphireTest { ); } + public function testArrayMapRecursive() { + $array = array( + 'a ', + array(' b', 'c'), + ); + $strtoupper = array( + 'A ', + array(' B', 'C'), + ); + $trim = array( + 'a', + array('b', 'c'), + ); + $this->assertEquals( + $strtoupper, + ArrayLib::array_map_recursive('strtoupper', $array) + ); + $this->assertEquals( + $trim, + ArrayLib::array_map_recursive('trim', $array) + ); + } + public function testArrayMergeRecursive() { $first = array( 'first' => 'a', diff --git a/tests/core/ClassInfoTest.php b/tests/core/ClassInfoTest.php index 923564fcc..fd437f41e 100644 --- a/tests/core/ClassInfoTest.php +++ b/tests/core/ClassInfoTest.php @@ -197,6 +197,16 @@ class ClassInfoTest extends SapphireTest { $this->assertNull( ClassInfo::table_for_object_field(null, null) ); + + // Test fixed fields + $this->assertEquals( + 'ClassInfoTest_BaseDataClass', + ClassInfo::table_for_object_field('ClassInfoTest_HasFields', 'ID') + ); + $this->assertEquals( + 'ClassInfoTest_BaseDataClass', + ClassInfo::table_for_object_field('ClassInfoTest_NoFields', 'Created') + ); } } diff --git a/tests/forms/EnumFieldTest.php b/tests/forms/EnumFieldTest.php index 394cd5bf3..be1de7754 100644 --- a/tests/forms/EnumFieldTest.php +++ b/tests/forms/EnumFieldTest.php @@ -16,4 +16,26 @@ class EnumFieldTest extends SapphireTest { $this->assertEquals(true, $searchField->getHasEmptyDefault()); $this->assertEquals($anyText, $searchField->getEmptyString()); } + + public function testEnumParsing() { + $enum = new Enum('testField', " + Item1, + Item2, + Item 3, + Item-4, + item 5 + still 5, + trailing comma, + "); + + $this->assertEquals(ArrayLib::valuekey(array( + 'Item1', + 'Item2', + 'Item 3', + 'Item-4', + 'item 5 + still 5', + 'trailing comma' + )), $enum->enumValues()); + } } diff --git a/tests/forms/FormTest.php b/tests/forms/FormTest.php index 6a7423903..a5a1974b7 100644 --- a/tests/forms/FormTest.php +++ b/tests/forms/FormTest.php @@ -19,6 +19,9 @@ class FormTest extends FunctionalTest { Config::inst()->update('Director', 'rules', array( 'FormTest_Controller' => 'FormTest_Controller' )); + + // Suppress themes + Config::inst()->remove('SSViewer', 'theme'); } public function testLoadDataFromRequest() { diff --git a/tests/forms/InlineFormActionTest.php b/tests/forms/InlineFormActionTest.php new file mode 100644 index 000000000..89ad65e1d --- /dev/null +++ b/tests/forms/InlineFormActionTest.php @@ -0,0 +1,18 @@ +Field(); + $this->assertContains('assertContains('type="submit"', $html); + $this->assertContains('name="action_dothing"', $html); + $this->assertContains('value="My Title"', $html); + $this->assertContains('id="dothing"', $html); + $this->assertContains('class="action ss-action"', $html); + } +} diff --git a/tests/forms/gridfield/GridFieldDetailFormTest.php b/tests/forms/gridfield/GridFieldDetailFormTest.php index a3bac5dfc..840777def 100644 --- a/tests/forms/gridfield/GridFieldDetailFormTest.php +++ b/tests/forms/gridfield/GridFieldDetailFormTest.php @@ -153,6 +153,38 @@ class GridFieldDetailFormTest extends FunctionalTest { $this->assertDOSContains(array(array('Surname' => 'Baggins')), $group->People()); } + public function testEditFormWithManyMany() { + $this->logInWithPermission('ADMIN'); + + // Edit the first person + $response = $this->get('GridFieldDetailFormTest_CategoryController'); + // Find the link to add a new favourite group + $parser = new CSSContentParser($response->getBody()); + $addLink = $parser->getBySelector('#Form_Form_testgroupsfield .new-link'); + $addLink = (string) $addLink[0]['href']; + + // Add a new favourite group + $response = $this->get($addLink); + $parser = new CSSContentParser($response->getBody()); + $addform = $parser->getBySelector('#Form_ItemEditForm'); + $addformurl = (string) $addform[0]['action']; + + $response = $this->post( + $addformurl, + array( + 'Name' => 'My Favourite Group', + 'ajax' => 1, + 'action_doSave' => 1 + ) + ); + $this->assertFalse($response->isError()); + + $person = GridFieldDetailFormTest_Person::get()->sort('FirstName')->First(); + $favouriteGroup = $person->FavouriteGroups()->first(); + + $this->assertInstanceOf('GridFieldDetailFormTest_PeopleGroup', $favouriteGroup); + } + public function testEditFormWithManyManyExtraData() { $this->logInWithPermission('ADMIN'); @@ -341,7 +373,8 @@ class GridFieldDetailFormTest_Person extends DataObject implements TestOnly { ); private static $many_many = array( - 'Categories' => 'GridFieldDetailFormTest_Category' + 'Categories' => 'GridFieldDetailFormTest_Category', + 'FavouriteGroups' => 'GridFieldDetailFormTest_PeopleGroup' ); private static $many_many_extraFields = array( @@ -362,6 +395,12 @@ class GridFieldDetailFormTest_Person extends DataObject implements TestOnly { GridFieldConfig_RelationEditor::create() ) ); + $fields->replaceField('FavouriteGroups', + GridField::create('FavouriteGroups', 'Favourite Groups', + $this->FavouriteGroups(), + GridFieldConfig_RelationEditor::create() + ) + ); return $fields; } @@ -386,6 +425,10 @@ class GridFieldDetailFormTest_PeopleGroup extends DataObject implements TestOnly 'People' => 'GridFieldDetailFormTest_Person' ); + private static $belongs_many_many = array( + 'People' => 'GridFieldDetailFormTest_Person' + ); + private static $default_sort = '"Name"'; public function getCMSFields() { @@ -499,13 +542,22 @@ class GridFieldDetailFormTest_CategoryController extends Controller implements T new CheckboxField('ManyMany[IsPublished]'), new TextField('ManyMany[PublishedBy]')) ); - $field = new GridField('testfield', 'testfield', $person->Categories()); - $field->getConfig()->addComponent($gridFieldForm = new GridFieldDetailForm($this, 'Form')); + $categoriesField = new GridField('testfield', 'testfield', $person->Categories()); + $categoriesField->getConfig()->addComponent($gridFieldForm = new GridFieldDetailForm($this, 'Form')); $gridFieldForm->setFields($detailFields); - $field->getConfig()->addComponent(new GridFieldToolbarHeader()); - $field->getConfig()->addComponent(new GridFieldAddNewButton('toolbar-header-right')); - $field->getConfig()->addComponent(new GridFieldEditButton()); - return new Form($this, 'Form', new FieldList($field), new FieldList()); + $categoriesField->getConfig()->addComponent(new GridFieldToolbarHeader()); + $categoriesField->getConfig()->addComponent(new GridFieldAddNewButton('toolbar-header-right')); + $categoriesField->getConfig()->addComponent(new GridFieldEditButton()); + + $favGroupsField = new GridField('testgroupsfield', 'testgroupsfield', $person->FavouriteGroups()); + $favGroupsField->getConfig()->addComponent(new GridFieldDetailForm($this, 'Form')); + $favGroupsField->getConfig()->addComponent(new GridFieldToolbarHeader()); + $favGroupsField->getConfig()->addComponent(new GridFieldAddNewButton('toolbar-header-right')); + $favGroupsField->getConfig()->addComponent(new GridFieldEditButton()); + + $fields = new FieldList($categoriesField, $favGroupsField); + + return new Form($this, 'Form', $fields, new FieldList()); } } diff --git a/tests/model/DataListTest.php b/tests/model/DataListTest.php index 6c7c97f96..57b204a2f 100755 --- a/tests/model/DataListTest.php +++ b/tests/model/DataListTest.php @@ -400,6 +400,11 @@ class DataListTest extends SapphireTest { // byID() returns a DataObject, rather than a DataList $this->assertInstanceOf('DataObjectTest_Team', $team); $this->assertEquals('Team 2', $team->Title); + + // Assert that filtering on ID searches by the base table, not the child table field + $query = DataObjectTest_SubTeam::get()->filter('ID', 4)->sql($parameters); + $this->assertContains('WHERE ("DataObjectTest_Team"."ID" = ?)', $query); + $this->assertNotContains('WHERE ("DataObjectTest_SubTeam"."ID" = ?)', $query); } /** diff --git a/tests/search/FulltextFilterTest.php b/tests/search/FulltextFilterTest.php index 8572d33e6..22575f7e3 100755 --- a/tests/search/FulltextFilterTest.php +++ b/tests/search/FulltextFilterTest.php @@ -40,29 +40,39 @@ class FulltextFilterTest extends SapphireTest { } public function testGenerateQuery() { + // Test if columns have table identifier + $filter1 = new FulltextFilter('SearchFields', 'SilverStripe'); + $filter1->setModel('FulltextFilterTest_DataObject'); + $query1 = FulltextFilterTest_DataObject::get()->dataQuery(); + $filter1->apply($query1); + $this->assertNotEquals('"ColumnA","ColumnB"', $filter1->getDbName()); + $this->assertNotEquals( + array("MATCH (\"ColumnA\",\"ColumnB\") AGAINST ('SilverStripe')"), + $query1->query()->getWhere() + ); + // Test SearchFields $filter1 = new FulltextFilter('SearchFields', 'SilverStripe'); $filter1->setModel('FulltextFilterTest_DataObject'); $query1 = FulltextFilterTest_DataObject::get()->dataQuery(); $filter1->apply($query1); - $this->assertEquals('"ColumnA", "ColumnB"', $filter1->getDbName()); + $this->assertEquals('"FulltextFilterTest_DataObject"."ColumnA","FulltextFilterTest_DataObject"."ColumnB"', $filter1->getDbName()); $this->assertEquals( array(array( - "MATCH (\"ColumnA\", \"ColumnB\") AGAINST (?)" => array('SilverStripe') + "MATCH (\"FulltextFilterTest_DataObject\".\"ColumnA\",\"FulltextFilterTest_DataObject\".\"ColumnB\") AGAINST (?)" => array('SilverStripe') )), $query1->query()->getWhere() ); - // Test Other searchfields $filter2 = new FulltextFilter('OtherSearchFields', 'SilverStripe'); $filter2->setModel('FulltextFilterTest_DataObject'); $query2 = FulltextFilterTest_DataObject::get()->dataQuery(); $filter2->apply($query2); - $this->assertEquals('"ColumnC", "ColumnD"', $filter2->getDbName()); + $this->assertEquals('"FulltextFilterTest_DataObject"."ColumnC","FulltextFilterTest_DataObject"."ColumnD"', $filter2->getDbName()); $this->assertEquals( array(array( - "MATCH (\"ColumnC\", \"ColumnD\") AGAINST (?)" => array('SilverStripe') + "MATCH (\"FulltextFilterTest_DataObject\".\"ColumnC\",\"FulltextFilterTest_DataObject\".\"ColumnD\") AGAINST (?)" => array('SilverStripe') )), $query2->query()->getWhere() );