diff --git a/admin/templates/ModelSidebar.ss b/admin/templates/ModelSidebar.ss
index 3599fba12..19f3d2985 100644
--- a/admin/templates/ModelSidebar.ss
+++ b/admin/templates/ModelSidebar.ss
@@ -1,7 +1,7 @@
-
<% _t('ModelSidebar_ss.SEARCHLISTINGS','Search') %>
+<%t ModelSidebar_ss.SEARCHLISTINGS 'Search' %>
$SearchForm
<% if $ImportForm %>
- <% _t('ModelSidebar_ss.IMPORT_TAB_HEADER', 'Import') %>
+ <%t ModelSidebar_ss.IMPORT_TAB_HEADER 'Import' %>
$ImportForm
<% end_if %>
diff --git a/admin/tests/LeftAndMainTest.php b/admin/tests/LeftAndMainTest.php
index 1940c18af..f594b43a8 100644
--- a/admin/tests/LeftAndMainTest.php
+++ b/admin/tests/LeftAndMainTest.php
@@ -135,7 +135,7 @@ class LeftAndMainTest extends FunctionalTest {
$link = $menuItem->Link;
// don't test external links
- if(preg_match('/^https?:\/\//',$link)) continue;
+ if(preg_match('/^(https?:)?\/\//',$link)) continue;
$response = $this->get($link);
diff --git a/api/RestfulService.php b/api/RestfulService.php
index 4da3971d5..ac5ef31eb 100644
--- a/api/RestfulService.php
+++ b/api/RestfulService.php
@@ -47,22 +47,22 @@ class RestfulService extends ViewableData implements Flushable {
* set a curl option that will be applied to all requests as default
* {@see http://php.net/manual/en/function.curl-setopt.php#refsect1-function.curl-setopt-parameters}
*
- * @deprecated 3.2 Use the "RestfulService.default_curl_options" config setting instead
+ * @deprecated 4.0 Use the "RestfulService.default_curl_options" config setting instead
* @param int $option The cURL opt Constant
* @param mixed $value The cURL opt value
*/
public static function set_default_curl_option($option, $value) {
- Deprecation::notice('3.2', 'Use the "RestfulService.default_curl_options" config setting instead');
+ Deprecation::notice('4.0', 'Use the "RestfulService.default_curl_options" config setting instead');
Config::inst()->update('RestfulService', 'default_curl_options', array($option => $value));
}
/**
* set many defauly curl options at once
*
- * @deprecated 3.2 Use the "RestfulService.default_curl_options" config setting instead
+ * @deprecated 4.0 Use the "RestfulService.default_curl_options" config setting instead
*/
public static function set_default_curl_options($optionArray) {
- Deprecation::notice('3.2', 'Use the "RestfulService.default_curl_options" config setting instead');
+ Deprecation::notice('4.0', 'Use the "RestfulService.default_curl_options" config setting instead');
Config::inst()->update('RestfulService', 'default_curl_options', $optionArray);
}
@@ -74,12 +74,12 @@ class RestfulService extends ViewableData implements Flushable {
* @param string $user The proxy auth user name
* @param string $password The proxy auth password
* @param boolean $socks Set true to use socks5 proxy instead of http
- * @deprecated 3.2 Use the "RestfulService.default_curl_options" config setting instead,
+ * @deprecated 4.0 Use the "RestfulService.default_curl_options" config setting instead,
* with direct reference to the CURL_* options
*/
public static function set_default_proxy($proxy, $port = 80, $user = "", $password = "", $socks = false) {
Deprecation::notice(
- '3.1',
+ '4.0',
'Use the "RestfulService.default_curl_options" config setting instead, '
. 'with direct reference to the CURL_* options'
);
@@ -144,8 +144,11 @@ class RestfulService extends ViewableData implements Flushable {
$this->customHeaders[] = $header;
}
+ /**
+ * @deprecated since version 4.0
+ */
protected function constructURL(){
- Deprecation::notice('3.2', 'constructURL is deprecated, please use `getAbsoluteRequestURL` instead');
+ Deprecation::notice('4.0', 'constructURL is deprecated, please use `getAbsoluteRequestURL` instead');
return Controller::join_links($this->baseURL, '?' . $this->queryString);
}
@@ -616,9 +619,10 @@ class RestfulService_Response extends SS_HTTPResponse {
/**
* @param string
+ * @deprecated since version 4.0
*/
public function setCachedBody($content) {
- Deprecation::notice('3.2', 'Setting the response body is now deprecated, set the cached request instead');
+ Deprecation::notice('4.0', 'Setting the response body is now deprecated, set the cached request instead');
if (!$this->cachedResponse) {
$this->cachedResponse = new RestfulService_Response($content);
}
diff --git a/composer.json b/composer.json
index e9c29f228..66403d26d 100644
--- a/composer.json
+++ b/composer.json
@@ -17,10 +17,10 @@
],
"require": {
"php": ">=5.3.3",
- "composer/installers": "*"
+ "composer/installers": "~1.0"
},
"require-dev": {
- "phpunit/PHPUnit": "~3.7@stable"
+ "phpunit/PHPUnit": "~3.7"
},
"extra": {
"branch-alias": {
@@ -29,6 +29,5 @@
},
"autoload": {
"classmap": ["tests/behat/features/bootstrap"]
- },
- "minimum-stability": "dev"
+ }
}
diff --git a/config.rb b/config.rb
index 0778f6195..66d0d3618 100644
--- a/config.rb
+++ b/config.rb
@@ -13,10 +13,16 @@ output_style = :compact
# To enable relative paths to assets via compass helper functions. Uncomment:
relative_assets = true
-# disable comments in the output. We want admin comments
-# to be verbose
+# Disable comments in the output. We want admin comments to be verbose.
line_comments = false
-asset_cache_buster :none
+# Disable asset cache buster. Using :none doesn't work in some versions of compass.
+asset_cache_buster do |http_path, real_path|
+ nil
+end
+
+sourcemap = true
+
+sass_options = { :unix_newlines => true }
Encoding.default_external = "utf-8"
diff --git a/control/ContentNegotiator.php b/control/ContentNegotiator.php
index c670dd8d0..c34e47171 100644
--- a/control/ContentNegotiator.php
+++ b/control/ContentNegotiator.php
@@ -56,10 +56,10 @@ class ContentNegotiator extends Object {
* Set the character set encoding for this page. By default it's utf-8, but you could change it to, say,
* windows-1252, to improve interoperability with extended characters being imported from windows excel.
*
- * @deprecated 3.2 Use the "ContentNegotiator.encoding" config setting instead
+ * @deprecated 4.0 Use the "ContentNegotiator.encoding" config setting instead
*/
public static function set_encoding($encoding) {
- Deprecation::notice('3.2', 'Use the "ContentNegotiator.encoding" config setting instead');
+ Deprecation::notice('4.0', 'Use the "ContentNegotiator.encoding" config setting instead');
Config::inst()->update('ContentNegotiator', 'encoding', $encoding);
}
@@ -67,30 +67,30 @@ class ContentNegotiator extends Object {
* Return the character encoding set bhy ContentNegotiator::set_encoding(). It's recommended that all classes
* that need to specify the character set make use of this function.
*
- * @deprecated 3.2 Use the "ContentNegotiator.encoding" config setting instead
+ * @deprecated 4.0 Use the "ContentNegotiator.encoding" config setting instead
*/
public static function get_encoding() {
- Deprecation::notice('3.2', 'Use the "ContentNegotiator.encoding" config setting instead');
+ Deprecation::notice('4.0', 'Use the "ContentNegotiator.encoding" config setting instead');
return Config::inst()->get('ContentNegotiator', 'encoding');
}
/**
* Enable content negotiation for all templates, not just those with the xml header.
*
- * @deprecated 3.2 Use the "ContentNegotiator.enabled" config setting instead
+ * @deprecated 4.0 Use the "ContentNegotiator.enabled" config setting instead
*/
public static function enable() {
- Deprecation::notice('3.2', 'Use the "ContentNegotiator.enabled" config setting instead');
+ Deprecation::notice('4.0', 'Use the "ContentNegotiator.enabled" config setting instead');
Config::inst()->update('ContentNegotiator', 'enabled', true);
}
/**
* Disable content negotiation for all templates, not just those with the xml header.
*
- * @deprecated 3.2 Use the "ContentNegotiator.enabled" config setting instead
+ * @deprecated 4.0 Use the "ContentNegotiator.enabled" config setting instead
*/
public static function disable() {
- Deprecation::notice('3.2', 'Use the "ContentNegotiator.enabled" config setting instead');
+ Deprecation::notice('4.0', 'Use the "ContentNegotiator.enabled" config setting instead');
Config::inst()->update('ContentNegotiator', 'enabled', false);
}
diff --git a/control/Director.php b/control/Director.php
index 7122453fa..c98af9743 100644
--- a/control/Director.php
+++ b/control/Director.php
@@ -84,13 +84,13 @@ class Director implements TemplateGlobalProvider {
*
* The director is responsible for turning URLs into Controller objects.
*
- * @deprecated 3.2 Use the "Director.rules" config setting instead
+ * @deprecated 4.0 Use the "Director.rules" config setting instead
* @param $priority The priority of the rules; higher values will get your rule checked first. We recommend
* priority 100 for your site's rules. The built-in rules are priority 10, standard modules are
* priority 50.
*/
public static function addRules($priority, $rules) {
- Deprecation::notice('3.2', 'Use the "Director.rules" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Director.rules" config setting instead');
Config::inst()->update('Director', 'rules', $rules);
}
@@ -610,10 +610,10 @@ class Director implements TemplateGlobalProvider {
* Sets the root URL for the website.
* If the site isn't accessible from the URL you provide, weird things will happen.
*
- * @deprecated 3.2 Use the "Director.alternate_base_url" config setting instead
+ * @deprecated 4.0 Use the "Director.alternate_base_url" config setting instead
*/
public static function setBaseURL($baseURL) {
- Deprecation::notice('3.2', 'Use the "Director.alternate_base_url" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Director.alternate_base_url" config setting instead');
Config::inst()->update('Director', 'alternate_base_url', $baseURL);
}
@@ -630,10 +630,10 @@ class Director implements TemplateGlobalProvider {
* Sets the root folder for the website.
* If the site isn't accessible from the folder you provide, weird things will happen.
*
- * @deprecated 3.2 Use the "Director.alternate_base_folder" config setting instead
+ * @deprecated 4.0 Use the "Director.alternate_base_folder" config setting instead
*/
public static function setBaseFolder($baseFolder) {
- Deprecation::notice('3.2', 'Use the "Director.alternate_base_folder" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Director.alternate_base_folder" config setting instead');
Config::inst()->update('Director', 'alternate_base_folder', $baseFolder);
}
@@ -1023,7 +1023,7 @@ class Director implements TemplateGlobalProvider {
* Once the environment type is set, it can be checked with {@link Director::isDev()}, {@link Director::isTest()},
* and {@link Director::isLive()}.
*
- * @deprecated 3.2 Use the "Director.environment_type" config setting instead
+ * @deprecated 4.0 Use the "Director.environment_type" config setting instead
* @param $et string The environment type: dev, test, or live.
*/
public static function set_environment_type($et) {
@@ -1031,7 +1031,7 @@ class Director implements TemplateGlobalProvider {
user_error("Director::set_environment_type passed '$et'. It should be passed dev, test, or live",
E_USER_WARNING);
} else {
- Deprecation::notice('3.2', 'Use the "Director.environment_type" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Director.environment_type" config setting instead');
Config::inst()->update('Director', 'environment_type', $et);
}
}
diff --git a/control/HTTP.php b/control/HTTP.php
index d8ac686ce..9a16b64ed 100644
--- a/control/HTTP.php
+++ b/control/HTTP.php
@@ -103,7 +103,7 @@ class HTTP {
*/
public static function urlRewriter($content, $code) {
if(!is_callable($code)) {
- Deprecation::notice(3.1, 'HTTP::urlRewriter expects a callable as the second parameter');
+ Deprecation::notice('4.0', 'HTTP::urlRewriter expects a callable as the second parameter');
}
// Replace attributes
@@ -308,7 +308,7 @@ class HTTP {
/**
* Add the appropriate caching headers to the response, including If-Modified-Since / 304 handling.
*
- * @param SS_HTTPResponse The SS_HTTPResponse object to augment. Omitted the argument or passing a string is
+ * @param SS_HTTPResponse $body The SS_HTTPResponse object to augment. Omitted the argument or passing a string is
* deprecated; in these cases, the headers are output directly.
*/
public static function add_cache_headers($body = null) {
@@ -328,21 +328,17 @@ class HTTP {
// us trying.
if(headers_sent() && !$body) return;
- // Popuplate $responseHeaders with all the headers that we want to build
+ // Populate $responseHeaders with all the headers that we want to build
$responseHeaders = array();
$config = Config::inst();
$cacheControlHeaders = Config::inst()->get('HTTP', 'cache_control');
- // currently using a config setting to cancel this, seems to be so taht the CMS caches ajax requests
+ // currently using a config setting to cancel this, seems to be so that the CMS caches ajax requests
if(function_exists('apache_request_headers') && $config->get(get_called_class(), 'cache_ajax_requests')) {
- $requestHeaders = apache_request_headers();
+ $requestHeaders = array_change_key_case(apache_request_headers(), CASE_LOWER);
- if(isset($requestHeaders['X-Requested-With']) && $requestHeaders['X-Requested-With']=='XMLHttpRequest') {
- $cacheAge = 0;
- }
- // bdc: now we must check for DUMB IE6:
if(isset($requestHeaders['x-requested-with']) && $requestHeaders['x-requested-with']=='XMLHttpRequest') {
$cacheAge = 0;
}
@@ -383,13 +379,16 @@ class HTTP {
foreach($cacheControlHeaders as $header => $value) {
if(is_null($value)) {
unset($cacheControlHeaders[$header]);
- } elseif(is_bool($value) || $value === "true") {
+ } elseif((is_bool($value) && $value) || $value === "true") {
$cacheControlHeaders[$header] = $header;
} else {
$cacheControlHeaders[$header] = $header."=".$value;
}
}
+ $responseHeaders['Cache-Control'] = implode(', ', $cacheControlHeaders);
+ unset($cacheControlHeaders, $header, $value);
+
if(self::$modification_date && $cacheAge > 0) {
$responseHeaders["Last-Modified"] = self::gmt_date(self::$modification_date);
diff --git a/control/Session.php b/control/Session.php
index 8fc6e8ba7..0cff41cad 100644
--- a/control/Session.php
+++ b/control/Session.php
@@ -162,24 +162,24 @@ class Session {
* To make cookies visible on all subdomains then the domain
* must be prefixed with a dot like '.php.net'.
*
- * @deprecated 3.2 Use the "Session.cookie_domain" config setting instead
+ * @deprecated 4.0 Use the "Session.cookie_domain" config setting instead
*
* @param string $domain The domain to set
*/
public static function set_cookie_domain($domain) {
- Deprecation::notice('3.2', 'Use the "Session.cookie_domain" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Session.cookie_domain" config setting instead');
Config::inst()->update('Session', 'cookie_domain', $domain);
}
/**
* Get the cookie domain.
*
- * @deprecated 3.2 Use the "Session.cookie_domain" config setting instead
+ * @deprecated 4.0 Use the "Session.cookie_domain" config setting instead
*
* @return string
*/
public static function get_cookie_domain() {
- Deprecation::notice('3.2', 'Use the "Session.cookie_domain" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Session.cookie_domain" config setting instead');
return Config::inst()->get('Session', 'cookie_domain');
}
@@ -187,24 +187,24 @@ class Session {
* Path to set on the domain where the session cookie will work.
* Use a single slash ('/') for all paths on the domain.
*
- * @deprecated 3.2 Use the "Session.cookie_path" config setting instead
+ * @deprecated 4.0 Use the "Session.cookie_path" config setting instead
*
* @param string $path The path to set
*/
public static function set_cookie_path($path) {
- Deprecation::notice('3.2', 'Use the "Session.cookie_path" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Session.cookie_path" config setting instead');
Config::inst()->update('Session', 'cookie_path', $path);
}
/**
* Get the path on the domain where the session cookie will work.
*
- * @deprecated 3.2 Use the "Session.cookie_path" config setting instead
+ * @deprecated 4.0 Use the "Session.cookie_path" config setting instead
*
* @return string
*/
public static function get_cookie_path() {
- Deprecation::notice('3.2', 'Use the "Session.cookie_path" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Session.cookie_path" config setting instead');
if(Config::inst()->get('Session', 'cookie_path')) {
return Config::inst()->get('Session', 'cookie_path');
} else {
@@ -215,45 +215,46 @@ class Session {
/**
* Secure cookie, tells the browser to only send it over SSL.
*
- * @deprecated 3.2 Use the "Session.cookie_secure" config setting instead
+ * @deprecated 4.0 Use the "Session.cookie_secure" config setting instead
*
* @param boolean $secure
*/
public static function set_cookie_secure($secure) {
- Deprecation::notice('3.2', 'Use the "Session.cookie_secure" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Session.cookie_secure" config setting instead');
Config::inst()->update('Session', 'cookie_secure', (bool)$secure);
}
/**
* Get if the cookie is secure
*
- * @deprecated 3.2 Use the "Session.cookie_secure" config setting instead
+ * @deprecated 4.0 Use the "Session.cookie_secure" config setting instead
*
* @return boolean
*/
public static function get_cookie_secure() {
- Deprecation::notice('3.2', 'Use the "Session.cookie_secure" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Session.cookie_secure" config setting instead');
return Config::inst()->get('Session', 'cookie_secure');
}
/**
* Set the session store path
*
- * @deprecated 3.2 Use the "Session.session_store_path" config setting instead
+ * @deprecated 4.0 Use the "Session.session_store_path" config setting instead
*
* @param string $path Filesystem path to the session store
*/
public static function set_session_store_path($path) {
- Deprecation::notice('3.2', 'Use the "Session.session_store_path" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Session.session_store_path" config setting instead');
Config::inst()->update('Session', 'session_store_path', $path);
}
/**
* Get the session store path
* @return string
+ * @deprecated since version 4.0
*/
public static function get_session_store_path() {
- Deprecation::notice('3.2', 'Use the "Session.session_store_path" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Session.session_store_path" config setting instead');
return Config::inst()->get('Session', 'session_store_path');
}
@@ -270,12 +271,12 @@ class Session {
*
* Session::set_timeout is used to set the timeout value for any users whose address is not in the given IP range.
*
- * @deprecated 3.2 Use the "Session.timeout_ips" config setting instead
+ * @deprecated 4.0 Use the "Session.timeout_ips" config setting instead
*
* @param array $session_ips Array of IPv4 rules.
*/
public static function set_timeout_ips($ips) {
- Deprecation::notice('3.2', 'Use the "Session.timeout_ips" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Session.timeout_ips" config setting instead');
Config::inst()->update('Session', 'timeout_ips', $ips);
}
@@ -605,20 +606,20 @@ class Session {
/**
* Set the timeout of a Session value
*
- * @deprecated 3.2 Use the "Session.timeout" config setting instead
+ * @deprecated 4.0 Use the "Session.timeout" config setting instead
*
* @param int $timeout Time until a session expires in seconds. Defaults to expire when browser is closed.
*/
public static function set_timeout($timeout) {
- Deprecation::notice('3.2', '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);
}
/**
- * @deprecated 3.2 Use the "Session.timeout" config setting instead
+ * @deprecated 4.0 Use the "Session.timeout" config setting instead
*/
public static function get_timeout() {
- Deprecation::notice('3.2', 'Use the "Session.timeout" config setting instead');
+ Deprecation::notice('4.0', 'Use the "Session.timeout" config setting instead');
return Config::inst()->get('Session', 'timeout');
}
}
diff --git a/control/injector/Injector.php b/control/injector/Injector.php
index 1e1343cdb..db2097868 100644
--- a/control/injector/Injector.php
+++ b/control/injector/Injector.php
@@ -272,7 +272,16 @@ class Injector {
* @return Injector Reference to restored active Injector instance
*/
public static function unnest() {
- return self::set_inst(self::$instance->nestedFrom);
+ if (self::inst()->nestedFrom) {
+ self::set_inst(self::inst()->nestedFrom);
+ }
+ else {
+ user_error(
+ "Unable to unnest root Injector, please make sure you don't have mis-matched nest/unnest",
+ E_USER_WARNING
+ );
+ }
+ return self::inst();
}
/**
@@ -787,10 +796,10 @@ class Injector {
/**
* Register a service with an explicit name
*
- * @deprecated since 3.1.1
+ * @deprecated since 4.0
*/
public function registerNamedService($name, $service) {
- Deprecation::notice('3.1.1', 'registerNamedService is deprecated, use registerService instead');
+ Deprecation::notice('4.0', 'registerNamedService is deprecated, use registerService instead');
return $this->registerService($service, $name);
}
diff --git a/control/injector/SilverStripeServiceConfigurationLocator.php b/control/injector/SilverStripeServiceConfigurationLocator.php
index 51cf31538..b26b6fcd9 100644
--- a/control/injector/SilverStripeServiceConfigurationLocator.php
+++ b/control/injector/SilverStripeServiceConfigurationLocator.php
@@ -11,21 +11,22 @@ class SilverStripeServiceConfigurationLocator extends ServiceConfigurationLocato
/**
* List of Injector configurations cached from Config in class => config format.
- * If any config is false, this denotes that this class and all its parents
+ * If any config is false, this denotes that this class and all its parents
* have no configuration specified.
- *
+ *
* @var array
*/
protected $configs = array();
public function locateConfigFor($name) {
+
// Check direct or cached result
$config = $this->configFor($name);
if($config !== null) return $config;
-
+
// do parent lookup if it's a class
if (class_exists($name)) {
- $parents = array_reverse(array_keys(ClassInfo::ancestry($name)));
+ $parents = array_reverse(array_values(ClassInfo::ancestry($name)));
array_shift($parents);
foreach ($parents as $parent) {
@@ -38,27 +39,27 @@ class SilverStripeServiceConfigurationLocator extends ServiceConfigurationLocato
}
}
}
-
+
// there is no parent config, so we'll record that as false so we don't do the expensive
// lookup through parents again
$this->configs[$name] = false;
}
-
+
/**
* Retrieves the config for a named service without performing a hierarchy walk
- *
+ *
* @param string $name Name of service
- * @return mixed Returns either the configuration data, if there is any. A missing config is denoted
+ * @return mixed Returns either the configuration data, if there is any. A missing config is denoted
* by a value of either null (there is no direct config assigned and a hierarchy walk is necessary)
- * or false (there is no config for this class, nor within the hierarchy for this class).
+ * or false (there is no config for this class, nor within the hierarchy for this class).
*/
protected function configFor($name) {
-
+
// Return cached result
if (isset($this->configs[$name])) {
return $this->configs[$name]; // Potentially false
}
-
+
$config = Config::inst()->get('Injector', $name);
if ($config) {
$this->configs[$name] = $config;
@@ -67,4 +68,4 @@ class SilverStripeServiceConfigurationLocator extends ServiceConfigurationLocato
return null;
}
}
-}
\ No newline at end of file
+}
diff --git a/core/ClassInfo.php b/core/ClassInfo.php
index a7bab59bb..b6aac6a56 100644
--- a/core/ClassInfo.php
+++ b/core/ClassInfo.php
@@ -3,8 +3,8 @@
/**
* Provides introspection information about the class tree.
*
- * It's a cached wrapper around the built-in class functions. SilverStripe uses
- * class introspection heavily and without the caching it creates an unfortunate
+ * It's a cached wrapper around the built-in class functions. SilverStripe uses
+ * class introspection heavily and without the caching it creates an unfortunate
* performance hit.
*
* @package framework
@@ -61,6 +61,7 @@ class ClassInfo {
* @return array List of subclasses
*/
public static function getValidSubClasses($class = 'SiteTree', $includeUnbacked = false) {
+ $class = self::class_name($class);
$classes = DB::get_schema()->enumValuesForField($class, 'ClassName');
if (!$includeUnbacked) $classes = array_filter($classes, array('ClassInfo', 'exists'));
return $classes;
@@ -77,9 +78,7 @@ class ClassInfo {
public static function dataClassesFor($class) {
$result = array();
- if (is_object($class)) {
- $class = get_class($class);
- }
+ $class = self::class_name($class);
$classes = array_merge(
self::ancestry($class),
@@ -101,7 +100,7 @@ class ClassInfo {
* @return string
*/
public static function baseDataClass($class) {
- if (is_object($class)) $class = get_class($class);
+ $class = self::class_name($class);
if (!is_subclass_of($class, 'DataObject')) {
throw new InvalidArgumentException("$class is not a subclass of DataObject");
@@ -125,7 +124,7 @@ class ClassInfo {
*
* ClassInfo::subclassesFor('BaseClass');
* array(
- * 0 => 'BaseClass',
+ * 'BaseClass' => 'BaseClass',
* 'ChildClass' => 'ChildClass',
* 'GrandChildClass' => 'GrandChildClass'
* )
@@ -135,8 +134,10 @@ class ClassInfo {
* @return array Names of all subclasses as an associative array.
*/
public static function subclassesFor($class) {
+ //normalise class case
+ $className = self::class_name($class);
$descendants = SS_ClassLoader::instance()->getManifest()->getDescendantsOf($class);
- $result = array($class => $class);
+ $result = array($className => $className);
if ($descendants) {
return $result + ArrayLib::valuekey($descendants);
@@ -145,6 +146,23 @@ class ClassInfo {
}
}
+ /**
+ * Convert a class name in any case and return it as it was defined in PHP
+ *
+ * eg: self::class_name('dataobJEct'); //returns 'DataObject'
+ *
+ * @param string|object $nameOrObject The classname or object you want to normalise
+ *
+ * @return string The normalised class name
+ */
+ public static function class_name($nameOrObject) {
+ if (is_object($nameOrObject)) {
+ return get_class($nameOrObject);
+ }
+ $reflection = new ReflectionClass($nameOrObject);
+ return $reflection->getName();
+ }
+
/**
* Returns the passed class name along with all its parent class names in an
* array, sorted with the root class first.
@@ -154,9 +172,11 @@ class ClassInfo {
* @return array
*/
public static function ancestry($class, $tablesOnly = false) {
- if (!is_string($class)) $class = get_class($class);
+ $class = self::class_name($class);
- $cacheKey = $class . '_' . (string)$tablesOnly;
+ $lClass = strtolower($class);
+
+ $cacheKey = $lClass . '_' . (string)$tablesOnly;
$parent = $class;
if(!isset(self::$_cache_ancestry[$cacheKey])) {
$ancestry = array();
@@ -183,7 +203,7 @@ class ClassInfo {
* Returns true if the given class implements the given interface
*/
public static function classImplements($className, $interfaceName) {
- return in_array($className, SS_ClassLoader::instance()->getManifest()->getImplementorsOf($interfaceName));
+ return in_array($className, self::implementorsOf($interfaceName));
}
/**
@@ -232,24 +252,28 @@ class ClassInfo {
private static $method_from_cache = array();
public static function has_method_from($class, $method, $compclass) {
- if (!isset(self::$method_from_cache[$class])) self::$method_from_cache[$class] = array();
+ $lClass = strtolower($class);
+ $lMethod = strtolower($method);
+ $lCompclass = strtolower($compclass);
+ if (!isset(self::$method_from_cache[$lClass])) self::$method_from_cache[$lClass] = array();
- if (!array_key_exists($method, self::$method_from_cache[$class])) {
- self::$method_from_cache[$class][$method] = false;
+ if (!array_key_exists($lMethod, self::$method_from_cache[$lClass])) {
+ self::$method_from_cache[$lClass][$lMethod] = false;
$classRef = new ReflectionClass($class);
if ($classRef->hasMethod($method)) {
$methodRef = $classRef->getMethod($method);
- self::$method_from_cache[$class][$method] = $methodRef->getDeclaringClass()->getName();
+ self::$method_from_cache[$lClass][$lMethod] = $methodRef->getDeclaringClass()->getName();
}
}
- return self::$method_from_cache[$class][$method] == $compclass;
+ return strtolower(self::$method_from_cache[$lClass][$lMethod]) == $lCompclass;
}
+
/**
- * Returns the table name in the class hierarchy which contains a given
+ * Returns the table name in the class hierarchy which contains a given
* field column for a {@link DataObject}. If the field does not exist, this
* will return null.
*
@@ -259,23 +283,26 @@ class ClassInfo {
* @return string
*/
public static function table_for_object_field($candidateClass, $fieldName) {
- if(!$candidateClass || !$fieldName) {
+ if(!$candidateClass || !$fieldName || !is_subclass_of($candidateClass, 'DataObject')) {
return null;
}
- $exists = class_exists($candidateClass);
+ //normalise class name
+ $candidateClass = self::class_name($candidateClass);
+
+ $exists = self::exists($candidateClass);
while($candidateClass && $candidateClass != 'DataObject' && $exists) {
if(DataObject::has_own_table($candidateClass)) {
$inst = singleton($candidateClass);
-
+
if($inst->hasOwnTableDatabaseField($fieldName)) {
break;
}
}
$candidateClass = get_parent_class($candidateClass);
- $exists = class_exists($candidateClass);
+ $exists = $candidateClass && self::exists($candidateClass);
}
if(!$candidateClass || !$exists) {
diff --git a/core/Config.php b/core/Config.php
index 7291390e0..91c2cb88a 100644
--- a/core/Config.php
+++ b/core/Config.php
@@ -237,7 +237,16 @@ class Config {
* @return Config Reference to new active Config instance
*/
public static function unnest() {
- return self::set_instance(self::$instance->nestedFrom);
+ if (self::inst()->nestedFrom) {
+ self::set_instance(self::inst()->nestedFrom);
+ }
+ else {
+ user_error(
+ "Unable to unnest root Config, please make sure you don't have mis-matched nest/unnest",
+ E_USER_WARNING
+ );
+ }
+ return self::inst();
}
/**
@@ -681,7 +690,7 @@ class Config {
/**
* @package framework
* @subpackage core
- * @deprecated 3.2
+ * @deprecated 4.0
*/
class Config_LRU {
const SIZE = 1000;
@@ -693,7 +702,7 @@ class Config_LRU {
protected $c = 0;
public function __construct() {
- Deprecation::notice('3.2', 'Please use Config_MemCache instead', Deprecation::SCOPE_CLASS);
+ Deprecation::notice('4.0', 'Please use Config_MemCache instead', Deprecation::SCOPE_CLASS);
if (version_compare(PHP_VERSION, '5.3.7', '<')) {
// SplFixedArray causes seg faults before PHP 5.3.7
$this->cache = array();
diff --git a/core/Constants.php b/core/Constants.php
index f8a130f75..323a3cc3c 100644
--- a/core/Constants.php
+++ b/core/Constants.php
@@ -111,6 +111,7 @@ if(!defined('TRUSTED_PROXY')) {
*/
if(!isset($_SERVER['HTTP_HOST'])) {
// HTTP_HOST, REQUEST_PORT, SCRIPT_NAME, and PHP_SELF
+ global $_FILE_TO_URL_MAPPING;
if(isset($_FILE_TO_URL_MAPPING)) {
$fullPath = $testPath = realpath($_SERVER['SCRIPT_FILENAME']);
while($testPath && $testPath != '/' && !preg_match('/^[A-Z]:\\\\$/', $testPath)) {
@@ -162,9 +163,10 @@ if(!isset($_SERVER['HTTP_HOST'])) {
}
}
-if (defined('SS_ALLOWED_HOSTS')) {
+// Filter by configured allowed hosts
+if (defined('SS_ALLOWED_HOSTS') && php_sapi_name() !== "cli") {
$all_allowed_hosts = explode(',', SS_ALLOWED_HOSTS);
- if (!in_array($_SERVER['HTTP_HOST'], $all_allowed_hosts)) {
+ if (!isset($_SERVER['HTTP_HOST']) || !in_array($_SERVER['HTTP_HOST'], $all_allowed_hosts)) {
header('HTTP/1.1 400 Invalid Host', true, 400);
die();
}
diff --git a/core/Core.php b/core/Core.php
index e55706d86..756941a1c 100644
--- a/core/Core.php
+++ b/core/Core.php
@@ -27,6 +27,9 @@ error_reporting(E_ALL | E_STRICT);
*/
require_once dirname(__FILE__).'/Constants.php';
+global $_increase_time_limit_max;
+$_increase_time_limit_max = -1;
+
/**
* Priorities definition. These constants are used in calls to _t() as an optional argument
*/
@@ -255,7 +258,7 @@ function translate_memstring($memString) {
*/
function increase_time_limit_to($timeLimit = null) {
$max = get_increase_time_limit_max();
- if($max != -1 && $timeLimit > $max) return false;
+ if($max != -1 && $max != null && $timeLimit > $max) return false;
if(!ini_get('safe_mode')) {
if(!$timeLimit) {
@@ -274,8 +277,6 @@ function increase_time_limit_to($timeLimit = null) {
}
}
-$_increase_time_limit_max = -1;
-
/**
* Set the maximum allowed value for {@link increase_timeLimit_to()};
*
diff --git a/core/Object.php b/core/Object.php
index e0e2bd587..338945716 100755
--- a/core/Object.php
+++ b/core/Object.php
@@ -584,7 +584,7 @@ abstract class Object {
$sources[] = $extensionClass;
if(!ClassInfo::has_method_from($extensionClass, 'add_to_class', 'Extension')) {
- Deprecation::notice('3.2.0',
+ Deprecation::notice('4.0',
"add_to_class deprecated on $extensionClass. Use get_extra_config instead");
}
@@ -995,6 +995,8 @@ abstract class Object {
* @return mixed the cached data
*/
public function cacheToFile($method, $lifetime = 3600, $ID = false, $arguments = array()) {
+ Deprecation::notice('4.0', 'Caching methods on Object have been deprecated. Use the SS_Cache API instead.');
+
if(!$this->hasMethod($method)) {
throw new InvalidArgumentException("Object->cacheToFile(): the method $method does not exist to cache");
}
@@ -1022,6 +1024,8 @@ abstract class Object {
* Clears the cache for the given cacheToFile call
*/
public function clearCache($method, $ID = false, $arguments = array()) {
+ Deprecation::notice('4.0', 'Caching methods on Object have been deprecated. Use the SS_Cache API instead.');
+
$cacheName = $this->class . '_' . $method;
if(!is_array($arguments)) $arguments = array($arguments);
if($ID) $cacheName .= '_' . $ID;
@@ -1039,6 +1043,8 @@ abstract class Object {
* @return mixed
*/
protected function loadCache($cache, $lifetime = 3600) {
+ Deprecation::notice('4.0', 'Caching methods on Object have been deprecated. Use the SS_Cache API instead.');
+
$path = TEMP_FOLDER . '/' . $this->sanitiseCachename($cache);
if(!isset($_REQUEST['flush']) && file_exists($path) && (filemtime($path) + $lifetime) > time()) {
@@ -1055,6 +1061,7 @@ abstract class Object {
* @param mixed $data data to save (must be serializable)
*/
protected function saveCache($cache, $data) {
+ Deprecation::notice('4.0', 'Caching methods on Object have been deprecated. Use the SS_Cache API instead.');
file_put_contents(TEMP_FOLDER . '/' . $this->sanitiseCachename($cache), serialize($data));
}
@@ -1065,6 +1072,7 @@ abstract class Object {
* @return string the name with all special cahracters replaced with underscores
*/
protected function sanitiseCachename($name) {
+ Deprecation::notice('4.0', 'Caching methods on Object have been deprecated. Use the SS_Cache API instead.');
return str_replace(array('~', '.', '/', '!', ' ', "\n", "\r", "\t", '\\', ':', '"', '\'', ';'), '_', $name);
}
diff --git a/core/manifest/ClassManifest.php b/core/manifest/ClassManifest.php
index 631415615..627f805cd 100644
--- a/core/manifest/ClassManifest.php
+++ b/core/manifest/ClassManifest.php
@@ -106,6 +106,33 @@ class SS_ClassManifest {
));
}
+ /**
+ * Create a {@link TokenisedRegularExpression} that extracts the namespaces imported with the 'use' keyword
+ *
+ * This searches symbols for a `use` followed by 1 or more namespaces which are optionally aliased using the `as`
+ * keyword. The relevant matching tokens are added one-by-one into an array (using `save_to` param).
+ *
+ * eg: use Namespace\ClassName as Alias, OtherNamespace\ClassName;
+ *
+ * @return TokenisedRegularExpression
+ */
+ public static function get_imported_namespace_parser() {
+ return new TokenisedRegularExpression(array(
+ 0 => T_USE,
+ 1 => T_WHITESPACE,
+ 2 => array(T_NS_SEPARATOR, 'save_to' => 'importString[]', 'optional' => true),
+ 3 => array(T_STRING, 'save_to' => 'importString[]', 'can_jump_to' => array(2, 8)),
+ 4 => array(T_WHITESPACE, 'save_to' => 'importString[]'),
+ 5 => array(T_AS, 'save_to' => 'importString[]'),
+ 6 => array(T_WHITESPACE, 'save_to' => 'importString[]'),
+ 7 => array(T_STRING, 'save_to' => 'importString[]'),
+ 8 => array(T_WHITESPACE, 'optional' => true),
+ 9 => array(',', 'save_to' => 'importString[]', 'optional' => true, 'can_jump_to' => 2),
+ 10 => array(T_WHITESPACE, 'optional' => true, 'can_jump_to' => 2),
+ 11 => ';',
+ ));
+ }
+
/**
* Constructs and initialises a new class manifest, either loading the data
* from the cache or re-scanning for classes.
@@ -333,6 +360,124 @@ class SS_ClassManifest {
}
}
+ /**
+ * Find a the full namespaced declaration of a class (or interface) from a list of candidate imports
+ *
+ * This is typically used to determine the full class name in classes that have imported namesapced symbols (having
+ * used the `use` keyword)
+ *
+ * NB: remember the '\\' is an escaped backslash and is interpreted as a single \
+ *
+ * @param string $class The class (or interface) name to find in the candidate imports
+ * @param string $namespace The namespace that was declared for the classes definition (if there was one)
+ * @param array $imports The list of imported symbols (Classes or Interfaces) to test against
+ *
+ * @return string The fully namespaced class name
+ */
+ protected function findClassOrInterfaceFromCandidateImports($class, $namespace = '', $imports = array()) {
+
+ //normalise the namespace
+ $namespace = rtrim($namespace, '\\');
+
+ //by default we'll use the $class as our candidate
+ $candidateClass = $class;
+
+ if (!$class) {
+ return $candidateClass;
+ }
+ //if the class starts with a \ then it is explicitly in the global namespace and we don't need to do
+ // anything else
+ if (substr($class, 0, 1) == '\\') {
+ $candidateClass = substr($class, 1);
+ return $candidateClass;
+ }
+ //if there's a namespace, starting assumption is the class is defined in that namespace
+ if ($namespace) {
+ $candidateClass = $namespace . '\\' . $class;
+ }
+
+ if (empty($imports)) {
+ return $candidateClass;
+ }
+
+ //normalised class name (PHP is case insensitive for symbols/namespaces
+ $lClass = strtolower($class);
+
+ //go through all the imports and see if the class exists within one of them
+ foreach ($imports as $alias => $import) {
+ //normalise import
+ $import = trim($import, '\\');
+
+ //if there is no string key, then there was no declared alias - we'll use the main declaration
+ if (is_int($alias)) {
+ $alias = strtolower($import);
+ } else {
+ $alias = strtolower($alias);
+ }
+
+ //exact match? Then it's a class in the global namespace that was imported OR it's an alias of
+ // another namespace
+ // or if it ends with the \ClassName then it's the class we are looking for
+ if ($lClass == $alias
+ || substr_compare(
+ $alias,
+ '\\' . $lClass,
+ strlen($alias) - strlen($lClass) - 1,
+ // -1 because the $lClass length is 1 longer due to \
+ strlen($alias)
+ ) === 0
+ ) {
+ $candidateClass = $import;
+ break;
+ }
+ }
+ return $candidateClass;
+ }
+
+ /**
+ * Return an array of array($alias => $import) from tokenizer's tokens of a PHP file
+ *
+ * NB: If there is no alias we don't set a key to the array
+ *
+ * @param array $tokens The parsed tokens from tokenizer's parsing of a PHP file
+ *
+ * @return array The array of imports as (optional) $alias => $import
+ */
+ protected function getImportsFromTokens($tokens) {
+ //parse out the imports
+ $imports = self::get_imported_namespace_parser()->findAll($tokens);
+
+ //if there are any imports, clean them up
+ // imports come to us as array('importString' => array([array of matching tokens]))
+ // we need to join this nested array into a string and split out the alias and the import
+ if (!empty($imports)) {
+ $cleanImports = array();
+ foreach ($imports as $import) {
+ if (!empty($import['importString'])) {
+ //join the array up into a string
+ $importString = implode('', $import['importString']);
+ //split at , to get each import declaration
+ $importSet = explode(',', $importString);
+ foreach ($importSet as $importDeclaration) {
+ //split at ' as ' (any case) to see if we are aliasing the namespace
+ $importDeclaration = preg_split('/\s+as\s+/i', $importDeclaration);
+ //shift off the fully namespaced import
+ $qualifiedImport = array_shift($importDeclaration);
+ //if there are still items in the array, it's the alias
+ if (!empty($importDeclaration)) {
+ $cleanImports[array_shift($importDeclaration)] = $qualifiedImport;
+ }
+ else {
+ $cleanImports[] = $qualifiedImport;
+ }
+ }
+ }
+ }
+ $imports = $cleanImports;
+ }
+ return $imports;
+ }
+
public function handleFile($basename, $pathname, $depth) {
if ($basename == self::CONF_FILE) {
$this->configs[] = $pathname;
@@ -342,6 +487,7 @@ class SS_ClassManifest {
$classes = null;
$interfaces = null;
$namespace = null;
+ $imports = null;
// The results of individual file parses are cached, since only a few
// files will have changed and TokenisedRegularExpression is quite
@@ -352,14 +498,17 @@ class SS_ClassManifest {
if ($data = $this->cache->load($key)) {
$valid = (
- isset($data['classes']) && isset($data['interfaces']) && isset($data['namespace'])
- && is_array($data['classes']) && is_array($data['interfaces']) && is_string($data['namespace'])
+ isset($data['classes']) && is_array($data['classes'])
+ && isset($data['interfaces']) && is_array($data['interfaces'])
+ && isset($data['namespace']) && is_string($data['namespace'])
+ && isset($data['imports']) && is_array($data['imports'])
);
if ($valid) {
- $classes = $data['classes'];
+ $classes = $data['classes'];
$interfaces = $data['interfaces'];
$namespace = $data['namespace'];
+ $imports = $data['imports'];
}
}
@@ -367,28 +516,52 @@ class SS_ClassManifest {
$tokens = token_get_all($file);
$classes = self::get_namespaced_class_parser()->findAll($tokens);
+
$namespace = self::get_namespace_parser()->findAll($tokens);
+
if($namespace) {
- $namespace = implode('', $namespace[0]['namespaceName']) . '\\';
+ $namespace = implode('', $namespace[0]['namespaceName']);
} else {
$namespace = '';
}
+ $imports = $this->getImportsFromTokens($tokens);
+
$interfaces = self::get_interface_parser()->findAll($tokens);
- $cache = array('classes' => $classes, 'interfaces' => $interfaces, 'namespace' => $namespace);
+ $cache = array(
+ 'classes' => $classes,
+ 'interfaces' => $interfaces,
+ 'namespace' => $namespace,
+ 'imports' => $imports
+ );
$this->cache->save($cache, $key);
}
foreach ($classes as $class) {
- $name = $namespace . $class['className'];
- $extends = isset($class['extends']) ? implode('', $class['extends']) : null;
+ $name = $class['className'];
+ if ($namespace) {
+ $namespace = rtrim($namespace, '\\');
+ $name = $namespace . '\\' . $name;
+ }
+ $extends = isset($class['extends']) ? implode('', $class['extends']) : null;
$implements = isset($class['interfaces']) ? $class['interfaces'] : null;
- if($extends && $extends[0] != '\\') {
- $extends = $namespace . $extends;
- } elseif($extends) {
- $extends = substr($extends, 1);
+ if ($extends) {
+ $extends = $this->findClassOrInterfaceFromCandidateImports($extends, $namespace, $imports);
+ }
+
+ if (!empty($implements)) {
+ //join all the tokens
+ $implements = implode('', $implements);
+ //split at comma
+ $implements = explode(',', $implements);
+ //normalise interfaces
+ foreach ($implements as &$interface) {
+ $interface = $this->findClassOrInterfaceFromCandidateImports($interface, $namespace, $imports);
+ }
+ //release the var name
+ unset($interface);
}
$lowercaseName = strtolower($name);
@@ -414,32 +587,24 @@ class SS_ClassManifest {
}
if ($implements) {
- $interface = $namespace;
- for($i = 0; $i < count($implements); ++$i) {
- if($implements[$i] == ',') {
- $interface = $namespace;
- continue;
- }
- if($implements[$i] == '\\' && $interface == $namespace) {
- $interface = '';
- } else {
- $interface .= $implements[$i];
- }
- if($i == count($implements)-1 || $implements[$i+1] == ',') {
- $interface = strtolower($interface);
+ foreach ($implements as $interface) {
+ $interface = strtolower($interface);
- if (!isset($this->implementors[$interface])) {
- $this->implementors[$interface] = array($name);
- } else {
- $this->implementors[$interface][] = $name;
- }
+ if (!isset($this->implementors[$interface])) {
+ $this->implementors[$interface] = array($name);
+ } else {
+ $this->implementors[$interface][] = $name;
}
}
}
}
+ $interfaceBase = '';
+ if ($namespace) {
+ $interfaceBase = $namespace . '\\';
+ }
foreach ($interfaces as $interface) {
- $this->interfaces[strtolower($namespace . $interface['interfaceName'])] = $pathname;
+ $this->interfaces[strtolower($interfaceBase . $interface['interfaceName'])] = $pathname;
}
}
diff --git a/core/manifest/ConfigStaticManifest.php b/core/manifest/ConfigStaticManifest.php
index fc1c54feb..ba488a5b7 100644
--- a/core/manifest/ConfigStaticManifest.php
+++ b/core/manifest/ConfigStaticManifest.php
@@ -79,7 +79,7 @@ class SS_ConfigStaticManifest {
$static = $this->statics[$class][$name];
if ($static['access'] != T_PRIVATE) {
- Deprecation::notice('3.2.0', "Config static $class::\$$name must be marked as private",
+ Deprecation::notice('4.0', "Config static $class::\$$name must be marked as private",
Deprecation::SCOPE_GLOBAL);
// Don't warn more than once per static
$this->statics[$class][$name]['access'] = T_PRIVATE;
diff --git a/css/AssetUploadField.css b/css/AssetUploadField.css
index 33e69e44c..2cd642f5e 100644
--- a/css/AssetUploadField.css
+++ b/css/AssetUploadField.css
@@ -16,7 +16,7 @@ Used in side panels and action tabs
.backlink { padding-left: 12px; }
body.cms.ss-uploadfield-edit-iframe, .composite.ss-assetuploadfield .details fieldset { overflow: auto; background: #E2E2E2; }
-body.cms.ss-uploadfield-edit-iframe span.readonly, .composite.ss-assetuploadfield .details fieldset span.readonly { font-style: italic; color: #777777; text-shadow: 0px 1px 0px #fff; }
+body.cms.ss-uploadfield-edit-iframe span.readonly, .composite.ss-assetuploadfield .details fieldset span.readonly { font-style: italic; color: #9ba5ae; text-shadow: 0px 1px 0px #fff; }
body.cms.ss-uploadfield-edit-iframe .fieldholder-small label, .composite.ss-assetuploadfield .details fieldset .fieldholder-small label { margin-left: 0; }
.composite.ss-assetuploadfield .details fieldset { padding: 16px; }
@@ -30,7 +30,7 @@ body.cms.ss-uploadfield-edit-iframe .fieldholder-small label, .composite.ss-asse
.ss-assetuploadfield .fileOverview .uploadStatus .state { float: left; font-size: 16px; font-weight: bold; line-height: 1.1em; }
.ss-assetuploadfield .fileOverview .uploadStatus .details { opacity: 0.9; float: right; }
.ss-assetuploadfield .ss-uploadfield-item-actions.edit-all { clear: both; position: relative; z-index: 9; }
-.ss-assetuploadfield .ss-uploadfield-item-actions.edit-all .ss-uploadfield-item-edit-all { z-index: 8; position: absolute; top: -33px; padding: 0; background: none; border: 0; right: 0; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; color: #444; }
+.ss-assetuploadfield .ss-uploadfield-item-actions.edit-all .ss-uploadfield-item-edit-all { z-index: 8; position: absolute; top: -33px; padding: 0; background: none; border: 0; right: 0; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; color: #66727d; }
.ss-assetuploadfield .ss-uploadfield-item-actions.edit-all .ss-uploadfield-item-edit-all:hover { color: #1e7cba; }
.ss-assetuploadfield .ss-uploadfield-files { margin: 0; padding: 0; clear: both; }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item { border: 1px solid #b3b3b3; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; -moz-background-clip: padding; -o-background-clip: padding-box; -webkit-background-clip: padding; background-clip: padding-box; margin: 0 0 5px; padding: 0; overflow: hidden; position: relative; }
@@ -41,8 +41,8 @@ body.cms.ss-uploadfield-edit-iframe .fieldholder-small label, .composite.ss-asse
.ss-assetuploadfield .ss-uploadfield-files .ui-state-error .ss-uploadfield-item-info { background-color: #c11f1d; padding-right: 130px; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2MxMWYxZCIvPjxzdG9wIG9mZnNldD0iNCUiIHN0b3AtY29sb3I9IiNiZjFkMWIiLz48c3RvcCBvZmZzZXQ9IjglIiBzdG9wLWNvbG9yPSIjYjcxYjFjIi8+PHN0b3Agb2Zmc2V0PSIxNSUiIHN0b3AtY29sb3I9IiNiNjFlMWQiLz48c3RvcCBvZmZzZXQ9IjI3JSIgc3RvcC1jb2xvcj0iI2IxMWQxZCIvPjxzdG9wIG9mZnNldD0iMzElIiBzdG9wLWNvbG9yPSIjYWIxZDFjIi8+PHN0b3Agb2Zmc2V0PSI0MiUiIHN0b3AtY29sb3I9IiNhNTFiMWIiLz48c3RvcCBvZmZzZXQ9IjQ2JSIgc3RvcC1jb2xvcj0iIzlmMWIxOSIvPjxzdG9wIG9mZnNldD0iNTAlIiBzdG9wLWNvbG9yPSIjOWYxYjE5Ii8+PHN0b3Agb2Zmc2V0PSI1NCUiIHN0b3AtY29sb3I9IiM5OTFjMWEiLz48c3RvcCBvZmZzZXQ9IjU4JSIgc3RvcC1jb2xvcj0iIzk3MWExOCIvPjxzdG9wIG9mZnNldD0iNjIlIiBzdG9wLWNvbG9yPSIjOTExYjFiIi8+PHN0b3Agb2Zmc2V0PSI2NSUiIHN0b3AtY29sb3I9IiM5MTFiMWIiLz48c3RvcCBvZmZzZXQ9Ijg4JSIgc3RvcC1jb2xvcj0iIzdlMTgxNiIvPjxzdG9wIG9mZnNldD0iOTIlIiBzdG9wLWNvbG9yPSIjNzcxOTE5Ii8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjNzMxODE3Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g'); background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #c11f1d), color-stop(4%, #bf1d1b), color-stop(8%, #b71b1c), color-stop(15%, #b61e1d), color-stop(27%, #b11d1d), color-stop(31%, #ab1d1c), color-stop(42%, #a51b1b), color-stop(46%, #9f1b19), color-stop(50%, #9f1b19), color-stop(54%, #991c1a), color-stop(58%, #971a18), color-stop(62%, #911b1b), color-stop(65%, #911b1b), color-stop(88%, #7e1816), color-stop(92%, #771919), color-stop(100%, #731817)); background-image: -moz-linear-gradient(top, #c11f1d 0%, #bf1d1b 4%, #b71b1c 8%, #b61e1d 15%, #b11d1d 27%, #ab1d1c 31%, #a51b1b 42%, #9f1b19 46%, #9f1b19 50%, #991c1a 54%, #971a18 58%, #911b1b 62%, #911b1b 65%, #7e1816 88%, #771919 92%, #731817 100%); background-image: -webkit-linear-gradient(top, #c11f1d 0%, #bf1d1b 4%, #b71b1c 8%, #b61e1d 15%, #b11d1d 27%, #ab1d1c 31%, #a51b1b 42%, #9f1b19 46%, #9f1b19 50%, #991c1a 54%, #971a18 58%, #911b1b 62%, #911b1b 65%, #7e1816 88%, #771919 92%, #731817 100%); background-image: linear-gradient(to bottom, #c11f1d 0%, #bf1d1b 4%, #b71b1c 8%, #b61e1d 15%, #b11d1d 27%, #ab1d1c 31%, #a51b1b 42%, #9f1b19 46%, #9f1b19 50%, #991c1a 54%, #971a18 58%, #911b1b 62%, #911b1b 65%, #7e1816 88%, #771919 92%, #731817 100%); }
.ss-assetuploadfield .ss-uploadfield-files .ui-state-error .ss-uploadfield-item-info .ss-uploadfield-item-name { width: 100%; cursor: default; background: #bcb9b9; background: rgba(201, 198, 198, 0.9); }
.ss-assetuploadfield .ss-uploadfield-files .ui-state-error .ss-uploadfield-item-info .ss-uploadfield-item-name .name { text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.7); }
-.ss-assetuploadfield .ss-uploadfield-files .ui-state-warning .ss-uploadfield-item-info { background-color: #E9D104; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2U1ZDMzYiIvPjxzdG9wIG9mZnNldD0iOCUiIHN0b3AtY29sb3I9IiNlMmNlMjQiLz48c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iI2QxYmUxYyIvPjxzdG9wIG9mZnNldD0iNTQlIiBzdG9wLWNvbG9yPSIjZDFiYzFiIi8+PHN0b3Agb2Zmc2V0PSI5NiUiIHN0b3AtY29sb3I9IiNkMDlhMWEiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNjZTg3MTkiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA='); background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e5d33b), color-stop(8%, #e2ce24), color-stop(50%, #d1be1c), color-stop(54%, #d1bc1b), color-stop(96%, #d09a1a), color-stop(100%, #ce8719)); background-image: -moz-linear-gradient(top, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bc1b 54%, #d09a1a 96%, #ce8719 100%); background-image: -webkit-linear-gradient(top, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bc1b 54%, #d09a1a 96%, #ce8719 100%); background-image: linear-gradient(to bottom, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bc1b 54%, #d09a1a 96%, #ce8719 100%); }
-.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name { position: relative; z-index: 1; margin: 3px 0 3px 50px; width: 50%; color: #5e5e5e; background: #eeeded; background: rgba(255, 255, 255, 0.8); -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; line-height: 24px; height: 22px; padding: 0 5px; text-align: left; cursor: pointer; display: table; table-layout: fixed; }
+.ss-assetuploadfield .ss-uploadfield-files .ui-state-warning .ss-uploadfield-item-info { background-color: #E9D104; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2U1ZDMzYiIvPjxzdG9wIG9mZnNldD0iOCUiIHN0b3AtY29sb3I9IiNlMmNlMjQiLz48c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iI2QxYmUxYyIvPjxzdG9wIG9mZnNldD0iNTQlIiBzdG9wLWNvbG9yPSIjZDFiZDFjIi8+PHN0b3Agb2Zmc2V0PSI5NiUiIHN0b3AtY29sb3I9IiNkMDlhMWEiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNjZjg3MWEiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA='); background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e5d33b), color-stop(8%, #e2ce24), color-stop(50%, #d1be1c), color-stop(54%, #d1bd1c), color-stop(96%, #d09a1a), color-stop(100%, #cf871a)); background-image: -moz-linear-gradient(top, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bd1c 54%, #d09a1a 96%, #cf871a 100%); background-image: -webkit-linear-gradient(top, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bd1c 54%, #d09a1a 96%, #cf871a 100%); background-image: linear-gradient(to bottom, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bd1c 54%, #d09a1a 96%, #cf871a 100%); }
+.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name { position: relative; z-index: 1; margin: 3px 0 3px 50px; width: 50%; color: #7f8c97; background: #eeeded; background: rgba(255, 255, 255, 0.8); -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; line-height: 24px; height: 22px; padding: 0 5px; text-align: left; cursor: pointer; display: table; table-layout: fixed; }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name .name { text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5); display: inline; float: left; max-width: 50%; font-weight: normal; padding: 0 5px 0 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; -o-text-overflow: ellipsis; }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name .ss-uploadfield-item-status { position: relative; float: right; padding: 0 0 0 5px; max-width: 30%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; -o-text-overflow: ellipsis; text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5); }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name .ss-uploadfield-item-status.ui-state-error-text { text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.6); color: #cc0000; }
@@ -78,7 +78,7 @@ body.cms.ss-uploadfield-edit-iframe .fieldholder-small label, .composite.ss-asse
.ss-insert-media .ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-item-uploador { font-size: 18px; margin-top: -5px; }
.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone { margin-top: 9px; padding: 8px 0; -moz-border-radius: 13px; -webkit-border-radius: 13px; border-radius: 13px; -moz-box-shadow: rgba(128, 128, 128, 0.4) 0 0 4px 0 inset, 0 1px 0 #FAFAFA; -webkit-box-shadow: rgba(128, 128, 128, 0.4) 0 0 4px 0 inset, 0 1px 0 #FAFAFA; box-shadow: rgba(128, 128, 128, 0.4) 0 0 4px 0 inset, 0 1px 0 #FAFAFA; border: 2px dashed #808080; background: #d4dbe0; display: none; height: 54px; min-width: 280px; float: left; text-align: center; }
.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone.active.hover { -moz-box-shadow: rgba(255, 255, 255, 0.6) 0 0 3px 2px inset; -webkit-box-shadow: rgba(255, 255, 255, 0.6) 0 0 3px 2px inset; box-shadow: rgba(255, 255, 255, 0.6) 0 0 3px 2px inset; }
-.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone div { color: #5e5e5e; text-shadow: 0px 1px 0px #fff; background: url("../images/upload.png") 0 10px no-repeat; z-index: 1; padding: 6px 48px 0; line-height: 25px; font-size: 20px; font-weight: bold; display: inline-block; }
+.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone div { color: #7f8c97; text-shadow: 0px 1px 0px #fff; background: url("../images/upload.png") 0 10px no-repeat; z-index: 1; padding: 6px 48px 0; line-height: 25px; font-size: 20px; font-weight: bold; display: inline-block; }
.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone div span { display: block; font-size: 12px; z-index: -1; margin-top: -3px; }
.ss-insert-media .ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone { height: 54px; min-width: 250px; overflow: hidden; padding: 0; margin-top: 2px; }
.ss-insert-media .ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone div { background-position: 0 11px; padding-top: 21px; margin-left: 33px; }
@@ -87,3 +87,5 @@ body.cms.ss-uploadfield-edit-iframe .fieldholder-small label, .composite.ss-asse
/** ---------------------------------------------------- "@2x" media query ---------------------------------------------------- */
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2 / 1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { /* Loading spinner */
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-editform.loading { background-image: url(../admin/images/spinner@2x.gif); background-size: 43px 43px; } }
+
+/*# sourceMappingURL=AssetUploadField.css.map */
diff --git a/css/AssetUploadField.css.map b/css/AssetUploadField.css.map
new file mode 100644
index 000000000..cfbd30444
--- /dev/null
+++ b/css/AssetUploadField.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "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",
+"sources": ["../scss/AssetUploadField.scss","../admin/scss/themes/_default.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_box-shadow.scss","../admin/scss/_mixins.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_border-radius.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_background-clip.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_images.scss","../scss/_elementMixins.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_text-shadow.scss"],
+"names": [],
+"file": "AssetUploadField.css"
+}
\ No newline at end of file
diff --git a/css/CheckboxSetField.css b/css/CheckboxSetField.css
index a45a1d202..8282fe740 100644
--- a/css/CheckboxSetField.css
+++ b/css/CheckboxSetField.css
@@ -1,3 +1,5 @@
#right form .CheckboxSetField ul { margin: 0; padding: 0; }
#right form .CheckboxSetField ul li { list-style: none !important; margin: 0; padding: 0; }
#right form .CheckboxSetField input { width: auto; }
+
+/*# sourceMappingURL=CheckboxSetField.css.map */
diff --git a/css/CheckboxSetField.css.map b/css/CheckboxSetField.css.map
new file mode 100644
index 000000000..3c023f54f
--- /dev/null
+++ b/css/CheckboxSetField.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AACC,gCAAE,GACD,MAAM,EAAC,CAAC,EACR,OAAO,EAAC,CAAC;AAEV,mCAAK,GACJ,UAAU,EAAC,eAAe,EAC1B,MAAM,EAAC,CAAC,EACR,OAAO,EAAC,CAAC;AAEV,mCAAK,GACJ,KAAK,EAAC,IAAI",
+"sources": ["../scss/CheckboxSetField.scss"],
+"names": [],
+"file": "CheckboxSetField.css"
+}
\ No newline at end of file
diff --git a/css/ConfirmedPasswordField.css b/css/ConfirmedPasswordField.css
index fe3ca6897..a6fc0e27b 100644
--- a/css/ConfirmedPasswordField.css
+++ b/css/ConfirmedPasswordField.css
@@ -1 +1,3 @@
.confirmedpassword .showOnClickContainer { /* used to hide a container by-default when loading it so there is no "flash" as the content loads */ display: none; }
+
+/*# sourceMappingURL=ConfirmedPasswordField.css.map */
diff --git a/css/ConfirmedPasswordField.css.map b/css/ConfirmedPasswordField.css.map
new file mode 100644
index 000000000..07b7a130a
--- /dev/null
+++ b/css/ConfirmedPasswordField.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAAA,wCAAyC,yGAExC,OAAO,EAAC,IAAI",
+"sources": ["../scss/ConfirmedPasswordField.scss"],
+"names": [],
+"file": "ConfirmedPasswordField.css"
+}
\ No newline at end of file
diff --git a/css/DatetimeField.css b/css/DatetimeField.css
index 8990d138f..1522eca57 100644
--- a/css/DatetimeField.css
+++ b/css/DatetimeField.css
@@ -1,3 +1,5 @@
.datetime .middleColumn .middleColumn { margin: 0; padding: 0; clear: none; float: left; }
.datetime .middleColumn .field { margin: 0; border-bottom: none; box-shadow: none; }
+
+/*# sourceMappingURL=DatetimeField.css.map */
diff --git a/css/DatetimeField.css.map b/css/DatetimeField.css.map
new file mode 100644
index 000000000..4434f325c
--- /dev/null
+++ b/css/DatetimeField.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAAA,qCAAsC,GACrC,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,CAAC,EACV,KAAK,EAAE,IAAI,EACX,KAAK,EAAE,IAAI;;AAEZ,8BAA+B,GAC9B,MAAM,EAAE,CAAC,EACT,aAAa,EAAE,IAAI,EACnB,UAAU,EAAE,IAAI",
+"sources": ["../scss/DatetimeField.scss"],
+"names": [],
+"file": "DatetimeField.css"
+}
\ No newline at end of file
diff --git a/css/Form.css b/css/Form.css
index 8677f2e90..65a41b6e4 100644
--- a/css/Form.css
+++ b/css/Form.css
@@ -20,3 +20,5 @@ form .message.required, form .message.validation { display: block; margin-top: 5
form .message.validation { color: #FF4040; width: 240px; border-color: #FF4040; }
.typography .ss-tabset ul { margin: 0; }
+
+/*# sourceMappingURL=Form.css.map */
diff --git a/css/Form.css.map b/css/Form.css.map
new file mode 100644
index 000000000..b42d316de
--- /dev/null
+++ b/css/Form.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAAA,IAAK;AAEJ,MAAE,GACD,SAAS,EAAE,IAAI;AAGhB,aAAS,GACR,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,CAAC,EACV,YAAY,EAAE,IAAI;AAGnB,WAAO,GACN,KAAK,EAAE,IAAI,EACX,OAAO,EAAE,KAAK,EACd,MAAM,EAAE,UAAU,EAClB,cAAc,EAAE,MAAM;AAGvB,eAAW,GACV,MAAM,EAAE,WAAW;AAGpB,mBAAe,GACd,WAAW,EAAE,CAAC;AAGf,eAAW,GACV,KAAK,EAAE,IAAI,EACX,KAAK,EAAE,IAAI,EACX,WAAW,EAAE,KAAK;AAGnB,oBAAgB,GACf,KAAK,EAAE,IAAI;AAGZ,aAAQ,GACP,KAAK,EAAG,KAAK;AAGd,6CAA+B,GAC9B,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,KAAK,EACd,KAAK,EAAE,GAAG;AAGX,yBAAqB,GACpB,MAAM,EAAE,eAAe,EACvB,gBAAgB,EAAE,OAAO,EACzB,OAAO,EAAE,KAAK,EACd,KAAK,EAAE,GAAG,EACV,OAAO,EAAE,GAAG,EACZ,MAAM,EAAC,KAAK;AAGb,sBAAkB,GACjB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,GAAG,EAChB,cAAc,EAAE,MAAM;AAGvB,qBAAiB,GAChB,OAAO,EAAE,MAAM;AAIhB,uBAAmB,GAClB,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,OAAO,EACd,eAAe,EAAE,SAAS;AAM3B,aAAS,GACR,MAAM,EAAE,KAAK,EACb,OAAO,EAAE,KAAK,EACd,WAAW,EAAE,IAAI,EACjB,MAAM,EAAE,eAAe,EACvB,gBAAgB,EAAE,OAAO,EACzB,YAAY,EAAE,OAAO;AAErB,oBAAS,GACR,gBAAgB,EAAE,OAAO,EACzB,YAAY,EAAE,OAAO;AAGtB,qBAAU,GACT,gBAAgB,EAAE,OAAO,EACzB,YAAY,EAAE,OAAO;AAGtB,iBAAM,GACL,gBAAgB,EAAE,OAAO,EACzB,YAAY,EAAE,OAAO;AAGtB,gDAAyB,GACxB,OAAO,EAAC,KAAK,EACb,UAAU,EAAC,GAAG,EACd,KAAK,EAAC,OAAO,EACb,KAAK,EAAC,KAAK,EACX,YAAY,EAAE,OAAO;AAGtB,wBAAa,GACZ,KAAK,EAAC,OAAO,EACb,KAAK,EAAC,KAAK,EACX,YAAY,EAAE,OAAO;;AAKxB,yBAA0B,GACzB,MAAM,EAAE,CAAC",
+"sources": ["../scss/Form.scss"],
+"names": [],
+"file": "Form.css"
+}
\ No newline at end of file
diff --git a/css/GridField.css b/css/GridField.css
index c671c0695..b27b067db 100644
--- a/css/GridField.css
+++ b/css/GridField.css
@@ -134,3 +134,5 @@ Used in side panels and action tabs
.cms table.ss-gridfield-table tr.last td { border-bottom: 0 none; }
.cms table.ss-gridfield-table td:first-child { border-left: 1px solid rgba(0, 0, 0, 0.1); }
.cms table.ss-gridfield-table td:last-child { border-right: 1px solid rgba(0, 0, 0, 0.1); }
+
+/*# sourceMappingURL=GridField.css.map */
diff --git a/css/GridField.css.map b/css/GridField.css.map
new file mode 100644
index 000000000..226fbc29e
--- /dev/null
+++ b/css/GridField.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": ";;;;;;;;;;;;;AAwCE,wBAAQ,GACP,aAAa,EAAE,IAAY;AAC3B,8CAAuB,GACtB,aAAa,EAAE,CAAC;AAChB,sDAAQ,GACR,aAAa,EAXL,IAAI;AAcb,sDAA+B,GAC9B,aAAa,EAAE,CAAC;AAChB,8DAAQ,GACR,aAAa,EAjBL,IAAI;AAoBb,qDAA8B,GAC7B,aAAa,EAAE,CAAC;AAChB,6DAAQ,GACR,UAAU,EAvBF,IAAI;AA6Bb,uGAAgC,GAC/B,UAAU,EAAE,kBAAkB;AAG/B,sCAAG,GACF,MAAM,EAAE,OAAO;AAIjB,4DAA0C,GACxC,OAAO,EAAC,IAAI;AAIb,oEAA2B,GAC1B,MAAM,EAAC,IAAI;AAGZ,yBAAO,GACN,KAAK,EAAC,KAAK;AACZ,6BAAM,GACL,KAAK,EAAE,KAAK,EACZ,WAAW,EAAC,GAAY;AAGzB,oDAA2B,GAC1B,SAAS,EAAE,KAAK,EAChB,OAAO,EAAE,aAAa,EACtB,KAAK,ECnDU,KAAK,ECMtB,WAAW,EANG,6BAAwB,EFqDpC,WAAW,EAAE,MAAM;AAGrB,wBAAM,GACL,KAAK,EAAC,IAAI;AACV,4BAAM,GACL,YAAY,EAAC,GAAY,EACzB,KAAK,EAAE,IAAI,EACX,SAAS,EAAE,MAAc;AAI3B,0CAAwB,GACvB,SAAS,EAAE,MAAc;AAK1B,gCAAc,GACb,WAAW,EAAE,OAAO,EAKpB,aAAa,EAAE,GAAG;AAJlB,mDAAkB,GACjB,UAAU,EAAE,+DAA+D,EAC3E,OAAO,EAAC,KAAK;AAKd,mDAAK,GACJ,KAAK,EAAE,IAAI,EGvGb,OAAO,EAAE,YAAY,EAEnB,cAAc,EHsGQ,GAAG,EGjGvB,eAAe,EAbmD,IAAI,EAexE,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,MAAM;AHgGjB,oEAAsB,GACrB,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAC1B,aAAa,EA5FL,IAAI,EA6FZ,uBAAuB,EAAE,CAAC,EAC1B,0BAA0B,EAAE,CAAC;AAE9B,kFAAoC,GACnC,MAAM,EAAE,IAAI,EACZ,WAAW,EAAE,CAAC,EACd,sBAAsB,EAAE,CAAC,EACzB,yBAAyB,EAAE,CAAC,EAC5B,WAAW,EAAE,IAAI;AAGnB,0EAAqC,GACpC,aAAa,EAAE,CAAC,EAChB,SAAS,EC3DK,IAAI,EE/DnB,OAAO,EAAE,YAAY,EAEnB,cAAc,EAXO,MAAM,EAgBzB,eAAe,EAbmD,IAAI,EAexE,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,MAAM;AHoHnB,6BAAyB,GACxB,OAAO,EAAE,KAAK,EIxHf,eAAe,EAAE,IAAI,EACrB,kBAAkB,EAAE,IAAI,EACrB,UAAU,EAAE,IAAI,EJwHlB,OAAO,EAAE,CAAC,EACV,eAAe,EAAE,QAAQ,EACzB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,IAAI;AAEX,mCAAM,GACL,KAAK,EAAE,OAAwB,EAC/B,UAAU,EAAE,WAAW;AAEtB,gEAAY,GACX,SAAS,EAAC,KAAa;AACvB,kFAAkB,GACjB,OAAO,EAAC,CAAC;AAKX,iEAAe,GKwLjB,0BAAwC,EL5TvB,GAAG,EK4TpB,8BAAwC,EL5TvB,GAAG,EK4TpB,sBAAwC,EL5TvB,GAAG;AAuIlB,gEAAc,GKqLhB,2BAAwC,EL5TvB,GAAG,EK4TpB,+BAAwC,EL5TvB,GAAG,EK4TpB,uBAAwC,EL5TvB,GAAG;AA6IpB,mCAAM,GACL,UAAU,EAAE,IAAI;AAChB,sCAAG,GAGF,MAAM,EAAE,OAAO;AAEhB,sCAAG,GACF,KAAK,EAAE,IAAI,EACX,SAAS,EAAE,KAAK,EAChB,SAAS,EAAC,UAAU;AAIpB,kDAAc,GACb,KAAK,EAAE,GAAG,EACV,OAAO,EAAC,KAAc,EACtB,UAAU,EAAE,KAAK,EACjB,WAAW,EAAE,MAAM;AAEpB,2DAAuB,GACtB,KAAK,EA/JE,IAAI,EAgKX,YAAY,EAAC,IAAI,EACjB,WAAW,EAAC,OAAO,EACnB,OAAO,EAAC,CAAC;AACT,+EAAoB,GACnB,UAAU,EAAE,2EAA2E,EACvF,OAAO,EAAC,KAAK;AAKd,iEAAU,GACT,KAAK,ECjKW,OAAO;ADmKxB,kEAAW,GACV,KAAK,EAAE,IAAI,EACX,cAAc,EAAE,SAAS,EACzB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,GAAG,EAChB,WAAW,EAAE,IAAI,EACjB,YAAY,EAAE,GAAG,EACjB,UAAU,EAAG,IAAI,EKmIrB,kBAAwC,EAAE,SAAM,EAAhD,qBAAwC,EC7SU,OAA+D,ED6SjH,aAAwC,EAAE,SAAM;AL/H7C,kFAA2B,GAC1B,KAAK,EAAG,OAAO,EACf,MAAM,EAAE,iBAAiB,EACzB,gBAAgB,EAAE,OAAO;AAG1B,sFAA+B,GAC9B,KAAK,EAAG,OAAO,EACf,MAAM,EAAE,iBAAiB,EACzB,gBAAgB,EAAE,OAAO;AAG1B,uFAAgC,GAC/B,KAAK,EAAG,OAAO,EACf,MAAM,EAAE,iBAAiB,EACzB,gBAAgB,EAAE,OAAO;AAG1B,0FAAmC,GAClC,KAAK,EAAG,OAAO,EACf,MAAM,EAAE,iBAAiB,EACzB,gBAAgB,EAAE,OAAO;AAG1B,2FAAoC,GACnC,KAAK,EAAG,OAAO,EACf,MAAM,EAAE,iBAAiB,EACzB,gBAAgB,EAAE,OAAO;AAI3B,6CAAO,GACN,MAAM,EAAE,IAAI,EACZ,UAAU,EAAE,IAAI,EAChB,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,KAAK,EACd,KAAK,EAAE,IAAI,EACX,WAAW,EAAE,IAAI;AACjB,4DAAiB,GAChB,UAAU,EAAC,IAAI,EI3OpB,eAAe,EAAE,IAAI,EACrB,kBAAkB,EAAE,IAAI,EACrB,UAAU,EAAE,IAAI;AJ4Of,6DAAkB,GACjB,MAAM,EAAC,IAAI,EI/OhB,eAAe,EAAE,IAAI,EACrB,kBAAkB,EAAE,IAAI,EACrB,UAAU,EAAE,IAAI;AJgPf,qEAA0B,GACzB,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,CAAC;AACT,2FAAsB,GACrB,IAAI,EAAE,GAAG;AAIZ,sGAAyB,GACxB,OAAO,EAAC,YAAY,EACpB,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,WAAW,EAAC,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM;AAEvB,kDAAY,GACX,UAAU,EAAE,2DAA2D;AAExE,kDAAY,GACX,UAAU,EAAE,oEAAoE;AAKnF,mCAAM,GACL,KAAK,EAAE,OAAwB;AAE9B,yCAAG,GACF,UAAU,EC/RF,OAAO,EDgSf,OAAO,EAAE,IAAI,EACb,aAAa,EAAE,4BAAwB;AAOxC,yCAAG,GACF,QAAQ,EAAE,QAAQ,EAClB,UAAU,EA1RW,OAAwB,EA2R7C,aAAa,EAAE,iBAA6C,EAC5D,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE,IAAI,EO9Of,gBAAY,EAAE,qhBAAgC,EA2B9C,eAAe,EAAE,IAAI,EA3BrB,gBAAY,EAAE,8FAAgC,EAA9C,gBAAY,EAAE,sCAAgC,EAA9C,gBAAY,EAAE,yCAAgC,EAE9C,gBAAY,EAAE,iCAAO,EL5BzB,WAAW,EANG,6BAAwB;AFiRpC,4CAAE,GACA,OAAO,EAAE,GAAG,EACZ,SAAS,EAAE,MAAc,EACzB,KAAK,EAAC,IAAI,EACV,MAAM,EAAE,SAAS,EACjB,OAAO,EAAC,YAAY,EACpB,KAAK,EAAC,IAAI;AAIb,gDAAkB,GACjB,UAAU,EA1SQ,OAAsC;AA2SxD,mDAAE,GACD,OAAO,EAAE,CAAC,EACV,WAAW,EAAE,MAAM;AACnB,iEAAc,GACb,WAAW,EAAE,MAAM;AAItB,sCAAQ,GACP,UAAU,EAAE,OAAO;AAEpB,4CAAc,GACb,UAAU,EAAE,WAAW;AAEvB,kDAAQ,GACP,UAAU,EAAE,OAAO;AAGrB,kDAAoB,GACnB,UAAU,EA5TI,OAAO;AA8TrB,oEAAoB,GACnB,aAAa,EAAE,IAAI;AAEpB,wDAAQ,GACP,UAAU,EAAE,OAAO;AAGrB,qCAAO,GACN,UAAU,EAtUI,OAAO;AAwUrB,2CAAQ,GACP,UAAU,EAAE,OAAO;AAIrB,mCAAG,GACF,WAAW,EAAE,IAAI,EACjB,SAAS,EAzUD,IAAI,EA0UZ,KAAK,EAAE,IAAI,EACX,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,4BAA2B;AAGxC,4GAAgC,GAC/B,KAAK,EAAE,IAAI,EACX,QAAQ,EAAC,QAAQ;AAElB,kDAAa,GACZ,SAAS,EAAE,KAAe,EAC1B,aAAa,EAAC,CAAC;AACf,iEAAgB,GACf,SAAS,EAAC,IAAI,EACd,UAAU,EAAE,IAAI,EAChB,MAAM,EAAE,IAAI;AACZ,qEAAG,GACF,KAAK,EAAC,IAAI,EACV,OAAO,EAAC,MAAM;AAKlB,wCAAM,GACL,WAAW,EAAC,MAAM,EAClB,UAAU,EAAE,iBAAgC,EAC5C,WAAW,EAAE,iBAAgC,EAC7C,KAAK,EAAC,IAAI,EACV,UAAU,EA/WW,OAAwB,EAgX7C,aAAa,EAAE,4BAA2B;AAC1C,6CAAI,GE5VP,WAAW,EANG,6BAAwB,EFoWlC,YAAY,EAAE,GAAY,EAC1B,aAAa,EAAE,GAAY,EI9XhC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EAInB,aAAa,EAAE,QAAQ,EACvB,gBAAgB,EAAE,QAAQ,EJ0XrB,YAAY,EAAE,GAAG;AAGlB,6DAAuB,GACtB,YAAY,EAAC,IAAI;AAGnB,qFAAiB,GAChB,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,OAAO;AAEhB,yCAAQ,GACP,QAAQ,EAAC,QAAQ,EACjB,UAAU,EAAC,OAA6B,EACxC,UAAU,EAAE,kBAAe,EAC3B,OAAO,EAAE,GAAG,EACZ,UAAU,EErVJ,kBAAmD;AFuVzD,+CAAM,GACL,MAAM,EAAC,IAAI;AAGZ,6DAAoB,GACnB,OAAO,EAAE,IAAI,EACb,WAAW,EAAE,CAAC,EI9YnB,eAAe,EAAE,IAAI,EACrB,kBAAkB,EAAE,IAAI,EACrB,UAAU,EAAE,IAAI,EJ8Yd,QAAQ,EAAE,QAAQ,EAClB,mBAAmB,EAAE,CAAC,EK9E1B,kBAAwC,EAAE,SAAM,EAAhD,qBAAwC,EC7SU,OAA+D,ED6SjH,aAAwC,EAAE,SAAM;ALkF7C,gDAAO,GACN,MAAM,EAAE,CAAC;AAGX,yCAAQ,GKtFV,0BAAwC,EL5TvB,GAAG,EK4TpB,8BAAwC,EL5TvB,GAAG,EK4TpB,sBAAwC,EL5TvB,GAAG;AAqZlB,wCAAO,GKzFT,2BAAwC,EL5TvB,GAAG,EK4TpB,+BAAwC,EL5TvB,GAAG,EK4TpB,uBAAwC,EL5TvB,GAAG;AA4ZjB,6EAAqC,GACpC,KAAK,EAAE,eAAe;AAEvB,gDAAQ,GACP,KAAK,EAAE,eAAe;AAEvB,kEAA0B,GACzB,KAAK,EAAE,eAAe,EI1a3B,eAAe,EAAE,IAAI,EACrB,kBAAkB,EAAE,IAAI,EACrB,UAAU,EAAE,IAAI;AJ2af,4DAAoB,GACnB,UAAU,EAAE,yDAAyD,EACrE,MAAM,EAAC,IAAI,EACX,KAAK,EAAC,IAAI,EACV,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,aAAa,EE7Z1B,WAAW,EANG,6BAAwB,EFqalC,KAAK,EAAE,IAAI,EKjHf,kBAAwC,ELkHb,CAAC,EKlH5B,qBAAwC,EC9Sb,CAAuB,ED8SlD,aAAwC,ELkHb,CAAC;AACxB,kEAAQ,GACP,mBAAmB,EAAE,WAAW;AAEjC,qFAA2B,GAC1B,mBAAmB,EAAE,WAAW;AAEjC,oFAA0B,GACzB,mBAAmB,EAAE,YAAY;AAKlC,kFAA4B,GAE3B,gBAAgB,EAAC,OAA+B,EQpdtD,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,KAAK,EACb,WAAW,EAAC,OAAO,EACnB,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,ED2DN,UAAY,EAAE,glBAAgC,EAA9C,UAAY,EAAE,yJAAgC,EAA9C,UAAY,EAAE,iGAAgC,EAA9C,UAAY,EAAE,oGAAgC,EAE9C,UAAY,EAAE,4FAAO,EP4ZpB,KAAK,EAAE,IAAI,EACX,UAAU,EAAE,iBAAyC;AAErD,0XAAuD,GOjaxD,UAAY,EAAE,glBAAgC,EAA9C,UAAY,EAAE,yJAAgC,EAA9C,UAAY,EAAE,iGAAgC,EAA9C,UAAY,EAAE,oGAAgC,EAE9C,UAAY,EAAE,4FAAO;APwapB,0FAAS,GACR,WAAW,EAjdP,IAAI,EAkdR,MAAM,EAAC,IAAI,EO1ab,UAAY,EAAE,yDAAO,EP4anB,aAAa,EAAE,IAAI,EACnB,MAAM,EAAE,KAAc;AAEtB,+FAAI,GACH,OAAO,EAAE,GAAG,EACZ,QAAQ,EAAC,QAAQ,EACjB,KAAK,EAAC,IAAI,EACV,IAAI,EAAC,IAAI,EACT,GAAG,EAAC,GAAG,EACP,UAAU,EAAE,8DAA8D;AAE3E,gGAAO,GOvbT,UAAY,EAAE,2DAAO,EHjD1B,eAAe,EAAE,IAAI,EACrB,kBAAkB,EAAE,IAAI,EACrB,UAAU,EAAE,IAAI;AJyeX,qGAAI,GACH,OAAO,EAAC,GAAG;AAMf,iFAA2B,GOjc3B,UAAY,EAAE,yDAAO,ECjE1B,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,KAAK,EACb,WAAW,EAAC,OAAO,EACnB,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,ERkgBL,KAAK,EAAC,IAAI,EACV,OAAO,EAAC,GAAG,EACX,YAAY,EAAC,IAAI;AACjB,sXAAuD,GACtD,OAAO,EAAC,CAAC,EO3cX,UAAY,EAAE,goBAAgC,EAA9C,UAAY,EAAE,2LAAgC,EAA9C,UAAY,EAAE,mIAAgC,EAA9C,UAAY,EAAE,sIAAgC,EAE9C,UAAY,EAAE,8HAAO;APodrB,iFAA2B,GQrhBhC,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,KAAK,EACb,WAAW,EAAC,OAAO,EACnB,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,ERmhBL,QAAQ,EAAC,QAAQ,EACjB,GAAG,EAAE,KAAK,EACV,KAAK,EAAE,IAAI,EACX,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,IAAI;AAEZ,0FAAU,GACT,OAAO,EAAC,KAAK,EAEb,UAAU,EAAE,yDAAyD,EACrE,OAAO,EAAC,GAAG;AACX,gGAAO,GACN,OAAO,EAAC,GAAG;AAEZ,iGAAS,GACR,OAAO,EAAC,CAAC;AAQb,2DAAoB,GACnB,MAAM,EAAC,IAAI,EACX,OAAO,EAAE,GAAG,EAKZ,MAAM,EAAE,iBAAiB;AAGxB,sFAAY,GACX,UAAU,EAAC,MAAM,EACjB,KAAK,EAAE,OAA6B;AAFrC,4EAAY,GACX,UAAU,EAAC,MAAM,EACjB,KAAK,EAAE,OAA6B;AAFrC,iFAAY,GACX,UAAU,EAAC,MAAM,EACjB,KAAK,EAAE,OAA6B;AAFrC,uEAAY,GACX,UAAU,EAAC,MAAM,EACjB,KAAK,EAAE,OAA6B;AAItC,iEAAQ,GI/iBb,eAAe,EAAE,IAAI,EACrB,kBAAkB,EAAE,IAAI,EACrB,UAAU,EAAE,IAAI;AJojBhB,qDAAkB,GACjB,OAAO,EAAC,KAAK,EACb,OAAO,EAAE,OAAO;AAIlB,mCAAG,GACF,YAAY,EAAE,4BAA2B,EACzC,OAAO,EAAE,OAAyB,EAClC,KAAK,EA3jBQ,IAAI;AA4jBjB,8CAAa,GK7Pf,6BAAwC,EL5TvB,GAAG,EK4TpB,iCAAwC,EL5TvB,GAAG,EK4TpB,yBAAwC,EL5TvB,GAAG,EK4TpB,8BAAwC,EL5TvB,GAAG,EK4TpB,kCAAwC,EL5TvB,GAAG,EK4TpB,0BAAwC,EL5TvB,GAAG,EOwChB,gBAAY,EAAE,qhBAAgC,EA2B9C,eAAe,EAAE,IAAI,EA3BrB,gBAAY,EAAE,8FAAgC,EAA9C,gBAAY,EAAE,sCAAgC,EAA9C,gBAAY,EAAE,yCAAgC,EAE9C,gBAAY,EAAE,iCAAO,EPkhBtB,OAAO,EAAE,QAAuB;AAEhC,uEAAyB,GACrB,UAAU,EAAE,MAAM,EACrB,WAAW,EAAE,GAAG,EACV,KAAK,ECzjBE,KAAK;AD2jBnB,mEAAqB,GACpB,WAAW,EAAC,GAAG,EACf,QAAQ,EAAC,QAAQ,EACjB,IAAI,EAAC,GAAG,EACR,WAAW,EAAC,MAAM,EAclB,OAAO,EAAC,CAAC;AAbT,2FAAwB,GACvB,KAAK,ECjkBO,KAAK,EDkkBjB,UAAU,EAAE,MAAM,EE5jBvB,WAAW,EANG,6BAAwB;AFokBjC,iGAAM,GACL,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,aAAa,EAAC,IAAI,EAClB,OAAO,EAAC,GAAG,EACX,MAAM,EAAE,iBAA8C,EACtD,aAAa,EAAE,iBAA+C;AAIhE,0EAAM,GI7lBX,eAAe,EAAE,IAAI,EACrB,kBAAkB,EAAE,IAAI,EACrB,UAAU,EAAE,IAAI,EJ6lBb,MAAM,EAAC,IAAI,EACX,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,MAAM,EACb,OAAO,EAAC,MAAM,EACd,KAAK,EAAC,IAAI;AACV,+EAAK,GACJ,WAAW,EAAC,OAAO;AAEpB,oGAA4B,GOtjB7B,UAAY,EAAE,8DAAO;APyjBpB,gGAAwB,GOzjBzB,UAAY,EAAE,8DAAO;AP4jBpB,iGAAyB,GO5jB1B,UAAY,EAAE,4DAAO;AP+jBpB,gGAAwB,GO/jBzB,UAAY,EAAE,8DAAO;APkkBpB,+FAAsB,GACrB,OAAO,EAAC,EAAE;AAIb,yEAA2B,GAC1B,KAAK,EAAC,KAAK,EACX,OAAO,EAAC,KAAK,EACb,KAAK,EC5mBQ,KAAK,ECMtB,WAAW,EANG,6BAAwB;AFknBrC,wCAAU,GACT,aAAa,EAAE,MAAM;AAGvB,4CAAc,GACb,WAAW,EAAE,4BAA2B;AAEzC,2CAAa,GACZ,YAAY,EAAE,4BAA2B",
+"sources": ["../scss/GridField.scss","../admin/scss/themes/_default.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_text-shadow.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_inline-block.scss","../admin/scss/_mixins.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_border-radius.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_images.scss","../scss/_elementMixins.scss"],
+"names": [],
+"file": "GridField.css"
+}
\ No newline at end of file
diff --git a/css/GridFieldPaginator.css b/css/GridFieldPaginator.css
index b11b1037a..1d1929b48 100644
--- a/css/GridFieldPaginator.css
+++ b/css/GridFieldPaginator.css
@@ -1,3 +1,5 @@
.ss-gridfield-pagination { text-align: center; padding-bottom: 10px; }
.ss-gridfield-pagination-button.loading { background: url(../images/network-save.gif) no-repeat 0% 50%; padding-left: 20px; }
+
+/*# sourceMappingURL=GridFieldPaginator.css.map */
diff --git a/css/GridFieldPaginator.css.map b/css/GridFieldPaginator.css.map
new file mode 100644
index 000000000..9fcbc4536
--- /dev/null
+++ b/css/GridFieldPaginator.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAAA,wBAAyB,GACxB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,IAAI;;AAErB,uCAAuC,GACtC,UAAU,EAAE,gDAAgD,EAAE,YAAY,EAAE,IAAI",
+"sources": ["../scss/GridFieldPaginator.scss"],
+"names": [],
+"file": "GridFieldPaginator.css"
+}
\ No newline at end of file
diff --git a/css/GridField_print.css b/css/GridField_print.css
index 5f28eac4c..2006e8314 100644
--- a/css/GridField_print.css
+++ b/css/GridField_print.css
@@ -5,3 +5,5 @@ table th { border-bottom: 2px solid #333; padding: 5px 10px; font-weight: bold;
table th:first-child { padding-left: 0px; }
table td { border-top: 1px solid #aaa; border-bottom: 1px solid #aaa; text-align: left; padding: 5px 10px; }
table td:first-child { padding-left: 0px; }
+
+/*# sourceMappingURL=GridField_print.css.map */
diff --git a/css/GridField_print.css.map b/css/GridField_print.css.map
new file mode 100644
index 000000000..36c28c9df
--- /dev/null
+++ b/css/GridField_print.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAAA,EAAG,GACF,WAAW,EAAE,iBAAiB;;AAE/B,KAAM,GACL,eAAe,EAAE,QAAQ,EACzB,WAAW,EAAE,iBAAiB,EAC9B,KAAK,EAAE,IAAI,EACX,SAAS,EAAE,IAAI;AAIf,QAAE,GACD,aAAa,EAAE,cAAc,EAC7B,OAAO,EAAE,QAAQ,EACjB,WAAW,EAAE,IAAI,EACjB,UAAU,EAAE,IAAI;AAChB,oBAAa,GACZ,YAAY,EAAE,GAAG;AAInB,QAAE,GACD,UAAU,EAAE,cAAc,EAC1B,aAAa,EAAE,cAAc,EAC7B,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,QAAQ;AACjB,oBAAa,GACZ,YAAY,EAAE,GAAG",
+"sources": ["../scss/GridField_print.scss"],
+"names": [],
+"file": "GridField_print.css"
+}
\ No newline at end of file
diff --git a/css/Security_login.css b/css/Security_login.css
index 92c56085e..a0283a5d8 100644
--- a/css/Security_login.css
+++ b/css/Security_login.css
@@ -7,3 +7,5 @@ p#Remember label { display: inline-block; margin: 0; }
#MemberLoginForm_LoginForm .Actions { padding-left: 12em; }
#ForgotPassword { margin-top: 1em; }
+
+/*# sourceMappingURL=Security_login.css.map */
diff --git a/css/Security_login.css.map b/css/Security_login.css.map
new file mode 100644
index 000000000..bd93eca99
--- /dev/null
+++ b/css/Security_login.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAAA,SAAU,GACT,MAAM,EAAE,6BAA6B;;AAErC,gBAAiB,GAChB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,CAAC;;AAEV,eAAgB,GACf,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,SAAS;;AAEnB,mCAAoC,GACnC,YAAY,EAAE,IAAI;;AAEnB,eAAgB,GACf,UAAU,EAAE,GAAG",
+"sources": ["../scss/Security_login.scss"],
+"names": [],
+"file": "Security_login.css"
+}
\ No newline at end of file
diff --git a/css/SelectionGroup.css b/css/SelectionGroup.css
index 59bfc12a4..5572d0864 100644
--- a/css/SelectionGroup.css
+++ b/css/SelectionGroup.css
@@ -9,3 +9,5 @@
.mainblock.allassets ul { padding: 0 0 0 10px; height: 100px; overflow-y: scroll; }
.mainblock.allassets ul li { width: 150px; }
+
+/*# sourceMappingURL=SelectionGroup.css.map */
diff --git a/css/SelectionGroup.css.map b/css/SelectionGroup.css.map
new file mode 100644
index 000000000..ccbf316de
--- /dev/null
+++ b/css/SelectionGroup.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAAA,eAAgB,GACf,OAAO,EAAE,GAAG,EACZ,KAAK,EAAG,IAAI;AAEZ,kBAAG,GACF,eAAe,EAAE,IAAI,EACrB,KAAK,EAAG,IAAI,EACZ,KAAK,EAAE,IAAI,EACX,KAAK,EAAG,IAAI;AAEb,iCAAkB,GACjB,KAAK,EAAE,IAAI,EACX,KAAK,EAAG,IAAI;AAEb,4CAA6B,GAC5B,OAAO,EAAE,IAAI,EACb,SAAS,EAAE,GAAG;AAEf,yEAA0C,GACzC,OAAO,EAAE,KAAK;AAEf,qDAAsC,GACrC,WAAW,EAAE,IAAI,EACjB,OAAO,EAAE,KAAK,EACd,aAAa,EAAE,GAAG;AAEnB,0CAA2B,GAC1B,WAAW,EAAE,IAAI;;AAInB,uBAAwB,GACrB,OAAO,EAAE,UAAU,EACnB,MAAM,EAAC,KAAK,EACZ,UAAU,EAAC,MAAM;;AAEpB,0BAA2B,GACxB,KAAK,EAAE,KAAK",
+"sources": ["../scss/SelectionGroup.scss"],
+"names": [],
+"file": "SelectionGroup.css"
+}
\ No newline at end of file
diff --git a/css/SubmittedFormReportField.css b/css/SubmittedFormReportField.css
index 283ec0cf8..de40a7664 100644
--- a/css/SubmittedFormReportField.css
+++ b/css/SubmittedFormReportField.css
@@ -5,3 +5,5 @@ div.report span.submitted { font-style: italic; }
div.report table * { font-size: 1em; }
div.report table td.field { font-weight: bold; padding-right: 10px; padding-left: 0px; }
+
+/*# sourceMappingURL=SubmittedFormReportField.css.map */
diff --git a/css/SubmittedFormReportField.css.map b/css/SubmittedFormReportField.css.map
new file mode 100644
index 000000000..d086b19bf
--- /dev/null
+++ b/css/SubmittedFormReportField.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAAA,gBAAiB,GAChB,WAAW,EAAE,IAAI,EACjB,aAAa,EAAE,IAAI;;AAGpB,yBAA0B,GACzB,UAAU,EAAE,MAAM;;AAGnB,kBAAmB,GAClB,SAAS,EAAE,GAAG;;AAGf,yBAA0B,GACzB,WAAW,EAAE,IAAI,EACjB,aAAa,EAAE,IAAI,EACnB,YAAY,EAAE,GAAG",
+"sources": ["../scss/SubmittedFormReportField.scss"],
+"names": [],
+"file": "SubmittedFormReportField.css"
+}
\ No newline at end of file
diff --git a/css/TreeDropdownField.css b/css/TreeDropdownField.css
index c06108c33..fbf30cff5 100644
--- a/css/TreeDropdownField.css
+++ b/css/TreeDropdownField.css
@@ -19,3 +19,5 @@ div.TreeDropdownField .treedropdownfield-toggle-panel-link { border: none; margi
div.TreeDropdownField .treedropdownfield-toggle-panel-link.treedropdownfield-open-tree { background: transparent; border: none; }
div.TreeDropdownField .treedropdownfield-toggle-panel-link a { text-decoration: none; display: block; border: 0; margin: 0; opacity: 0.5; }
div.TreeDropdownField a.jstree-loading .jstree-pageicon { background: #fff url("../images/network-save.gif") center center no-repeat; }
+
+/*# sourceMappingURL=TreeDropdownField.css.map */
diff --git a/css/TreeDropdownField.css.map b/css/TreeDropdownField.css.map
new file mode 100644
index 000000000..7c8836f5f
--- /dev/null
+++ b/css/TreeDropdownField.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "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",
+"sources": ["../scss/TreeDropdownField.scss","../admin/scss/_mixins.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_images.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_box-sizing.scss"],
+"names": [],
+"file": "TreeDropdownField.css"
+}
\ No newline at end of file
diff --git a/css/UnitTesting.css b/css/UnitTesting.css
index 472b51952..58b7ea4e6 100644
--- a/css/UnitTesting.css
+++ b/css/UnitTesting.css
@@ -35,3 +35,5 @@ CODE.expected { color: green; background: none; font-weight: normal; }
CODE.actual { color: red; background: none; font-weight: normal; }
.typeinfo { color: gray; }
+
+/*# sourceMappingURL=UnitTesting.css.map */
diff --git a/css/UnitTesting.css.map b/css/UnitTesting.css.map
new file mode 100644
index 000000000..623e3ae02
--- /dev/null
+++ b/css/UnitTesting.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AACA,IAAK,GACJ,IAAI,EAAC,kCAAkC,EACvC,KAAK,EAAC,OAAO;;AAEd,wBAAyB,GACrB,SAAS,EAAE,GAAG;;AAElB,mBAAmB,GAClB,WAAW,EAAE,IAAI,EACjB,UAAU,EAAC,IAAI,EACf,UAAU,EAAC,OAAO;;AAEnB,gBAAgB,GACf,UAAU,EAAC,OAAO;;AAGnB,CAAE,GACD,WAAW,EAAC,KAAK,EACjB,UAAU,EAAC,KAAK,EAAE,aAAa,EAAC,KAAK;;AAEtC,EAAG,GACF,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,8BAAY;;AAExC,EAAG,GACF,UAAU,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,mCAAiB;;AAE/D,EAAG,GACF,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,mCAAiB;;AAE9C,EAAG,GACF,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,mCAAiB;;AAE9C,EAAG,GACF,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,mCAAiB;;AAE9C,EAAG,GACF,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,mCAAiB;;AAE9C,MAAO,GACN,WAAW,EAAC,IAAI,EAAE,KAAK,EAAC,GAAG;;AAE5B,qBAAsB,GACrB,UAAU,EAAC,OAAO,EAAE,WAAW,EAAC,IAAI,EAAE,KAAK,EAAC,KAAK;;AAElD,QAAS,GACR,UAAU,EAAC,OAAO,EAAE,WAAW,EAAC,IAAI,EAAE,KAAK,EAAC,KAAK;;AAElD,gBAAiB,GAChB,UAAU,EAAC,OAAO,EAAE,WAAW,EAAC,IAAI,EAAE,KAAK,EAAC,KAAK;;AAElD,WAAY,GACV,UAAU,EAAC,KAAK;;AAGlB,aAAc,GACb,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM;;AAEpD,WAAY,GACX,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM;;AAElD,SAAU,GACT,KAAK,EAAE,IAAI",
+"sources": ["../scss/UnitTesting.scss"],
+"names": [],
+"file": "UnitTesting.css"
+}
\ No newline at end of file
diff --git a/css/UploadField.css b/css/UploadField.css
index f8adb7825..3e2fcc118 100644
--- a/css/UploadField.css
+++ b/css/UploadField.css
@@ -12,14 +12,14 @@ Used in side panels and action tabs
*/
.ss-uploadfield .clear { clear: both; }
.ss-uploadfield .description { margin-left: 0; }
-.ss-uploadfield .middleColumn { min-width: 510px; max-width: 600px; width: 100%; margin-left: 0; clear: both; padding: 0; background: #fff; border: 1px solid #b3b3b3; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2VmZWZlZiIvPjxzdG9wIG9mZnNldD0iMTAlIiBzdG9wLWNvbG9yPSIjZmZmZmZmIi8+PHN0b3Agb2Zmc2V0PSI5MCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNlZmVmZWYiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA='); background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #efefef), color-stop(10%, #ffffff), color-stop(90%, #ffffff), color-stop(100%, #efefef)); background-image: -moz-linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); background-image: -webkit-linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); background-image: linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); }
+.ss-uploadfield .middleColumn { min-width: 510px; max-width: 696px; width: 100%; margin-left: 0; clear: both; padding: 0; background: #fff; border: 1px solid #b3b3b3; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2VmZWZlZiIvPjxzdG9wIG9mZnNldD0iMTAlIiBzdG9wLWNvbG9yPSIjZmZmZmZmIi8+PHN0b3Agb2Zmc2V0PSI5MCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNlZmVmZWYiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA='); background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #efefef), color-stop(10%, #ffffff), color-stop(90%, #ffffff), color-stop(100%, #efefef)); background-image: -moz-linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); background-image: -webkit-linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); background-image: linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); }
.ss-uploadfield .ss-uploadfield-item { margin: 0; padding: 15px; overflow: auto; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-preview { height: 60px; line-height: 60px; width: 80px; text-align: center; font-weight: bold; float: left; overflow: hidden; }
-.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-preview.ss-uploadfield-dropzone { -moz-box-shadow: #808080 0 0 4px 0 inset; -webkit-box-shadow: #808080 0 0 4px 0 inset; box-shadow: #808080 0 0 4px 0 inset; border: 2px dashed #808080; background: #d0d3d5; display: none; margin-right: 15px; }
+.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-preview.ss-uploadfield-dropzone { -moz-box-shadow: #808080 0 0 4px 0 inset; -webkit-box-shadow: #808080 0 0 4px 0 inset; box-shadow: #808080 0 0 4px 0 inset; border: 2px dashed #808080; background: #D2D5D8; display: none; margin-right: 15px; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info { margin-left: 95px; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name { display: block; line-height: 13px; height: 26px; margin: 0; text-align: left; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name .name { max-width: 240px; font-weight: bold; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; -o-text-overflow: ellipsis; display: inline; float: left; }
-.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name .size { color: #848484; padding: 0 0 0 5px; display: inline; float: left; }
+.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name .size { color: #a9b2b9; padding: 0 0 0 5px; display: inline; float: left; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name .ss-uploadfield-item-status { float: right; padding: 0 0 0 5px; text-align: right; max-width: 75%; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name .ss-uploadfield-item-status.ui-state-error-text { color: #f00; font-weight: bold; width: 150px; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name .ss-uploadfield-item-status.ui-state-warning-text { color: #b7a403; }
@@ -34,7 +34,7 @@ Used in side panels and action tabs
.ss-uploadfield .ss-ui-button { display: block; float: left; margin: 0 10px 6px 0; }
.ss-uploadfield .ss-ui-button.ss-uploadfield-fromcomputer { position: relative; overflow: hidden; }
.ss-uploadfield .ss-uploadfield-files { margin: 0; padding: 0; overflow: auto; position: relative; }
-.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item, .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item.ui-state-error { border: 0; border-bottom: 1px solid #b3b3b3; background: none; color: #444; }
+.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item, .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item.ui-state-error { border: 0; border-bottom: 1px solid #b3b3b3; background: none; color: #66727d; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item:last-child, .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item.ui-state-error:last-child { border-bottom: 0; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-actions { min-height: 28px; overflow: hidden; margin: 6px 0 -6px 0; position: relative; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-progress { position: absolute; left: 0; right: 42px; width: auto; margin: 11px 0 0; height: 15px; }
@@ -49,7 +49,7 @@ Used in side panels and action tabs
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform { /* don't use display none, for it will break jQuery('iframe').contents().height() */ height: 0; overflow: hidden; clear: both; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform.loading { width: 100%; height: 22px; margin: 15px 0 0; background: url(../admin/images/spinner.gif) no-repeat 50% 0; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform.loading iframe { /* Old IE needs this or it'll give the iframe a white background, covering the spinner */ padding-top: 0; margin-top: 22px; border: none; }
-.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform iframe { margin-top: 8px; padding-top: 8px; border-top: 1px solid #d0d3d5; width: 100%; }
+.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform iframe { margin-top: 8px; padding-top: 8px; border-top: 1px solid #D2D5D8; width: 100%; }
.ss-uploadfield .ss-uploadfield-addfile.borderTop { border-top: 1px solid #b3b3b3; }
.ss-upload .clear { clear: both; }
@@ -59,3 +59,5 @@ Used in side panels and action tabs
/** ---------------------------------------------------- "@2x" media query ---------------------------------------------------- */
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2 / 1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform.loading { background-image: url(../admin/images/spinner@2x.gif); background-size: 43px 43px; }
.ss-upload .loader { background-image: url(../admin/images/spinner@2x.gif); background-size: 43px 43px; } }
+
+/*# sourceMappingURL=UploadField.css.map */
diff --git a/css/UploadField.css.map b/css/UploadField.css.map
new file mode 100644
index 000000000..7f1f947ea
--- /dev/null
+++ b/css/UploadField.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "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",
+"sources": ["../scss/UploadField.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_border-radius.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_images.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_box-shadow.scss","../admin/scss/themes/_default.scss","../admin/scss/_mixins.scss"],
+"names": [],
+"file": "UploadField.css"
+}
\ No newline at end of file
diff --git a/css/debug.css b/css/debug.css
index 0ef85d85b..16bf0b42a 100644
--- a/css/debug.css
+++ b/css/debug.css
@@ -33,3 +33,5 @@ fieldset { border: 1px solid #b2b2b2; margin-bottom: 18px; padding: 17px; }
.pass { margin-top: 18px; padding: 2px 20px 2px 40px; color: #006600; background: #E2F9E3; border: 1px solid #8DD38D; border-radius: 4px; }
.fail { margin-top: 18px; padding: 2px 20px 2px 40px; color: #C80700; background: #FFE9E9; border: 1px solid #C80700; border-radius: 4px; }
+
+/*# sourceMappingURL=debug.css.map */
diff --git a/css/debug.css.map b/css/debug.css.map
new file mode 100644
index 000000000..f05d5a12d
--- /dev/null
+++ b/css/debug.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAEA,IAAK,GACH,UAAU,EAAE,eAAe,EAC3B,MAAM,EAAC,CAAC,EACR,UAAU,EAAE,MAAM,EAClB,OAAO,EAAC,CAAC,EACT,WAAW,EAAE,0BAA0B;;AAGzC,KAAM,GACL,MAAM,EAAC,SAAS,EAChB,OAAO,EAAE,IAAI,EACb,gBAAgB,EAAE,OAAO,EACzB,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,IAAI,EACjB,KAAK,EAAE,IAAI,ECwDN,gBAAY,EAAE,ioBAAgC,EA2B9C,eAAe,EAAE,IAAI,EA3BrB,gBAAY,EAAE,kJAAgC,EAA9C,gBAAY,EAAE,gEAAgC,EAA9C,gBAAY,EAAE,mEAAgC,EAE9C,gBAAY,EAAE,2DAAO,EDnD1B,OAAO,EAAE,IAAI;AACb,QAAG,GACF,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,IAAI,EACX,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,aAAyB,EACtC,WAAW,EAAE,IAAI,EAEjB,UAAU,EAAE,uDAAuD;AAGpE,QAAG,GACF,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,IAAI,EACjB,WAAW,EAAE,MAAM;AAEpB,OAAE,GACD,MAAM,EAAE,CAAC,EACT,SAAS,EAAE,IAAI,EACf,KAAK,EAAE,IAAI;AAGZ,OAAE,GACD,KAAK,EAAE,IAAI,EACX,WAAW,EAAE,IAAI,EACjB,eAAe,EAAE,IAAI;AAErB,6BACS,GACR,KAAK,EAAE,IAAI,EACX,eAAe,EAAE,SAAS;;AAO7B,OAAQ,GACP,MAAM,EAAE,CAAC,EACT,aAAa,EAAE,iBAAiB,EAChC,MAAM,EAAE,IAAI,EACZ,gBAAgB,EAAE,OAAO,EACzB,OAAO,EAAE,aAAa;;AAGvB,wBAES,GACR,OAAO,EAAC,QAAQ,EAEhB,UAAU,EAAE,eAAe,EAE3B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,IAAI;AACb,iCAAG,GACF,SAAS,EAAC,IAAI,EACd,MAAM,EAAC,KAAK;;AAId,CAAE,GACD,KAAK,EAAE,IAAI;AAEX,OAAQ,GACP,KAAK,EAAE,IAAI;AAGZ,QAAS,GACR,KAAK,EAAE,IAAI;;AAIb,CAAE,GACD,aAAa,EAAE,GAAG;;AAGnB,GAAI,GACH,aAAa,EAAE,IAAI,EACnB,gBAAgB,EAAE,OAAO,EACzB,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,6BAAyB,EACjC,KAAK,EAAE,IAAI,EACX,OAAO,EAAE,IAAI,EACb,QAAQ,EAAE,IAAI,EEgPb,kBAAwC,EF9OlB,GAAG,EE8OzB,qBAAwC,EC9Sb,GAAuB,ED8SlD,aAAwC,EF9OlB,GAAG,EE8OzB,eAAwC,EEnT/B,mCAAkD,EFmT3D,kBAAwC,EEnT/B,mCAAkD,EFmT3D,UAAwC,EEnT/B,mCAAkD;AJwE3D,QAAK,GACL,KAAK,EAAC,IAAI;AAEX,UAAO,GACN,KAAK,EAAC,IAAI;;AAIZ,EAAG,GACF,MAAM,EAAE,UAAU;;AAGnB,EAAG,GACF,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,IAAI,EACX,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,IAAI;;AAGlB,EAAG,GACF,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,UAAU;;AAGpB,QAAS,GACR,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,IAAI,EACnB,OAAO,EAAE,IAAI;;AAGd,KAAM,GACL,UAAU,EAAC,IAAI,EAAE,OAAO,EAAC,iBAAiB,EAAE,KAAK,EAAC,OAAO,EAAE,UAAU,EAAC,OAAO,EAAE,MAAM,EAAE,iBAAiB,EACxG,aAAa,EAAC,GAAG;;AAGlB,KAAM,GACL,UAAU,EAAC,IAAI,EAAE,OAAO,EAAC,iBAAiB,EAAE,KAAK,EAAC,OAAO,EAAE,UAAU,EAAC,OAAO,EAC7E,MAAM,EAAC,iBAAiB,EAAE,aAAa,EAAC,GAAG",
+"sources": ["../scss/debug.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_images.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_border-radius.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_box-shadow.scss"],
+"names": [],
+"file": "debug.css"
+}
\ No newline at end of file
diff --git a/dev/Debug.php b/dev/Debug.php
index f063090ee..3c7480775 100644
--- a/dev/Debug.php
+++ b/dev/Debug.php
@@ -524,7 +524,8 @@ function exceptionHandler($exception) {
$file = $exception->getFile();
$line = $exception->getLine();
$context = $exception->getTrace();
- return Debug::fatalHandler($errno, $message, $file, $line, $context);
+ Debug::fatalHandler($errno, $message, $file, $line, $context);
+ exit(1);
}
/**
@@ -558,6 +559,7 @@ function errorHandler($errno, $errstr, $errfile, $errline) {
case E_CORE_ERROR:
case E_USER_ERROR:
default:
- return Debug::fatalHandler($errno, $errstr, $errfile, $errline, debug_backtrace());
+ Debug::fatalHandler($errno, $errstr, $errfile, $errline, debug_backtrace());
+ exit(1);
}
}
diff --git a/dev/Deprecation.php b/dev/Deprecation.php
index de70ab04b..b31aefdce 100644
--- a/dev/Deprecation.php
+++ b/dev/Deprecation.php
@@ -42,6 +42,19 @@ class Deprecation {
*/
protected static $version;
+ /**
+ * Override whether deprecation is enabled. If null, then fallback to
+ * SS_DEPRECATION_ENABLED, and then true if not defined.
+ *
+ * Deprecation is only available on dev.
+ *
+ * Must be configured outside of the config API, as deprecation API
+ * must be available before this to avoid infinite loops.
+ *
+ * @var boolean|null
+ */
+ protected static $enabled = null;
+
/**
*
* @var array
@@ -116,20 +129,47 @@ class Deprecation {
return $called['function'];
}
}
+
+ /**
+ * Determine if deprecation notices should be displayed
+ *
+ * @return bool
+ */
+ public static function get_enabled() {
+ // Deprecation is only available on dev
+ if(!Director::isDev()) {
+ return false;
+ }
+ if(isset(self::$enabled)) {
+ return self::$enabled;
+ }
+ if(defined('SS_DEPRECATION_ENABLED')) {
+ return SS_DEPRECATION_ENABLED;
+ }
+ return true;
+ }
+
+ /**
+ * Toggle on or off deprecation notices. Will be ignored in live.
+ *
+ * @param bool $enabled
+ */
+ public static function set_enabled($enabled) {
+ self::$enabled = $enabled;
+ }
/**
* Raise a notice indicating the method is deprecated if the version passed as the second argument is greater
* than or equal to the check version set via ::notification_version
*
- * @static
- * @param $string - The notice to raise
- * @param $atVersion - The version at which this notice should start being raised
- * @param Boolean $scope - Notice relates to the method or class context its called in.
- * @return void
+ * @param string $atVersion The version at which this notice should start being raised
+ * @param string $string The notice to raise
+ * @param bool $scope Notice relates to the method or class context its called in.
*/
public static function notice($atVersion, $string = '', $scope = Deprecation::SCOPE_METHOD) {
- // Never raise deprecation notices in a live environment
- if(Director::isLive(true)) return;
+ if(!static::get_enabled()) {
+ return;
+ }
$checkVersion = self::$version;
// Getting a backtrace is slow, so we only do it if we need it
@@ -179,25 +219,27 @@ class Deprecation {
/**
* Method for when testing. Dump all the current version settings to a variable for later passing to restore
- * @return array - opaque array that should only be used to pass to ::restore_version_settings
+ *
+ * @return array Opaque array that should only be used to pass to {@see Deprecation::restore_settings()}
*/
public static function dump_settings() {
return array(
'level' => self::$notice_level,
'version' => self::$version,
- 'moduleVersions' => self::$module_version_overrides
+ 'moduleVersions' => self::$module_version_overrides,
+ 'enabled' => self::$enabled,
);
}
/**
* Method for when testing. Restore all the current version settings from a variable
- * @static
- * @param $settings array - An array as returned by ::dump_version_settings
- * @return void
+ *
+ * @param $settings array An array as returned by {@see Deprecation::dump_settings()}
*/
public static function restore_settings($settings) {
self::$notice_level = $settings['level'];
self::$version = $settings['version'];
self::$module_version_overrides = $settings['moduleVersions'];
+ self::$enabled = $settings['enabled'];
}
}
diff --git a/dev/LogEmailWriter.php b/dev/LogEmailWriter.php
index 55ece9873..6a4d81b17 100644
--- a/dev/LogEmailWriter.php
+++ b/dev/LogEmailWriter.php
@@ -31,18 +31,18 @@ class SS_LogEmailWriter extends Zend_Log_Writer_Abstract {
}
/**
- * @deprecated 3.2 Use the "SS_LogEmailWriter.send_from" config setting instead
+ * @deprecated 4.0 Use the "SS_LogEmailWriter.send_from" config setting instead
*/
public static function set_send_from($address) {
- Deprecation::notice('3.2', 'Use the "SS_LogEmailWriter.send_from" config setting instead');
+ Deprecation::notice('4.0', 'Use the "SS_LogEmailWriter.send_from" config setting instead');
Config::inst()->update('SS_LogEmailWriter', 'send_from', $address);
}
/**
- * @deprecated 3.2 Use the "SS_LogEmailWriter.send_from" config setting instead
+ * @deprecated 4.0 Use the "SS_LogEmailWriter.send_from" config setting instead
*/
public static function get_send_from() {
- Deprecation::notice('3.2', 'Use the "SS_LogEmailWriter.send_from" config setting instead');
+ Deprecation::notice('4.0', 'Use the "SS_LogEmailWriter.send_from" config setting instead');
return Config::inst()->get('SS_LogEmailWriter', 'send_from');
}
diff --git a/dev/MigrationTask.php b/dev/MigrationTask.php
index 1001465b2..276b62fd8 100644
--- a/dev/MigrationTask.php
+++ b/dev/MigrationTask.php
@@ -16,7 +16,7 @@
* protected $description = "Description"; // description of what it does
*
* public function run($request) {
- * if ($request->param('Direction') == 'down') {
+ * if ($request->getVar('Direction') == 'down') {
* $this->down();
* } else {
* $this->up();
diff --git a/dev/SapphireTest.php b/dev/SapphireTest.php
index c659c4bf2..5519e0f76 100644
--- a/dev/SapphireTest.php
+++ b/dev/SapphireTest.php
@@ -5,12 +5,12 @@ require_once 'TestRunner.php';
* Test case class for the Sapphire framework.
* Sapphire unit testing is based on PHPUnit, but provides a number of hooks into our data model that make it easier
* to work with.
- *
+ *
* @package framework
* @subpackage testing
*/
class SapphireTest extends PHPUnit_Framework_TestCase {
-
+
/** @config */
private static $dependencies = array(
'fixtureFactory' => '%$FixtureFactory',
@@ -21,7 +21,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* If passed as an array, multiple fixture files will be loaded.
* Please note that you won't be able to refer with "=>" notation
* between the fixtures, they act independent of each other.
- *
+ *
* @var string|array
*/
protected static $fixture_file = null;
@@ -30,53 +30,57 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* @var FixtureFactory
*/
protected $fixtureFactory;
-
+
/**
* @var bool Set whether to include this test in the TestRunner or to skip this.
*/
protected $skipTest = false;
-
+
/**
* @var Boolean If set to TRUE, this will force a test database to be generated
- * in {@link setUp()}. Note that this flag is overruled by the presence of a
+ * in {@link setUp()}. Note that this flag is overruled by the presence of a
* {@link $fixture_file}, which always forces a database build.
*/
protected $usesDatabase = null;
-
+
+ /**
+ * @deprecated since version 4.0
+ */
protected $originalMailer;
+
protected $originalMemberPasswordValidator;
protected $originalRequirements;
protected $originalIsRunningTest;
protected $originalTheme;
protected $originalNestedURLsState;
protected $originalMemoryLimit;
-
+
protected $mailer;
-
+
/**
* Pointer to the manifest that isn't a test manifest
*/
protected static $regular_manifest;
-
+
/**
* @var boolean
*/
protected static $is_running_test = false;
-
+
protected static $test_class_manifest;
-
+
/**
* By default, setUp() does not require default records. Pass
* class names in here, and the require/augment default records
* function will be called on them.
*/
protected $requireDefaultRecordsFrom = array();
-
-
+
+
/**
* A list of extensions that can't be applied during the execution of this run. If they are
* applied, they will be temporarily removed and a database migration called.
- *
+ *
* The keys of the are the classes that the extensions can't be applied the extensions to, and
* the values are an array of illegal extensions on that class.
*/
@@ -86,10 +90,10 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
/**
* A list of extensions that must be applied during the execution of this run. If they are
* not applied, they will be temporarily added and a database migration called.
- *
+ *
* The keys of the are the classes to apply the extensions to, and the values are an array
* of required extensions on that class.
- *
+ *
* Example:
*
* array("MyTreeDataObject" => array("Versioned", "Hierarchy"))
@@ -97,35 +101,35 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
*/
protected $requiredExtensions = array(
);
-
+
/**
* By default, the test database won't contain any DataObjects that have the interface TestOnly.
* This variable lets you define additional TestOnly DataObjects to set up for this test.
* Set it to an array of DataObject subclass names.
*/
protected $extraDataObjects = array();
-
+
/**
* We need to disabling backing up of globals to avoid overriding
* the few globals SilverStripe relies on, like $lang for the i18n subsystem.
- *
+ *
* @see http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html
*/
protected $backupGlobals = FALSE;
- /**
+ /**
* Helper arrays for illegalExtensions/requiredExtensions code
*/
private $extensionsToReapply = array(), $extensionsToRemove = array();
-
+
/**
* Determines if unit tests are currently run (via {@link TestRunner}).
* This is used as a cheap replacement for fully mockable state
* in certain contiditions (e.g. access checks).
* Caution: When set to FALSE, certain controllers might bypass
* access checks, so this is a very security sensitive setting.
- *
+ *
* @return boolean
*/
public static function is_running_test() {
@@ -133,7 +137,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
}
public static function set_is_running_test($bool) {
- self::$is_running_test = $bool;
+ self::$is_running_test = $bool;
}
/**
@@ -157,20 +161,31 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
return static::$fixture_file;
}
+ /**
+ * @var array $fixtures Array of {@link YamlFixture} instances
+ * @deprecated 3.1 Use $fixtureFactory instad
+ */
+ protected $fixtures = array();
+
protected $model;
public function setUp() {
+
+ //nest config and injector for each test so they are effectively sandboxed per test
+ Config::nest();
+ Injector::nest();
+
// We cannot run the tests on this abstract class.
if(get_class($this) == "SapphireTest") $this->skipTest = true;
-
+
if($this->skipTest) {
$this->markTestSkipped(sprintf(
'Skipping %s ', get_class($this)
));
-
+
return;
}
-
+
// Mark test as being run
$this->originalIsRunningTest = self::$is_running_test;
self::$is_running_test = true;
@@ -179,16 +194,16 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
i18n::set_locale(i18n::default_locale());
i18n::config()->date_format = null;
i18n::config()->time_format = null;
-
+
// Set default timezone consistently to avoid NZ-specific dependencies
date_default_timezone_set('UTC');
-
+
// Remove password validation
$this->originalMemberPasswordValidator = Member::password_validator();
$this->originalRequirements = Requirements::backend();
Member::set_password_validator(null);
Config::inst()->update('Cookie', 'report_errors', false);
-
+
if(class_exists('RootURLController')) RootURLController::reset();
if(class_exists('Translatable')) Translatable::reset();
Versioned::reset();
@@ -210,9 +225,9 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
// Set up email
$this->originalMailer = Email::mailer();
$this->mailer = new TestMailer();
- Email::set_mailer($this->mailer);
+ Injector::inst()->registerService($this->mailer, 'Mailer');
Config::inst()->remove('Email', 'send_all_emails_to');
-
+
// Todo: this could be a special test model
$this->model = DataModel::inst();
@@ -227,9 +242,9 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
}
singleton('DataObject')->flushCache();
-
+
self::empty_temp_db();
-
+
foreach($this->requireDefaultRecordsFrom as $className) {
$instance = singleton($className);
if (method_exists($instance, 'requireDefaultRecords')) $instance->requireDefaultRecords();
@@ -244,14 +259,14 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
foreach($fixtureFiles as $fixtureFilePath) {
// Support fixture paths relative to the test class, rather than relative to webroot
// String checking is faster than file_exists() calls.
- $isRelativeToFile = (strpos('/', $fixtureFilePath) === false
+ $isRelativeToFile = (strpos('/', $fixtureFilePath) === false
|| preg_match('/^\.\./', $fixtureFilePath));
if($isRelativeToFile) {
$resolvedPath = realpath($pathForClass . '/' . $fixtureFilePath);
if($resolvedPath) $fixtureFilePath = $resolvedPath;
}
-
+
$fixture = Injector::inst()->create('YamlFixture', $fixtureFilePath);
$fixture->writeInto($this->getFixtureFactory());
$this->fixtures[] = $fixture;
@@ -261,20 +276,20 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$i++;
}
}
-
+
$this->logInWithPermission("ADMIN");
}
-
+
// Preserve memory settings
$this->originalMemoryLimit = ini_get('memory_limit');
-
+
// turn off template debugging
Config::inst()->update('SSViewer', 'source_file_comments', false);
-
+
// Clear requirements
Requirements::clear();
}
-
+
/**
* Called once per test case ({@link SapphireTest} subclass).
* This is different to {@link setUp()}, which gets called once
@@ -284,6 +299,10 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* for tearing down the state again.
*/
public function setUpOnce() {
+
+ //nest config and injector for each suite so they are effectively sandboxed
+ Config::nest();
+ Injector::nest();
$isAltered = false;
if(!Director::isDev()) {
@@ -314,46 +333,34 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
}
}
}
-
+
// If we have made changes to the extensions present, then migrate the database schema.
if($isAltered || $this->extensionsToReapply || $this->extensionsToRemove || $this->extraDataObjects) {
if(!self::using_temp_db()) self::create_temp_db();
$this->resetDBSchema(true);
}
- // clear singletons, they're caching old extension info
+ // clear singletons, they're caching old extension info
// which is used in DatabaseAdmin->doBuild()
Injector::inst()->unregisterAllObjects();
// Set default timezone consistently to avoid NZ-specific dependencies
date_default_timezone_set('UTC');
}
-
+
/**
* tearDown method that's called once per test class rather once per test method.
*/
public function tearDownOnce() {
- // If we have made changes to the extensions present, then migrate the database schema.
- if($this->extensionsToReapply || $this->extensionsToRemove) {
- // Remove extensions added for testing
- foreach($this->extensionsToRemove as $class => $extensions) {
- foreach($extensions as $extension) {
- $class::remove_extension($extension);
- }
- }
+ //unnest injector / config now that the test suite is over
+ // this will reset all the extensions on the object too (see setUpOnce)
+ Injector::unnest();
+ Config::unnest();
- // Reapply ones removed
- foreach($this->extensionsToReapply as $class => $extensions) {
- foreach($extensions as $extension) {
- $class::add_extension($extension);
- }
- }
- }
-
- if($this->extensionsToReapply || $this->extensionsToRemove || $this->extraDataObjects) {
+ if(!empty($this->extensionsToReapply) || !empty($this->extensionsToRemove) || !empty($this->extraDataObjects)) {
$this->resetDBSchema();
}
}
-
+
/**
* @return FixtureFactory
*/
@@ -366,10 +373,10 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$this->fixtureFactory = $factory;
return $this;
}
-
+
/**
* Get the ID of an object from the fixture.
- *
+ *
* @param $className The data class, as specified in your fixture file. Parent classes won't work
* @param $identifier The identifier string, as provided in your fixture file
* @return int
@@ -415,12 +422,12 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
"Couldn't find object '%s' (class: %s)",
$identifier,
$className
- ), E_USER_ERROR);
+ ), E_USER_ERROR);
}
-
+
return $obj;
}
-
+
/**
* Load a YAML fixture file into the database.
* Once loaded, you can use idFromFixture() and objFromFixture() to get items from the fixture.
@@ -433,18 +440,18 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$fixture->writeInto($this->getFixtureFactory());
$this->fixtures[] = $fixture;
}
-
+
/**
* Clear all fixtures which were previously loaded through
- * {@link loadFixture()}
+ * {@link loadFixture()}
*/
public function clearFixtures() {
$this->getFixtureFactory()->clear();
}
-
+
/**
* Useful for writing unit tests without hardcoding folder structures.
- *
+ *
* @return String Absolute path to current class.
*/
protected function getCurrentAbsolutePath() {
@@ -452,7 +459,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
if(!$filename) throw new LogicException("getItemPath returned null for " . get_class($this));
return dirname($filename);
}
-
+
/**
* @return String File path relative to webroot
*/
@@ -462,26 +469,23 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
if(substr($path,0,strlen($base)) == $base) $path = preg_replace('/^\/*/', '', substr($path,strlen($base)));
return $path;
}
-
+
public function tearDown() {
// Preserve memory settings
ini_set('memory_limit', ($this->originalMemoryLimit) ? $this->originalMemoryLimit : -1);
// Restore email configuration
- if($this->originalMailer) {
- Email::set_mailer($this->originalMailer);
- $this->originalMailer = null;
- }
- $this->mailer = null;
+ $this->originalMailer = null;
+ $this->mailer = null;
// Restore password validation
if($this->originalMemberPasswordValidator) {
- Member::set_password_validator($this->originalMemberPasswordValidator);
+ Member::set_password_validator($this->originalMemberPasswordValidator);
}
-
+
// Restore requirements
if($this->originalRequirements) {
- Requirements::set_backend($this->originalRequirements);
+ Requirements::set_backend($this->originalRequirements);
}
// Mark test as no longer being run - we use originalIsRunningTest to allow for nested SapphireTest calls
@@ -490,15 +494,18 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
// Reset mocked datetime
SS_Datetime::clear_mock_now();
-
+
// Stop the redirection that might have been requested in the test.
- // Note: Ideally a clean Controller should be created for each test.
+ // Note: Ideally a clean Controller should be created for each test.
// Now all tests executed in a batch share the same controller.
$controller = Controller::has_curr() ? Controller::curr() : null;
if ( $controller && $controller->response && $controller->response->getHeader('Location') ) {
$controller->response->setStatusCode(200);
$controller->response->removeHeader('Location');
}
+ //unnest injector / config now that tests are over
+ Injector::unnest();
+ Config::unnest();
}
public static function assertContains(
@@ -545,7 +552,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
public function findEmail($to, $from = null, $subject = null, $content = null) {
return $this->mailer->findEmail($to, $from, $subject, $content);
}
-
+
/**
* Assert that the matching email was sent since the last call to clearEmails()
* All of the parameters can either be a string, or, if they start with "/", a PREG-compatible regular expression.
@@ -577,7 +584,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
/**
* Assert that the given {@link SS_List} includes DataObjects matching the given key-value
* pairs. Each match must correspond to 1 distinct record.
- *
+ *
* @param $matches The patterns to match. Each pattern is a map of key-value pairs. You can
* either pass a single pattern or an array of patterns.
* @param $dataObjectSet The {@link SS_List} to test.
@@ -585,19 +592,19 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* Examples
* --------
* Check that $members includes an entry with Email = sam@example.com:
- * $this->assertDOSContains(array('Email' => '...@example.com'), $members);
- *
- * Check that $members includes entries with Email = sam@example.com and with
+ * $this->assertDOSContains(array('Email' => '...@example.com'), $members);
+ *
+ * Check that $members includes entries with Email = sam@example.com and with
* Email = ingo@example.com:
- * $this->assertDOSContains(array(
- * array('Email' => '...@example.com'),
- * array('Email' => 'i...@example.com'),
- * ), $members);
+ * $this->assertDOSContains(array(
+ * array('Email' => '...@example.com'),
+ * array('Email' => 'i...@example.com'),
+ * ), $members);
*/
public function assertDOSContains($matches, $dataObjectSet) {
$extracted = array();
foreach($dataObjectSet as $item) $extracted[] = $item->toMap();
-
+
foreach($matches as $match) {
$matched = false;
foreach($extracted as $i => $item) {
@@ -613,35 +620,35 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$this->assertTrue(
$matched,
"Failed asserting that the SS_List contains an item matching "
- . var_export($match, true) . "\n\nIn the following SS_List:\n"
+ . var_export($match, true) . "\n\nIn the following SS_List:\n"
. $this->DOSSummaryForMatch($dataObjectSet, $match)
);
}
- }
-
+ }
+
/**
- * Assert that the given {@link SS_List} includes only DataObjects matching the given
+ * Assert that the given {@link SS_List} includes only DataObjects matching the given
* key-value pairs. Each match must correspond to 1 distinct record.
- *
+ *
* @param $matches The patterns to match. Each pattern is a map of key-value pairs. You can
* either pass a single pattern or an array of patterns.
* @param $dataObjectSet The {@link SS_List} to test.
*
* Example
* --------
- * Check that *only* the entries Sam Minnee and Ingo Schommer exist in $members. Order doesn't
+ * Check that *only* the entries Sam Minnee and Ingo Schommer exist in $members. Order doesn't
* matter:
- * $this->assertDOSEquals(array(
- * array('FirstName' =>'Sam', 'Surname' => 'Minnee'),
- * array('FirstName' => 'Ingo', 'Surname' => 'Schommer'),
- * ), $members);
+ * $this->assertDOSEquals(array(
+ * array('FirstName' =>'Sam', 'Surname' => 'Minnee'),
+ * array('FirstName' => 'Ingo', 'Surname' => 'Schommer'),
+ * ), $members);
*/
public function assertDOSEquals($matches, $dataObjectSet) {
if(!$dataObjectSet) return false;
-
+
$extracted = array();
foreach($dataObjectSet as $item) $extracted[] = $item->toMap();
-
+
foreach($matches as $match) {
$matched = false;
foreach($extracted as $i => $item) {
@@ -657,11 +664,11 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$this->assertTrue(
$matched,
"Failed asserting that the SS_List contains an item matching "
- . var_export($match, true) . "\n\nIn the following SS_List:\n"
+ . var_export($match, true) . "\n\nIn the following SS_List:\n"
. $this->DOSSummaryForMatch($dataObjectSet, $match)
);
}
-
+
// If we have leftovers than the DOS has extra data that shouldn't be there
$this->assertTrue(
(count($extracted) == 0),
@@ -669,19 +676,19 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
"Failed asserting that the SS_List contained only the given items, the "
. "following items were left over:\n" . var_export($extracted, true)
);
- }
+ }
/**
* Assert that the every record in the given {@link SS_List} matches the given key-value
* pairs.
- *
+ *
* @param $match The pattern to match. The pattern is a map of key-value pairs.
* @param $dataObjectSet The {@link SS_List} to test.
*
* Example
* --------
* Check that every entry in $members has a Status of 'Active':
- * $this->assertDOSAllMatch(array('Status' => 'Active'), $members);
+ * $this->assertDOSAllMatch(array('Status' => 'Active'), $members);
*/
public function assertDOSAllMatch($match, $dataObjectSet) {
$extracted = array();
@@ -690,7 +697,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
foreach($extracted as $i => $item) {
$this->assertTrue(
$this->dataObjectArrayMatch($item, $match),
- "Failed asserting that the the following item matched "
+ "Failed asserting that the the following item matched "
. var_export($match, true) . ": " . var_export($item, true)
);
}
@@ -763,7 +770,6 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$this->assertNotContains($needleSQL, $haystackSQL, $message, $ignoreCase, $checkForObjectIdentity);
}
-
/**
* Helper function for the DOS matchers
*/
@@ -792,14 +798,14 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
return $dbConn && (substr($dbConn->getSelectedDatabase(), 0, strlen($prefix) + 5)
== strtolower(sprintf('%stmpdb', $prefix)));
}
-
+
public static function kill_temp_db() {
// Delete our temporary database
if(self::using_temp_db()) {
$dbConn = DB::get_conn();
$dbName = $dbConn->getSelectedDatabase();
if($dbName && DB::get_conn()->databaseExists($dbName)) {
- // Some DataExtensions keep a static cache of information that needs to
+ // Some DataExtensions keep a static cache of information that needs to
// be reset whenever the database is killed
foreach(ClassInfo::subclassesFor('DataExtension') as $class) {
$toCall = array($class, 'on_db_reset');
@@ -811,15 +817,15 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
}
}
}
-
+
/**
* Remove all content from the temporary database.
*/
public static function empty_temp_db() {
if(self::using_temp_db()) {
DB::get_conn()->clearAllData();
-
- // Some DataExtensions keep a static cache of information that needs to
+
+ // Some DataExtensions keep a static cache of information that needs to
// be reset whenever the database is cleaned out
$classes = array_merge(ClassInfo::subclassesFor('DataExtension'), ClassInfo::subclassesFor('DataObject'));
foreach($classes as $class) {
@@ -828,7 +834,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
}
}
}
-
+
public static function create_temp_db() {
// Disable PHPUnit error handling
restore_error_handler();
@@ -848,13 +854,13 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$st = Injector::inst()->create('SapphireTest');
$st->resetDBSchema();
-
+
// Reinstate PHPUnit error handling
set_error_handler(array('PHPUnit_Util_ErrorHandler', 'handleError'));
-
+
return $dbname;
}
-
+
public static function delete_all_temp_dbs() {
$prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_';
foreach(DB::get_schema()->databaseList() as $dbName) {
@@ -869,7 +875,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
}
}
}
-
+
/**
* Reset the testing database's schema.
* @param $includeExtraDataObjects If true, the extraDataObjects tables will also be included
@@ -909,7 +915,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
singleton('DataObject')->flushCache();
}
}
-
+
/**
* Create a member and group with the given permission code, and log in with it.
* Returns the member ID.
@@ -924,25 +930,25 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$permission->Code = $permCode;
$permission->write();
$group->Permissions()->add($permission);
-
+
$member = DataObject::get_one('Member', array(
'"Member"."Email"' => "$permCode@example.org"
));
if(!$member) $member = Injector::inst()->create('Member');
-
+
$member->FirstName = $permCode;
$member->Surname = "User";
$member->Email = "$permCode@example.org";
$member->write();
$group->Members()->add($member);
-
+
$this->cache_generatedMembers[$permCode] = $member;
}
-
+
$this->cache_generatedMembers[$permCode]->logIn();
return $this->cache_generatedMembers[$permCode]->ID;
}
-
+
/**
* Cache for logInWithPermission()
*/
diff --git a/dev/install/install.php5 b/dev/install/install.php5
index 9491e354f..91b5f4b06 100755
--- a/dev/install/install.php5
+++ b/dev/install/install.php5
@@ -415,6 +415,13 @@ class InstallRequirements {
"Is the mysite/_config.php file writeable?",
null
));
+
+ $this->requireWriteable('mysite/_config/config.yml', array(
+ "File permissions",
+ "Is the mysite/_config/config.yml file writeable?",
+ null
+ ));
+
if(!$this->checkModuleExists('cms')) {
$this->requireWriteable('mysite/code/RootURLController.php', array(
"File permissions",
diff --git a/docs/en/00_Getting_Started/00_Server_Requirements.md b/docs/en/00_Getting_Started/00_Server_Requirements.md
index a45bff786..e4dcdfd82 100644
--- a/docs/en/00_Getting_Started/00_Server_Requirements.md
+++ b/docs/en/00_Getting_Started/00_Server_Requirements.md
@@ -8,7 +8,7 @@ Our web-based [PHP installer](installation/) can check if you meet the requireme
## Web server software requirements
- * PHP 5.3.2+
+ * PHP 5.3.3+
* We recommend using a PHP accelerator or opcode cache, such as [xcache](http://xcache.lighttpd.net/) or [WinCache](http://www.iis.net/download/wincacheforphp).
* Allocate at least 48MB of memory to each PHP process. (SilverStripe can be resource hungry for some intensive operations.)
* Required modules: dom, gd2, fileinfo, hash, iconv, mbstring, mysqli (or other database driver), session, simplexml, tokenizer, xml.
diff --git a/docs/en/00_Getting_Started/03_Environment_Management.md b/docs/en/00_Getting_Started/03_Environment_Management.md
index b3f50ad7e..e915a003b 100644
--- a/docs/en/00_Getting_Started/03_Environment_Management.md
+++ b/docs/en/00_Getting_Started/03_Environment_Management.md
@@ -116,6 +116,7 @@ This is my `_ss_environment.php` file. I have it placed in `/var`, as each of th
| `SS_DATABASE_TIMEZONE`| Set the database timezone to something other than the system timezone.
| `SS_DATABASE_NAME` | Set the database name. Assumes the `$database` global variable in your config is missing or empty. |
| `SS_DATABASE_CHOOSE_NAME`| Boolean/Int. If defined, then the system will choose a default database name for you if one isn't give in the $database variable. The database name will be "SS_" followed by the name of the folder into which you have installed SilverStripe. If this is enabled, it means that the phpinstaller will work out of the box without the installer needing to alter any files. This helps prevent accidental changes to the environment. If `SS_DATABASE_CHOOSE_NAME` is an integer greater than one, then an ancestor folder will be used for the database name. This is handy for a site that's hosted from /sites/examplesite/www or /buildbot/allmodules-2.3/build. If it's 2, the parent folder will be chosen; if it's 3 the grandparent, and so on.|
+| `SS_DEPRECATION_ENABLED` | Enable deprecation notices for this environment.|
| `SS_ENVIRONMENT_TYPE`| The environment type: dev, test or live.|
| `SS_DEFAULT_ADMIN_USERNAME`| The username of the default admin. This is a user with administrative privileges.|
| `SS_DEFAULT_ADMIN_PASSWORD`| The password of the default admin. This will not be stored in the database.|
diff --git a/docs/en/00_Getting_Started/index.md b/docs/en/00_Getting_Started/index.md
index bd891249d..5cb43f81d 100644
--- a/docs/en/00_Getting_Started/index.md
+++ b/docs/en/00_Getting_Started/index.md
@@ -9,8 +9,8 @@ lets you install and upgrade SilverStripe and its modules. Although installing
Other ways to get SilverStripe:
- * If you just want to get the code as quickly as possible, you can [download SilverStripe from our website](http://silverstripe.org/download).
- * If you already have an installed version of SilverStripe, and you haven't used Composer to get it, please see our [upgrading](upgrading) guide. Note that [Composer](composer) provides its own tools for upgrading.
+ * If you just want to get the code as quickly as possible, you can [download SilverStripe from our website](http://www.silverstripe.org/software/download/).
+ * If you already have an installed version of SilverStripe, and you haven't used Composer to get it, please see our [upgrading](/upgrading) guide. Note that [Composer](composer) provides its own tools for upgrading.
## Setting up a server
@@ -18,25 +18,25 @@ Other ways to get SilverStripe:
To run SilverStripe on Linux/Unix, set up one of the following web servers:
-* [Install using Apache](webserver) - our preferred platform
-* [Install using Lighttpd](lighttpd) - fast, but a bit tricker to get going
-* [Install using Nginx](nginx) - Super fast at serving static files. Great for large traffic sites.
-* [Install using nginx and HHVM](nginx-hhvm) - nginx and [HHVM](http://hhvm.com/) as a faster alternative to PHP
+* [Install using Apache](installation) - our preferred platform
+* [Install using Lighttpd](installation/how_to/configure_lighttpd) - fast, but a bit trickier to get going
+* [Install using Nginx](installation/how_to/configure_nginx) - Super fast at serving static files. Great for large traffic sites.
+* [Install using nginx and HHVM](installation/how_to/setup_nginx_and_hhvm) - nginx and [HHVM](http://hhvm.com/) as a faster alternative to PHP.
### Windows
-The most straightforward way to get SilverStripe running on Windows is with the [Microsoft Web Platform installer](windows-pi). You can skip the "getting the code" step.
+The most straightforward way to get SilverStripe running on Windows is with the [Microsoft Web Platform installer](installation/other_installation_options/windows_platform_installer). You can skip the "getting the code" step.
For more flexibility, you can set up either of the following web servers, and use Composer to get the code:
- * [Install using IIS](windows-manual-iis)
- * [Install using Apache/WAMP](windows-wamp)
+ * [Install using IIS](installation/other_installation_options/windows_iis7)
+ * [Install using Apache/WAMP](installation/windows)
### Mac OS X
Mac OS X comes with a built-in webserver, but there are a number of other options:
- * [Install using MAMP](mac-osx)
+ * [Install using MAMP](installation/mac_osx)
* [Install using Homebrew](installation/other_installation_options/mac_osx_homebrew)
### Virtual Machines through Vagrant
@@ -61,10 +61,9 @@ ready for download or installation on a cloud platform.
## Troubleshooting
-If you run into trouble, see [common-problems](common-problems) or post to the
-[SilverStripe forums](http://silverstripe.com/silverstripe-forum/).
+If you run into trouble, see [common-problems](installation/common_problems) or post to the
+[SilverStripe forums](http://silverstripe.org/community/forums/).
## Related
- * [Module installation](../topics/modules)
- * [Suggested web hosts](http://doc.silverstripe.org/old/suggested-web-hosts)
+ * [Module installation](/developer_guides/extending/modules)
diff --git a/docs/en/01_Tutorials/index.md b/docs/en/01_Tutorials/index.md
index 8403c74e9..525dd3bcd 100644
--- a/docs/en/01_Tutorials/index.md
+++ b/docs/en/01_Tutorials/index.md
@@ -27,6 +27,7 @@ These include video screencasts, written tutorials and code examples to get you
* [Lesson 15: Building a Search Form](http://www.silverstripe.org/learn/lessons/building-a-search-form)
* [Lesson 16: Lists and Pagination](http://www.silverstripe.org/learn/lessons/lists-and-pagination)
* [Lesson 17: Ajax Behaviour and Viewable Data](http://www.silverstripe.org/learn/lessons/ajax-behaviour-and-viewabledata)
+* [Lesson 18: Dealing with Arbitrary Template Data](http://www.silverstripe.org/learn/lessons/dealing-with-arbitrary-template-data)
## Help: If you get stuck
diff --git a/docs/en/02_Developer_Guides/01_Templates/01_Syntax.md b/docs/en/02_Developer_Guides/01_Templates/01_Syntax.md
index 2a1c54a22..5806195be 100644
--- a/docs/en/02_Developer_Guides/01_Templates/01_Syntax.md
+++ b/docs/en/02_Developer_Guides/01_Templates/01_Syntax.md
@@ -493,4 +493,4 @@ for adding notes for other developers but for things you don't want published in
## API Documentation
* [api:SSViewer]
-* [api:SS_TemplateManifest]
\ No newline at end of file
+* [api:SS_TemplateManifest]
diff --git a/docs/en/02_Developer_Guides/01_Templates/04_Rendering_Templates.md b/docs/en/02_Developer_Guides/01_Templates/04_Rendering_Templates.md
index c49b6f1eb..d61b1d9b8 100644
--- a/docs/en/02_Developer_Guides/01_Templates/04_Rendering_Templates.md
+++ b/docs/en/02_Developer_Guides/01_Templates/04_Rendering_Templates.md
@@ -80,7 +80,7 @@ does, such as `ArrayData` or `ArrayList`.
'Name' => 'John',
'Role' => 'Head Coach',
'Experience' => $experience
- ))->renderWith("AjaxTemplate");
+ )))->renderWith("AjaxTemplate");
} else {
return $this->httpError(404);
}
diff --git a/docs/en/02_Developer_Guides/05_Extending/04_Shortcodes.md b/docs/en/02_Developer_Guides/05_Extending/04_Shortcodes.md
index 42484385d..91e22794a 100644
--- a/docs/en/02_Developer_Guides/05_Extending/04_Shortcodes.md
+++ b/docs/en/02_Developer_Guides/05_Extending/04_Shortcodes.md
@@ -56,7 +56,7 @@ First we need to define a callback for the shortcode.
'MyShortCodeMethod' => 'HTMLText'
);
- public function MyShortCodeMethod($arguments, $content = null, $parser = null, $tagName) {
+ public static function MyShortCodeMethod($arguments, $content = null, $parser = null, $tagName) {
return "" . $tagName . " " . $content . "; " . count($arguments) . " arguments.";
}
}
diff --git a/docs/en/02_Developer_Guides/06_Testing/00_Unit_Testing.md b/docs/en/02_Developer_Guides/06_Testing/00_Unit_Testing.md
index 1771e640b..7afd1894c 100644
--- a/docs/en/02_Developer_Guides/06_Testing/00_Unit_Testing.md
+++ b/docs/en/02_Developer_Guides/06_Testing/00_Unit_Testing.md
@@ -182,18 +182,10 @@ end of each test.
$page->publish('Stage', 'Live');
}
- // reset configuration for the test.
- Config::nest();
+ // set custom configuration for the test.
Config::inst()->update('Foo', 'bar', 'Hello!');
}
- public function tearDown() {
- // restores the config variables
- Config::unnest();
-
- parent::tearDown();
- }
-
public function testMyMethod() {
// ..
}
@@ -223,6 +215,32 @@ individual test case.
// ..
}
}
+
+### Config and Injector Nesting
+
+A powerful feature of both [`Config`](/developer_guides/configuration/configuration/) and [`Injector`](/developer_guides/extending/injector/) is the ability to "nest" them so that you can make changes that can easily be discarded without having to manage previous values.
+
+The testing suite makes use of this to "sandbox" each of the unit tests as well as each suite to prevent leakage between tests.
+
+If you need to make changes to `Config` (or `Injector) for each test (or the whole suite) you can safely update `Config` (or `Injector`) settings in the `setUp` or `tearDown` functions.
+
+It's important to remember that the `parent::setUp();` functions will need to be called first to ensure the nesting feature works as expected.
+
+ :::php
+ function setUpOnce() {
+ parent::setUpOnce();
+ //this will remain for the whole suite and be removed for any other tests
+ Config::inst()->update('ClassName', 'var_name', 'var_value');
+ }
+
+ function testFeatureDoesAsExpected() {
+ //this will be reset to 'var_value' at the end of this test function
+ Config::inst()->update('ClassName', 'var_name', 'new_var_value');
+ }
+
+ function testAnotherFeatureDoesAsExpected() {
+ Config::inst()->get('ClassName', 'var_name'); // this will be 'var_value'
+ }
## Generating a Coverage Report
@@ -266,4 +284,4 @@ some `thirdparty/` directories add the following to the `phpunit.xml` configurat
* [api:TestRunner]
* [api:SapphireTest]
-* [api:FunctionalTest]
\ No newline at end of file
+* [api:FunctionalTest]
diff --git a/docs/en/02_Developer_Guides/08_Performance/01_Caching.md b/docs/en/02_Developer_Guides/08_Performance/01_Caching.md
index efa9020b4..9974ed7d0 100644
--- a/docs/en/02_Developer_Guides/08_Performance/01_Caching.md
+++ b/docs/en/02_Developer_Guides/08_Performance/01_Caching.md
@@ -117,14 +117,16 @@ To use this backend, you need a memcached daemon and the memcache PECL extension
'primary_memcached',
'Memcached',
array(
- 'host' => 'localhost',
- 'port' => 11211,
- 'persistent' => true,
- 'weight' => 1,
- 'timeout' => 5,
- 'retry_interval' => 15,
- 'status' => true,
- 'failure_callback' => ''
+ 'servers' => array(
+ 'host' => 'localhost',
+ 'port' => 11211,
+ 'persistent' => true,
+ 'weight' => 1,
+ 'timeout' => 5,
+ 'retry_interval' => 15,
+ 'status' => true,
+ 'failure_callback' => ''
+ )
)
);
SS_Cache::pick_backend('primary_memcached', 'any', 10);
diff --git a/docs/en/02_Developer_Guides/12_Search/02_FulltextSearch.md b/docs/en/02_Developer_Guides/12_Search/02_FulltextSearch.md
index 11fdb7c20..82153ca2d 100644
--- a/docs/en/02_Developer_Guides/12_Search/02_FulltextSearch.md
+++ b/docs/en/02_Developer_Guides/12_Search/02_FulltextSearch.md
@@ -39,6 +39,43 @@ records and cannot easily be adapted to include custom `DataObject` instances. T
default site search, have a look at those extensions and modify as required.
+### Fulltext Filter
+
+SilverStripe provides a `[api:FulltextFiler]` which you can use to perform custom fulltext searches on
+`[api:DataList]`'s.
+
+Example DataObject:
+
+ :::php
+ class SearchableDataObject extends DataObject {
+
+ private static $db = array(
+ "Title" => "Varchar(255)",
+ "Content" => "HTMLText",
+ );
+
+ private static $indexes = array(
+ 'SearchFields' => array(
+ 'type' => 'fulltext',
+ 'name' => 'SearchFields',
+ 'value' => '"Title", "Content"',
+ )
+ );
+
+ private static $create_table_options = array(
+ 'MySQLDatabase' => 'ENGINE=MyISAM'
+ );
+
+ }
+
+Performing the search:
+
+ :::php
+ SearchableDataObject::get()->filter('SearchFields:fulltext', 'search term');
+
+If your search index is a single field size, then you may also specify the search filter by the name of the
+field instead of the index.
+
## API Documentation
* [api:FulltextSearchable]
\ No newline at end of file
diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Menu.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Menu.md
index fab2624aa..5efe5f92a 100644
--- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Menu.md
+++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Menu.md
@@ -1,6 +1,6 @@
# How to customize the CMS Menu
-## Adding a administration panel
+## Adding an administration panel
Every time you add a new extension of the `[api:LeftAndMain]` class to the CMS,
SilverStripe will automatically create a new `[api:CMSMenuItem]` for it
diff --git a/docs/en/03_Upgrading/index.md b/docs/en/03_Upgrading/index.md
index e051ff8ae..825876142 100644
--- a/docs/en/03_Upgrading/index.md
+++ b/docs/en/03_Upgrading/index.md
@@ -40,7 +40,7 @@ Never update a website on the live server without trying it on a development cop
How easy will it be to update my project? It's a fair question, and sometimes a difficult one to answer.
-* "Micro" releases (x.y.z) are explicitly backwards compatible, "minor" and "major" releases can deprecate features and change APIs (see our [/misc/release-process](release process) for details)
+* "Micro" releases (x.y.z) are explicitly backwards compatible, "minor" and "major" releases can deprecate features and change APIs (see our [/misc/release-process](../contributing/release_process) for details)
* If you've made custom branches of SilverStripe core, or any thirdparty module, it's going to be harder to upgrade.
* The more custom features you have, the harder it will be to upgrade. You will have to re-test all of those features, and adapt to API changes in core.
* Customizations of a well defined type - such as custom page types or custom blog widgets - are going to be easier to upgrade than customisations that modify deep system internals like rewriting SQL queries.
diff --git a/docs/en/04_Changelogs/3.2.0.md b/docs/en/04_Changelogs/3.2.0.md
index 53f84e11d..a3206cfda 100644
--- a/docs/en/04_Changelogs/3.2.0.md
+++ b/docs/en/04_Changelogs/3.2.0.md
@@ -55,7 +55,7 @@
* Implementation of a parameterised query framework eliminating the need to manually escape variables for
use in SQL queries. This has been integrated into nearly every level of the database ORM.
* Refactor of database connectivity classes into separate components linked together through dependency injection
-* Refactor of `SQLQuery` into separate objects for each query type: `SQLQuery`, `SQLDelete`, `SQLUpdate` and `SQLInsert`
+* Refactor of `SQLQuery` into separate objects for each query type: `SQLSelect`, `SQLDelete`, `SQLUpdate` and `SQLInsert`
* PDO is now a standard connector, and is available for all database interfaces
* `DataObject::doValidate()` method visibility added to access `DataObject::validate` externally
* `NumericField` now uses HTML5 "number" type instead of "text"
@@ -73,6 +73,8 @@
* Security: The multiple authenticator login page should now be styled manually - i.e. without the default jQuery
UI layout. A new template, Security_MultiAuthenticatorLogin.ss is available.
* Security: This controller's templates can be customised by overriding the `getTemplatesFor` function.
+* `Deprecation::set_enabled()` or `SS_DEPRECATION_ENABLED` can now be used to
+ enable or disable deprecation notices. Deprecation notices are no longer displayed on test.
* API: Form and FormField ID attributes rewritten.
* `SearchForm::getSearchQuery` no longer pre-escapes search keywords and must
be cast in your template
@@ -455,6 +457,26 @@ After:
$query->execute();
+When working with SQLQuery passed into user code, it is advisable to strictly
+cast it into either a SQLSelect or SQLDelete. This can be done by using the new
+`SQLQuery::toAppropriateExpression()` method, which will automatically convert
+to the correct type based on whether the SQLQuery is set to delete or not.
+
+If a SQLQuery is not converted, then the result of `getWhere` will not be parameterised.
+This is because user code written for 3.1 expects this list to be a flat array
+of strings. This format is inherently unsafe, and should be avoided where possible.
+
+
+ :::php
+ getWhere(); // Will be flattened (unsafe 3.1 compatible format)
+ $expression = $query->toAppropriateExpression(); // Either SQLSelect or SQLDelete
+ $expression->getWhere(); // Will be parameterised (preferred 3.2 compatible format)
+ }
+
+
+
Alternatively:
@@ -463,7 +485,8 @@ Alternatively:
$query = SQLQuery::create()
->setFrom('"SiteTree"')
->setWhere(array('"SiteTree"."ShowInMenus"' => 0))
- ->toDelete();
+ ->setDelete(true)
+ ->toAppropriateExpression();
$query->execute();
@@ -616,12 +639,14 @@ E.g.
DB::prepared_query('DELETE FROM "MyObject" WHERE ParentID = ? OR IsValid = ?', $parameters);
-#### 4. Interaction with `SQLQuery::getWhere()` method
+#### 4. Interaction with `SQLSelect::getWhere()` method
-As all where conditions are now parameterised, the format of the results returned by `SQLQuery::getWhere()`
-will not always equate with that in FrameWork 3.1. Once this would be a list of strings, what will
-now be returned is a list of conditions, each of which is an associative array mapping the
-condition string to a list of parameters provided.
+The `SQLSelect` class supercedes the old `SQLQuery` object for performing select queries. Although
+both implement the `getWhere()` method, the results returned by `SQLSelect::getWhere()` will be
+parameterised while `SQLQuery::getWhere()` will be a flattened array of strings.
+
+`SQLSelect::getWhere()` returns a list of conditions, each of which is an
+associative array mapping the condition string to a list of parameters provided.
Before:
@@ -630,6 +655,7 @@ Before:
getWhere();
$new = array();
foreach($conditions as $condition) {
@@ -646,6 +672,7 @@ After:
:::php
// Increment value of a single condition
+ $query = new SQLSelect(/*...*/);
$conditions = $query->getWhere();
$new = array();
foreach($conditions as $condition) {
@@ -665,7 +692,7 @@ replace this method call with the new `getWhereParameterised($parameters)` metho
applicable.
This method returns a manipulated form of the where conditions stored by the query, so
-that it matches the list of strings consistent with the old 3.1 `SQLQuery::getWhere()` behaviour.
+that it matches the list of strings similar to the old 3.1 `SQLQuery::getWhere()` behaviour.
Additionally, the list of parameters is safely extracted, flattened, and can be passed out
through the `$parameters` argument which is passed by reference.
diff --git a/docs/en/04_Changelogs/beta/3.2.0-beta1.md b/docs/en/04_Changelogs/beta/3.2.0-beta1.md
new file mode 100644
index 000000000..e7db421de
--- /dev/null
+++ b/docs/en/04_Changelogs/beta/3.2.0-beta1.md
@@ -0,0 +1,923 @@
+# 3.2.0 beta1
+
+## Contents
+
+* [Major Changes](#major-changes)
+* [Removed API](#deprecated-classesmethods-removed)
+* [New API](#new-and-changed-api)
+* [Bugfixes](#bugfixes)
+* [Upgrading Notes](#upgrading-notes)
+* [Changelog](#changelog)
+
+## Major changes
+
+* Minimum PHP version raised to 5.3.3
+* Introduction of new parameterised ORM
+* Default support for PDO
+* Moved SS_Report and ReportAdmin out to a separate module. If you're using
+ composer or downloading a release, this module should be included for you.
+ Otherwise, you'll need to include the module yourself
+ (https://github.com/silverstripe-labs/silverstripe-reports)
+* Moved SiteConfig also out to its own module. This will be included by
+ default if you include the CMS module.
+ (https://github.com/silverstripe/silverstripe-siteconfig)
+* Implementation of new "Archive" concept for page removal, which supercedes
+ "delete from draft". Where deletion removed pages only from draft, archiving
+ removes from both draft and live simultaneously.
+* Most of the `Image` manipulation methods have been renamed
+
+## Deprecated classes/methods removed
+
+* `ToggleField` was deprecated in 3.1, and has been removed. Use custom Javascript with `ReadonlyField` instead.
+* `ExactMatchMultiFilter` was deprecated in 3.1, and has been removed. Use `ExactMatchFilter` instead.
+* `NegationFilter` was deprecated in 3.1, and has been removed. Use `ExactMatchFilter:not` instead.
+* `StartsWithMultiFilter` was deprecated in 3.1, and has been removed. Use `StartsWithFilter` instead.
+* `ScheduledTask` and subclasses like `DailyTask` were deprecated in 3.1, and have been removed.
+ Use custom code instead, or a module like silverstripe-crontask: https://github.com/silverstripe-labs/silverstripe-crontask
+* `Cookie::forceExpiry()` was removed. Use `Cookie::force_expiry()` instead
+* `Object` statics removal: `get_static()`, `set_static()`, `uninherited_static()`, `combined_static()`,
+ `addStaticVars()` and `add_static_var()` removed. Use the Config methods instead.
+* `GD` methods removed: `setGD()`, `getGD()`, `hasGD()`. Use `setImageResource()`, `getImageResource()`, and `hasImageResource()` instead
+* `DataExtension::get_extra_config()` removed, no longer supports `extraStatics` or `extraDBFields`. Define your
+ statics on the class directly.
+* `DataList::getRange()` removed. Use `limit()` instead.
+* `SQLMap` removed. Call `map()` on a `DataList` or use `SS_Map` directly instead.
+* `Profiler` removed. Use xhprof or xdebug for profiling instead.
+* `Aggregate` removed. Call aggregate methods on a `DataList` instead e.g. `Member::get()->max('LastEdited')`
+* `MySQLDatabase::set_connection_charset()` removed. Use `MySQLDatabase.connection_charset` config setting instead
+* `SQLConditionalExpression/SQLQuery` `select()`, `limit()`, `orderby()`, `groupby()`, `having()`, `from()`, `leftjoin()`, `innerjoin()`, `where()` and `whereAny()` removed.
+ Use `set*()` and `add*()` methods instead.
+* Template `<% control $MyList %>` syntax removed. Use `<% loop $MyList %>` instead.
+* Removed `Member.LastVisited` and `Member.NumVisits` properties, see
+ [Howto: Track Member Logins](/developer_guides/extending/how_tos/track_member_logins) to restore functionality as custom code
+
+## New and changed API
+
+* Implementation of a parameterised query framework eliminating the need to manually escape variables for
+ use in SQL queries. This has been integrated into nearly every level of the database ORM.
+* Refactor of database connectivity classes into separate components linked together through dependency injection
+* Refactor of `SQLQuery` into separate objects for each query type: `SQLSelect`, `SQLDelete`, `SQLUpdate` and `SQLInsert`
+* PDO is now a standard connector, and is available for all database interfaces
+* `DataObject::doValidate()` method visibility added to access `DataObject::validate` externally
+* `NumericField` now uses HTML5 "number" type instead of "text"
+* `UploadField` "Select from files" shows files in all folders by default
+* `UploadField` won't display an overwrite warning unless `Upload::replaceFile` is true
+* `HtmlEditorField` no longer substitutes `
` for indented text
+* `ClassInfo::dataClassesFor` now returns classes which should have tables, regardless of whether those
+ tables actually exist.
+* `SS_Filterable`, `SS_Limitable` and `SS_Sortable` now explicitly extend `SS_List`
+* `Convert::html2raw` no longer wraps text by default and can decode single quotes.
+* `Mailer` no longer calls `xml2raw` on all email subject line, and now must be passed in via plain text.
+* `ErrorControlChain` now supports reload on exceptions
+* `FormField::validate` now requires an instance of `Validator`
+* API: Removed URL routing by controller name
+* Security: The multiple authenticator login page should now be styled manually - i.e. without the default jQuery
+ UI layout. A new template, Security_MultiAuthenticatorLogin.ss is available.
+* Security: This controller's templates can be customised by overriding the `getTemplatesFor` function.
+* API: Form and FormField ID attributes rewritten.
+* `SearchForm::getSearchQuery` no longer pre-escapes search keywords and must
+ be cast in your template
+* Helper function `DB::placeholders` can be used to generate a comma separated list of placeholders
+ useful for creating "WHERE ... IN (?,...)" SQL fragments
+* Implemented Convert::symbol2sql to safely encode database and table names and identifiers.
+ E.g. `Convert::symbol2sql('table.column') => '"table"."column"';`
+* `Convert::raw2sql` may now quote the escaped value, as well as safely escape it, according to the current
+ database adaptor's preference.
+* `DB` class has been updated and many static methods have been renamed to conform to coding convention.
+ * Renamed API:
+ * `affectedRows` -> `affected_rows`
+ * `checkAndRepairTable` -> `check_and_repair_table`
+ * `createDatabase` -> `create_database`
+ * `createField` -> `create_field`
+ * `createTable` -> `create_table`
+ * `dontRequireField` -> `dont_require_field`
+ * `dontRequireTable` -> `dont_require_table`
+ * `fieldList` -> `field_list`
+ * `getConn` -> `get_conn`
+ * `getGeneratedID` -> `get_generated_id`
+ * `isActive` -> `is_active`
+ * `requireField` -> `require_field`
+ * `requireIndex` -> `require_index`
+ * `requireTable` -> `require_table`
+ * `setConn` -> `set_conn`
+ * `tableList` -> `table_list`
+ * Deprecated API:
+ * `getConnect` (Was placeholder for PDO connection string building code, but is made
+ redundant after the PDOConnector being fully abstracted)
+ * New API:
+ * `build_sql` - Hook into new SQL generation code
+ * `get_connector` (Nothing to do with getConnect)
+ * `get_schema`
+ * `placeholders`
+ * `prepared_query`
+* `SS_Database` class has been updated and many functions have been deprecated, or refactored into
+ the various other database classes. Most of the database management classes remain in the database
+ controller, due to individual databases (changing, creating of, etc) varying quite a lot from
+ API to API, but schema updates within a database itself is managed by an attached DBSchemaManager
+ * Refactored into DBSchemaManager:
+ * `createTable`
+ * `alterTable`
+ * `renameTable`
+ * `createField`
+ * `renameField`
+ * `fieldList`
+ * `tableList`
+ * `hasTable`
+ * `enumValuesForField`
+ * `beginSchemaUpdate` and `endSchemaUpdate` -> Use `schemaUpdate` with a callback
+ * `cancelSchemaUpdate`
+ * `isSchemaUpdating`
+ * `doesSchemaNeedUpdating`
+ * `transCreateTable`
+ * `transAlterTable`
+ * `transCreateField`
+ * `transCreateField`
+ * `transCreateIndex`
+ * `transAlterField`
+ * `transAlterIndex`
+ * `requireTable`
+ * `dontRequireTable`
+ * `requireIndex`
+ * `hasField`
+ * `requireField`
+ * `dontRequireField`
+ * Refactored into DBQueryBuilder
+ * `sqlQueryToString`
+ * Deprecated:
+ * `getConnect` - Was intended for use with PDO, but was never implemented, and is now
+ redundant, now that there is a stand-alone `PDOConnector`
+ * `prepStringForDB` - Use `quoteString` instead
+ * `dropDatabase` - Use `dropSelectedDatabase`
+ * `createDatabase` - Use `selectDatabase` with the second parameter set to true instead
+ * `allDatabaseNames` - Use `databaseList` instead
+ * `currentDatabase` - Use `getSelectedDatabase` instead
+ * `addslashes` - Use `escapeString` instead
+* `LogErrorEmailFormatter` now better displays SQL queries in errors by respecting line breaks
+* Installer has been majorly upgraded to handle the new database configuration options
+ and additional PDO functionality.
+* Created `SS_DatabaseException` to emit database errors. Query information such as SQL
+ and any relevant parameters may be used by error handling user code that catches
+ this exception.
+* The `SQLConditionGroup` interface has been created to represent dynamically
+ evaluated SQL conditions. This may be used to wrap a class that generates
+ a custom SQL clause(s) to be evaluated at the time of execution.
+* `DataObject` constants CHANGE_NONE, CHANGE_STRICT, and CHANGE_VALUE have been created
+ to provide more verbosity to field modification detection. This replaces the use of
+ various magic numbers with the same meaning.
+* create_table_options now uses constants as API specific filters rather than strings.
+ This is in order to promote better referencing of elements across the codebase.
+ See `FulltextSearchable->enable` for example.
+* `$FromEnd` iterator variable now available in templates.
+* Support for multiple HtmlEditorConfigs on the same page.
+* Object::singleton() method for better type-friendly singleton generation
+* New `Image` methods `CropWidth` and `CropHeight` added
+* 'Max' versions of `Image` methods introduced to prevent up-sampling
+* Update Image method names in PHP code and templates
+ * `SetRatioSize` -> `Fit`
+ * `CroppedImage` -> `Fill`
+ * `PaddedImage` -> `Pad`
+ * `SetSize` -> `Pad`
+ * `SetWidth` -> `ScaleWidth`
+ * `SetHeight` -> `ScaleHeight`
+
+## Bugfixes
+
+* Reduced database regeneration chances on subsequent rebuilds after the initial dev/build
+* Elimination of various SQL injection vulnerability points
+* `DataObject::writeComponents()` now called correctly during `DataObject::write()`
+* Fixed missing theme declaration in installer
+* Fixed incorrect use of non-existing exception classes (e.g. `HTTPResponse_exception`)
+* `GridState` fixed to distinguish between check for missing values, and creation of
+ nested state values, in order to prevent non-empty values being returned for
+ missing keys. This was breaking `DataObject::get_by_id` by passing in an object
+ for the ID.
+* Fixed order of `File` fulltext searchable fields to use same order as actual fields.
+ This is required to prevent unnecessary rebuild of MS SQL databases when fulltext
+ searching is enabled.
+* In the past E_RECOVERABLE_ERROR would be ignored, and now correctly appear as warnings.
+
+## Upgrading Notes
+
+### UploadField "Select from files" shows files in all folders by default
+
+In order to list files in a single folder by default (previous default behaviour),
+use `setDisplayFolderName()` with a folder path relative to `assets/`:
+
+
+ :::php
+ UploadField::create('MyField')->setDisplayFolderName('Uploads');
+
+
+### UploadField won't display an overwrite warning unless Upload:replaceFile is true
+
+The configuration setting `UploadField:overwriteWarning` is dependent on `Upload:replaceFile`
+which is set to false by default.
+
+To display a warning before overwriting a file:
+
+Via config:
+
+
+ ::yaml
+ Upload:
+ # Replace an existing file rather than renaming the new one.
+ replaceFile: true
+ UploadField:
+ # Warning before overwriting existing file (only relevant when Upload: replaceFile is true)
+ overwriteWarning: true
+
+
+Or per instance:
+
+
+ ::php
+ $uploadField->getUpload()->setReplaceFile(true);
+ $uploadField->setOverwriteWarning(true);
+
+
+### File.allowed_extensions restrictions
+
+Certain file types such as swf, html, htm, xhtml and xml have been removed from the list
+of allowable file uploads. If your application requires the ability to upload these,
+you will need to append these to the `File.allowed_extensions` config as necessary.
+Also if uploading other file types, it's necessary to ensure that `File.allowed_extensions`
+includes that extension, as extensions passed to `[api:UploadField]` will be filtered against
+this list.
+
+### Removed format detection in i18n::$date_format and i18n::$time_format
+
+Localized dates cause inconsistencies in client-side vs. server-side formatting
+and validation, particularly in abbreviated month names. The default date
+format has been changed to "yyyy-MM-dd" (e.g. 2014-12-31).
+New users will continue to have the option for a localized date
+format in their profile (based on their chosen locale).
+If you have existing users with `Member.DateFormat` set to a format
+including "MMM" or "MMMM", consider deleting those formats to fall back to
+the global (and more stable) default.
+
+### Cookies set via Cookie::set() are now HTTP only by default
+
+Cookies set through `Cookie::set()` now default to "HTTP only". This means that scripting
+languages like JavaScript won't be able to read them.
+
+To set it back to be non-HTTP only, you need to set the `$httpOnly` argument to false when calling
+`Cookie::set()`.
+
+### API: Removed URL routing by controller name
+
+The auto-routing of controller class names to URL endpoints
+has been removed (rule: `'$Controller//$Action/$ID/$OtherID': '*'`).
+This increases clarity in routing since it makes URL entpoints explicit,
+and thereby simplifies system and security reviews.
+
+Please access any custom controllers exclusively through self-defined
+[routes](/reference/director). For controllers extending `Page_Controller`,
+simply use the provided page URLs.
+
+
+ :::php
+ class MyController extends Controller {
+ static $allowed_actions = array('myaction');
+ public function myaction($request) {
+ // ...
+ }
+ }
+
+
+Create a new file `mysite/_config/routes.yml`
+(read more about the [config format](/topics/configuration)).
+Your controller is now available on `http://yourdomain.com/my-controller-endpoint`,
+after refreshing the configuration cache through `?flush=all`.
+
+
+ :::yaml
+ ---
+ Name: my-routes
+ After: framework/routes#coreroutes
+ ---
+ Director:
+ rules:
+ 'my-controller-endpoint//$Action' : 'MyController'
+
+
+The auto-routing is still in place for unit tests,
+since its a frequently used feature there. Although we advise against it,
+you can reinstate the old behaviour through a director rule:
+
+
+ :::yaml
+ ---
+ Name: my-routes
+ After: framework/routes#coreroutes
+ ---
+ Director:
+ rules:
+ '$Controller//$Action/$ID/$OtherID': '*'
+
+
+### API: Default Form and FormField ID attributes rewritten.
+
+Previously the automatic generation of ID attributes throughout the Form API
+could generate invalid ID values such as Password[ConfirmedPassword] as well
+as duplicate ID values between forms on the same page. For example, if you
+created a field called `Email` on more than one form on the page, the resulting
+HTML would have multiple instances of `#Email`. ID should be a unique
+identifier for a single element within the document.
+
+This rewrite has several angles, each of which is described below. If you rely
+on ID values in your CSS files, Javascript code or application unit tests *you
+will need to update your code*.
+
+#### Conversion of invalid form ID values
+
+ID attributes on Form and Form Fields will now follow the
+[HTML specification](http://www.w3.org/TR/REC-html40/types.html#type-cdata).
+Generating ID attributes is now handled by the new `FormTemplateHelper` class.
+
+Please test each of your existing site forms to ensure that they work
+correctly in particular, javascript and css styles which rely on specific ID
+values.
+
+#### Invalid ID attributes stripped
+
+ID attributes will now be run through `Convert::raw2htmlid`. Invalid characters
+are replaced with a single underscore character. Duplicate, leading and trailing
+underscores are removed. Custom ID attributes (set through `setHTMLID`) will not
+be altered.
+
+Before:
+
+
+ :::html
+