From 08a5a7c3872ddfb4f22a70a5bae436f16390331b Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Tue, 10 Mar 2009 22:08:52 +0000 Subject: [PATCH] Merged from branches/2.3 git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@72803 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- _config.php | 3 +- api/RestfulServer.php | 2 +- api/VersionedRestfulServer.php | 15 ++++++ core/Core.php | 4 +- core/Requirements.php | 63 ++++++++++---------------- core/SSViewer.php | 9 +++- core/control/Director.php | 7 ++- core/control/ModelAsController.php | 8 ++++ core/control/RootURLController.php | 7 +++ core/i18n.php | 32 +++++++++++++ core/model/DataObjectSet.php | 15 +++--- core/model/DatabaseAdmin.php | 9 +++- core/model/SiteTree.php | 1 + dev/install/config-form.html | 4 +- filesystem/Folder.php | 4 +- forms/AjaxUniqueTextField.php | 1 + forms/ComplexTableField.php | 2 + forms/HasManyComplexTableField.php | 2 +- forms/RestrictedTextField.php | 1 + forms/ScaffoldingComplexTableField.php | 1 + forms/TableField.php | 2 +- forms/TableListField.php | 2 +- forms/TreeDropdownField.php | 1 + forms/TreeMultiselectField.php | 1 + forms/TreeSelectorField.php | 2 +- forms/UniqueTextField.php | 2 +- forms/Validator.php | 5 +- javascript/HasManyFileField.js | 4 +- javascript/TableField.js | 2 +- javascript/TableListField.js | 2 +- javascript/TreeSelectorField.js | 4 +- javascript/UniqueFields.js | 10 ++-- javascript/UpdateURL.js | 2 +- javascript/Validator.js | 2 +- javascript/i18n.js | 10 ++-- javascript/i18nx.js | 40 ++++++++++++++++ search/SearchContext.php | 4 +- security/BasicAuth.php | 9 +++- security/MemberLoginForm.php | 21 +++++---- 39 files changed, 217 insertions(+), 98 deletions(-) create mode 100644 api/VersionedRestfulServer.php create mode 100644 javascript/i18nx.js diff --git a/_config.php b/_config.php index 41198ca91..243f453e5 100644 --- a/_config.php +++ b/_config.php @@ -25,6 +25,7 @@ Director::addRules(10, array( '$Controller//$Action/$ID/$OtherID' => '*', 'images' => 'Image_Uploader', '' => 'RootURLController', + 'api/v1/live' => 'VersionedRestfulServer', 'api/v1' => 'RestfulServer', 'soap/v1' => 'SOAPModelAccess', 'dev' => 'DevelopmentAdmin', @@ -69,4 +70,4 @@ define('MCE_ROOT', 'jsparty/tiny_mce2/'); */ define('EMAIL_BOUNCEHANDLER_KEY', '1aaaf8fb60ea253dbf6efa71baaacbb3'); -?> \ No newline at end of file +?> diff --git a/api/RestfulServer.php b/api/RestfulServer.php index e764bf3f8..16274fc2d 100644 --- a/api/RestfulServer.php +++ b/api/RestfulServer.php @@ -457,7 +457,7 @@ class RestfulServer extends Controller { */ protected function getObjectQuery($className, $id, $params) { $baseClass = ClassInfo::baseDataClass($className); - return singleton($className)->buildSQL( + return singleton($className)->extendedSQL( "\"$baseClass\".ID = {$id}" ); } diff --git a/api/VersionedRestfulServer.php b/api/VersionedRestfulServer.php new file mode 100644 index 000000000..e5342e6c3 --- /dev/null +++ b/api/VersionedRestfulServer.php @@ -0,0 +1,15 @@ +handleRequest($request); + return $response; + } +} + +?> diff --git a/core/Core.php b/core/Core.php index fbd913269..2420f45ed 100755 --- a/core/Core.php +++ b/core/Core.php @@ -28,7 +28,7 @@ error_reporting(E_ALL); */ $envFiles = array('../_ss_environment.php', '../../_ss_environment.php', '../../../_ss_environment.php'); foreach($envFiles as $envFile) { - if(file_exists($envFile)) { + if(@file_exists($envFile)) { define('SS_ENVIRONMENT_FILE', $envFile); include_once($envFile); break; @@ -286,4 +286,4 @@ function _t($entity, $string = "", $priority = 40, $context = "") { return i18n::_t($entity, $string, $priority, $context); } -?> \ No newline at end of file +?> diff --git a/core/Requirements.php b/core/Requirements.php index 88f1daba7..2b4effc7a 100644 --- a/core/Requirements.php +++ b/core/Requirements.php @@ -192,12 +192,13 @@ class Requirements { } /** - * Automatically includes the necessary lang-files from the module. + * Add i18n files from the given javascript directory. + * @param $langDir The javascript lang directory, relative to the site root, e.g., 'sapphire/javascript/lang' * - * See {@link Requirements_Backend::process_i18n_javascript()} for more info. + * See {@link Requirements_Backend::add_i18n_javascript()} for more information. */ - protected static function process_i18n_javascript() { - return self::backend()->process_i18n_javascript(); + public static function add_i18n_javascript($langDir) { + return self::backend()->add_i18n_javascript($langDir); } /** @@ -548,7 +549,6 @@ class Requirements_Backend { $jsRequirements = ''; // Combine files - updates $this->javascript and $this->css - $this->process_i18n_javascript(); $this->process_combined_files(); foreach(array_diff_key($this->javascript,$this->blocked) as $file => $dummy) { @@ -636,41 +636,28 @@ class Requirements_Backend { $response->addHeader('X-Include-CSS', implode(',', $cssRequirements)); } - /** - * Automatically includes the necessary lang-files from the module - * according to the locale set in {@link i18n::$current_locale}. - * Assumes that a subfolder /javascript exists relative to the included - * javascript file, with a file named after the locale - - * so usually /javascript/lang/en_US.js. + /** + * Add i18n files from the given javascript directory. Sapphire expects that the given directory + * will contain a number of java script files named by language: en_US.js, de_DE.js, etc. + * @param $langDir The javascript lang directory, relative to the site root, e.g., 'sapphire/javascript/lang' */ - protected function process_i18n_javascript() { - // ensure to include the i18n base library - if( - count(array_diff_key($this->javascript,$this->blocked)) - && !isset($this->javascript[SAPPHIRE_DIR . '/javascript/i18n.js']) - ) { - $this->javascript[THIRDPARTY_DIR . '/prototype.js'] = true; - $this->javascript[SAPPHIRE_DIR . '/javascript/i18n.js'] = true; - } - - // include the specific locale and the master locale for each module - foreach(array_diff_key($this->javascript,$this->blocked) as $file => $dummy) { - if(preg_match('/^http[s]?/', $file)) continue; - - $absolutePath = Director::baseFolder() . '/' . $file; - $absoluteLangPath = dirname($absolutePath) . '/lang/' . i18n::get_locale() . '.js'; - $absoluteDefaultLangPath = dirname($absolutePath) . '/lang/' . i18n::default_locale() . '.js'; - foreach(array($absoluteDefaultLangPath, $absoluteLangPath) as $path) { - if(Director::fileExists($path)) { - $langFile = Director::makeRelative($path); - // Remove rogue leading slashes from Director::makeRelative() - $langFile = preg_replace('/^\//', '', $langFile); - $this->javascript[$langFile] = true; - } - } - } + public function add_i18n_javascript($langDir) { + if(i18n::get_js_i18n()) { + // Include i18n.js even if no languages are found. The fact that + // add_i18n_javascript() was called indicates that the methods in + // here are needed. + $this->javascript(SAPPHIRE_DIR . '/javascript/i18n.js'); - } + if(substr($langDir,-1) != '/') $langDir .= '/'; + + $this->javascript($langDir . i18n::default_locale() . '.js'); + $this->javascript($langDir . i18n::get_locale() . '.js'); + + // Stub i18n implementation for when i18n is disabled. + } else { + $this->javascript[SAPPHIRE_DIR . '/javascript/i18nx.js'] = true; + } + } /** * Finds the path for specified file. diff --git a/core/SSViewer.php b/core/SSViewer.php index 739d06ecb..48d2a486d 100644 --- a/core/SSViewer.php +++ b/core/SSViewer.php @@ -121,7 +121,12 @@ class SSViewer extends Object { // flush template manifest cache if requested if (isset($_GET['flush']) && $_GET['flush'] == 'all') { - self::flush_template_cache(); + if(Director::isDev() || Permission::check('ADMIN')) { + self::flush_template_cache(); + Debug::message('flushed!'); + } else { + Security::permissionFailure(null, 'Please log in as an administrator to flush the template cache.'); + } } if(substr((string) $templateList,-3) == '.ss') { @@ -592,4 +597,4 @@ function supressOutput() { return ""; } -?> \ No newline at end of file +?> diff --git a/core/control/Director.php b/core/control/Director.php index 851a91c4a..934e44298 100644 --- a/core/control/Director.php +++ b/core/control/Director.php @@ -397,8 +397,11 @@ class Director { if(self::$alternateBaseURL) return self::$alternateBaseURL; else { $base = dirname(dirname($_SERVER['SCRIPT_NAME'])); - if($base == '/' || $base == '/.' || $base == '\\') return '/'; - else return $base . '/'; + if($base == '/' || $base == '/.' || $base == '\\') $baseURL = '/'; + else $baseURL = $base . '/'; + + if(defined('BASE_SCRIPT_URL')) return $baseURL . BASE_SCRIPT_URL; + else return $baseURL; } } diff --git a/core/control/ModelAsController.php b/core/control/ModelAsController.php index 88f74e9c7..23b637d29 100644 --- a/core/control/ModelAsController.php +++ b/core/control/ModelAsController.php @@ -13,6 +13,14 @@ class ModelAsController extends Controller implements NestedController { $this->urlParams = $request->allParams(); $this->init(); + + // If the basic database hasn't been created, then build it. + if(!DB::isActive() || !ClassInfo::hasTable('SiteTree')) { + $this->response = new HTTPResponse(); + $this->redirect("dev/build?returnURL=" . urlencode($_GET['url'])); + return $this->response; + } + $result = $this->getNestedController(); if(is_object($result) && $result instanceOf RequestHandler) { diff --git a/core/control/RootURLController.php b/core/control/RootURLController.php index 9ae06d7e4..7000f9f42 100755 --- a/core/control/RootURLController.php +++ b/core/control/RootURLController.php @@ -30,6 +30,13 @@ class RootURLController extends Controller { $this->init(); + // If the basic database hasn't been created, then build it. + if(!DB::isActive() || !ClassInfo::hasTable('SiteTree')) { + $this->response = new HTTPResponse(); + $this->redirect("dev/build?returnURL="); + return $this->response; + } + $controller = new ModelAsController(); $request = new HTTPRequest("GET", self::get_homepage_urlsegment().'/', $request->getVars(), $request->postVars()); $request->match('$URLSegment//$Action', true); diff --git a/core/i18n.php b/core/i18n.php index 9268cdcea..1eebd1ffe 100755 --- a/core/i18n.php +++ b/core/i18n.php @@ -59,6 +59,38 @@ class i18n extends Object { * @var string */ protected static $default_locale = 'en_US'; + + /** + * @var boolean + */ + protected static $js_i18n = true; + + /** + * Use javascript i18n through the ss.i18n class (enabled by default). + * If set to TRUE, includes javascript requirements for the base library + * (sapphire/javascript/i18n.js) and all necessary lang files (e.g. sapphire/lang/de_DE.js) + * plus fallbacks to the default locale (e.g. sapphire/lang/en_US.js). + * If set to FALSE, only includes a stub implementation + * which is necessary. Mainly disabled to save bandwidth + * in a frontend context when website is in single language. + * + * Caution: This flag gets overwritten in {@link LeftAndMain::init()} to enforce javascript + * i18n for the CMS interfaces. + * + * @see Requirements::process_i18n_javascript() + * + * @param bool $bool + */ + public static function set_js_i18n($bool) { + self::$js_i18n = $bool; + } + + /** + * @return bool + */ + public static function get_js_i18n() { + return self::$js_i18n; + } /** * An exhaustive list of possible locales (code => language and country) diff --git a/core/model/DataObjectSet.php b/core/model/DataObjectSet.php index bb62d50e1..d6e3ecdbe 100644 --- a/core/model/DataObjectSet.php +++ b/core/model/DataObjectSet.php @@ -809,9 +809,9 @@ class DataObjectSet extends ViewableData implements IteratorAggregate { } /** - * Returns a new DataObjectSet of the sorted array - * @param string $fieldname the name of the field on the dataobject that you wish to sort the set by - * @param string $direction the direction of the sort e.g. Ascending = ASC ( LIKE SQL ) + * Sorts the current DataObjectSet instance. + * @param string $fieldname The name of the field on the DataObject that you wish to sort the set by. + * @param string $direction Direction to sort by, either "ASC" or "DESC". */ public function sort($fieldname, $direction = "ASC") { if($this->items) { @@ -981,11 +981,10 @@ class DataObjectSet extends ViewableData implements IteratorAggregate { } /** - * Sort a 2D array by particular comma separated list of columns. - * Prefix column names with - for a descending search. - * @param array $data The array to sort - * @param string $column Comma separated list of columns - * @param string $direction Direction to sort by, either "ASC" or "DESC" + * Sort a 2D array by particular column. + * @param array $data The array to sort. + * @param string $column The name of the column you wish to sort by. + * @param string $direction Direction to sort by, either "ASC" or "DESC". * @param boolean $preserveIndexes Preserve indexes */ function column_sort(&$data, $column, $direction = "ASC", $preserveIndexes = true) { diff --git a/core/model/DatabaseAdmin.php b/core/model/DatabaseAdmin.php index 6abb62a8f..1264e34cc 100644 --- a/core/model/DatabaseAdmin.php +++ b/core/model/DatabaseAdmin.php @@ -78,7 +78,14 @@ class DatabaseAdmin extends Controller { ManifestBuilder::create_manifest_file(); require(MANIFEST_FILE); - $this->doBuild(isset($_REQUEST['quiet']) || isset($_REQUEST['from_installer']), !isset($_REQUEST['dont_populate'])); + if(isset($_GET['returnURL'])) { + echo "

Setting up the database; you will be returned to your site shortly....

"; + $this->doBuild(true); + echo "

Done!

"; + Director::redirect($_GET['returnURL']); + } else { + $this->doBuild(isset($_REQUEST['quiet']) || isset($_REQUEST['from_installer']), !isset($_REQUEST['dont_populate'])); + } } /** diff --git a/core/model/SiteTree.php b/core/model/SiteTree.php index f6587f8d2..47cc505a3 100644 --- a/core/model/SiteTree.php +++ b/core/model/SiteTree.php @@ -1114,6 +1114,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid function getCMSFields() { require_once("forms/Form.php"); Requirements::javascript(CMS_DIR . "/javascript/SitetreeAccess.js"); + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/UpdateURL.js'); // Status / message diff --git a/dev/install/config-form.html b/dev/install/config-form.html index d866cf6ac..6a864fe90 100644 --- a/dev/install/config-form.html +++ b/dev/install/config-form.html @@ -55,8 +55,8 @@ Template to install:

You can change the template or download another from the SilverStripe website after installation.

diff --git a/filesystem/Folder.php b/filesystem/Folder.php index 4aa6cad58..d4535c199 100755 --- a/filesystem/Folder.php +++ b/filesystem/Folder.php @@ -91,8 +91,8 @@ class Folder extends File { // A record with a bad class type doesn't deserve to exist. It must be purged! if(isset($hasDbChild[$actualChild])) { $child = $hasDbChild[$actualChild]; - if( ($child->class != 'Folder' && is_dir($baseDir . $actualChild)) - || ($child->class == 'Folder' && !is_dir($baseDir . $actualChild)) ) { + if(( !( $child instanceof Folder ) && is_dir($baseDir . $actualChild) ) + || (( $child instanceof Folder ) && !is_dir($baseDir . $actualChild)) ) { DB::query("DELETE FROM \"File\" WHERE \"ID\" = $child->ID"); unset($hasDbChild[$actualChild]); } diff --git a/forms/AjaxUniqueTextField.php b/forms/AjaxUniqueTextField.php index 3cd8d0f9e..63a3d2725 100644 --- a/forms/AjaxUniqueTextField.php +++ b/forms/AjaxUniqueTextField.php @@ -29,6 +29,7 @@ class AjaxUniqueTextField extends TextField { } function Field() { + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(SAPPHIRE_DIR . "/javascript/UniqueFields.js"); $this->jsValidation(); diff --git a/forms/ComplexTableField.php b/forms/ComplexTableField.php index 0242b6d4e..09abad26b 100755 --- a/forms/ComplexTableField.php +++ b/forms/ComplexTableField.php @@ -200,6 +200,7 @@ class ComplexTableField extends TableListField { Requirements::javascript(THIRDPARTY_DIR . "/greybox/AmiJS.js"); Requirements::javascript(THIRDPARTY_DIR . "/greybox/greybox.js"); + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/TableListField.js'); Requirements::javascript(SAPPHIRE_DIR . "/javascript/ComplexTableField.js"); Requirements::css(THIRDPARTY_DIR . "/greybox/greybox.css"); @@ -1030,6 +1031,7 @@ class ComplexTableField_Popup extends Form { Requirements::javascript(THIRDPARTY_DIR . "/scriptaculous/scriptaculous.js"); Requirements::javascript(THIRDPARTY_DIR . "/scriptaculous/controls.js"); Requirements::javascript(THIRDPARTY_DIR . "/layout_helpers.js"); + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(CMS_DIR . "/javascript/LeftAndMain.js"); Requirements::javascript(CMS_DIR . "/javascript/LeftAndMain_right.js"); Requirements::javascript(SAPPHIRE_DIR . "/javascript/TableField.js"); diff --git a/forms/HasManyComplexTableField.php b/forms/HasManyComplexTableField.php index 008fe2bcb..aaf1e27c7 100644 --- a/forms/HasManyComplexTableField.php +++ b/forms/HasManyComplexTableField.php @@ -23,7 +23,7 @@ class HasManyComplexTableField extends ComplexTableField { function __construct($controller, $name, $sourceClass, $fieldList, $detailFormFields = null, $sourceFilter = "", $sourceSort = "", $sourceJoin = "") { parent::__construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter, $sourceSort, $sourceJoin); - Requirements::javascript(SAPPHIRE_DIR . "/javascript/i18n.js"); + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(SAPPHIRE_DIR . "/javascript/HasManyFileField.js"); Requirements::javascript(SAPPHIRE_DIR . '/javascript/RelationComplexTableField.js'); Requirements::css(SAPPHIRE_DIR . '/css/HasManyFileField.css'); diff --git a/forms/RestrictedTextField.php b/forms/RestrictedTextField.php index 0e5744057..8516cb930 100755 --- a/forms/RestrictedTextField.php +++ b/forms/RestrictedTextField.php @@ -15,6 +15,7 @@ class RestrictedTextField extends TextField { } function Field() { + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript( SAPPHIRE_DIR . '/javascript/UniqueFields.js' ); if($this->maxLength){ diff --git a/forms/ScaffoldingComplexTableField.php b/forms/ScaffoldingComplexTableField.php index 3577768cb..b3ac9c616 100644 --- a/forms/ScaffoldingComplexTableField.php +++ b/forms/ScaffoldingComplexTableField.php @@ -32,6 +32,7 @@ class ScaffoldingComplexTableField_Popup extends Form { Requirements::javascript(THIRDPARTY_DIR . "/scriptaculous/scriptaculous.js"); Requirements::javascript(THIRDPARTY_DIR . "/scriptaculous/controls.js"); Requirements::javascript(THIRDPARTY_DIR . "/layout_helpers.js"); + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(CMS_DIR . "/javascript/LeftAndMain.js"); Requirements::javascript(CMS_DIR . "/javascript/LeftAndMain_right.js"); Requirements::javascript(SAPPHIRE_DIR . "/javascript/TableField.js"); diff --git a/forms/TableField.php b/forms/TableField.php index 168a77780..cc4f66ace 100644 --- a/forms/TableField.php +++ b/forms/TableField.php @@ -114,7 +114,7 @@ class TableField extends TableListField { } parent::__construct($name, $sourceClass, $fieldList, $sourceFilter, $sourceSort, $sourceJoin); - Requirements::javascript(SAPPHIRE_DIR . "/javascript/i18n.js"); + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/TableField.js'); } diff --git a/forms/TableListField.php b/forms/TableListField.php index c3a167c6b..9aaa3ac15 100755 --- a/forms/TableListField.php +++ b/forms/TableListField.php @@ -247,7 +247,7 @@ class TableListField extends FormField { Requirements::javascript(THIRDPARTY_DIR . '/behaviour.js'); Requirements::javascript(THIRDPARTY_DIR . '/prototype_improvements.js'); Requirements::javascript(THIRDPARTY_DIR . '/scriptaculous/effects.js'); - Requirements::javascript(SAPPHIRE_DIR . "/javascript/i18n.js"); + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(SAPPHIRE_DIR . '/javascript/TableListField.js'); Requirements::css(SAPPHIRE_DIR . '/css/TableListField.css'); } diff --git a/forms/TreeDropdownField.php b/forms/TreeDropdownField.php index bb0a4f743..e7968ee13 100755 --- a/forms/TreeDropdownField.php +++ b/forms/TreeDropdownField.php @@ -37,6 +37,7 @@ class TreeDropdownField extends FormField { Requirements::css(SAPPHIRE_DIR . '/css/TreeDropdownField.css'); Requirements::javascript(THIRDPARTY_DIR . "/tree/tree.js"); Requirements::css(THIRDPARTY_DIR . "/tree/tree.css"); + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(SAPPHIRE_DIR . "/javascript/TreeSelectorField.js"); if($this->value) { diff --git a/forms/TreeMultiselectField.php b/forms/TreeMultiselectField.php index ac1b74b2d..0fa7bb735 100755 --- a/forms/TreeMultiselectField.php +++ b/forms/TreeMultiselectField.php @@ -29,6 +29,7 @@ class TreeMultiselectField extends TreeDropdownField { function Field() { $value = ''; $itemList = ''; + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(SAPPHIRE_DIR . "/javascript/TreeSelectorField.js"); $items = $this->getItems(); diff --git a/forms/TreeSelectorField.php b/forms/TreeSelectorField.php index becf70a25..cae75fc38 100755 --- a/forms/TreeSelectorField.php +++ b/forms/TreeSelectorField.php @@ -13,7 +13,7 @@ class TreeSelectorField extends FormField { } function Field() { - Requirements::javascript(SAPPHIRE_DIR . "/javascript/i18n.js"); + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(SAPPHIRE_DIR . "/javascript/TreeSelectorField.js"); $fieldName = $this->name; diff --git a/forms/UniqueTextField.php b/forms/UniqueTextField.php index 992492977..6a2132db5 100755 --- a/forms/UniqueTextField.php +++ b/forms/UniqueTextField.php @@ -24,7 +24,7 @@ class UniqueTextField extends TextField { } function Field() { - Requirements::javascript(SAPPHIRE_DIR . "/javascript/i18n.js"); + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(SAPPHIRE_DIR . "/javascript/UniqueFields.js"); /* diff --git a/forms/Validator.php b/forms/Validator.php index 9bf63393b..083aa0f22 100755 --- a/forms/Validator.php +++ b/forms/Validator.php @@ -153,8 +153,7 @@ abstract class Validator extends Object { Requirements::javascript(THIRDPARTY_DIR . "/prototype.js"); Requirements::javascript(THIRDPARTY_DIR . "/behaviour.js"); Requirements::javascript(THIRDPARTY_DIR . "/prototype_improvements.js"); - //Requirements::add_i18n_javascript(SAPPHIRE_DIR); - Requirements::javascript(SAPPHIRE_DIR . "/javascript/i18n.js"); + Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang'); Requirements::javascript(SAPPHIRE_DIR . "/javascript/Validator.js"); $code = $this->javascript(); @@ -223,4 +222,4 @@ JS; abstract function php($data); } -?> \ No newline at end of file +?> diff --git a/javascript/HasManyFileField.js b/javascript/HasManyFileField.js index b8b223fae..abcee4f1b 100644 --- a/javascript/HasManyFileField.js +++ b/javascript/HasManyFileField.js @@ -84,7 +84,7 @@ HasManyFileFieldUploadButton.prototype = { uploadFileQueuedCallback: function(file,queueLength) { var message = ss.i18n.sprintf( - ss.i18n._t('HASMANYFILEFIELD.UPLOADING'), + ss.i18n._t('HASMANYFILEFIELD.UPLOADING', 'Uploading... %s'), this.upload.getFilesToUpload() ); this.parentNode.parentNode.uploadMessage.innerHTML = message; @@ -92,7 +92,7 @@ HasManyFileFieldUploadButton.prototype = { uploadFileCompleteCallback: function(file,serverData) { var message = ss.i18n.sprintf( - ss.i18n._t('HASMANYFILEFIELD.UPLOADING'), + ss.i18n._t('HASMANYFILEFIELD.UPLOADING', 'Uploading... %s'), this.upload.getFilesUploaded() + "/" + this.upload.getFilesToUpload() ); this.parentNode.parentNode.uploadMessage.innerHTML = message; diff --git a/javascript/TableField.js b/javascript/TableField.js index 2fa831c0b..673f7a191 100755 --- a/javascript/TableField.js +++ b/javascript/TableField.js @@ -75,7 +75,7 @@ TableField.prototype = { } // TODO ajaxErrorHandler and loading-image are dependent on cms, but formfield is in sapphire - var confirmed = confirm(ss.i18n._t('TABLEFIELD.DELETECONFIRMMESSAGE')); + var confirmed = confirm(ss.i18n._t('TABLEFIELD.DELETECONFIRMMESSAGE', 'Are you sure you want to delete this record?')); if(confirmed){ img.setAttribute("src",'cms/images/network-save.gif'); // TODO doesn't work new Ajax.Request( diff --git a/javascript/TableListField.js b/javascript/TableListField.js index 8776865a8..576c29581 100755 --- a/javascript/TableListField.js +++ b/javascript/TableListField.js @@ -84,7 +84,7 @@ TableListField.prototype = { var row = Event.findElement(e,"tr"); // TODO ajaxErrorHandler and loading-image are dependent on cms, but formfield is in sapphire - var confirmed = confirm(ss.i18n._t('TABLEFIELD.DELETECONFIRMMESSAGE')); + var confirmed = confirm(ss.i18n._t('TABLEFIELD.DELETECONFIRMMESSAGE', 'Are you sure you want to delete this record?')); if(confirmed) { img.setAttribute("src",'cms/images/network-save.gif'); // TODO doesn't work diff --git a/javascript/TreeSelectorField.js b/javascript/TreeSelectorField.js index 13d5c17a0..8e0917ac1 100755 --- a/javascript/TreeSelectorField.js +++ b/javascript/TreeSelectorField.js @@ -67,7 +67,7 @@ TreeDropdownField.prototype = { } this.itemTree.className = 'tree_holder'; - this.itemTree.innerHTML = ss.i18n._t('LOADING'); + this.itemTree.innerHTML = ss.i18n._t('LOADING', 'Loading...'); this.appendChild(this.itemTree); } }, @@ -186,7 +186,7 @@ TreeDropdownField.prototype = { ajaxExpansion: function() { this.addNodeClass('loading'); var ul = this.treeNodeHolder(); - ul.innerHTML = ss.i18n._t('LOADING'); + ul.innerHTML = ss.i18n._t('LOADING', 'Loading...'); var ajaxURL = this.options.dropdownField.helperURLBase() + 'getsubtree?&SubtreeRootID=' + this.getIdx(); ajaxURL += $('SecurityID') ? '&SecurityID=' + $('SecurityID').value : ''; diff --git a/javascript/UniqueFields.js b/javascript/UniqueFields.js index ea7cec083..3e9bf2d09 100755 --- a/javascript/UniqueFields.js +++ b/javascript/UniqueFields.js @@ -7,7 +7,7 @@ UniqueFormField.prototype = { if( this.restrictedValues[suggested] || suggested == null ) { suggested = this.suggestNewValue(); statusMessage(ss.i18n.sprintf( - ss.i18n._t('UNIQUEFIELD.SUGGESTED'), + ss.i18n._t('UNIQUEFIELD.SUGGESTED', "Changed value to '%s' : %s"), suggested, this.restrictedMessage )); @@ -112,9 +112,9 @@ UniqueRestrictedTextField.prototype = { if( suggested == null || suggested.length == 0 || suggestedValue || suggested.match( this.charRegex ) ) { var message; if( suggested == null ) - message = ss.i18n._t('UNIQUEFIELD.ENTERNEWVALUE'); + message = ss.i18n._t('UNIQUEFIELD.ENTERNEWVALUE', 'You will need to enter a new value for this field'); else if( suggested.length == 0 ) - message = ss.i18n._t('UNIQUEFIELD.CANNOTLEAVEEMPTY'); + message = ss.i18n._t('UNIQUEFIELD.CANNOTLEAVEEMPTY', 'This field cannot be left empty'); else if( suggestedValue ) message = this.restrictedMessage; else @@ -122,7 +122,7 @@ UniqueRestrictedTextField.prototype = { suggested = this.suggestNewValue(); statusMessage(ss.i18n.sprintf( - ss.i18n._t('UNIQUEFIELD.SUGGESTED'), + ss.i18n._t('UNIQUEFIELD.SUGGESTED', "Changed value to '%s' : %s"), suggested, message )); @@ -152,7 +152,7 @@ RestrictedTextField.prototype = { for( var index = 0; index < this.restrictedChars.length; index++ ) { if( lastChar == this.restrictedChars.charAt(index) ) { alert(ss.i18n.sprintf( - ss.i18n._t('RESTRICTEDTEXTFIELD.CHARCANTBEUSED'), + ss.i18n._t('RESTRICTEDTEXTFIELD.CHARCANTBEUSED', "The character '%s' cannot be used in this field"), lastChar )); this.value = this.value.substring( 0, this.value.length - 1 ); diff --git a/javascript/UpdateURL.js b/javascript/UpdateURL.js index 40c03f0da..36ddee2a9 100755 --- a/javascript/UpdateURL.js +++ b/javascript/UpdateURL.js @@ -11,7 +11,7 @@ Behaviour.register({ var newSuggestion = urlSegmentField.suggestNewValue( this.value.toLowerCase() ); var isNew = urlSegmentField.value.indexOf("new") == 0; var confirmMessage = ss.i18n.sprintf( - ss.i18n._t('UPDATEURL.CONFIRM'), + ss.i18n._t('UPDATEURL.CONFIRM', 'Would you like me to change the URL to:\n\n%s/\n\nClick Ok to change the URL, click Cancel to leave it as:\n\n%s'), newSuggestion, urlSegmentField.value ); diff --git a/javascript/Validator.js b/javascript/Validator.js index 7fc061bf2..2dd0b3b9b 100755 --- a/javascript/Validator.js +++ b/javascript/Validator.js @@ -147,7 +147,7 @@ function require(fieldName,cachedError) { fieldlabel = "this field"; } - var errorMessage = ss.i18n.sprintf(ss.i18n._t('VALIDATOR.FIELDREQUIRED'), fieldLabel); + var errorMessage = ss.i18n.sprintf(ss.i18n._t('VALIDATOR.FIELDREQUIRED', 'Please fill out "%s", it is required.'), fieldLabel); if(baseEl.requiredErrorMsg) errorMessage = baseEl.requiredErrorMsg; else if(_CURRENT_FORM.requiredErrorMsg) errorMessage = _CURRENT_FORM.requiredErrorMsg; diff --git a/javascript/i18n.js b/javascript/i18n.js index f8548feb8..6701ae68d 100644 --- a/javascript/i18n.js +++ b/javascript/i18n.js @@ -4,10 +4,10 @@ if(typeof(ss) == 'undefined') ss = {}; * Lightweight clientside i18n implementation. * Caution: Only available after DOM loaded because we need to detect the language * + * For non-i18n stub implementation, see sapphire/javascript/i18nx.js + * * Based on jQuery i18n plugin: 1.0.0 Feb-10-2008 - * @requires jQuery v1.1 or later - * - * Examples at: http://recurser.com/articles/2008/02/21/jquery-i18n-translation-plugin/ + * * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html @@ -51,8 +51,8 @@ ss.i18n = { * dictionary and returns the translation if one exists. If a translation * is not found, returns the original word * - * @param string entity - * @param string fallbackString + * @param string entity A "long" locale format, e.g. "de_DE" (Required) + * @param string fallbackString (Required) * @param int priority (not used) * @param string context Give translators context for the string * @return string : Translated word diff --git a/javascript/i18nx.js b/javascript/i18nx.js new file mode 100644 index 000000000..c66886a11 --- /dev/null +++ b/javascript/i18nx.js @@ -0,0 +1,40 @@ +if(typeof(ss) == 'undefined') ss = {}; + +/** + * Stub implementation for ss.i18n code. + * Use instead of sapphire/javascript/i18n.js + * if you want to use any SilverStripe javascript + * without internationalization support. + */ +ss.i18n = { + currentLocale: 'en_US', + + defaultLocale: 'en_US', + + _t: function (entity, fallbackString, priority, context) { + return fallbackString; + }, + + sprintf: function(S) { + if (arguments.length == 1) return S; + + var nS = ""; + var tS = S.split("%s"); + + var args = []; + for (var i=1, len = arguments.length; i buildSQL(); + $query = $model->extendedSQL(); } $SQL_limit = Convert::raw2sql($limit); @@ -266,4 +266,4 @@ class SearchContext extends Object { } } -?> \ No newline at end of file +?> diff --git a/security/BasicAuth.php b/security/BasicAuth.php index 243f66269..4b53ef75b 100755 --- a/security/BasicAuth.php +++ b/security/BasicAuth.php @@ -11,6 +11,7 @@ class BasicAuth extends Object { * @var boolean */ static protected $enabled = false; + static protected $autologin = false; /** * Require basic authentication. Will request a username and password if none is given. @@ -33,6 +34,9 @@ class BasicAuth extends Object { if($member) { $authenticated = true; + if(self::$autologin) { + $member->logIn(); + } } } @@ -64,10 +68,11 @@ class BasicAuth extends Object { return $member; } - static function enable() { + static function enable($auto = false) { self::$enabled = true; + self::$autologin = $auto; } static function disable() { self::$enabled = false; } -} \ No newline at end of file +} diff --git a/security/MemberLoginForm.php b/security/MemberLoginForm.php index e0b4fc927..4aff32f42 100644 --- a/security/MemberLoginForm.php +++ b/security/MemberLoginForm.php @@ -37,15 +37,6 @@ class MemberLoginForm extends LoginForm { Requirements::css($customCSS); } - // Focus on the email input when the page is loaded - Requirements::customScript(" - (function($){ - $(document).ready(function() { - $('#Email input').focus(); - }); - })(jQuery); - "); - if(isset($_REQUEST['BackURL'])) { $backURL = $_REQUEST['BackURL']; } else { @@ -85,6 +76,18 @@ class MemberLoginForm extends LoginForm { } parent::__construct($controller, $name, $fields, $actions); + + // Focus on the email input when the page is loaded + // Only include this if other form JS validation is enabled + if($this->getValidator()->getJavascriptValidationHandler() != 'none') { + Requirements::customScript(<<