From 29016645e5e759b1ecf49876fa79c357a68c5794 Mon Sep 17 00:00:00 2001 From: "Elvinas L." Date: Wed, 5 Aug 2015 09:41:44 +0300 Subject: [PATCH 01/60] BUGFIX. FulltextFilter requires table identifiers in match query Fixes #4483 --- search/filters/FulltextFilter.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/search/filters/FulltextFilter.php b/search/filters/FulltextFilter.php index 43c6b75a6..22dbd6f07 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 . "'"); @@ -73,5 +73,18 @@ class FulltextFilter extends SearchFilter { return parent::getDbName(); } + + private function prepareColumns($columns) { + $class = ''; + $parts = explode(',', $columns); + array_walk($parts, function(&$col, $key) use (&$class) { + $name = trim($col, " \t\n\r\0\x0B\""); + if (empty($class)) { + $class = ClassInfo::table_for_object_field($this->model, $name); + } + $col = sprintf('"%s"."%s"', $class, $name); + }); + return implode(',', $parts); + } } From 6056e9cb1bc4f8073aef07b83f7417edbe7f2ac4 Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Thu, 10 Sep 2015 09:57:50 +0100 Subject: [PATCH 02/60] FIX: Editing existing file links in HtmlEditorField was broken --- javascript/HtmlEditorField.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/javascript/HtmlEditorField.js b/javascript/HtmlEditorField.js index b992d08b1..3bcdb374e 100644 --- a/javascript/HtmlEditorField.js +++ b/javascript/HtmlEditorField.js @@ -823,9 +823,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()) { From c9ba6e5d0064bfb09ebdb9e5f7054f8c3179f99a Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Thu, 17 Sep 2015 13:39:42 +1200 Subject: [PATCH 03/60] BUG Fix ClassInfo::table_for_object_field --- core/ClassInfo.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/ClassInfo.php b/core/ClassInfo.php index ac04c2508..529c8bf37 100644 --- a/core/ClassInfo.php +++ b/core/ClassInfo.php @@ -291,7 +291,11 @@ 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; } From e97b14ea65cac0d3178d45fa113b3066d9941e5d Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Thu, 17 Sep 2015 14:23:52 +1200 Subject: [PATCH 04/60] Minor: Suppress custom themes in Formtest --- tests/forms/FormTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/forms/FormTest.php b/tests/forms/FormTest.php index 409bac60a..2215551b9 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() { From e64d73c1f741399412b6015f6602ed707b2e9778 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Thu, 17 Sep 2015 13:39:42 +1200 Subject: [PATCH 05/60] BUG Fix ClassInfo::table_for_object_field --- core/ClassInfo.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/ClassInfo.php b/core/ClassInfo.php index ac04c2508..529c8bf37 100644 --- a/core/ClassInfo.php +++ b/core/ClassInfo.php @@ -291,7 +291,11 @@ 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; } From 7f71a2ccfe78d9ecfc143f4a69d6ba2d0bf77ba0 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Fri, 18 Sep 2015 14:21:20 +1200 Subject: [PATCH 06/60] Update translations --- lang/cs.yml | 8 ++++++++ lang/lt.yml | 6 ++++++ lang/sk.yml | 8 ++++++++ 3 files changed, 22 insertions(+) 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í

  • Povolené sloupce: %s
  • Existující skupiny jsou porovnány jejich unikátním Code hodnotou, a aktualizovány s novými hodnotami z importovaného souboru
  • Hierarchie skupin může být tvořena použitím ParentCode sloupce.
  • Kódy oprávnění mohou být přiřazeny PermissionCode sloupcem. Existující oprávnění nejsou smazána.
' 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í

  • Povolené sloupce: %s
  • Existující uživatelé jsou porovnáni jejich unikátní vlastností Code, a aktualizováni s novými hodnotami z importovaného souboru.
  • Skupiny mohou být přiřazeny sloupcem Groups. Skupiny jsou identifikovány svojí vlastností Code, více skupin může být odděleno čárkou. Existující členství ve skupině nejsou smazána.
' ResultCreated: 'Vytvořeno {count} členů' ResultDeleted: 'Smazáno %d členů' ResultNone: 'Žádné změny' 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

  • Galimi stulpeliai: %s.
  • Esamos grupės yra surandamos su jų unikalia Code reikšme ir atnaujinamos duomenimis iš importuojamos bylos.
  • Grupių hierarchija gali būti sukurta naudojant ParentCode stulpelį.
  • Leidimų kodai gali būti priskirti naudojant PermissionCode stulpelį. Esami leidimai nebus pakeisti.
' 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

  • Galimi stulpeliai: %s.
  • Esami vartotojai yra surandami su jų unikalia Code reikšme ir atnaujinami duomenimis iš importuojamos bylos.
  • Grupės gali būti priskirtos naudojant Groups column. stulpelį. Grupės yra atpažįstamos pagal Code stulpelį, kelios grupės nurodomos per kablelį. Jau priskirtos vartotojui grupės nebus pakeistos.
' 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

  • Povolené stĺpce: %s
  • Existujúce skupiny sú porovnávané s ich unikátnou Code; hodnotou, a aktualizované s novými hodnotami z importovaného súbory</li>
  • Skupina hierarchií môže byť tvorená použitím ParentCode; stĺpce.</li>
  • Kódy oprávnení môžu byť priradené PermissionCode; stĺpcom. Existujúce oprávnenia nie sú smazáné.
' 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

  • Povolené stĺpce: %s
  • Existujúci užívatelia sú porovnávaní ich unikátnou vlastnosťou Code, a aktualizovaní s novými hodnotami z importovaného súboru.
  • Skupiny môžu byťt priradené stĺpcom Groups. Skupiny sú identifikované ich vlastnosťou Code, viacero skupín môže byť oddelené čiarkou. Existujúce členstvá skupiny nie sú smazané.
' ResultCreated: 'Vytvorených {count} členov' ResultDeleted: 'Zmazaných %d členov' ResultNone: 'Žiadne zmeny' From b12bdb754b46d16b9279887c3ce6c7cc007127d4 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Fri, 18 Sep 2015 14:21:20 +1200 Subject: [PATCH 07/60] Added 3.1.15 changelog --- docs/en/04_Changelogs/3.1.15.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 docs/en/04_Changelogs/3.1.15.md 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..e4965b5a9 --- /dev/null +++ b/docs/en/04_Changelogs/3.1.15.md @@ -0,0 +1,11 @@ +# 3.1.15 + + + +## 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) From c2a407a01b362981d070d6062fef52c8679e4a2b Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Fri, 18 Sep 2015 14:51:04 +1200 Subject: [PATCH 08/60] Add note to changelog --- docs/en/04_Changelogs/3.1.15.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/04_Changelogs/3.1.15.md b/docs/en/04_Changelogs/3.1.15.md index e4965b5a9..2110b4190 100644 --- a/docs/en/04_Changelogs/3.1.15.md +++ b/docs/en/04_Changelogs/3.1.15.md @@ -1,5 +1,7 @@ # 3.1.15 +This release resolves issues with compatibility with PHP 5.3.3 introduced in 3.1.14 + ## Change Log From 7ca97cd86d6e60190748c5741db5c59b3b98a807 Mon Sep 17 00:00:00 2001 From: Peter Thaleikis Date: Sun, 20 Sep 2015 15:15:54 +1200 Subject: [PATCH 09/60] Update 01_Extensions.md adding missing space --- docs/en/02_Developer_Guides/05_Extending/01_Extensions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 a00a037cf..d88d77362 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; } } From 4c19c183fe7b76329d59fdc944a1bebd544aabbb Mon Sep 17 00:00:00 2001 From: Peter Thaleikis Date: Sun, 20 Sep 2015 20:18:48 +1200 Subject: [PATCH 10/60] improve readibility --- core/Object.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/core/Object.php b/core/Object.php index 384b3494d..d2cf878dc 100755 --- a/core/Object.php +++ b/core/Object.php @@ -509,13 +509,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 From 0d89a13c2d02dc08d8ff14884b12f22b2f1cf4f2 Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Tue, 22 Sep 2015 14:46:57 +0100 Subject: [PATCH 11/60] FIX: GridFieldDetailForm failing to save many_many relations --- model/DataObject.php | 6 +- .../gridfield/GridFieldDetailFormTest.php | 66 +++++++++++++++++-- 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/model/DataObject.php b/model/DataObject.php index 85ba65b4f..96877b6bc 100644 --- a/model/DataObject.php +++ b/model/DataObject.php @@ -1780,10 +1780,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/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()); } } From c39cf2d55fadab448a303a72bee7757cc62844b0 Mon Sep 17 00:00:00 2001 From: Nicola Fontana Date: Mon, 21 Sep 2015 14:30:12 +0200 Subject: [PATCH 12/60] Do not hang on nested parameters in search context --- admin/code/ModelAdmin.php | 2 +- core/ArrayLib.php | 17 +++++++++++++++++ tests/core/ArrayLibTest.php | 23 +++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) 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/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/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', From 8f0f6475daa6cb32a33089ef60f18d5f4f8735ed Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Wed, 23 Sep 2015 15:19:24 +0100 Subject: [PATCH 13/60] FIX: Issues with field focus in edit forms (fixes #4621) --- admin/javascript/LeftAndMain.EditForm.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) 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(); } }); From c0be44d238c45853503fe1550fba0460a9a0f05c Mon Sep 17 00:00:00 2001 From: Stevie Mayhew Date: Fri, 25 Sep 2015 09:11:25 +1200 Subject: [PATCH 14/60] BUGFIX: fix response regression in initiation of request handler --- control/Controller.php | 1 + 1 file changed, 1 insertion(+) diff --git a/control/Controller.php b/control/Controller.php index 86cbf7f34..da8ce704d 100644 --- a/control/Controller.php +++ b/control/Controller.php @@ -133,6 +133,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider { $this->pushCurrent(); $this->urlParams = $request->allParams(); $this->setRequest($request); + $this->getResponse(); $this->setDataModel($model); $this->extend('onBeforeInit'); From 5c04dc5d673aa11249310bcb6e382db4ee2bff7f Mon Sep 17 00:00:00 2001 From: Marco Kernler Date: Fri, 25 Sep 2015 09:03:04 +0200 Subject: [PATCH 15/60] ENHANCEMENT - Added new method to display the number of total items in a paginated list within templates --- core/PaginatedList.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/PaginatedList.php b/core/PaginatedList.php index 0d8c87d61..2d07f82d2 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 * From e6084b7ad23fdde98cb148ce91f9d56d890dabe8 Mon Sep 17 00:00:00 2001 From: Peter Thaleikis Date: Mon, 28 Sep 2015 22:21:02 +1300 Subject: [PATCH 16/60] adding a space before casting into a different type --- control/Controller.php | 2 +- control/Director.php | 8 ++++---- control/HTTPRequest.php | 4 ++-- control/HTTPResponse.php | 2 +- control/PjaxResponseNegotiator.php | 2 +- control/RequestHandler.php | 4 ++-- control/Session.php | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/control/Controller.php b/control/Controller.php index 79fda01de..6cb92494a 100644 --- a/control/Controller.php +++ b/control/Controller.php @@ -576,7 +576,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider { $queryargs = array_merge($queryargs, $localargs); } if((is_string($arg) && $arg) || is_numeric($arg)) { - $arg = (string)$arg; + $arg = (string) $arg; if($result && substr($result,-1) != '/' && $arg[0] != '/') $result .= "/$arg"; else $result .= (substr($result, -1) == '/' && $arg[0] == '/') ? ltrim($arg, '/') : $arg; } diff --git a/control/Director.php b/control/Director.php index 1e315318f..c5de0f226 100644 --- a/control/Director.php +++ b/control/Director.php @@ -122,7 +122,7 @@ class Director implements TemplateGlobalProvider { : $_SERVER['REQUEST_METHOD'], $url, $_GET, - ArrayLib::array_merge_recursive((array)$_POST, (array)$_FILES), + ArrayLib::array_merge_recursive((array) $_POST, (array) $_FILES), @file_get_contents('php://input') ); @@ -295,9 +295,9 @@ class Director implements TemplateGlobalProvider { } // Replace the superglobals with appropriate test values - $_REQUEST = ArrayLib::array_merge_recursive((array)$getVars, (array)$postVars); - $_GET = (array)$getVars; - $_POST = (array)$postVars; + $_REQUEST = ArrayLib::array_merge_recursive((array) $getVars, (array) $postVars); + $_GET = (array) $getVars; + $_POST = (array) $postVars; $_SESSION = $session ? $session->inst_getAll() : array(); $_COOKIE = $cookieJar->getAll(false); Injector::inst()->registerService($cookieJar, 'Cookie_Backend'); diff --git a/control/HTTPRequest.php b/control/HTTPRequest.php index 3a8756d31..1aab8f26a 100644 --- a/control/HTTPRequest.php +++ b/control/HTTPRequest.php @@ -109,8 +109,8 @@ class SS_HTTPRequest implements ArrayAccess { $this->httpMethod = strtoupper(self::detect_method($httpMethod, $postVars)); $this->setUrl($url); - $this->getVars = (array)$getVars; - $this->postVars = (array)$postVars; + $this->getVars = (array) $getVars; + $this->postVars = (array) $postVars; $this->body = $body; } diff --git a/control/HTTPResponse.php b/control/HTTPResponse.php index 40d1db497..aefa6dde1 100644 --- a/control/HTTPResponse.php +++ b/control/HTTPResponse.php @@ -160,7 +160,7 @@ class SS_HTTPResponse { * @return SS_HTTPRequest $this */ public function setBody($body) { - $this->body = $body ? (string)$body : $body; // Don't type-cast false-ish values, eg null is null not '' + $this->body = $body ? (string) $body : $body; // Don't type-cast false-ish values, eg null is null not '' return $this; } diff --git a/control/PjaxResponseNegotiator.php b/control/PjaxResponseNegotiator.php index fa7782d41..5514326a0 100644 --- a/control/PjaxResponseNegotiator.php +++ b/control/PjaxResponseNegotiator.php @@ -87,7 +87,7 @@ class PjaxResponseNegotiator { foreach($fragments as $fragment) { if(isset($callbacks[$fragment])) { $res = call_user_func($callbacks[$fragment]); - $responseParts[$fragment] = $res ? (string)$res : $res; + $responseParts[$fragment] = $res ? (string) $res : $res; } else { throw new SS_HTTPResponse_Exception("X-Pjax = '$fragment' not supported for this URL.", 400); } diff --git a/control/RequestHandler.php b/control/RequestHandler.php index 1cbb41f56..41f5eba60 100644 --- a/control/RequestHandler.php +++ b/control/RequestHandler.php @@ -351,7 +351,7 @@ class RequestHandler extends ViewableData { if($action == 'index') return true; // Don't allow access to any non-public methods (inspect instance plus all extensions) - $insts = array_merge(array($this), (array)$this->getExtensionInstances()); + $insts = array_merge(array($this), (array) $this->getExtensionInstances()); foreach($insts as $inst) { if(!method_exists($inst, $action)) continue; $r = new ReflectionClass(get_class($inst)); @@ -389,7 +389,7 @@ class RequestHandler extends ViewableData { $action = strtolower($actionOrigCasing); $definingClass = null; - $insts = array_merge(array($this), (array)$this->getExtensionInstances()); + $insts = array_merge(array($this), (array) $this->getExtensionInstances()); foreach($insts as $inst) { if(!method_exists($inst, $action)) continue; $r = new ReflectionClass(get_class($inst)); diff --git a/control/Session.php b/control/Session.php index 0a7bdc59a..9725783b2 100644 --- a/control/Session.php +++ b/control/Session.php @@ -612,7 +612,7 @@ class Session { */ public static function set_timeout($timeout) { Deprecation::notice('4.0', 'Use the "Session.timeout" config setting instead'); - Config::inst()->update('Session', 'timeout', (int)$timeout); + Config::inst()->update('Session', 'timeout', (int) $timeout); } /** From 21216b47abac16e6f76bbef8fe886d87e13255bb Mon Sep 17 00:00:00 2001 From: Peter Thaleikis Date: Mon, 28 Sep 2015 22:21:08 +1300 Subject: [PATCH 17/60] remove trailing spaces in the codebase --- control/Cookie_Backend.php | 8 ++++---- control/Director.php | 2 +- control/FlushRequestFilter.php | 2 +- control/HTTP.php | 2 +- control/injector/Injector.php | 6 +++--- control/injector/ServiceConfigurationLocator.php | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/control/Cookie_Backend.php b/control/Cookie_Backend.php index bd1c40ec9..3c2b81580 100644 --- a/control/Cookie_Backend.php +++ b/control/Cookie_Backend.php @@ -18,7 +18,7 @@ interface Cookie_Backend { * @param array $cookies The existing cookies to load into the cookie jar */ public function __construct($cookies = array()); - + /** * Set a cookie * @@ -31,7 +31,7 @@ interface Cookie_Backend { * @param boolean $httpOnly Prevent the cookie being accessible by JS */ public function set($name, $value, $expiry = 90, $path = null, $domain = null, $secure = false, $httpOnly = true); - + /** * Get the cookie value by name * @@ -41,7 +41,7 @@ interface Cookie_Backend { * @return string|null The cookie value or null if unset */ public function get($name, $includeUnsent = true); - + /** * Get all the cookies * @@ -49,7 +49,7 @@ interface Cookie_Backend { * @return array All the cookies */ public function getAll($includeUnsent = true); - + /** * Force the expiry of a cookie by name * diff --git a/control/Director.php b/control/Director.php index 1e315318f..2abf9bf30 100644 --- a/control/Director.php +++ b/control/Director.php @@ -442,7 +442,7 @@ class Director implements TemplateGlobalProvider { if ($url == '.' || $url == './') { $url = ''; } - + if(strpos($url,'/') === false && !$relativeToSiteBase) { //if there's no URL we want to force a trailing slash on the link if (!$url) { diff --git a/control/FlushRequestFilter.php b/control/FlushRequestFilter.php index 35541618a..ab7133ffb 100644 --- a/control/FlushRequestFilter.php +++ b/control/FlushRequestFilter.php @@ -15,7 +15,7 @@ class FlushRequestFilter implements RequestFilter { } return true; - } + } public function postRequest(SS_HTTPRequest $request, SS_HTTPResponse $response, DataModel $model) { return true; diff --git a/control/HTTP.php b/control/HTTP.php index 586ecddef..e53f9db67 100644 --- a/control/HTTP.php +++ b/control/HTTP.php @@ -378,7 +378,7 @@ class HTTP { // (http://support.microsoft.com/kb/323308) // Note: this is also fixable by ticking "Do not save encrypted pages to disk" in advanced options. $cacheControlHeaders['max-age'] = 3; - + // Set empty pragma to avoid PHP's session_cache_limiter adding conflicting caching information, // defaulting to "nocache" on most PHP configurations (see http://php.net/session_cache_limiter). // Since it's a deprecated HTTP 1.0 option, all modern HTTP clients and proxies should diff --git a/control/injector/Injector.php b/control/injector/Injector.php index dc400c9b5..09fda499c 100644 --- a/control/injector/Injector.php +++ b/control/injector/Injector.php @@ -180,11 +180,11 @@ class Injector { * @var Factory */ protected $objectCreator; - + /** * Locator for determining Config properties for services - * - * @var ServiceConfigurationLocator + * + * @var ServiceConfigurationLocator */ protected $configLocator; diff --git a/control/injector/ServiceConfigurationLocator.php b/control/injector/ServiceConfigurationLocator.php index d1bd28de4..424267fc6 100644 --- a/control/injector/ServiceConfigurationLocator.php +++ b/control/injector/ServiceConfigurationLocator.php @@ -9,11 +9,11 @@ * @subpackage injector */ class ServiceConfigurationLocator { - - + + /** * Finds the Injector config for a named service. - * + * * @param string $name * @return mixed */ From 5fda95d95102f3bff32b90b8be02b04a69d2429e Mon Sep 17 00:00:00 2001 From: Peter Thaleikis Date: Mon, 28 Sep 2015 22:21:30 +1300 Subject: [PATCH 18/60] converting spaces as intentation to tabs --- control/HTTP.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/control/HTTP.php b/control/HTTP.php index 586ecddef..a87e6006e 100644 --- a/control/HTTP.php +++ b/control/HTTP.php @@ -25,9 +25,9 @@ class HTTP { protected static $etag = null; /** - * @config - */ - private static $cache_ajax_requests = true; + * @config + */ + private static $cache_ajax_requests = true; /** * Turns a local system filename into a URL by comparing it to the script From 5224fc460c6155c4f2253f42d88729b8f31066f6 Mon Sep 17 00:00:00 2001 From: Manuel Teuber Date: Tue, 29 Sep 2015 23:49:29 +0200 Subject: [PATCH 19/60] FIX: Permission::checkMember() use of undefined variable $codes --- security/Permission.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) ? ", ?" : ''; From 71a2ef13501cc9344875d739c67eabb8eb074c8a Mon Sep 17 00:00:00 2001 From: Liam Whittle Date: Tue, 29 Sep 2015 18:51:08 -0400 Subject: [PATCH 20/60] fixed minor GridField initialization syntax. --- .../en/02_Developer_Guides/03_Forms/Field_types/04_GridField.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 5e68512e1ceba4722f9d742cfc6db68f06f37b57 Mon Sep 17 00:00:00 2001 From: Matthew Hailwood Date: Wed, 30 Sep 2015 14:19:20 +1300 Subject: [PATCH 21/60] Remove extra set of li's --- .../01_Templates/How_Tos/01_Navigation_Menu.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 %> -
    • +
        <% loop $Children %>
      • $MenuTitle
      • <% end_loop %> -
      +
    <% 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) From cb55a0a621494873a04c697ecd326bb7a4d02173 Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Wed, 30 Sep 2015 16:25:17 +0100 Subject: [PATCH 22/60] FIX: GridFieldSortableHeader incorrectly reporting fields as sortable --- forms/gridfield/GridFieldSortableHeader.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forms/gridfield/GridFieldSortableHeader.php b/forms/gridfield/GridFieldSortableHeader.php index 67af41e73..41efc1c71 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; From 4a70ffea0687c8c83b6210856e4c10f5aff0a883 Mon Sep 17 00:00:00 2001 From: Corey Sewell Date: Mon, 5 Oct 2015 15:58:46 +1300 Subject: [PATCH 23/60] FIX: Typo in cur methods PHPDoc --- control/Controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/control/Controller.php b/control/Controller.php index e0416661c..42181000e 100644 --- a/control/Controller.php +++ b/control/Controller.php @@ -387,7 +387,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider { /** * Returns the current controller - * @returns Controller + * @return Controller */ public static function curr() { if(Controller::$controller_stack) { From 6c117cd62960670239c5a6f6b3832c819e21332a Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Tue, 6 Oct 2015 12:40:24 +1300 Subject: [PATCH 24/60] BUG fix imagick interface and add to travis --- .travis.yml | 1 + filesystem/GD.php | 1 + filesystem/ImagickBackend.php | 3 ++- model/Image_Backend.php | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 05a390383..681efa09c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,7 @@ matrix: env: DB=MYSQL BEHAT_TEST=1 before_script: + - 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/filesystem/GD.php b/filesystem/GD.php index 623923cec..d34704f56 100644 --- a/filesystem/GD.php +++ b/filesystem/GD.php @@ -108,6 +108,7 @@ class GDBackend extends Object implements Image_Backend { /** * @param string $filename + * @param string $manipulation * @return boolean */ public function imageAvailable($filename, $manipulation) { diff --git a/filesystem/ImagickBackend.php b/filesystem/ImagickBackend.php index 3112d8b10..8f302cb24 100644 --- a/filesystem/ImagickBackend.php +++ b/filesystem/ImagickBackend.php @@ -99,9 +99,10 @@ class ImagickBackend extends Imagick implements Image_Backend { * @todo Implement memory checking for Imagick? See {@link GD} * * @param string $filename + * @param string $manipulation * @return boolean */ - public function imageAvailable($filename) { + public function imageAvailable($filename, $manipulation) { return true; } diff --git a/model/Image_Backend.php b/model/Image_Backend.php index 919a916f2..131252c77 100644 --- a/model/Image_Backend.php +++ b/model/Image_Backend.php @@ -115,6 +115,7 @@ interface Image_Backend { * imageAvailable * * @param string $filename + * @param string $manipulation * @return boolean */ public function imageAvailable($filename, $manipulation); From ad42f802c4a621916a352c3a7c5d4f849b896c3e Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Tue, 6 Oct 2015 12:54:35 +1300 Subject: [PATCH 25/60] BUG Fix duplicate HolderID on TreeDropdownField --- templates/forms/TreeDropdownField.ss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 @@ -
    Date: Tue, 6 Oct 2015 16:35:44 +1300 Subject: [PATCH 26/60] BUG Imagick tests compare image dimensions rather than image hashes --- tests/model/ImageTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/model/ImageTest.php b/tests/model/ImageTest.php index 5ba108662..1f8a251d4 100644 --- a/tests/model/ImageTest.php +++ b/tests/model/ImageTest.php @@ -320,10 +320,10 @@ class ImageTest extends SapphireTest { $this->assertEquals(3, count($filesInFolder), 'Image folder contains only the expected number of images before regeneration'); - $hash = md5_file($imageThirdPath); + $stats = getimagesize($imageThirdPath); $this->assertEquals(3, $image->regenerateFormattedImages(), 'Cached images were regenerated in the right number'); - $this->assertEquals($hash, md5_file($imageThirdPath), 'Regeneration of third image is correct'); + $this->assertEquals($stats, getimagesize($imageThirdPath), 'Regeneration of third image is correct'); /* Check that no other images exist, to ensure that the regeneration did not create other images */ $this->assertEquals($filesInFolder, $folder->find(dirname($imageThirdPath)), From 0cd3569fb9f7723604b9ab60b0ba2dda9302d419 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Tue, 6 Oct 2015 18:33:16 +1300 Subject: [PATCH 27/60] Update translations --- admin/javascript/lang/eo.js | 14 ++-- admin/javascript/lang/src/eo.js | 14 ++-- admin/javascript/lang/src/zh.js | 8 +-- admin/javascript/lang/zh.js | 8 +-- lang/cs.yml | 4 ++ lang/en.yml | 8 +-- lang/eo.yml | 9 +++ lang/fa_IR.yml | 117 +++++++++++++++++++++++++++++++- lang/lt.yml | 2 + lang/sk.yml | 4 ++ lang/tr.yml | 6 ++ lang/zh.yml | 34 ++++++++++ 12 files changed, 201 insertions(+), 27 deletions(-) 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/lang/cs.yml b/lang/cs.yml index adbd61569..a96f65879 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í

    • Povolené sloupce: %s
    • Existující skupiny jsou porovnány jejich unikátním Code hodnotou, a aktualizovány s novými hodnotami z importovaného souboru
    • Hierarchie skupin může být tvořena použitím ParentCode sloupce.
    • Kódy oprávnění mohou být přiřazeny PermissionCode sloupcem. Existující oprávnění nejsou smazána.
    ' ResultCreated: 'Vytvořeno {count} skupin' ResultDeleted: 'Smazáno %d skupin' ResultUpdated: 'Aktualizováno %d skupin' @@ -326,6 +327,8 @@ cs: DropdownBatchActionsDefault: Akcie HELP: Nápověda 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.' PreviewButton: Náhled REORGANISATIONSUCCESSFUL: 'Strom webu reorganizován úspěšně.' SAVEDUP: Uloženo. @@ -413,6 +416,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í

    • Povolené sloupce: %s
    • Existující uživatelé jsou porovnáni jejich unikátní vlastností Code, a aktualizováni s novými hodnotami z importovaného souboru.
    • Skupiny mohou být přiřazeny sloupcem Groups. Skupiny jsou identifikovány svojí vlastností Code, více skupin může být odděleno čárkou. Existující členství ve skupině nejsou smazána.
    ' 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 e194d2225..5cc8afeff 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

    • Eblaj kolumnoj: %s
    • Ekzistantaj grupoj kongruiĝas laŭ la valoro de ilia unika Kodo, kaj ĝisdatiĝas per eventualaj valoroj el la importita dosiero
    • Eblas krei grupajn hierarĥiojn per la kolumno ParentCode.
    • Eblas agordi permeskodojn per la kolumno PermissionCode. Ekzistantaj permeskodoj ne vakiĝas.
    ' 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

    • Eblaj kolumnoj: %s
    • Ekzistantaj uzantoj kongruiĝas laŭ la valoro de sia unika atributo Code, kaj ĝisdatiĝas per eventualaj novaj valoroj el la importita dosiero.
    • Eblas agordi grupojn per la kolumno Groups. Grupoj estas identigeblaj per sia atributo Code, plurobla grupo estu apartigitaj per komo. Ekzistantaj grupaj membrecoj ne vakiĝas.
    ' 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..296fc1e23 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

    • Galimi stulpeliai: %s.
    • Esamos grupės yra surandamos su jų unikalia Code reikšme ir atnaujinamos duomenimis iš importuojamos bylos.
    • Grupių hierarchija gali būti sukurta naudojant ParentCode stulpelį.
    • Leidimų kodai gali būti priskirti naudojant PermissionCode stulpelį. Esami leidimai nebus pakeisti.
    ' ResultCreated: 'Sukurta {count} grupių' ResultDeleted: 'Ištrinta %d grupių' ResultUpdated: 'Atnaujinta %d grupių' @@ -415,6 +416,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

    • Galimi stulpeliai: %s.
    • Esami vartotojai yra surandami su jų unikalia Code reikšme ir atnaujinami duomenimis iš importuojamos bylos.
    • Grupės gali būti priskirtos naudojant Groups column. stulpelį. Grupės yra atpažįstamos pagal Code stulpelį, kelios grupės nurodomos per kablelį. Jau priskirtos vartotojui grupės nebus pakeistos.
    ' 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..91f68461c 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

    • Povolené stĺpce: %s
    • Existujúce skupiny sú porovnávané s ich unikátnou Code; hodnotou, a aktualizované s novými hodnotami z importovaného súbory</li>
    • Skupina hierarchií môže byť tvorená použitím ParentCode; stĺpce.</li>
    • Kódy oprávnení môžu byť priradené PermissionCode; stĺpcom. Existujúce oprávnenia nie sú smazáné.
    ' ResultCreated: 'Vytvorených {count} skupín' ResultDeleted: 'Zmazané %d skupiny' ResultUpdated: 'Aktualizované %d skupiny' @@ -326,6 +327,8 @@ sk: DropdownBatchActionsDefault: Akcie HELP: Pomoc 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.' PreviewButton: Náhľad REORGANISATIONSUCCESSFUL: 'Strom webu bol reorganizovaný úspešne.' SAVEDUP: Uložené. @@ -413,6 +416,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

    • Povolené stĺpce: %s
    • Existujúci užívatelia sú porovnávaní ich unikátnou vlastnosťou Code, a aktualizovaní s novými hodnotami z importovaného súboru.
    • Skupiny môžu byťt priradené stĺpcom Groups. Skupiny sú identifikované ich vlastnosťou Code, viacero skupín môže byť oddelené čiarkou. Existujúce členstvá skupiny nie sú smazané.
    ' 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: From 4af684f2f3ab8c07cdeb03097063af352ad3715b Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Tue, 6 Oct 2015 18:49:35 +1300 Subject: [PATCH 28/60] Added 3.2.0-rc2 changelog --- docs/en/04_Changelogs/rc/3.2.0-rc2.md | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 docs/en/04_Changelogs/rc/3.2.0-rc2.md 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..04c02b8df --- /dev/null +++ b/docs/en/04_Changelogs/rc/3.2.0-rc2.md @@ -0,0 +1,31 @@ +# 3.2.0-rc2 + + + +## 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) From ee6b250a46e18c563d7107dc24c5f8d7bd09d55e Mon Sep 17 00:00:00 2001 From: "Elvinas L." Date: Tue, 6 Oct 2015 18:58:22 +0300 Subject: [PATCH 29/60] Ajustments Altered code to according to the feedback and added phpdoc. --- search/filters/FulltextFilter.php | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/search/filters/FulltextFilter.php b/search/filters/FulltextFilter.php index 22dbd6f07..233a63f70 100755 --- a/search/filters/FulltextFilter.php +++ b/search/filters/FulltextFilter.php @@ -73,18 +73,20 @@ class FulltextFilter extends SearchFilter { return parent::getDbName(); } - - private function prepareColumns($columns) { - $class = ''; - $parts = explode(',', $columns); - array_walk($parts, function(&$col, $key) use (&$class) { - $name = trim($col, " \t\n\r\0\x0B\""); - if (empty($class)) { - $class = ClassInfo::table_for_object_field($this->model, $name); - } - $col = sprintf('"%s"."%s"', $class, $name); - }); - return implode(',', $parts); + + /** + * 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); } } From 19c754bf9a1570ca59305c05bedb904bd2015959 Mon Sep 17 00:00:00 2001 From: "Elvinas L." Date: Tue, 6 Oct 2015 18:59:39 +0300 Subject: [PATCH 30/60] Fixed tests --- tests/search/FulltextFilterTest.php | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/search/FulltextFilterTest.php b/tests/search/FulltextFilterTest.php index efca15c6e..0bbe7e8cc 100755 --- a/tests/search/FulltextFilterTest.php +++ b/tests/search/FulltextFilterTest.php @@ -40,26 +40,36 @@ 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("MATCH (\"ColumnA\", \"ColumnB\") AGAINST ('SilverStripe')"), + array("MATCH (\"FulltextFilterTest_DataObject\".\"ColumnA\", \"FulltextFilterTest_DataObject\".\"ColumnB\") AGAINST ('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("MATCH (\"ColumnC\", \"ColumnD\") AGAINST ('SilverStripe')"), + array("MATCH (\"FulltextFilterTest_DataObject\".\"ColumnC\", \"FulltextFilterTest_DataObject\".\"ColumnD\") AGAINST ('SilverStripe')"), $query2->query()->getWhere() ); @@ -102,4 +112,4 @@ class FulltextFilterTest_DataObject extends DataObject implements TestOnly { "MySQLDatabase" => "ENGINE=MyISAM", ); -} \ No newline at end of file +} From 12c423909f721c6f5223007ad5e7ba6c162d63a4 Mon Sep 17 00:00:00 2001 From: Patrick Nelson Date: Mon, 5 Oct 2015 11:26:21 -0400 Subject: [PATCH 31/60] FIX (partial) for #3181 where non-submit buttons are being activated on "enter" key press (relates to CMS issue at https://github.com/silverstripe/silverstripe-cms/issues/1288). --- forms/HtmlEditorField.php | 2 +- forms/gridfield/GridFieldSortableHeader.php | 2 +- javascript/GridField.js | 2 +- javascript/UploadField_downloadtemplate.js | 2 +- javascript/UploadField_uploadtemplate.js | 6 +++--- templates/AssetUploadField.ss | 2 +- templates/Includes/HtmlEditorField_viewfile.ss | 4 ++-- templates/Includes/UploadField_FileButtons.ss | 8 ++++---- templates/UploadField.ss | 4 ++-- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/forms/HtmlEditorField.php b/forms/HtmlEditorField.php index d51139c4c..65541ffaa 100644 --- a/forms/HtmlEditorField.php +++ b/forms/HtmlEditorField.php @@ -352,7 +352,7 @@ class HtmlEditorField_Toolbar extends RequestHandler { '

    ' . sprintf($numericLabelTmpl, '1', _t('HtmlEditorField.ADDURL', 'Add URL')) . '

    '), $remoteURL = new TextField('RemoteURL', 'http://'), new LiteralField('addURLImage', - '') ); diff --git a/forms/gridfield/GridFieldSortableHeader.php b/forms/gridfield/GridFieldSortableHeader.php index 67af41e73..d05b68635 100644 --- a/forms/gridfield/GridFieldSortableHeader.php +++ b/forms/gridfield/GridFieldSortableHeader.php @@ -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 5472547a8..e45055ee2 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/UploadField_downloadtemplate.js b/javascript/UploadField_downloadtemplate.js index 43340b201..73709dbfd 100644 --- a/javascript/UploadField_downloadtemplate.js +++ b/javascript/UploadField_downloadtemplate.js @@ -22,7 +22,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 3df123759..c54851e90 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/templates/AssetUploadField.ss b/templates/AssetUploadField.ss index db2cdb6ed..a6485db72 100644 --- a/templates/AssetUploadField.ss +++ b/templates/AssetUploadField.ss @@ -47,7 +47,7 @@
    - 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 %>
    From 557c4211fa0e2ebaf10fb65bbad5af20712141cb Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Wed, 7 Oct 2015 09:51:24 +1300 Subject: [PATCH 32/60] Update changelog --- docs/en/04_Changelogs/rc/3.2.0-rc2.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/04_Changelogs/rc/3.2.0-rc2.md b/docs/en/04_Changelogs/rc/3.2.0-rc2.md index 04c02b8df..12478d756 100644 --- a/docs/en/04_Changelogs/rc/3.2.0-rc2.md +++ b/docs/en/04_Changelogs/rc/3.2.0-rc2.md @@ -1,5 +1,7 @@ # 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 From b03ae843ca5ba96929bbc386c99ebfe73403ae46 Mon Sep 17 00:00:00 2001 From: Hamish Friedlander Date: Wed, 7 Oct 2015 14:35:29 +1300 Subject: [PATCH 33/60] Update core contributors docs to include Jono Menz --- docs/en/05_Contributing/06_Core_committers.md | 1 + 1 file changed, 1 insertion(+) 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/) From 666ce269292521288eef8aeac4af30378f775576 Mon Sep 17 00:00:00 2001 From: Manuel Teuber Date: Tue, 29 Sep 2015 23:49:29 +0200 Subject: [PATCH 34/60] FIX: Permission::checkMember() use of undefined variable $codes --- security/Permission.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) ? ", ?" : ''; From a679680c0de3b46ddcc56670ecea39a9115dc410 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Wed, 7 Oct 2015 15:56:22 +1300 Subject: [PATCH 35/60] Update changelogs to include PDO upgrade instructions --- .../03_Environment_Management.md | 5 ++-- docs/en/04_Changelogs/3.2.0.md | 30 +++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) 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/04_Changelogs/3.2.0.md b/docs/en/04_Changelogs/3.2.0.md index dad837b06..eda9f2414 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 From 630062c0e08307b9a68295102baa68df84927423 Mon Sep 17 00:00:00 2001 From: "Elvinas L." Date: Wed, 7 Oct 2015 09:33:02 +0300 Subject: [PATCH 36/60] Removed whitespaces --- tests/search/FulltextFilterTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/search/FulltextFilterTest.php b/tests/search/FulltextFilterTest.php index 0bbe7e8cc..213c309ba 100755 --- a/tests/search/FulltextFilterTest.php +++ b/tests/search/FulltextFilterTest.php @@ -45,9 +45,9 @@ class FulltextFilterTest extends SapphireTest { $filter1->setModel('FulltextFilterTest_DataObject'); $query1 = FulltextFilterTest_DataObject::get()->dataQuery(); $filter1->apply($query1); - $this->assertNotEquals('"ColumnA", "ColumnB"', $filter1->getDbName()); + $this->assertNotEquals('"ColumnA","ColumnB"', $filter1->getDbName()); $this->assertNotEquals( - array("MATCH (\"ColumnA\", \"ColumnB\") AGAINST ('SilverStripe')"), + array("MATCH (\"ColumnA\",\"ColumnB\") AGAINST ('SilverStripe')"), $query1->query()->getWhere() ); @@ -56,9 +56,9 @@ class FulltextFilterTest extends SapphireTest { $filter1->setModel('FulltextFilterTest_DataObject'); $query1 = FulltextFilterTest_DataObject::get()->dataQuery(); $filter1->apply($query1); - $this->assertEquals('"FulltextFilterTest_DataObject"."ColumnA", "FulltextFilterTest_DataObject"."ColumnB"', $filter1->getDbName()); + $this->assertEquals('"FulltextFilterTest_DataObject"."ColumnA","FulltextFilterTest_DataObject"."ColumnB"', $filter1->getDbName()); $this->assertEquals( - array("MATCH (\"FulltextFilterTest_DataObject\".\"ColumnA\", \"FulltextFilterTest_DataObject\".\"ColumnB\") AGAINST ('SilverStripe')"), + array("MATCH (\"FulltextFilterTest_DataObject\".\"ColumnA\",\"FulltextFilterTest_DataObject\".\"ColumnB\") AGAINST ('SilverStripe')"), $query1->query()->getWhere() ); @@ -67,9 +67,9 @@ class FulltextFilterTest extends SapphireTest { $filter2->setModel('FulltextFilterTest_DataObject'); $query2 = FulltextFilterTest_DataObject::get()->dataQuery(); $filter2->apply($query2); - $this->assertEquals('"FulltextFilterTest_DataObject"."ColumnC", "FulltextFilterTest_DataObject"."ColumnD"', $filter2->getDbName()); + $this->assertEquals('"FulltextFilterTest_DataObject"."ColumnC","FulltextFilterTest_DataObject"."ColumnD"', $filter2->getDbName()); $this->assertEquals( - array("MATCH (\"FulltextFilterTest_DataObject\".\"ColumnC\", \"FulltextFilterTest_DataObject\".\"ColumnD\") AGAINST ('SilverStripe')"), + array("MATCH (\"FulltextFilterTest_DataObject\".\"ColumnC\",\"FulltextFilterTest_DataObject\".\"ColumnD\") AGAINST ('SilverStripe')"), $query2->query()->getWhere() ); From a71d99cf8445a906ccd9b13242d36ae1e6a75d74 Mon Sep 17 00:00:00 2001 From: Patrick Nelson Date: Tue, 6 Oct 2015 19:37:48 -0400 Subject: [PATCH 37/60] FIX for #4663 ensuring return values from TabSet are retained from parent. Removing useless override. Cleaning up documentation in TabSet and return types. --- forms/CompositeField.php | 3 +++ forms/FieldList.php | 4 +++- forms/TabSet.php | 29 ++++++++++++++++++----------- 3 files changed, 24 insertions(+), 12 deletions(-) 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/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/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); } } From d9b3982323f4729b9a40f2b8840a3626677ec5db Mon Sep 17 00:00:00 2001 From: Nick Spiel Date: Thu, 8 Oct 2015 17:32:35 +1100 Subject: [PATCH 38/60] Adding SVG to allowed file types Adding svg to allowed extensions array, this should be merged in conjunction with a change I am making to the htaccess file in the silverstripe-installer repo (also on 3 branch). I will link to this when I have completed the PR --- filesystem/File.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filesystem/File.php b/filesystem/File.php index bb99e8fb6..b9e11e314 100644 --- a/filesystem/File.php +++ b/filesystem/File.php @@ -129,7 +129,7 @@ class File extends DataObject { '','ace','arc','arj','asf','au','avi','bmp','bz2','cab','cda','css','csv','dmg','doc','docx','dotx','dotm', 'flv','gif','gpx','gz','hqx','ico','jar','jpeg','jpg','js','kml', 'm4a','m4v', 'mid','midi','mkv','mov','mp3','mp4','mpa','mpeg','mpg','ogg','ogv','pages','pcx','pdf','pkg', - 'png','pps','ppt','pptx','potx','potm','ra','ram','rm','rtf','sit','sitx','tar','tgz','tif','tiff', + 'png','pps','ppt','pptx','potx','potm','ra','ram','rm','rtf','sit','sitx', 'svg', 'tar','tgz','tif','tiff', 'txt','wav','webm','wma','wmv','xls','xlsx','xltx','xltm','zip','zipx', ); From f6a1e5ec3006df185a49f59d8356e13d9dc5cca9 Mon Sep 17 00:00:00 2001 From: JorisDebonnet Date: Thu, 8 Oct 2015 19:02:47 +0200 Subject: [PATCH 39/60] Bugfix for DropdownField->castedCopy The Newsletter module crashed on it when viewing a sent Newsletter. --- forms/DropdownField.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/forms/DropdownField.php b/forms/DropdownField.php index 861a26686..52be4be23 100644 --- a/forms/DropdownField.php +++ b/forms/DropdownField.php @@ -362,7 +362,9 @@ class DropdownField extends FormField { */ public function castedCopy($classOrCopy) { $field = parent::castedCopy($classOrCopy); - $field->setHasEmptyDefault($this->getHasEmptyDefault()); + if(method_exists($field, 'setHasEmptyDefault')) { + $field->setHasEmptyDefault($this->getHasEmptyDefault()); + } return $field; } } From f192a6ecaf70446ec60f6c7ef2a555395f83ea16 Mon Sep 17 00:00:00 2001 From: Patrick Nelson Date: Sun, 12 Jul 2015 04:36:39 -0400 Subject: [PATCH 40/60] FIX #4392: Ensure headers are checked first before being clobbered by globally maintained state. Also ensuring tests utilize separate responses for isolation. --- control/HTTP.php | 10 ++++++++-- tests/control/HTTPTest.php | 21 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/control/HTTP.php b/control/HTTP.php index 7a17d54c4..b1b2b3cae 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/tests/control/HTTPTest.php b/tests/control/HTTPTest.php index 42d6e2d88..b0bd98703 100644 --- a/tests/control/HTTPTest.php +++ b/tests/control/HTTPTest.php @@ -13,18 +13,37 @@ class HTTPTest extends FunctionalTest { $this->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)); + } } /** From 0092792568fb8a33674669aa200c7c81b163a365 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Mon, 12 Oct 2015 08:44:34 +1300 Subject: [PATCH 41/60] Added 3.2.0 changelog --- docs/en/04_Changelogs/3.2.0.md | 160 +++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/docs/en/04_Changelogs/3.2.0.md b/docs/en/04_Changelogs/3.2.0.md index dad837b06..4e8e35036 100644 --- a/docs/en/04_Changelogs/3.2.0.md +++ b/docs/en/04_Changelogs/3.2.0.md @@ -788,3 +788,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) From 6030854725011282c94994244fec1c5181f3be9a Mon Sep 17 00:00:00 2001 From: Stephen Shkardoon Date: Mon, 12 Oct 2015 20:10:48 +1300 Subject: [PATCH 42/60] Fix page reordering bug with ParentID If you are viewing PageA in the CMS, but move PageB into PageC, the edit form will recieve an edit form ParentID of PageC. This is incorrect, as only PageB had it's ParentID change. --- admin/javascript/LeftAndMain.Tree.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/admin/javascript/LeftAndMain.Tree.js b/admin/javascript/LeftAndMain.Tree.js index 0404dc792..4faa4654a 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: { From 862429e5d7cc17e5151e39f37b46054a52bb1328 Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Tue, 13 Oct 2015 09:09:22 +0100 Subject: [PATCH 43/60] Only notify users about PDO native mode once --- model/connect/MySQLSchemaManager.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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; } From 1974e79d71d5dd232c44cd5e7d49f4804a96d78d Mon Sep 17 00:00:00 2001 From: Daniel Hensby Date: Thu, 15 Oct 2015 15:18:32 +0100 Subject: [PATCH 44/60] Allow multi-line enum declarations --- model/fieldtypes/Enum.php | 2 +- tests/forms/EnumFieldTest.php | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/model/fieldtypes/Enum.php b/model/fieldtypes/Enum.php index 7998f5bf6..c09ef3c2d 100644 --- a/model/fieldtypes/Enum.php +++ b/model/fieldtypes/Enum.php @@ -38,7 +38,7 @@ class Enum extends StringField { public function __construct($name = null, $enum = NULL, $default = NULL) { if($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; 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()); + } } From a555817d6fd42f56f955d8ebf227f171f132a2cd Mon Sep 17 00:00:00 2001 From: Cam Findlay Date: Mon, 19 Oct 2015 11:44:31 +1300 Subject: [PATCH 45/60] DOCS Module standard 1.0 Adding the module standard to 3.2+ docs. --- .../05_Extending/00_Modules.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) 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 From c3641587a5d5977af4fa053e5813846ce990d86c Mon Sep 17 00:00:00 2001 From: Cam Findlay Date: Tue, 20 Oct 2015 12:39:04 +1300 Subject: [PATCH 46/60] FIX only use sethasemptydefault if exists. Backport of #4672 with a slight rewrite incase of subclasses of the field. --- forms/DropdownField.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/forms/DropdownField.php b/forms/DropdownField.php index 861a26686..89feef34a 100644 --- a/forms/DropdownField.php +++ b/forms/DropdownField.php @@ -362,7 +362,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; } } From e88032a7aa94f8c658defa8d66ea8a19c128fe2f Mon Sep 17 00:00:00 2001 From: David Alexander Date: Fri, 23 Oct 2015 13:49:03 +1300 Subject: [PATCH 47/60] DOCS : spelling --- docs/en/02_Developer_Guides/01_Templates/09_Casting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From a1e343629b951fda7f2ec10c7b93c24bb25d08a4 Mon Sep 17 00:00:00 2001 From: Christopher Darling Date: Mon, 26 Oct 2015 11:02:47 +0000 Subject: [PATCH 48/60] DOCS: correct config setting for custom editor.css see https://github.com/silverstripe/silverstripe-framework/blob/a964e7636e25879def67648bee2ba127ed5d1b7f/admin/code/LeftAndMain.php#L287-L308 --- .../15_Customising_the_Admin_Interface/05_Typography.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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. From 293d84721efafedf3dd3fe69dd1d013a8c07d3ff Mon Sep 17 00:00:00 2001 From: Patrick Nelson Date: Tue, 27 Oct 2015 12:24:36 -0400 Subject: [PATCH 49/60] FIX for #4712: Dropping in some PHP documentation on return types for dynamically generated image methods. --- model/Image.php | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/model/Image.php b/model/Image.php index c72a29c8e..59c646f60 100644 --- a/model/Image.php +++ b/model/Image.php @@ -208,7 +208,7 @@ class Image extends File implements Flushable { * * @param integer $width The width to size within * @param integer $height The height to size within - * @return Image + * @return Image|null */ public function Fit($width, $height) { // Prevent divide by zero on missing/blank file @@ -266,7 +266,7 @@ class Image extends File implements Flushable { * * @param integer $width Width to crop to * @param integer $height Height to crop to - * @return Image + * @return Image|null */ public function Fill($width, $height) { return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample') @@ -323,7 +323,7 @@ class Image extends File implements Flushable { * * @param integer $width The width to size to * @param integer $height The height to size to - * @return Image + * @return Image|null */ public function Pad($width, $height, $backgroundColor='FFFFFF') { return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample') @@ -347,7 +347,7 @@ class Image extends File implements Flushable { * Scale image proportionally by width. Use in templates with $ScaleWidth. * * @param integer $width The width to set - * @return Image + * @return Image|null */ public function ScaleWidth($width) { return $this->isWidth($width) && !Config::inst()->get('Image', 'force_resample') @@ -387,7 +387,7 @@ class Image extends File implements Flushable { * Scale image proportionally by height. Use in templates with $ScaleHeight. * * @param integer $height The height to set - * @return Image + * @return Image|null */ public function ScaleHeight($height) { return $this->isHeight($height) && !Config::inst()->get('Image', 'force_resample') @@ -564,6 +564,11 @@ class Image extends File implements Flushable { return $backend->paddedResize($width, $height); } + /** + * Resize this image for the CMS. Use in templates with $CMSThumbnail + * + * @return Image_Cached|null + */ public function CMSThumbnail() { return $this->getFormattedImage('CMSThumbnail'); } @@ -667,7 +672,7 @@ class Image extends File implements Flushable { * Just pass the correct number of parameters expected by the working function * * @param string $format The name of the format. - * @return Image_Cached + * @return Image_Cached|null */ public function getFormattedImage($format) { $args = func_get_args(); @@ -768,7 +773,7 @@ class Image extends File implements Flushable { * @param Image_Backend $backend * @param integer $width Width to resize to * @param integer $height Height to resize to - * @return Image_Backend + * @return Image_Backend|null */ public function generateResizedImage(Image_Backend $backend, $width, $height) { if(!$backend){ @@ -933,7 +938,7 @@ class Image extends File implements Flushable { * Get the dimensions of this Image. * @param string $dim If this is equal to "string", return the dimensions in string form, * if it is 0 return the height, if it is 1 return the width. - * @return string|int + * @return string|int|null */ public function getDimensions($dim = "string") { if($this->getField('Filename')) { From e44f22c6b25a60237a7b5762ae123d71a1931133 Mon Sep 17 00:00:00 2001 From: Michael Parkhill Date: Wed, 28 Oct 2015 11:52:35 +1300 Subject: [PATCH 50/60] Fix broken link to DataObject api --- .../en/02_Developer_Guides/00_Model/05_Extending_DataObjects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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]. From 0197b46001f2873a32c80b279b0b14193f5ffef0 Mon Sep 17 00:00:00 2001 From: Damian Kissick Date: Wed, 28 Oct 2015 21:28:45 +1300 Subject: [PATCH 51/60] Update 01_Code.md Corrected 'submiting' spelling --- docs/en/05_Contributing/01_Code.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/05_Contributing/01_Code.md b/docs/en/05_Contributing/01_Code.md index 9b0295251..a46670290 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. From db16248b9ab7677cc4b4e25857a6b6d36f8c35f0 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Wed, 28 Oct 2015 16:44:14 +1300 Subject: [PATCH 52/60] BUG Fix broken InlineFormAction --- forms/InlineFormAction.php | 5 +++-- tests/forms/InlineFormActionTest.php | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tests/forms/InlineFormActionTest.php 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/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); + } +} From daa86d3a4ce75bf8637134726864ae14fbbdf586 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Thu, 29 Oct 2015 17:36:38 +1300 Subject: [PATCH 53/60] BUG Fix regression from #4396 in test fixtures --- dev/FixtureBlueprint.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dev/FixtureBlueprint.php b/dev/FixtureBlueprint.php index e7eb51d33..651480566 100644 --- a/dev/FixtureBlueprint.php +++ b/dev/FixtureBlueprint.php @@ -192,6 +192,11 @@ class FixtureBlueprint { if($data && array_key_exists('LastEdited', $data)) { $this->overrideField($obj, 'LastEdited', $data['LastEdited'], $fixtures); } + + // Ensure Folder objects exist physically, as otherwise future File fixtures can't detect them + if($obj instanceof Folder) { + Filesystem::makeFolder($obj->getFullPath()); + } } catch(Exception $e) { Config::inst()->update('DataObject', 'validation_enabled', $validationenabled); throw $e; From b857bdf209d79fc623724e68f6a660354cbd5f93 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Tue, 20 Oct 2015 17:46:46 +1300 Subject: [PATCH 54/60] BUG Fix duplicate files being included in case of flush Fixes #4553 --- javascript/jquery-ondemand/jquery.ondemand.js | 54 ++++++++++++++++--- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/javascript/jquery-ondemand/jquery.ondemand.js b/javascript/jquery-ondemand/jquery.ondemand.js index ec647e66b..44d0b6198 100644 --- a/javascript/jquery-ondemand/jquery.ondemand.js +++ b/javascript/jquery-ondemand/jquery.ondemand.js @@ -15,34 +15,74 @@ */ (function($){ + /** + * Decode URL from header string + * + * @param {String} str + * @returns {String} + */ var decodePath = function(str) { return str.replace(/%2C/g,',').replace(/\&/g, '&').replace(/^\s+|\s+$/g, ''); }; + + /** + * Remove querystring from the url. Necessary to prevent a file being included twice in the same page if + * requested at different times (e.g. during flush) + * + * @param {String} str + * @returns {String} + */ + var removeQuerystring = function(str) { + return str.split("?")[0]; + }; $.extend({ // loaded files list - to protect against loading existed file again (by PGA) _ondemand_loaded_list : null, + + /** + * Add a new url to the loaded item + * + * @param {String} url + */ + registerLoadedItem : function(url) { + this._ondemand_loaded_list[removeQuerystring(url)] = 1; + }, /** * Returns true if the given CSS or JS script has already been loaded + * + * @param {String} scriptUrl Decoded CSS or JS file url + * @returns {Boolean} */ isItemLoaded : function(scriptUrl) { - var self = this, src; + var self = this, src, result; if(this._ondemand_loaded_list === null) { this._ondemand_loaded_list = {}; $('script').each(function() { src = $(this).attr('src'); - if(src) self._ondemand_loaded_list[src] = 1; + if(src) { + self.registerLoadedItem(src); + } }); $('link[rel="stylesheet"]').each(function() { src = $(this).attr('href'); - if(src) self._ondemand_loaded_list[src] = 1; + if(src) { + self.registerLoadedItem(src); + } }); } - return (this._ondemand_loaded_list[decodePath(scriptUrl)] !== undefined); + result = this._ondemand_loaded_list[removeQuerystring(scriptUrl)]; + return typeof result !== 'undefined'; }, + /** + * Requires a CSS File + * + * @param {String} styleUrl Decoded CSS file url + * @param {String} media + */ requireCss : function(styleUrl, media){ if(!media) media = 'all'; @@ -53,6 +93,7 @@ var ss = document.createStyleSheet(styleUrl); ss.media = media; + } else { var styleTag = document.createElement('link'); $(styleTag).attr({ @@ -63,8 +104,7 @@ }).appendTo($('head').get(0)); } - this._ondemand_loaded_list[styleUrl] = 1; - + this.registerLoadedItem(styleUrl); }, /** @@ -110,7 +150,7 @@ dataType: 'script', url: newJsInclude, success: function() { - self._ondemand_loaded_list[newJsInclude] = 1; + self.registerLoadedItem(newJsInclude); getScriptQueue(); }, cache: false, From 38ca9632c4e9df0a74eae70cec98fdce242da529 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Fri, 30 Oct 2015 15:31:54 +1300 Subject: [PATCH 55/60] BUG Add missing CMSSecurity route --- _config/routes.yml | 1 + 1 file changed, 1 insertion(+) 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' From 2813f94124c2ba14f1e4a51001e3898b0e0c32aa Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Fri, 30 Oct 2015 16:26:14 +1300 Subject: [PATCH 56/60] BUG Ensure that filters on any fixed field are scoped to the base data table Fixes #4700 --- core/ClassInfo.php | 18 +++++++++++------- tests/core/ClassInfoTest.php | 10 ++++++++++ tests/model/DataListTest.php | 5 +++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/core/ClassInfo.php b/core/ClassInfo.php index af166f77a..5d7672d3f 100644 --- a/core/ClassInfo.php +++ b/core/ClassInfo.php @@ -307,16 +307,20 @@ class ClassInfo { //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/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/model/DataListTest.php b/tests/model/DataListTest.php index b894daebc..7d7b453bc 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); } /** From cacbbd75bc994f396a70005c8c6a90ce9a15d969 Mon Sep 17 00:00:00 2001 From: Ed Linklater Date: Sun, 1 Nov 2015 05:46:13 +1300 Subject: [PATCH 57/60] DOCS: jQuery delegation in Admin interface --- .../06_Javascript_Development.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) 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 From 42d2e0ebbf293c0d300673affed7924d8eea5dc3 Mon Sep 17 00:00:00 2001 From: Ed Linklater Date: Sun, 1 Nov 2015 05:56:39 +1300 Subject: [PATCH 58/60] Don't try to unbind events from inside top-level iframes --- admin/javascript/LeftAndMain.ActionTabSet.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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); }); From 275ecfd8a95d4f7a025bb5025bb8d729a0e9eb70 Mon Sep 17 00:00:00 2001 From: madmatt Date: Sun, 1 Nov 2015 09:10:29 +1300 Subject: [PATCH 59/60] BUGFIX: Use `Object->hasMethod()` instead of `method_exists()` This fixes an issue when you pass a `PaginatedList` back from `ModelAdmin::getList()` --- forms/gridfield/GridField.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) { From 074718fcfae18b0f3df874825b08021930c37cee Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Mon, 2 Nov 2015 17:11:22 +1300 Subject: [PATCH 60/60] Revert "BUG Fix duplicate files being included in case of flush" --- javascript/jquery-ondemand/jquery.ondemand.js | 54 +++---------------- 1 file changed, 7 insertions(+), 47 deletions(-) diff --git a/javascript/jquery-ondemand/jquery.ondemand.js b/javascript/jquery-ondemand/jquery.ondemand.js index 44d0b6198..ec647e66b 100644 --- a/javascript/jquery-ondemand/jquery.ondemand.js +++ b/javascript/jquery-ondemand/jquery.ondemand.js @@ -15,74 +15,34 @@ */ (function($){ - /** - * Decode URL from header string - * - * @param {String} str - * @returns {String} - */ var decodePath = function(str) { return str.replace(/%2C/g,',').replace(/\&/g, '&').replace(/^\s+|\s+$/g, ''); }; - - /** - * Remove querystring from the url. Necessary to prevent a file being included twice in the same page if - * requested at different times (e.g. during flush) - * - * @param {String} str - * @returns {String} - */ - var removeQuerystring = function(str) { - return str.split("?")[0]; - }; $.extend({ // loaded files list - to protect against loading existed file again (by PGA) _ondemand_loaded_list : null, - - /** - * Add a new url to the loaded item - * - * @param {String} url - */ - registerLoadedItem : function(url) { - this._ondemand_loaded_list[removeQuerystring(url)] = 1; - }, /** * Returns true if the given CSS or JS script has already been loaded - * - * @param {String} scriptUrl Decoded CSS or JS file url - * @returns {Boolean} */ isItemLoaded : function(scriptUrl) { - var self = this, src, result; + var self = this, src; if(this._ondemand_loaded_list === null) { this._ondemand_loaded_list = {}; $('script').each(function() { src = $(this).attr('src'); - if(src) { - self.registerLoadedItem(src); - } + if(src) self._ondemand_loaded_list[src] = 1; }); $('link[rel="stylesheet"]').each(function() { src = $(this).attr('href'); - if(src) { - self.registerLoadedItem(src); - } + if(src) self._ondemand_loaded_list[src] = 1; }); } - result = this._ondemand_loaded_list[removeQuerystring(scriptUrl)]; - return typeof result !== 'undefined'; + return (this._ondemand_loaded_list[decodePath(scriptUrl)] !== undefined); }, - /** - * Requires a CSS File - * - * @param {String} styleUrl Decoded CSS file url - * @param {String} media - */ requireCss : function(styleUrl, media){ if(!media) media = 'all'; @@ -93,7 +53,6 @@ var ss = document.createStyleSheet(styleUrl); ss.media = media; - } else { var styleTag = document.createElement('link'); $(styleTag).attr({ @@ -104,7 +63,8 @@ }).appendTo($('head').get(0)); } - this.registerLoadedItem(styleUrl); + this._ondemand_loaded_list[styleUrl] = 1; + }, /** @@ -150,7 +110,7 @@ dataType: 'script', url: newJsInclude, success: function() { - self.registerLoadedItem(newJsInclude); + self._ondemand_loaded_list[newJsInclude] = 1; getScriptQueue(); }, cache: false,