Merge remote-tracking branch 'origin/3.2' into 3

Conflicts:
	forms/DropdownField.php
	tests/model/ImageTest.php
This commit is contained in:
Damian Mooyman 2015-11-03 13:06:39 +13:00
commit c4dc10b255
65 changed files with 790 additions and 131 deletions

View File

@ -29,6 +29,8 @@ matrix:
env: DB=MYSQL BEHAT_TEST=1 env: DB=MYSQL BEHAT_TEST=1
before_script: before_script:
# Until http://pecl.php.net/package/imagick is working again
# - printf "\n" | pecl install imagick
- composer self-update || true - composer self-update || true
- phpenv rehash - phpenv rehash
- git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support - git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support

View File

@ -15,6 +15,7 @@ After:
Director: Director:
rules: rules:
'Security//$Action/$ID/$OtherID': 'Security' 'Security//$Action/$ID/$OtherID': 'Security'
'CMSSecurity//$Action/$ID/$OtherID': 'CMSSecurity'
'dev': 'DevelopmentAdmin' 'dev': 'DevelopmentAdmin'
'interactive': 'SapphireREPL' 'interactive': 'SapphireREPL'
'InstallerTest//$Action/$ID/$OtherID': 'InstallerTest' 'InstallerTest//$Action/$ID/$OtherID': 'InstallerTest'

View File

@ -278,21 +278,23 @@
sessionData = hasSessionStorage ? window.sessionStorage.getItem(this.attr('id')) : null, sessionData = hasSessionStorage ? window.sessionStorage.getItem(this.attr('id')) : null,
sessionStates = sessionData ? JSON.parse(sessionData) : false, sessionStates = sessionData ? JSON.parse(sessionData) : false,
elementID, elementID,
tabbed = this.find('.ss-tabset'), tabbed = (this.find('.ss-tabset').length !== 0),
activeTab, activeTab,
elementTab, elementTab,
toggleComposite, toggleComposite,
scrollY; scrollY;
if(hasSessionStorage && sessionStates.length > 0){ if(hasSessionStorage && sessionStates.length > 0){
$.each(sessionStates, function(i, sessionState) { $.each(sessionStates, function(i, sessionState) {
if(self.is('#' + sessionState.id)){ if(self.is('#' + sessionState.id)){
elementID = $('#' + sessionState.selected); 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){ if($(elementID).length < 1){
this.focusFirstInput();
return; return;
} }
@ -330,14 +332,18 @@
} }
} else { } else {
// If there is no focus data attribute set, focus input on first form element. Exclude elements which // If session storage is not supported or there is nothing stored yet, focus on the first input
// specifically opt-out of this behaviour via "data-skip-autofocus". this.focusFirstInput();
// 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();
} }
},
/**
* 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();
} }
}); });

View File

@ -105,7 +105,10 @@
SiblingIDs: siblingIDs SiblingIDs: siblingIDs
}, },
success: function() { 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]); self.updateNodesFromServer([nodeID]);
}, },
statusCode: { statusCode: {

View File

@ -4,13 +4,13 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined');
} else { } else {
ss.i18n.addDictionary('eo', { ss.i18n.addDictionary('eo', {
"CMSMAIN.SELECTONEPAGE": "Please select at least one page", "CMSMAIN.SELECTONEPAGE": "Bonvole elektu almenaŭ 1 paĝon.",
"CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas malpublikigi?",
"CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", "CMSMAIN.BATCH_PUBLISH_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas publikigi?",
"CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", "CMSMAIN.BATCH_DELETE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas forigi?",
"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_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": "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_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": "You have {num} page(s) selected.\n\nDo you really want to delete these pages from live?", "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.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.", "LeftAndMain.CONFIRMUNSAVEDSHORT": "AVERTO: Viaj ŝanĝoj ne estas konservitaj.",
"SecurityAdmin.BATCHACTIONSDELETECONFIRM": "Ĉu vi vere volas forigi %s grupojn?", "SecurityAdmin.BATCHACTIONSDELETECONFIRM": "Ĉu vi vere volas forigi %s grupojn?",

View File

@ -1,11 +1,11 @@
{ {
"CMSMAIN.SELECTONEPAGE": "Please select at least one page", "CMSMAIN.SELECTONEPAGE": "Bonvole elektu almenaŭ 1 paĝon.",
"CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas malpublikigi?",
"CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", "CMSMAIN.BATCH_PUBLISH_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas publikigi?",
"CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", "CMSMAIN.BATCH_DELETE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas forigi?",
"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_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": "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_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": "You have {num} page(s) selected.\n\nDo you really want to delete these pages from live?", "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.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.", "LeftAndMain.CONFIRMUNSAVEDSHORT": "AVERTO: Viaj ŝanĝoj ne estas konservitaj.",
"SecurityAdmin.BATCHACTIONSDELETECONFIRM": "Ĉu vi vere volas forigi %s grupojn?", "SecurityAdmin.BATCHACTIONSDELETECONFIRM": "Ĉu vi vere volas forigi %s grupojn?",

View File

@ -1,8 +1,8 @@
{ {
"CMSMAIN.SELECTONEPAGE": "Please select at least one page", "CMSMAIN.SELECTONEPAGE": "请至少选择一个页面",
"CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "您已选了{num}个页面。\n\n是否确定要取消发布",
"CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", "CMSMAIN.BATCH_PUBLISH_PROMPT": "您已选了{num}个页面。\n\n是否确定要发布",
"CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", "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_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_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.BATCH_DELETELIVE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete these pages from live?",

View File

@ -4,10 +4,10 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined');
} else { } else {
ss.i18n.addDictionary('zh', { ss.i18n.addDictionary('zh', {
"CMSMAIN.SELECTONEPAGE": "Please select at least one page", "CMSMAIN.SELECTONEPAGE": "请至少选择一个页面",
"CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "您已选了{num}个页面。\n\n是否确定要取消发布",
"CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", "CMSMAIN.BATCH_PUBLISH_PROMPT": "您已选了{num}个页面。\n\n是否确定要发布",
"CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", "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_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_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.BATCH_DELETELIVE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete these pages from live?",

View File

@ -591,7 +591,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider {
$queryargs = array_merge($queryargs, $localargs); $queryargs = array_merge($queryargs, $localargs);
} }
if((is_string($arg) && $arg) || is_numeric($arg)) { if((is_string($arg) && $arg) || is_numeric($arg)) {
$arg = (string)$arg; $arg = (string) $arg;
if($result && substr($result,-1) != '/' && $arg[0] != '/') $result .= "/$arg"; if($result && substr($result,-1) != '/' && $arg[0] != '/') $result .= "/$arg";
else $result .= (substr($result, -1) == '/' && $arg[0] == '/') ? ltrim($arg, '/') : $arg; else $result .= (substr($result, -1) == '/' && $arg[0] == '/') ? ltrim($arg, '/') : $arg;
} }

View File

@ -18,7 +18,7 @@ interface Cookie_Backend {
* @param array $cookies The existing cookies to load into the cookie jar * @param array $cookies The existing cookies to load into the cookie jar
*/ */
public function __construct($cookies = array()); public function __construct($cookies = array());
/** /**
* Set a cookie * Set a cookie
* *
@ -31,7 +31,7 @@ interface Cookie_Backend {
* @param boolean $httpOnly Prevent the cookie being accessible by JS * @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); public function set($name, $value, $expiry = 90, $path = null, $domain = null, $secure = false, $httpOnly = true);
/** /**
* Get the cookie value by name * Get the cookie value by name
* *
@ -41,7 +41,7 @@ interface Cookie_Backend {
* @return string|null The cookie value or null if unset * @return string|null The cookie value or null if unset
*/ */
public function get($name, $includeUnsent = true); public function get($name, $includeUnsent = true);
/** /**
* Get all the cookies * Get all the cookies
* *
@ -49,7 +49,7 @@ interface Cookie_Backend {
* @return array All the cookies * @return array All the cookies
*/ */
public function getAll($includeUnsent = true); public function getAll($includeUnsent = true);
/** /**
* Force the expiry of a cookie by name * Force the expiry of a cookie by name
* *

View File

@ -122,7 +122,7 @@ class Director implements TemplateGlobalProvider {
: $_SERVER['REQUEST_METHOD'], : $_SERVER['REQUEST_METHOD'],
$url, $url,
$_GET, $_GET,
ArrayLib::array_merge_recursive((array)$_POST, (array)$_FILES), ArrayLib::array_merge_recursive((array) $_POST, (array) $_FILES),
@file_get_contents('php://input') @file_get_contents('php://input')
); );
@ -295,9 +295,9 @@ class Director implements TemplateGlobalProvider {
} }
// Replace the superglobals with appropriate test values // Replace the superglobals with appropriate test values
$_REQUEST = ArrayLib::array_merge_recursive((array)$getVars, (array)$postVars); $_REQUEST = ArrayLib::array_merge_recursive((array) $getVars, (array) $postVars);
$_GET = (array)$getVars; $_GET = (array) $getVars;
$_POST = (array)$postVars; $_POST = (array) $postVars;
$_SESSION = $session ? $session->inst_getAll() : array(); $_SESSION = $session ? $session->inst_getAll() : array();
$_COOKIE = $cookieJar->getAll(false); $_COOKIE = $cookieJar->getAll(false);
Injector::inst()->registerService($cookieJar, 'Cookie_Backend'); Injector::inst()->registerService($cookieJar, 'Cookie_Backend');
@ -442,7 +442,7 @@ class Director implements TemplateGlobalProvider {
if ($url == '.' || $url == './') { if ($url == '.' || $url == './') {
$url = ''; $url = '';
} }
if(strpos($url,'/') === false && !$relativeToSiteBase) { if(strpos($url,'/') === false && !$relativeToSiteBase) {
//if there's no URL we want to force a trailing slash on the link //if there's no URL we want to force a trailing slash on the link
if (!$url) { if (!$url) {

View File

@ -15,7 +15,7 @@ class FlushRequestFilter implements RequestFilter {
} }
return true; return true;
} }
public function postRequest(SS_HTTPRequest $request, SS_HTTPResponse $response, DataModel $model) { public function postRequest(SS_HTTPRequest $request, SS_HTTPResponse $response, DataModel $model) {
return true; return true;

View File

@ -25,9 +25,9 @@ class HTTP {
protected static $etag = null; protected static $etag = null;
/** /**
* @config * @config
*/ */
private static $cache_ajax_requests = true; private static $cache_ajax_requests = true;
/** /**
* Turns a local system filename into a URL by comparing it to the script * Turns a local system filename into a URL by comparing it to the script
@ -378,7 +378,7 @@ class HTTP {
// (http://support.microsoft.com/kb/323308) // (http://support.microsoft.com/kb/323308)
// Note: this is also fixable by ticking "Do not save encrypted pages to disk" in advanced options. // Note: this is also fixable by ticking "Do not save encrypted pages to disk" in advanced options.
$cacheControlHeaders['max-age'] = 3; $cacheControlHeaders['max-age'] = 3;
// Set empty pragma to avoid PHP's session_cache_limiter adding conflicting caching information, // 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). // 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 // Since it's a deprecated HTTP 1.0 option, all modern HTTP clients and proxies should
@ -448,8 +448,14 @@ class HTTP {
// Now that we've generated them, either output them or attach them to the SS_HTTPResponse as appropriate // Now that we've generated them, either output them or attach them to the SS_HTTPResponse as appropriate
foreach($responseHeaders as $k => $v) { foreach($responseHeaders as $k => $v) {
if($body) $body->addHeader($k, $v); if($body) {
else if(!headers_sent()) header("$k: $v"); // 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");
}
} }
} }

View File

@ -109,8 +109,8 @@ class SS_HTTPRequest implements ArrayAccess {
$this->httpMethod = strtoupper(self::detect_method($httpMethod, $postVars)); $this->httpMethod = strtoupper(self::detect_method($httpMethod, $postVars));
$this->setUrl($url); $this->setUrl($url);
$this->getVars = (array)$getVars; $this->getVars = (array) $getVars;
$this->postVars = (array)$postVars; $this->postVars = (array) $postVars;
$this->body = $body; $this->body = $body;
} }

View File

@ -160,7 +160,7 @@ class SS_HTTPResponse {
* @return SS_HTTPRequest $this * @return SS_HTTPRequest $this
*/ */
public function setBody($body) { 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; return $this;
} }

View File

@ -87,7 +87,7 @@ class PjaxResponseNegotiator {
foreach($fragments as $fragment) { foreach($fragments as $fragment) {
if(isset($callbacks[$fragment])) { if(isset($callbacks[$fragment])) {
$res = call_user_func($callbacks[$fragment]); $res = call_user_func($callbacks[$fragment]);
$responseParts[$fragment] = $res ? (string)$res : $res; $responseParts[$fragment] = $res ? (string) $res : $res;
} else { } else {
throw new SS_HTTPResponse_Exception("X-Pjax = '$fragment' not supported for this URL.", 400); throw new SS_HTTPResponse_Exception("X-Pjax = '$fragment' not supported for this URL.", 400);
} }

View File

@ -351,7 +351,7 @@ class RequestHandler extends ViewableData {
if($action == 'index') return true; if($action == 'index') return true;
// Don't allow access to any non-public methods (inspect instance plus all extensions) // 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) { foreach($insts as $inst) {
if(!method_exists($inst, $action)) continue; if(!method_exists($inst, $action)) continue;
$r = new ReflectionClass(get_class($inst)); $r = new ReflectionClass(get_class($inst));
@ -389,7 +389,7 @@ class RequestHandler extends ViewableData {
$action = strtolower($actionOrigCasing); $action = strtolower($actionOrigCasing);
$definingClass = null; $definingClass = null;
$insts = array_merge(array($this), (array)$this->getExtensionInstances()); $insts = array_merge(array($this), (array) $this->getExtensionInstances());
foreach($insts as $inst) { foreach($insts as $inst) {
if(!method_exists($inst, $action)) continue; if(!method_exists($inst, $action)) continue;
$r = new ReflectionClass(get_class($inst)); $r = new ReflectionClass(get_class($inst));

View File

@ -612,7 +612,7 @@ class Session {
*/ */
public static function set_timeout($timeout) { public static function set_timeout($timeout) {
Deprecation::notice('4.0', 'Use the "Session.timeout" config setting instead'); 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);
} }
/** /**

View File

@ -180,11 +180,11 @@ class Injector {
* @var Factory * @var Factory
*/ */
protected $objectCreator; protected $objectCreator;
/** /**
* Locator for determining Config properties for services * Locator for determining Config properties for services
* *
* @var ServiceConfigurationLocator * @var ServiceConfigurationLocator
*/ */
protected $configLocator; protected $configLocator;

View File

@ -9,11 +9,11 @@
* @subpackage injector * @subpackage injector
*/ */
class ServiceConfigurationLocator { class ServiceConfigurationLocator {
/** /**
* Finds the Injector config for a named service. * Finds the Injector config for a named service.
* *
* @param string $name * @param string $name
* @return mixed * @return mixed
*/ */

View File

@ -311,16 +311,20 @@ class ClassInfo {
//normalise class name //normalise class name
$candidateClass = self::class_name($candidateClass); $candidateClass = self::class_name($candidateClass);
$exists = self::exists($candidateClass); $exists = self::exists($candidateClass);
while($candidateClass && $candidateClass != 'DataObject' && $exists) { // Short circuit for fixed fields
if(DataObject::has_own_table($candidateClass)) { $fixed = DataObject::config()->fixed_fields;
$inst = singleton($candidateClass); if($exists && isset($fixed[$fieldName])) {
return self::baseDataClass($candidateClass);
}
if($inst->hasOwnTableDatabaseField($fieldName)) { // Find regular field
break; 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); $candidateClass = get_parent_class($candidateClass);

View File

@ -60,6 +60,7 @@ class CsvBulkLoader extends BulkLoader {
* @return null|BulkLoader_Result * @return null|BulkLoader_Result
*/ */
protected function processAll($filepath, $preview = false) { protected function processAll($filepath, $preview = false) {
$filepath = Director::getAbsFile($filepath);
$files = $this->splitFile($filepath); $files = $this->splitFile($filepath);
$result = null; $result = null;

View File

@ -192,6 +192,11 @@ class FixtureBlueprint {
if($data && array_key_exists('LastEdited', $data)) { if($data && array_key_exists('LastEdited', $data)) {
$this->overrideField($obj, 'LastEdited', $data['LastEdited'], $fixtures); $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) { } catch(Exception $e) {
Config::inst()->update('DataObject', 'validation_enabled', $validationenabled); Config::inst()->update('DataObject', 'validation_enabled', $validationenabled);
throw $e; throw $e;

View File

@ -69,7 +69,8 @@ This is my `_ss_environment.php` file. I have it placed in `/var`, as each of th
:::php :::php
<?php <?php
// These three defines set the database connection details. // These four define set the database connection details.
define('SS_DATABASE_CLASS', 'MySQLPDODatabase');
define('SS_DATABASE_SERVER', 'localhost'); define('SS_DATABASE_SERVER', 'localhost');
define('SS_DATABASE_USERNAME', 'root'); define('SS_DATABASE_USERNAME', 'root');
define('SS_DATABASE_PASSWORD', '<password>'); define('SS_DATABASE_PASSWORD', '<password>');
@ -106,7 +107,7 @@ This is my `_ss_environment.php` file. I have it placed in `/var`, as each of th
| Name | Description | | 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*.| | `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_SERVER`| The database server to use, defaulting to localhost.|
| `SS_DATABASE_USERNAME`| The database username (mandatory).| | `SS_DATABASE_USERNAME`| The database username (mandatory).|
| `SS_DATABASE_PASSWORD`| The database password (mandatory).| | `SS_DATABASE_PASSWORD`| The database password (mandatory).|

View File

@ -3,7 +3,7 @@ summary: Modify the data model without using subclasses.
# Extending DataObjects # 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 classing by using [api:DataExtension]. See the [Extending SilverStripe](../extending) guide for more information on
[api:DataExtension]. [api:DataExtension].

View File

@ -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. 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 # Formatting and Casting

View File

@ -17,11 +17,11 @@ top level menu with a nested second level using the `Menu` loop and a `Children`
<% if $LinkOrSection == section %> <% if $LinkOrSection == section %>
<% if $Children %> <% if $Children %>
<li><ul class="secondary"> <ul class="secondary">
<% loop $Children %> <% loop $Children %>
<li class="$LinkingMode"><a href="$Link">$MenuTitle</a></li> <li class="$LinkingMode"><a href="$Link">$MenuTitle</a></li>
<% end_loop %> <% end_loop %>
</ul></li> </ul>
<% end_if %> <% end_if %>
<% end_if %> <% end_if %>
</li> </li>
@ -31,4 +31,4 @@ top level menu with a nested second level using the `Menu` loop and a `Children`
## Related ## Related
* [Template Syntax](../syntax) * [Template Syntax](../syntax)
* [Common Variables](../common_variables) * [Common Variables](../common_variables)

View File

@ -67,7 +67,7 @@ the `getConfig()` method on `GridField`.
$fields = parent::getCMSFields(); $fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Pages', $fields->addFieldToTab('Root.Pages',
$grid = GridField('Pages', 'All pages', SiteTree::get()) $grid = new GridField('Pages', 'All pages', SiteTree::get())
); );
// GridField configuration // GridField configuration

View File

@ -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 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 modules with the community
## Module Standard
The SilverStripe module standard defines a set of conventions that high-quality SilverStripe modules should follow. Its 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 ## Related

View File

@ -23,7 +23,7 @@ the [api:Extension] class for non DataObject subclasses (such as [api:Controller
public function SayHi() { public function SayHi() {
// $this->owner refers to the original instance. In this case a `Member`. // $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() { public function SayHi() {
// $this->owner refers to the original instance. In this case a `Member`. // $this->owner refers to the original instance. In this case a `Member`.
return "Hi ". $this->owner->Name; return "Hi " . $this->owner->Name;
} }
} }

View File

@ -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 `editor.css` in either your theme or in your `mysite` folder. This is set through
:::php :::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. Will load the `mysite/css/editor.css` file.

View File

@ -0,0 +1,13 @@
# 3.1.15
This release resolves issues with compatibility with PHP 5.3.3 introduced in 3.1.14
<!--- Changes below this line will be automatically regenerated -->
## 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)

View File

@ -3,8 +3,8 @@
## Contents ## Contents
* [Major Changes](#major-changes) * [Major Changes](#major-changes)
* [Removed API](#deprecated-classesmethods-removed) * [Deprecated classes/methods](#deprecated-classesmethods-removed)
* [New API](#new-and-changed-api) * [New and changed API](#new-and-changed-api)
* [Bugfixes](#bugfixes) * [Bugfixes](#bugfixes)
* [Upgrading Notes](#upgrading-notes) * [Upgrading Notes](#upgrading-notes)
@ -183,6 +183,32 @@ The following functionality deprecated in 3.0 has been removed:
## Upgrading Notes ## 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 ### Disable `LastVisited` and `NumVisits` counter
These fields were deprecated in 3.1 due to performance concerns, and should be disabled unless required by These fields were deprecated in 3.1 due to performance concerns, and should be disabled unless required by
@ -788,3 +814,163 @@ In order to remove the new "archive" action and restore the old "delete" action
enabled_legacy_actions: enabled_legacy_actions:
- CMSBatchAction_Delete - CMSBatchAction_Delete
<!--- Changes below this line will be automatically regenerated -->
## 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-&gt;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)

View File

@ -0,0 +1,33 @@
# 3.2.0-rc2
See [3.2.0](/changelogs/3.2.0) changelog for more information on what is new in 3.2
<!--- Changes below this line will be automatically regenerated -->
## 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)

View File

@ -1,7 +1,7 @@
title: Contributing Code title: Contributing Code
summary: Fix bugs and add new features to help make SilverStripe better. 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. 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.

View File

@ -6,6 +6,7 @@ The core committers team is reviewed approximately annually, new members are add
* [Daniel Hensby](https://github.com/dhensby) * [Daniel Hensby](https://github.com/dhensby)
* [Hamish Friedlander](https://github.com/hafriedlander) * [Hamish Friedlander](https://github.com/hafriedlander)
* [Ingo Schommer](https://github.com/chillu) * [Ingo Schommer](https://github.com/chillu)
* [Jono Menz](https://github.com/jonom)
* [Loz Calver](https://github.com/kinglozzer) * [Loz Calver](https://github.com/kinglozzer)
* [Sam Minnée](https://github.com/sminnee) * [Sam Minnée](https://github.com/sminnee)
* [Sean Harvey](https://github.com/halkyon/) * [Sean Harvey](https://github.com/halkyon/)

View File

@ -108,6 +108,7 @@ class GDBackend extends Object implements Image_Backend {
/** /**
* @param string $filename * @param string $filename
* @param string $manipulation
* @return boolean * @return boolean
*/ */
public function imageAvailable($filename, $manipulation) { public function imageAvailable($filename, $manipulation) {

View File

@ -99,9 +99,10 @@ class ImagickBackend extends Imagick implements Image_Backend {
* @todo Implement memory checking for Imagick? See {@link GD} * @todo Implement memory checking for Imagick? See {@link GD}
* *
* @param string $filename * @param string $filename
* @param string $manipulation
* @return boolean * @return boolean
*/ */
public function imageAvailable($filename) { public function imageAvailable($filename, $manipulation) {
return true; return true;
} }

View File

@ -362,7 +362,7 @@ class DropdownField extends FormField {
*/ */
public function castedCopy($classOrCopy) { public function castedCopy($classOrCopy) {
$field = parent::castedCopy($classOrCopy); $field = parent::castedCopy($classOrCopy);
if(method_exists($field, 'setHasEmptyDefault')) { if($field->hasMethod('setHasEmptyDefault')) {
$field->setHasEmptyDefault($this->getHasEmptyDefault()); $field->setHasEmptyDefault($this->getHasEmptyDefault());
} }
return $field; return $field;

View File

@ -20,7 +20,7 @@ class InlineFormAction extends FormField {
*/ */
public function __construct($action, $title = "", $extraClass = '') { public function __construct($action, $title = "", $extraClass = '') {
$this->extraClass = ' '.$extraClass; $this->extraClass = ' '.$extraClass;
parent::__construct($action, $title, null, null); parent::__construct($action, $title);
} }
public function performReadonlyTransformation() { public function performReadonlyTransformation() {
@ -39,7 +39,8 @@ class InlineFormAction extends FormField {
return DBField::create_field( return DBField::create_field(
'HTMLText', 'HTMLText',
FormField::create('input', array( FormField::create_tag('input', array(
'type' => 'submit',
'name' => sprintf('action_%s', $this->getName()), 'name' => sprintf('action_%s', $this->getName()),
'value' => $this->title, 'value' => $this->title,
'id' => $this->ID(), 'id' => $this->ID(),

View File

@ -114,8 +114,8 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM
} elseif(method_exists($tmpItem, 'hasMethod') && $tmpItem->hasMethod($methodName)) { } elseif(method_exists($tmpItem, 'hasMethod') && $tmpItem->hasMethod($methodName)) {
// The part is a relation name, so get the object/list from it // The part is a relation name, so get the object/list from it
$tmpItem = $tmpItem->$methodName(); $tmpItem = $tmpItem->$methodName();
} elseif($tmpItem instanceof DataObject && $tmpItem->hasField($methodName)) { } elseif($tmpItem instanceof DataObject && $tmpItem->hasDatabaseField($methodName)) {
// Else, if we've found a field at the end of the chain, we can sort on it. // 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. // If a method is applied further to this field (E.g. 'Cost.Currency') then don't try to sort.
$allowSort = $idx === sizeof($parts) - 1; $allowSort = $idx === sizeof($parts) - 1;
break; break;

View File

@ -823,9 +823,11 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
} else if(el.is(':radio')) { } else if(el.is(':radio')) {
el.val([selected]).change(); el.val([selected]).change();
} else if(fieldName == 'file') { } else if(fieldName == 'file') {
// Can't rely on fieldName, ad UploadFields have different naming convention // UploadField inputs have a slightly different naming convention
el = $('#' + fieldName); 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 // We have to wait for the UploadField to initialise
(function attach(el, selected) { (function attach(el, selected) {
if( ! el.getConfig()) { if( ! el.getConfig()) {

View File

@ -260,6 +260,7 @@ cs:
many_many_Members: Členové many_many_Members: Členové
GroupImportForm: GroupImportForm:
Help1: '<p>Import jedné nebo více skupin v <em>CSV</em> formátu (čárkou-oddělené hodnoty). <small><a href="#" class="toggle-advanced">Zobrazit rozšířené použití</a></small></p>' Help1: '<p>Import jedné nebo více skupin v <em>CSV</em> formátu (čárkou-oddělené hodnoty). <small><a href="#" class="toggle-advanced">Zobrazit rozšířené použití</a></small></p>'
Help2: '<div class="advanced"> <h4>Pokročilé použití</h4> <ul> <li>Povolené sloupce: <em>%s</em></li> <li>Existující skupiny jsou porovnány jejich unikátním <em>Code</em> hodnotou, a aktualizovány s novými hodnotami z importovaného souboru</li> <li>Hierarchie skupin může být tvořena použitím <em>ParentCode</em> sloupce.<li> <li>Kódy oprávnění mohou být přiřazeny <em>PermissionCode</em> sloupcem. Existující oprávnění nejsou smazána.</li> </ul> </div>'
ResultCreated: 'Vytvořeno {count} skupin' ResultCreated: 'Vytvořeno {count} skupin'
ResultDeleted: 'Smazáno %d skupin' ResultDeleted: 'Smazáno %d skupin'
ResultUpdated: 'Aktualizováno %d skupin' ResultUpdated: 'Aktualizováno %d skupin'
@ -291,6 +292,8 @@ cs:
FROMWEB: 'Z webu' FROMWEB: 'Z webu'
FindInFolder: 'Hledat ve složce' FindInFolder: 'Hledat ve složce'
IMAGEALT: 'Alternativní text (alt)' 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 IMAGEDIMENSIONS: Rozměry
IMAGEHEIGHTPX: Výška IMAGEHEIGHTPX: Výška
IMAGETITLE: 'Titul text (tooltip) - další informace o obrázku' IMAGETITLE: 'Titul text (tooltip) - další informace o obrázku'
@ -325,7 +328,11 @@ cs:
DELETED: Smazáno. DELETED: Smazáno.
DropdownBatchActionsDefault: Akcie DropdownBatchActionsDefault: Akcie
HELP: Nápověda 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.' 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 PreviewButton: Náhled
REORGANISATIONSUCCESSFUL: 'Strom webu reorganizován úspěšně.' REORGANISATIONSUCCESSFUL: 'Strom webu reorganizován úspěšně.'
SAVEDUP: Uloženo. SAVEDUP: Uloženo.
@ -413,6 +420,7 @@ cs:
Toggle: 'Ukázat nápovědu formátování' Toggle: 'Ukázat nápovědu formátování'
MemberImportForm: MemberImportForm:
Help1: '<p>Import členů v <em>CSV formátu</em> (čárkou-oddělené hodnoty). <small><a href="#" class="toggle-advanced">Zobrazit rozšířené použití</a></small></p>' Help1: '<p>Import členů v <em>CSV formátu</em> (čárkou-oddělené hodnoty). <small><a href="#" class="toggle-advanced">Zobrazit rozšířené použití</a></small></p>'
Help2: '<div class="advanced"> <h4>Pokročilé použití</h4> <ul> <li>Povolené sloupce: <em>%s</em></li> <li>Existující uživatelé jsou porovnáni jejich unikátní vlastností <em>Code</em>, a aktualizováni s novými hodnotami z importovaného souboru.</li> <li>Skupiny mohou být přiřazeny sloupcem <em>Groups</em>. Skupiny jsou identifikovány svojí vlastností <em>Code</em>, více skupin může být odděleno čárkou. Existující členství ve skupině nejsou smazána.</li> </ul> </div>'
ResultCreated: 'Vytvořeno {count} členů' ResultCreated: 'Vytvořeno {count} členů'
ResultDeleted: 'Smazáno %d členů' ResultDeleted: 'Smazáno %d členů'
ResultNone: 'Žádné změny' ResultNone: 'Žádné změny'

View File

@ -292,8 +292,8 @@ en:
FROMWEB: 'From the web' FROMWEB: 'From the web'
FindInFolder: 'Find in Folder' FindInFolder: 'Find in Folder'
IMAGEALT: 'Alternative text (alt)' IMAGEALT: 'Alternative text (alt)'
IMAGEALTTEXT: 'Alternative text (alt) - shown if image cannot be displayed' IMAGEALTTEXT: 'Alternative text (alt) - shown if image can''t be displayed'
IMAGEALTTEXTDESC: 'Shown to screen readers or if image can not be displayed' IMAGEALTTEXTDESC: 'Shown to screen readers or if image can''t be displayed'
IMAGEDIMENSIONS: Dimensions IMAGEDIMENSIONS: Dimensions
IMAGEHEIGHTPX: Height IMAGEHEIGHTPX: Height
IMAGETITLE: 'Title text (tooltip) - for additional information about the image' IMAGETITLE: 'Title text (tooltip) - for additional information about the image'
@ -328,11 +328,11 @@ en:
DELETED: Deleted. DELETED: Deleted.
DropdownBatchActionsDefault: Actions DropdownBatchActionsDefault: Actions
HELP: Help 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.' 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.' 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.' 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 PreviewButton: Preview
REORGANISATIONSUCCESSFUL: 'Reorganised the site tree successfully.' REORGANISATIONSUCCESSFUL: 'Reorganised the site tree successfully.'
SAVEDUP: Saved. SAVEDUP: Saved.

View File

@ -260,6 +260,7 @@ eo:
many_many_Members: Membroj many_many_Members: Membroj
GroupImportForm: GroupImportForm:
Help1: '<p>Importi unu aŭ pliaj grupojn en formato <em>CSV</em> (perkome disigitaj valoroj values). <small><a href="#" class="toggle-advanced">Vidigi spertulan uzadon</a></small></p>' Help1: '<p>Importi unu aŭ pliaj grupojn en formato <em>CSV</em> (perkome disigitaj valoroj values). <small><a href="#" class="toggle-advanced">Vidigi spertulan uzadon</a></small></p>'
Help2: '<div class="advanced"><h4>Speciala uzado </h4><ul><li>Eblaj kolumnoj: <em>%s</em></li><li>Ekzistantaj grupoj kongruiĝas laŭ la valoro de ilia unika <em>Kodo</em>, kaj ĝisdatiĝas per eventualaj valoroj el la importita dosiero</li><li>Eblas krei grupajn hierarĥiojn per la kolumno <em>ParentCode</em>.</li><li>Eblas agordi permeskodojn per la kolumno <em>PermissionCode</em>. Ekzistantaj permeskodoj ne vakiĝas.</li></ul></div>'
ResultCreated: 'Kreiĝis {count} grupoj' ResultCreated: 'Kreiĝis {count} grupoj'
ResultDeleted: 'Forigis %d grupojn' ResultDeleted: 'Forigis %d grupojn'
ResultUpdated: 'Aktualigis %d grupojn' ResultUpdated: 'Aktualigis %d grupojn'
@ -326,15 +327,20 @@ eo:
DropdownBatchActionsDefault: Agoj DropdownBatchActionsDefault: Agoj
HELP: Helpo HELP: Helpo
PERMAGAIN: 'Vin adiaŭis la CMS. Se vi volas denove saluti, enigu salutnomon kaj pasvorton malsupre.' 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 PreviewButton: Antaŭvido
REORGANISATIONSUCCESSFUL: 'Sukcese reorganizis la retejan arbon.' REORGANISATIONSUCCESSFUL: 'Sukcese reorganizis la retejan arbon.'
SAVEDUP: Konservita. SAVEDUP: Konservita.
ShowAsList: 'vidigi kiel liston' ShowAsList: 'vidigi kiel liston'
TooManyPages: 'Tro da paĝoj' TooManyPages: 'Tro da paĝoj'
ValidationError: 'Validiga eraro' ValidationError: 'Validiga eraro'
VersionUnknown: nekonata
LeftAndMain_Menu_ss: LeftAndMain_Menu_ss:
Hello: Saluton Hello: Saluton
LOGOUT: 'Elsaluti' LOGOUT: 'Elsaluti'
ListboxField:
SOURCE_VALIDATION: 'Bonvolu elekti valoron el la listo donita. %s ne estas valida agordo'
LoginAttempt: LoginAttempt:
Email: 'Retadreso' Email: 'Retadreso'
IP: 'IP-Adreso' IP: 'IP-Adreso'
@ -410,6 +416,7 @@ eo:
Toggle: 'Vidigi aranĝa helpo' Toggle: 'Vidigi aranĝa helpo'
MemberImportForm: MemberImportForm:
Help1: '<p>Importi membrojn en <em>CSV-formato</em> (diskomaj valoroj ). <small><a href="#" class="toggle-advanced">Vidigi spertulan uzadon</a></small></p>' Help1: '<p>Importi membrojn en <em>CSV-formato</em> (diskomaj valoroj ). <small><a href="#" class="toggle-advanced">Vidigi spertulan uzadon</a></small></p>'
Help2: '<div class="advanced"><h4>Speciala uzado </h4><ul><li>Eblaj kolumnoj: <em>%s</em></li><li>Ekzistantaj uzantoj kongruiĝas laŭ la valoro de sia unika atributo <em>Code</em>, kaj ĝisdatiĝas per eventualaj novaj valoroj el la importita dosiero. </li><li>Eblas agordi grupojn per la kolumno <em>Groups</em>. Grupoj estas identigeblaj per sia atributo <em>Code</em>, plurobla grupo estu apartigitaj per komo. Ekzistantaj grupaj membrecoj ne vakiĝas.</li></ul></div>'
ResultCreated: 'Krei {count} membrojn' ResultCreated: 'Krei {count} membrojn'
ResultDeleted: 'Forigis %d membrojn' ResultDeleted: 'Forigis %d membrojn'
ResultNone: 'Neniu ŝanĝo' ResultNone: 'Neniu ŝanĝo'
@ -539,6 +546,8 @@ eo:
Print: Presi Print: Presi
TableListField_PageControls_ss: TableListField_PageControls_ss:
OF: de OF: de
TextField:
VALIDATEMAXLENGTH: 'La longo de la valoro por {name} devas ne superi {maxLength} signojn'
TimeField: TimeField:
VALIDATEFORMAT: 'Bonvole enigu validan horan formaton ({format})' VALIDATEFORMAT: 'Bonvole enigu validan horan formaton ({format})'
ToggleField: ToggleField:

View File

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

View File

@ -260,6 +260,7 @@ lt:
many_many_Members: Vartotojai many_many_Members: Vartotojai
GroupImportForm: GroupImportForm:
Help1: '<p>Importuoti vieną ar kelias grupes <em>CSV</em> formatu (kableliu atskirtos reikšmės). <small><a href="#" class="toggle-advanced">Rodyti detalesnį aprašymą</a></small></p>' Help1: '<p>Importuoti vieną ar kelias grupes <em>CSV</em> formatu (kableliu atskirtos reikšmės). <small><a href="#" class="toggle-advanced">Rodyti detalesnį aprašymą</a></small></p>'
Help2: '<div class="advanced"><h4>Detalesnis aprašymas</h4><ul><li>Galimi stulpeliai: <em>%s</em>.</li><li>Esamos grupės yra surandamos su jų unikalia <em>Code</em> reikšme ir atnaujinamos duomenimis iš importuojamos bylos.</li><li>Grupių hierarchija gali būti sukurta naudojant <em>ParentCode</em> stulpelį.</li><li>Leidimų kodai gali būti priskirti naudojant <em>PermissionCode</em> stulpelį. Esami leidimai nebus pakeisti.</li></ul></div>'
ResultCreated: 'Sukurta {count} grupių' ResultCreated: 'Sukurta {count} grupių'
ResultDeleted: 'Ištrinta %d grupių' ResultDeleted: 'Ištrinta %d grupių'
ResultUpdated: 'Atnaujinta %d grupių' ResultUpdated: 'Atnaujinta %d grupių'
@ -291,6 +292,8 @@ lt:
FROMWEB: 'Iš interneto' FROMWEB: 'Iš interneto'
FindInFolder: 'Rasti kataloge' FindInFolder: 'Rasti kataloge'
IMAGEALT: 'Alternatyvus tekstas (alt)' IMAGEALT: 'Alternatyvus tekstas (alt)'
IMAGEALTTEXT: 'Alternatyvus tekstas (alt) - rodomas, jeigu nepavyko parodyti paveikslėlio'
IMAGEALTTEXTDESC: 'Rodomas, jeigu nepavyko parodyti paveikslėlio'
IMAGEDIMENSIONS: Matmenys IMAGEDIMENSIONS: Matmenys
IMAGEHEIGHTPX: Aukštis IMAGEHEIGHTPX: Aukštis
IMAGETITLE: 'Pavadinimo tekstas (tooltip) - papildomai informacijai apie paveikslėlį' IMAGETITLE: 'Pavadinimo tekstas (tooltip) - papildomai informacijai apie paveikslėlį'
@ -325,9 +328,11 @@ lt:
DELETED: Ištrinta. DELETED: Ištrinta.
DropdownBatchActionsDefault: Veiksmai DropdownBatchActionsDefault: Veiksmai
HELP: Pagalba HELP: Pagalba
PAGETYPE: 'Puslapio tipas:'
PERMAGAIN: 'Jūs atsijungėte. Norėdami vėl prisijungti, įveskite savo duomenis į žemiau esančius laukelius.' 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.' 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.' 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 PreviewButton: Peržiūra
REORGANISATIONSUCCESSFUL: 'Puslapių medis pertvarkytas sėkmingai.' REORGANISATIONSUCCESSFUL: 'Puslapių medis pertvarkytas sėkmingai.'
SAVEDUP: Išsaugota. SAVEDUP: Išsaugota.
@ -415,6 +420,7 @@ lt:
Toggle: 'Rodyti formatavimo aprašymą' Toggle: 'Rodyti formatavimo aprašymą'
MemberImportForm: MemberImportForm:
Help1: '<p>Importuoti vartotojus <em>CSV</em> formatu (kableliu atskirtos reikšmės). <small><a href="#" class="toggle-advanced">Rodyti detalesnį aprašymą</a></small></p>' Help1: '<p>Importuoti vartotojus <em>CSV</em> formatu (kableliu atskirtos reikšmės). <small><a href="#" class="toggle-advanced">Rodyti detalesnį aprašymą</a></small></p>'
Help2: '<div class="advanced"><h4>Detalesnis aprašymas</h4><ul><li>Galimi stulpeliai: <em>%s</em>.</li><li>Esami vartotojai yra surandami su jų unikalia <em>Code</em> reikšme ir atnaujinami duomenimis iš importuojamos bylos.</li><li>Grupės gali būti priskirtos naudojant <em>Groups</em> column. stulpelį. Grupės yra atpažįstamos pagal <em>Code</em> stulpelį, kelios grupės nurodomos per kablelį. Jau priskirtos vartotojui grupės nebus pakeistos.</li></ul></div>'
ResultCreated: 'Sukurta {count} vartotojų' ResultCreated: 'Sukurta {count} vartotojų'
ResultDeleted: 'Ištrinta %d vartotojų' ResultDeleted: 'Ištrinta %d vartotojų'
ResultNone: 'Nėra jokių pakeitimų' ResultNone: 'Nėra jokių pakeitimų'

View File

@ -260,6 +260,7 @@ sk:
many_many_Members: Členovia many_many_Members: Členovia
GroupImportForm: GroupImportForm:
Help1: 'Importovať jednu alebo viac skupín v CSV formáte (čiarkov oddelené hodnoty). Zobraziť pokročilé použitie' Help1: 'Importovať jednu alebo viac skupín v CSV formáte (čiarkov oddelené hodnoty). Zobraziť pokročilé použitie'
Help2: '<div class="advanced"> <h4>Pokročilé použitie</h4> <ul> <li>Povolené stĺpce: <em>%s</em></li> <li>Existujúce skupiny sú porovnávané s ich unikátnou <em>Code</em>; hodnotou, a aktualizované s novými hodnotami z importovaného súbory&lt;/li> <li>Skupina hierarchií môže byť tvorená použitím <em>ParentCode</em>; stĺpce.&lt;/li> <li>Kódy oprávnení môžu byť priradené <em>PermissionCode</em>; stĺpcom. Existujúce oprávnenia nie sú smazáné.</li> </ul> </div>'
ResultCreated: 'Vytvorených {count} skupín' ResultCreated: 'Vytvorených {count} skupín'
ResultDeleted: 'Zmazané %d skupiny' ResultDeleted: 'Zmazané %d skupiny'
ResultUpdated: 'Aktualizované %d skupiny' ResultUpdated: 'Aktualizované %d skupiny'
@ -291,6 +292,8 @@ sk:
FROMWEB: 'Z webu' FROMWEB: 'Z webu'
FindInFolder: 'Vyhľadať v priečinku' FindInFolder: 'Vyhľadať v priečinku'
IMAGEALT: 'Atlernatívny text (alt)' 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 IMAGEDIMENSIONS: Rozmery
IMAGEHEIGHTPX: Výška IMAGEHEIGHTPX: Výška
IMAGETITLE: 'Text titulky (tooltip) - pre doplňujúce informácie o obrázku' IMAGETITLE: 'Text titulky (tooltip) - pre doplňujúce informácie o obrázku'
@ -325,7 +328,11 @@ sk:
DELETED: Zmazané. DELETED: Zmazané.
DropdownBatchActionsDefault: Akcie DropdownBatchActionsDefault: Akcie
HELP: Pomoc HELP: Pomoc
PAGETYPE: 'Typ stránky:'
PERMAGAIN: 'Boli ste odhlásený' 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 PreviewButton: Náhľad
REORGANISATIONSUCCESSFUL: 'Strom webu bol reorganizovaný úspešne.' REORGANISATIONSUCCESSFUL: 'Strom webu bol reorganizovaný úspešne.'
SAVEDUP: Uložené. SAVEDUP: Uložené.
@ -413,6 +420,7 @@ sk:
Toggle: 'Ukázať nápovedu formátovania' Toggle: 'Ukázať nápovedu formátovania'
MemberImportForm: MemberImportForm:
Help1: 'Importovať členov v <em>CSV formáte</em> (čiarkov oddelené hodnoty). Zobraziť pokročile použitie' Help1: 'Importovať členov v <em>CSV formáte</em> (čiarkov oddelené hodnoty). Zobraziť pokročile použitie'
Help2: '<div class="advanced"> <h4>Pokročilé použitie</h4> <ul> <li>Povolené stĺpce: <em>%s</em></li> <li>Existujúci užívatelia sú porovnávaní ich unikátnou vlastnosťou <em>Code</em>, a aktualizovaní s novými hodnotami z importovaného súboru.</li> <li>Skupiny môžu byťt priradené stĺpcom <em>Groups</em>. Skupiny sú identifikované ich vlastnosťou <em>Code</em>, viacero skupín môže byť oddelené čiarkou. Existujúce členstvá skupiny nie sú smazané.</li> </ul> </div>'
ResultCreated: 'Vytvorených {count} členov' ResultCreated: 'Vytvorených {count} členov'
ResultDeleted: 'Zmazaných %d členov' ResultDeleted: 'Zmazaných %d členov'
ResultNone: 'Žiadne zmeny' ResultNone: 'Žiadne zmeny'

View File

@ -47,6 +47,8 @@ tr:
ERRORNOTREC: 'Kullanıcı adı / şifre hatalı' ERRORNOTREC: 'Kullanıcı adı / şifre hatalı'
Boolean: Boolean:
ANY: Herhangi ANY: Herhangi
NOANSWER: 'Hayır'
YESANSWER: 'Evet'
CMSMain: CMSMain:
ACCESSALLINTERFACES: 'Tüm İYS arayüzlerine erişim' ACCESSALLINTERFACES: 'Tüm İYS arayüzlerine erişim'
SAVE: Kaydet SAVE: Kaydet
@ -56,6 +58,9 @@ tr:
EMAIL: E-Posta EMAIL: E-Posta
HELLO: Merhaba HELLO: Merhaba
PASSWORD: Parola PASSWORD: Parola
CheckboxField:
NOANSWER: 'Hayır'
YESANSWER: 'Evet'
ConfirmedPasswordField: ConfirmedPasswordField:
SHOWONCLICKTITLE: 'Parola Değiştir' SHOWONCLICKTITLE: 'Parola Değiştir'
CreditCardField: CreditCardField:
@ -87,6 +92,7 @@ tr:
TEXT2: 'şifre sıfırlama linki' TEXT2: 'şifre sıfırlama linki'
TEXT3: için TEXT3: için
Form: Form:
SubmitBtnLabel: Başla
VALIDATIONNOTUNIQUE: 'Girilen değer benzersiz olmalıdır' VALIDATIONNOTUNIQUE: 'Girilen değer benzersiz olmalıdır'
VALIDATIONPASSWORDSDONTMATCH: 'Şifre tekrarı hatalı' VALIDATIONPASSWORDSDONTMATCH: 'Şifre tekrarı hatalı'
VALIDATIONPASSWORDSNOTEMPTY: 'Şifreler boş geçilemez' VALIDATIONPASSWORDSNOTEMPTY: 'Şifreler boş geçilemez'

View File

@ -60,6 +60,8 @@ zh:
ERRORNOTREC: '那个用户名 / 密码无法被辨认' ERRORNOTREC: '那个用户名 / 密码无法被辨认'
Boolean: Boolean:
ANY: 任何 ANY: 任何
NOANSWER: '不是'
YESANSWER: '是'
CMSLoadingScreen_ss: CMSLoadingScreen_ss:
LOADING: 正在载入…… LOADING: 正在载入……
REQUIREJS: 'CMS 要求您启用 JavaScript。' REQUIREJS: 'CMS 要求您启用 JavaScript。'
@ -68,16 +70,35 @@ zh:
ACCESSALLINTERFACES: '对所有 CMS 部分的访问' ACCESSALLINTERFACES: '对所有 CMS 部分的访问'
ACCESSALLINTERFACESHELP: '支配更多的特殊访问设置' ACCESSALLINTERFACESHELP: '支配更多的特殊访问设置'
SAVE: 保存 SAVE: 保存
CMSMemberLoginForm:
BUTTONFORGOTPASSWORD: '忘记密码?'
BUTTONLOGIN: '重新登录'
BUTTONLOGOUT: '登出'
PASSWORDEXPIRED: '<p>您的密码已过期。 <a target="_top" href="{link}">请选择一个新的。</a></ P>'
CMSPageHistoryController_versions_ss: CMSPageHistoryController_versions_ss:
PREVIEW: '网站预览' PREVIEW: '网站预览'
CMSProfileController: CMSProfileController:
MENUTITLE: '我的个人资料' MENUTITLE: '我的个人资料'
CMSSecurity:
INVALIDUSER: '<p>用户已无效。 <a target="_top" href="{link}">请在此继续重新进行身份验证</a>。</ p>'
LoginMessage: '<p>如果您有任何未保存的工作,你可以重新登录以回到你未保存的地方。</p>'
SUCCESS: 成功
SUCCESSCONTENT: '<p>登录成功。如果您没有自动重定向<a target="_top" href="{link}">点击此处</a></p>'
TimedOutTitleAnonymous: '你的登陆超时已过期。'
TimedOutTitleMember: '你好{name}!<br />你的登陆超时已过期。'
ChangePasswordEmail_ss: ChangePasswordEmail_ss:
CHANGEPASSWORDTEXT1: '您的密码已更改为:' CHANGEPASSWORDTEXT1: '您的密码已更改为:'
CHANGEPASSWORDTEXT2: '现在,您可以使用下列证书来登录了:' CHANGEPASSWORDTEXT2: '现在,您可以使用下列证书来登录了:'
EMAIL: 电子邮件 EMAIL: 电子邮件
HELLO: 您好 HELLO: 您好
PASSWORD: 密码 PASSWORD: 密码
CheckboxField:
NOANSWER: '不是'
YESANSWER: '是'
CheckboxFieldSetField:
SOURCE_VALIDATION: '请选择列表内提供的选项。{value}不是一个有效的选项'
CheckboxSetField:
SOURCE_VALIDATION: '请选择列表内提供的选项。''{value}''不是一个有效的选项'
ConfirmedPasswordField: ConfirmedPasswordField:
ATLEAST: '密码长度必须至少 {min} 个字符。' ATLEAST: '密码长度必须至少 {min} 个字符。'
BETWEEN: '密码长度必须含 {min} 到 {max} 个字符。' BETWEEN: '密码长度必须含 {min} 到 {max} 个字符。'
@ -124,6 +145,7 @@ zh:
DropdownField: DropdownField:
CHOOSE: (选择) CHOOSE: (选择)
CHOOSESEARCH: '(选择或搜索)' CHOOSESEARCH: '(选择或搜索)'
SOURCE_VALIDATION: '请选择列表内提供的选项。{value}不是一个有效的选项'
EmailField: EmailField:
VALIDATION: '请输入一个电子邮件地址' VALIDATION: '请输入一个电子邮件地址'
Enum: Enum:
@ -171,6 +193,7 @@ zh:
TEXT2: '密码重设链接' TEXT2: '密码重设链接'
TEXT3: TEXT3:
Form: Form:
CSRF_FAILED_MESSAGE: '似乎是一个技术问题。请点击返回按钮,刷新浏览器,然后再试一次。'
FIELDISREQUIRED: '{name} 为必填' FIELDISREQUIRED: '{name} 为必填'
SubmitBtnLabel: 前往 SubmitBtnLabel: 前往
VALIDATIONCREDITNUMBER: '请确保您输入了正确的 {number} 信用卡号码' VALIDATIONCREDITNUMBER: '请确保您输入了正确的 {number} 信用卡号码'
@ -244,6 +267,8 @@ zh:
HtmlEditorField: HtmlEditorField:
ADDURL: '添加网址' ADDURL: '添加网址'
ADJUSTDETAILSDIMENSIONS: '详情 &amp;amp; 体积' ADJUSTDETAILSDIMENSIONS: '详情 &amp;amp; 体积'
ANCHORSCANNOTACCESSPAGE: '您不允许访问该页面的内容。'
ANCHORSPAGENOTFOUND: '无法找到该页面。'
ANCHORVALUE: 固定 ANCHORVALUE: 固定
BUTTONADDURL: '添加网址' BUTTONADDURL: '添加网址'
BUTTONINSERT: 插入 BUTTONINSERT: 插入
@ -282,6 +307,7 @@ zh:
LINKOPENNEWWIN: '在新窗口中打开链接?' LINKOPENNEWWIN: '在新窗口中打开链接?'
LINKTO: '链接到' LINKTO: '链接到'
PAGE: 页面 PAGE: 页面
SUBJECT: '电子邮件标题'
URL: 网址 URL: 网址
URLNOTANOEMBEDRESOURCE: '''{url}'' 该网址无法转换成媒体来源。' URLNOTANOEMBEDRESOURCE: '''{url}'' 该网址无法转换成媒体来源。'
UpdateMEDIA: '更新媒体' UpdateMEDIA: '更新媒体'
@ -299,15 +325,19 @@ zh:
DropdownBatchActionsDefault: 动作 DropdownBatchActionsDefault: 动作
HELP: 帮助 HELP: 帮助
PERMAGAIN: '您已经退出 CMS。如果您想再次登录请在下面输入用户名和密码。' PERMAGAIN: '您已经退出 CMS。如果您想再次登录请在下面输入用户名和密码。'
PERMALREADY: '抱歉,您不能访问这一部分的后台管理。如果您想以不同的身份登录,请在下面进行操作。'
PreviewButton: 预览 PreviewButton: 预览
REORGANISATIONSUCCESSFUL: '重新组织网站地图已成功' REORGANISATIONSUCCESSFUL: '重新组织网站地图已成功'
SAVEDUP: 已保存。 SAVEDUP: 已保存。
ShowAsList: '以列表方式展示' ShowAsList: '以列表方式展示'
TooManyPages: '页面数目过多' TooManyPages: '页面数目过多'
ValidationError: '验证错误' ValidationError: '验证错误'
VersionUnknown: 未知
LeftAndMain_Menu_ss: LeftAndMain_Menu_ss:
Hello: 您好 Hello: 您好
LOGOUT: '退出' LOGOUT: '退出'
ListboxField:
SOURCE_VALIDATION: '请选择列表内提供的选项。%s不是一个有效的选项'
LoginAttempt: LoginAttempt:
Email: '电子邮件地址' Email: '电子邮件地址'
IP: 'IP 地址' IP: 'IP 地址'
@ -340,6 +370,7 @@ zh:
NEWPASSWORD: '新密码' NEWPASSWORD: '新密码'
NoPassword: '该成员无密码' NoPassword: '该成员无密码'
PASSWORD: 密码 PASSWORD: 密码
PASSWORDEXPIRED: '您的密码已过期。 请选择一个新的。'
PLURALNAME: 成员 PLURALNAME: 成员
REMEMBERME: '下次记住我?' REMEMBERME: '下次记住我?'
SINGULARNAME: 成员 SINGULARNAME: 成员
@ -445,6 +476,7 @@ zh:
SINGULARNAME: 角色 SINGULARNAME: 角色
Title: 标题 Title: 标题
PermissionRoleCode: PermissionRoleCode:
PLURALNAME: '权限角色代码'
PermsError: '无法为代码 "%s"分配特权权限(要求具备 ADMIN 访问)' PermsError: '无法为代码 "%s"分配特权权限(要求具备 ADMIN 访问)'
SINGULARNAME: '权限角色代码' SINGULARNAME: '权限角色代码'
Permissions: Permissions:
@ -510,6 +542,8 @@ zh:
Print: 打印 Print: 打印
TableListField_PageControls_ss: TableListField_PageControls_ss:
OF: OF:
TextField:
VALIDATEMAXLENGTH: '{name} 的长度必须至多{maxLength} 个字符。'
TimeField: TimeField:
VALIDATEFORMAT: '请输入有效的时间格式 ({format})' VALIDATEFORMAT: '请输入有效的时间格式 ({format})'
ToggleField: ToggleField:

View File

@ -1780,10 +1780,8 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
return $this->unsavedRelations[$componentName]; return $this->unsavedRelations[$componentName];
} }
$result = ManyManyList::create( $extraFields = $this->manyManyExtraFieldsForComponent($componentName) ?: array();
$componentClass, $table, $componentField, $parentField, $result = ManyManyList::create($componentClass, $table, $componentField, $parentField, $extraFields);
$this->manyManyExtraFieldsForComponent($componentName)
);
if($this->model) $result->setDataModel($this->model); if($this->model) $result->setDataModel($this->model);

View File

@ -220,7 +220,7 @@ class Image extends File implements Flushable {
* *
* @param integer $width The width to size within * @param integer $width The width to size within
* @param integer $height The height to size within * @param integer $height The height to size within
* @return Image * @return Image|null
*/ */
public function Fit($width, $height) { public function Fit($width, $height) {
// Prevent divide by zero on missing/blank file // Prevent divide by zero on missing/blank file
@ -278,7 +278,7 @@ class Image extends File implements Flushable {
* *
* @param integer $width Width to crop to * @param integer $width Width to crop to
* @param integer $height Height to crop to * @param integer $height Height to crop to
* @return Image * @return Image|null
*/ */
public function Fill($width, $height) { public function Fill($width, $height) {
return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample') return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample')
@ -335,7 +335,7 @@ class Image extends File implements Flushable {
* *
* @param integer $width The width to size to * @param integer $width The width to size to
* @param integer $height The height to size to * @param integer $height The height to size to
* @return Image * @return Image|null
*/ */
public function Pad($width, $height, $backgroundColor='FFFFFF') { public function Pad($width, $height, $backgroundColor='FFFFFF') {
return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample') return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample')
@ -359,7 +359,7 @@ class Image extends File implements Flushable {
* Scale image proportionally by width. Use in templates with $ScaleWidth. * Scale image proportionally by width. Use in templates with $ScaleWidth.
* *
* @param integer $width The width to set * @param integer $width The width to set
* @return Image * @return Image|null
*/ */
public function ScaleWidth($width) { public function ScaleWidth($width) {
return $this->isWidth($width) && !Config::inst()->get('Image', 'force_resample') return $this->isWidth($width) && !Config::inst()->get('Image', 'force_resample')
@ -399,7 +399,7 @@ class Image extends File implements Flushable {
* Scale image proportionally by height. Use in templates with $ScaleHeight. * Scale image proportionally by height. Use in templates with $ScaleHeight.
* *
* @param integer $height The height to set * @param integer $height The height to set
* @return Image * @return Image|null
*/ */
public function ScaleHeight($height) { public function ScaleHeight($height) {
return $this->isHeight($height) && !Config::inst()->get('Image', 'force_resample') return $this->isHeight($height) && !Config::inst()->get('Image', 'force_resample')
@ -576,6 +576,11 @@ class Image extends File implements Flushable {
return $backend->paddedResize($width, $height); return $backend->paddedResize($width, $height);
} }
/**
* Resize this image for the CMS. Use in templates with $CMSThumbnail
*
* @return Image_Cached|null
*/
public function CMSThumbnail() { public function CMSThumbnail() {
return $this->getFormattedImage('CMSThumbnail'); return $this->getFormattedImage('CMSThumbnail');
} }
@ -679,7 +684,7 @@ class Image extends File implements Flushable {
* Just pass the correct number of parameters expected by the working function * Just pass the correct number of parameters expected by the working function
* *
* @param string $format The name of the format. * @param string $format The name of the format.
* @return Image_Cached * @return Image_Cached|null
*/ */
public function getFormattedImage($format) { public function getFormattedImage($format) {
$args = func_get_args(); $args = func_get_args();
@ -789,7 +794,7 @@ class Image extends File implements Flushable {
* @param Image_Backend $backend * @param Image_Backend $backend
* @param integer $width Width to resize to * @param integer $width Width to resize to
* @param integer $height Height 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) { public function generateResizedImage(Image_Backend $backend, $width, $height) {
if(!$backend){ if(!$backend){
@ -955,7 +960,7 @@ class Image extends File implements Flushable {
* Get the dimensions of this Image. * Get the dimensions of this Image.
* @param string $dim If this is equal to "string", return the dimensions in string form, * @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. * 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") { public function getDimensions($dim = "string") {
if($this->getField('Filename')) { if($this->getField('Filename')) {

View File

@ -115,6 +115,7 @@ interface Image_Backend {
* imageAvailable * imageAvailable
* *
* @param string $filename * @param string $filename
* @param string $manipulation
* @return boolean * @return boolean
*/ */
public function imageAvailable($filename, $manipulation); public function imageAvailable($filename, $manipulation);

View File

@ -125,9 +125,16 @@ class MySQLSchemaManager extends DBSchemaManager {
} }
public function checkAndRepairTable($tableName) { 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 running PDO and not in emulated mode, check table will fail
if($this->database->getConnector() instanceof PDOConnector && !PDOConnector::is_emulate_prepare()) { 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; return true;
} }

View File

@ -38,7 +38,7 @@ class Enum extends StringField {
public function __construct($name = null, $enum = NULL, $default = NULL) { public function __construct($name = null, $enum = NULL, $default = NULL) {
if($enum) { if($enum) {
if(!is_array($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; $this->enum = $enum;

View File

@ -58,12 +58,12 @@ class FulltextFilter extends SearchFilter {
if(is_array($indexes) && array_key_exists($this->getName(), $indexes)) { if(is_array($indexes) && array_key_exists($this->getName(), $indexes)) {
$index = $indexes[$this->getName()]; $index = $indexes[$this->getName()];
if(is_array($index) && array_key_exists("value", $index)) { if(is_array($index) && array_key_exists("value", $index)) {
return $index['value']; return $this->prepareColumns($index['value']);
} else { } else {
// Parse a fulltext string (eg. fulltext ("ColumnA", "ColumnB")) to figure out which columns // Parse a fulltext string (eg. fulltext ("ColumnA", "ColumnB")) to figure out which columns
// we need to search. // we need to search.
if(preg_match('/^fulltext\s+\((.+)\)$/i', $index, $matches)) { if(preg_match('/^fulltext\s+\((.+)\)$/i', $index, $matches)) {
return $matches[1]; return $this->prepareColumns($matches[1]);
} else { } else {
throw new Exception("Invalid fulltext index format for '" . $this->getName() throw new Exception("Invalid fulltext index format for '" . $this->getName()
. "' on '" . $this->model . "'"); . "' on '" . $this->model . "'");
@ -74,4 +74,19 @@ class FulltextFilter extends SearchFilter {
return parent::getDbName(); return parent::getDbName();
} }
/**
* Adds table identifier to the every column.
* Columns must have table identifier to prevent duplicate column name error.
*
* @return string
*/
protected function prepareColumns($columns) {
$cols = preg_split('/"?\s*,\s*"?/', trim($columns, '(") '));
$class = ClassInfo::table_for_object_field($this->model, current($cols));
$cols = array_map(function($col) use ($class) {
return sprintf('"%s"."%s"', $class, $col);
}, $cols);
return implode(',', $cols);
}
} }

View File

@ -1,5 +1,4 @@
<div id="$HolderID" <div class="TreeDropdownField <% if $extraClass %> $extraClass<% end_if %><% if $ShowSearch %> searchable<% end_if %>"
class="TreeDropdownField <% if $extraClass %> $extraClass<% end_if %><% if $ShowSearch %> searchable<% end_if %>"
data-url-tree="$Link('tree')" data-url-tree="$Link('tree')"
data-title="$Title.ATT" data-title="$Title.ATT"
data-empty-title="$EmptyTitle.ATT" data-empty-title="$EmptyTitle.ATT"

View File

@ -13,18 +13,37 @@ class HTTPTest extends FunctionalTest {
$this->assertEmpty($response->getHeader('Cache-Control')); $this->assertEmpty($response->getHeader('Cache-Control'));
HTTP::set_cache_age(30); HTTP::set_cache_age(30);
HTTP::add_cache_headers($response);
HTTP::add_cache_headers($response);
$this->assertNotEmpty($response->getHeader('Cache-Control')); $this->assertNotEmpty($response->getHeader('Cache-Control'));
// Ensure max-age is zero for development.
Config::inst()->update('Director', 'environment_type', 'dev'); Config::inst()->update('Director', 'environment_type', 'dev');
$response = new SS_HTTPResponse($body, 200);
HTTP::add_cache_headers($response); HTTP::add_cache_headers($response);
$this->assertContains('max-age=0', $response->getHeader('Cache-Control')); $this->assertContains('max-age=0', $response->getHeader('Cache-Control'));
// Ensure max-age setting is respected in production.
Config::inst()->update('Director', 'environment_type', 'live'); Config::inst()->update('Director', 'environment_type', 'live');
$response = new SS_HTTPResponse($body, 200);
HTTP::add_cache_headers($response); HTTP::add_cache_headers($response);
$this->assertContains('max-age=30', explode(', ', $response->getHeader('Cache-Control'))); $this->assertContains('max-age=30', explode(', ', $response->getHeader('Cache-Control')));
$this->assertNotContains('max-age=0', $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));
}
} }
/** /**

View File

@ -197,6 +197,16 @@ class ClassInfoTest extends SapphireTest {
$this->assertNull( $this->assertNull(
ClassInfo::table_for_object_field(null, null) 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')
);
} }
} }

View File

@ -16,4 +16,26 @@ class EnumFieldTest extends SapphireTest {
$this->assertEquals(true, $searchField->getHasEmptyDefault()); $this->assertEquals(true, $searchField->getHasEmptyDefault());
$this->assertEquals($anyText, $searchField->getEmptyString()); $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());
}
} }

View File

@ -0,0 +1,18 @@
<?php
/**
* Tests {@see InlineFormAction}
*/
class InlineFormActionTest extends SapphireTest {
public function testField() {
$action = new InlineFormAction('dothing', 'My Title', 'ss-action');
$html = (string)$action->Field();
$this->assertContains('<input', $html);
$this->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);
}
}

View File

@ -153,6 +153,38 @@ class GridFieldDetailFormTest extends FunctionalTest {
$this->assertDOSContains(array(array('Surname' => 'Baggins')), $group->People()); $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() { public function testEditFormWithManyManyExtraData() {
$this->logInWithPermission('ADMIN'); $this->logInWithPermission('ADMIN');
@ -341,7 +373,8 @@ class GridFieldDetailFormTest_Person extends DataObject implements TestOnly {
); );
private static $many_many = array( private static $many_many = array(
'Categories' => 'GridFieldDetailFormTest_Category' 'Categories' => 'GridFieldDetailFormTest_Category',
'FavouriteGroups' => 'GridFieldDetailFormTest_PeopleGroup'
); );
private static $many_many_extraFields = array( private static $many_many_extraFields = array(
@ -362,6 +395,12 @@ class GridFieldDetailFormTest_Person extends DataObject implements TestOnly {
GridFieldConfig_RelationEditor::create() GridFieldConfig_RelationEditor::create()
) )
); );
$fields->replaceField('FavouriteGroups',
GridField::create('FavouriteGroups', 'Favourite Groups',
$this->FavouriteGroups(),
GridFieldConfig_RelationEditor::create()
)
);
return $fields; return $fields;
} }
@ -386,6 +425,10 @@ class GridFieldDetailFormTest_PeopleGroup extends DataObject implements TestOnly
'People' => 'GridFieldDetailFormTest_Person' 'People' => 'GridFieldDetailFormTest_Person'
); );
private static $belongs_many_many = array(
'People' => 'GridFieldDetailFormTest_Person'
);
private static $default_sort = '"Name"'; private static $default_sort = '"Name"';
public function getCMSFields() { public function getCMSFields() {
@ -499,13 +542,22 @@ class GridFieldDetailFormTest_CategoryController extends Controller implements T
new CheckboxField('ManyMany[IsPublished]'), new CheckboxField('ManyMany[IsPublished]'),
new TextField('ManyMany[PublishedBy]')) new TextField('ManyMany[PublishedBy]'))
); );
$field = new GridField('testfield', 'testfield', $person->Categories()); $categoriesField = new GridField('testfield', 'testfield', $person->Categories());
$field->getConfig()->addComponent($gridFieldForm = new GridFieldDetailForm($this, 'Form')); $categoriesField->getConfig()->addComponent($gridFieldForm = new GridFieldDetailForm($this, 'Form'));
$gridFieldForm->setFields($detailFields); $gridFieldForm->setFields($detailFields);
$field->getConfig()->addComponent(new GridFieldToolbarHeader()); $categoriesField->getConfig()->addComponent(new GridFieldToolbarHeader());
$field->getConfig()->addComponent(new GridFieldAddNewButton('toolbar-header-right')); $categoriesField->getConfig()->addComponent(new GridFieldAddNewButton('toolbar-header-right'));
$field->getConfig()->addComponent(new GridFieldEditButton()); $categoriesField->getConfig()->addComponent(new GridFieldEditButton());
return new Form($this, 'Form', new FieldList($field), new FieldList());
$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());
} }
} }

View File

@ -400,6 +400,11 @@ class DataListTest extends SapphireTest {
// byID() returns a DataObject, rather than a DataList // byID() returns a DataObject, rather than a DataList
$this->assertInstanceOf('DataObjectTest_Team', $team); $this->assertInstanceOf('DataObjectTest_Team', $team);
$this->assertEquals('Team 2', $team->Title); $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);
} }
/** /**

View File

@ -319,10 +319,10 @@ class ImageTest extends SapphireTest {
'Image folder contains only the expected number of images before regeneration'); 'Image folder contains only the expected number of images before regeneration');
$imageThirdPath = $imageThird->getFullPath(); $imageThirdPath = $imageThird->getFullPath();
$hash = md5_file($imageThirdPath); $stats = getimagesize($imageThirdPath);
$this->assertEquals(3, $image->regenerateFormattedImages(), $this->assertEquals(3, $image->regenerateFormattedImages(),
'Cached images were regenerated in the right number'); '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 */ /* Check that no other images exist, to ensure that the regeneration did not create other images */
$this->assertEquals($filesInFolder, $folder->find($resampledFolder), $this->assertEquals($filesInFolder, $folder->find($resampledFolder),

View File

@ -40,26 +40,36 @@ class FulltextFilterTest extends SapphireTest {
} }
public function testGenerateQuery() { 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 // Test SearchFields
$filter1 = new FulltextFilter('SearchFields', 'SilverStripe'); $filter1 = new FulltextFilter('SearchFields', 'SilverStripe');
$filter1->setModel('FulltextFilterTest_DataObject'); $filter1->setModel('FulltextFilterTest_DataObject');
$query1 = FulltextFilterTest_DataObject::get()->dataQuery(); $query1 = FulltextFilterTest_DataObject::get()->dataQuery();
$filter1->apply($query1); $filter1->apply($query1);
$this->assertEquals('"ColumnA", "ColumnB"', $filter1->getDbName()); $this->assertEquals('"FulltextFilterTest_DataObject"."ColumnA","FulltextFilterTest_DataObject"."ColumnB"', $filter1->getDbName());
$this->assertEquals( $this->assertEquals(
array("MATCH (\"ColumnA\", \"ColumnB\") AGAINST ('SilverStripe')"), array("MATCH (\"FulltextFilterTest_DataObject\".\"ColumnA\",\"FulltextFilterTest_DataObject\".\"ColumnB\") AGAINST ('SilverStripe')"),
$query1->query()->getWhere() $query1->query()->getWhere()
); );
// Test Other searchfields // Test Other searchfields
$filter2 = new FulltextFilter('OtherSearchFields', 'SilverStripe'); $filter2 = new FulltextFilter('OtherSearchFields', 'SilverStripe');
$filter2->setModel('FulltextFilterTest_DataObject'); $filter2->setModel('FulltextFilterTest_DataObject');
$query2 = FulltextFilterTest_DataObject::get()->dataQuery(); $query2 = FulltextFilterTest_DataObject::get()->dataQuery();
$filter2->apply($query2); $filter2->apply($query2);
$this->assertEquals('"ColumnC", "ColumnD"', $filter2->getDbName()); $this->assertEquals('"FulltextFilterTest_DataObject"."ColumnC","FulltextFilterTest_DataObject"."ColumnD"', $filter2->getDbName());
$this->assertEquals( $this->assertEquals(
array("MATCH (\"ColumnC\", \"ColumnD\") AGAINST ('SilverStripe')"), array("MATCH (\"FulltextFilterTest_DataObject\".\"ColumnC\",\"FulltextFilterTest_DataObject\".\"ColumnD\") AGAINST ('SilverStripe')"),
$query2->query()->getWhere() $query2->query()->getWhere()
); );
@ -102,4 +112,4 @@ class FulltextFilterTest_DataObject extends DataObject implements TestOnly {
"MySQLDatabase" => "ENGINE=MyISAM", "MySQLDatabase" => "ENGINE=MyISAM",
); );
} }