Merged branches/2.3

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@66108 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Sam Minnee 2008-11-18 01:48:37 +00:00
parent 8052c5dce4
commit 3d9532db83
24 changed files with 244 additions and 113 deletions

View File

@ -54,6 +54,14 @@ class RestfulService extends ViewableData {
return "$this->baseURL" . ($this->queryString ? "?$this->queryString" : ""); return "$this->baseURL" . ($this->queryString ? "?$this->queryString" : "");
} }
/**
* @deprecated Use RestfulService::request()
*/
public function connect($subURL = '') {
user_error("RestfulService::connect is deprecated; use RestfulService::request", E_USER_NOTICE);
return $this->request($subURL, 'GET');
}
/** /**
* Makes a request to the RESTful server, and return a {@link RestfulService_Response} object for parsing of the result. * Makes a request to the RESTful server, and return a {@link RestfulService_Response} object for parsing of the result.
* @todo Better POST, PUT, DELETE, and HEAD support * @todo Better POST, PUT, DELETE, and HEAD support

View File

@ -14,6 +14,12 @@
* - SS_DATABASE_SUFFIX: A suffix to add to the database name. * - SS_DATABASE_SUFFIX: A suffix to add to the database name.
* - SS_DATABASE_PREFIX: A prefix to add to the database name. * - SS_DATABASE_PREFIX: A prefix to add to the database name.
* *
* There is one more setting that is intended to be used by people who work on SilverStripe.
* - SS_DATABASE_CHOOSE_NAME: Boolean. If true, 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.
*
* You can configure the environment with this define: * You can configure the environment with this define:
* - SS_ENVIRONMENT_TYPE: The environment type: dev, test or live. * - SS_ENVIRONMENT_TYPE: The environment type: dev, test or live.
* *
@ -31,15 +37,31 @@
/* /*
* _ss_environment.php handler * _ss_environment.php handler
*/ */
if(defined('SS_ENVIRONMENT_FILE')) {
// Only perform valdiation if SS_ENVIRONMENT_FILE is actually set, which is to say, there is an _ss_environment.php file
foreach(array( foreach(array(
'SS_DATABASE_PASSWORD', 'SS_DATABASE_PASSWORD',
'SS_DATABASE_USERNAME', 'SS_DATABASE_USERNAME',
'SS_ENVIRONMENT_TYPE',) as $reqDefine) { 'SS_ENVIRONMENT_TYPE',) as $reqDefine) {
if(!defined($reqDefine)) user_error("$reqDefine must be defined in your _ss_environment.php. See http://doc.silverstripe.com/doku.php?id=environment-management for more infomration", E_USER_ERROR); if(!defined($reqDefine)) user_error("$reqDefine must be defined in your _ss_environment.php. See http://doc.silverstripe.com/doku.php?id=environment-management for more infomration", E_USER_ERROR);
} }
}
if(defined('SS_ENVIRONMENT_TYPE')) {
Director::set_environment_type(SS_ENVIRONMENT_TYPE); Director::set_environment_type(SS_ENVIRONMENT_TYPE);
}
global $database;
// No database provided
if(!isset($database) || !$database) {
// if SS_DATABASE_CHOOSE_NAME
if(defined('SS_DATABASE_CHOOSE_NAME') && SS_DATABASE_CHOOSE_NAME) {
$database = "SS_" . basename(dirname(dirname($_SERVER['SCRIPT_FILENAME'])));
}
}
if(defined('SS_DATABASE_USERNAME') && defined('SS_DATABASE_PASSWORD')) {
global $databaseConfig; global $databaseConfig;
$databaseConfig = array( $databaseConfig = array(
"type" => "MySQLDatabase", "type" => "MySQLDatabase",
@ -50,6 +72,7 @@ $databaseConfig = array(
. $database . $database
. (defined('SS_DATABASE_SUFFIX') ? SS_DATABASE_SUFFIX : ''), . (defined('SS_DATABASE_SUFFIX') ? SS_DATABASE_SUFFIX : ''),
); );
}
if(defined('SS_SEND_ALL_EMAILS_TO')) { if(defined('SS_SEND_ALL_EMAILS_TO')) {
Email::send_all_emails_to(SS_SEND_ALL_EMAILS_TO); Email::send_all_emails_to(SS_SEND_ALL_EMAILS_TO);

View File

@ -29,6 +29,7 @@ error_reporting(E_ALL);
$envFiles = array('../_ss_environment.php', '../../_ss_environment.php', '../../../_ss_environment.php'); $envFiles = array('../_ss_environment.php', '../../_ss_environment.php', '../../../_ss_environment.php');
foreach($envFiles as $envFile) { foreach($envFiles as $envFile) {
if(file_exists($envFile)) { if(file_exists($envFile)) {
define('SS_ENVIRONMENT_FILE', $envFile);
include_once($envFile); include_once($envFile);
break; break;
} }
@ -257,6 +258,7 @@ function getClassFile($className) {
function singleton($className) { function singleton($className) {
static $_SINGLETONS; static $_SINGLETONS;
if(!isset($className)) user_error("singleton() Called without a class", E_USER_ERROR); if(!isset($className)) user_error("singleton() Called without a class", E_USER_ERROR);
if(!is_string($className)) user_error("singleton() passed bad class_name: " . var_export($className,true), E_USER_ERROR);
if(!isset($_SINGLETONS[$className])) { if(!isset($_SINGLETONS[$className])) {
if(!class_exists($className)) user_error("Bad class to singleton() - $className", E_USER_ERROR); if(!class_exists($className)) user_error("Bad class to singleton() - $className", E_USER_ERROR);
$_SINGLETONS[$className] = Object::strong_create($className,null, true); $_SINGLETONS[$className] = Object::strong_create($className,null, true);

View File

@ -104,6 +104,8 @@ class HTTP {
} }
static function findByTagAndAttribute($content, $attribs) { static function findByTagAndAttribute($content, $attribs) {
$regExps = array();
$content = '';
foreach($attribs as $tag => $attrib) { foreach($attribs as $tag => $attrib) {
if(!is_numeric($tag)) $tagPrefix = "$tag "; if(!is_numeric($tag)) $tagPrefix = "$tag ";
@ -114,9 +116,11 @@ class HTTP {
$regExps[] = "/(<{$tagPrefix}[^>]*$attrib *= *)([^\"' ]*)( )/ie"; $regExps[] = "/(<{$tagPrefix}[^>]*$attrib *= *)([^\"' ]*)( )/ie";
} }
if($regExps) {
foreach($regExps as $regExp) { foreach($regExps as $regExp) {
$content = preg_replace($regExp, '$items[] = "$2"', $content); $content = preg_replace($regExp, '$items[] = "$2"', $content);
} }
}
return isset($items) ? $items : null; return isset($items) ? $items : null;
} }

View File

@ -343,18 +343,11 @@ class Object {
if($builtIn) { if($builtIn) {
$val = $this->stat($name); $val = $this->stat($name);
$val2 = null; $val2 = null;
try {
// The reflection doesn't work properly in 5.1.2 // isset() can handle the case where a variable isn't defined; more reliable than reflection
if(phpversion() == '5.1.2') { $propertyName = get_parent_class($this) . "::\$$name";
$val2 = eval('return ' . get_parent_class($this) . "::\$$name;"); $val2 = eval("return isset($propertyName) ? $propertyName : null;");
} else {
$reflection = new ReflectionClass(get_parent_class($this));
$property = $reflection->getProperty($name);
$val2 = $property->getValue();
}
} catch(Exception $exc) {
// do nothing.. the property doesn't exists!
}
return ($val != $val2) ? $val : null; return ($val != $val2) ? $val : null;
} }

View File

@ -793,11 +793,6 @@ class Requirements_Backend {
} }
} }
// @todo Alters the original information, which means you can't call this
// method repeatedly - it will behave different on the second call!
$this->javascript = $newJSRequirements;
$this->css = $newCSSRequirements;
// Process the combined files // Process the combined files
$base = Director::baseFolder() . '/'; $base = Director::baseFolder() . '/';
foreach(array_diff_key($combinedFiles,$this->blocked) as $combinedFile => $dummy) { foreach(array_diff_key($combinedFiles,$this->blocked) as $combinedFile => $dummy) {
@ -834,11 +829,35 @@ class Requirements_Backend {
if(!file_exists(dirname($base . $combinedFile))) { if(!file_exists(dirname($base . $combinedFile))) {
Filesytem::makeFolder(dirname($base . $combinedFile)); Filesytem::makeFolder(dirname($base . $combinedFile));
} }
$successfulWrite = false;
$fh = fopen($base . $combinedFile, 'w'); $fh = fopen($base . $combinedFile, 'w');
fwrite($fh, $combinedData); if($fh) {
if(fwrite($fh, $combinedData) == strlen($combinedData)) $successfulWrite = true;
fclose($fh); fclose($fh);
unset($fh); unset($fh);
} }
// Unsuccessful write - just include the regular JS files, rather than the combined one
if(!$successfulWrite) {
user_error("Requirements_Backend::process_combined_files(): Couldn't create '$base$combinedFile'", E_USER_WARNING);
$keyedFileList = array();
foreach($fileList as $file) $keyedFileList[$file] = true;
$combinedPos = array_search($combinedFile, array_keys($newJSRequirements));
if($combinedPos) {
$newJSRequirements = array_merge(
array_slice($newJSRequirements, 0, $combinedPos),
$keyedFileList,
array_slice($newJSRequirements, $combinedPos+1)
);
}
}
}
// @todo Alters the original information, which means you can't call this
// method repeatedly - it will behave different on the second call!
$this->javascript = $newJSRequirements;
$this->css = $newCSSRequirements;
} }
function get_custom_scripts() { function get_custom_scripts() {

View File

@ -963,7 +963,7 @@ class ViewableData_Customised extends ViewableData {
} }
function XML_val($fieldName, $args = null) { function XML_val($fieldName, $args = null, $cache = false) {
if(isset($this->extraData[$fieldName])) { if(isset($this->extraData[$fieldName])) {
if(isset($_GET['debug_profile'])) { if(isset($_GET['debug_profile'])) {
Profiler::mark("template($fieldName)", " on $this->class object"); Profiler::mark("template($fieldName)", " on $this->class object");
@ -981,7 +981,7 @@ class ViewableData_Customised extends ViewableData {
return $val; return $val;
} else { } else {
return $this->obj->XML_val($fieldName, $args); return $this->obj->XML_val($fieldName, $args, $cache);
} }
} }

View File

@ -677,8 +677,6 @@ class Director {
* For information about environment types, see {@link Director::set_environment_type()}. * For information about environment types, see {@link Director::set_environment_type()}.
*/ */
static function isDev() { static function isDev() {
if(self::$environment_type) return self::$environment_type == 'dev';
// Use ?isDev=1 to get development access on the live server // Use ?isDev=1 to get development access on the live server
if(isset($_GET['isDev'])) { if(isset($_GET['isDev'])) {
if(Security::database_is_ready()) { if(Security::database_is_ready()) {
@ -691,6 +689,8 @@ class Director {
if(isset($_SESSION['isDev']) && $_SESSION['isDev']) return true; if(isset($_SESSION['isDev']) && $_SESSION['isDev']) return true;
if(self::$environment_type) return self::$environment_type == 'dev';
// Check if we are running on one of the development servers // Check if we are running on one of the development servers
if(in_array($_SERVER['HTTP_HOST'], Director::$dev_servers)) { if(in_array($_SERVER['HTTP_HOST'], Director::$dev_servers)) {
return true; return true;
@ -710,6 +710,8 @@ class Director {
* For information about environment types, see {@link Director::set_environment_type()}. * For information about environment types, see {@link Director::set_environment_type()}.
*/ */
static function isTest() { static function isTest() {
if(self::isDev()) return false;
if(self::$environment_type) { if(self::$environment_type) {
return self::$environment_type == 'test'; return self::$environment_type == 'test';
} }

View File

@ -132,7 +132,8 @@ class DB {
* @return boolean * @return boolean
*/ */
static function isActive() { static function isActive() {
return DB::$globalConn->isActive(); if(DB::$globalConn) return DB::$globalConn->isActive();
else return false;
} }
/** /**

View File

@ -1250,7 +1250,13 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
return $candidate; return $candidate;
} }
} else { } else {
eval("\$items = isset(\$items) ? array_merge((array){$class}::\$has_one, (array)\$items) : (array){$class}::\$has_one;"); $newItems = eval("return (array){$class}::\$has_one;");
// Validate the data
foreach($newItems as $k => $v) {
if(!is_string($k) || is_numeric($k) || !is_string($v)) user_error("$class::\$has_one has a bad entry: "
. var_export($k,true). " => " . var_export($v,true) . ". Each map key should be a relationship name, and the map value should be the data class to join to.", E_USER_ERROR);
}
$items = isset($items) ? array_merge($newItems, (array)$items) : $newItems;
} }
} }
return isset($items) ? $items : null; return isset($items) ? $items : null;
@ -1282,7 +1288,13 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
return $candidate; return $candidate;
} }
} else { } else {
eval("\$items = array_merge((array)\$items, (array){$class}::\$db);"); $newItems = eval("return (array){$class}::\$db;");
// Validate the data
foreach($newItems as $k => $v) {
if(!is_string($k) || is_numeric($k) || !is_string($v)) user_error("$class::\$db has a bad entry: "
. var_export($k,true). " => " . var_export($v,true) . ". Each map key should be a property name, and the map value should be the property type.", E_USER_ERROR);
}
$items = isset($items) ? array_merge($newItems, (array)$items) : $newItems;
} }
} }
@ -1310,7 +1322,13 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
return $candidate; return $candidate;
} }
} else { } else {
eval("\$items = isset(\$items) ? array_merge((array){$class}::\$has_many, (array)\$items) : (array){$class}::\$has_many;"); $newItems = eval("return (array){$class}::\$has_many;");
// Validate the data
foreach($newItems as $k => $v) {
if(!is_string($k) || is_numeric($k) || !is_string($v)) user_error("$class::\$has_many has a bad entry: "
. var_export($k,true). " => " . var_export($v,true) . ". Each map key should be a relationship name, and the map value should be the data class to join to.", E_USER_ERROR);
}
$items = isset($items) ? array_merge($newItems, (array)$items) : $newItems;
} }
} }
@ -1369,10 +1387,25 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
user_error("Orphaned \$belongs_many_many value for $this->class.$component", E_USER_ERROR); user_error("Orphaned \$belongs_many_many value for $this->class.$component", E_USER_ERROR);
} }
} else { } else {
eval("\$items = isset(\$items) ? array_merge((array){$class}::\$many_many, (array)\$items) : (array){$class}::\$many_many;"); $newItems = eval("return (array){$class}::\$many_many;");
eval("\$items = array_merge((array){$class}::\$belongs_many_many, (array)\$items);"); // Validate the data
foreach($newItems as $k => $v) {
if(!is_string($k) || is_numeric($k) || !is_string($v)) user_error("$class::\$many_many has a bad entry: "
. var_export($k,true). " => " . var_export($v,true) . ". Each map key should be a relationship name, and the map value should be the data class to join to.", E_USER_ERROR);
}
$items = isset($items) ? array_merge($newItems, $items) : $newItems;
$newItems = eval("return (array){$class}::\$belongs_many_many;");
// Validate the data
foreach($newItems as $k => $v) {
if(!is_string($k) || is_numeric($k) || !is_string($v)) user_error("$class::\$belongs_many_many has a bad entry: "
. var_export($k,true). " => " . var_export($v,true) . ". Each map key should be a relationship name, and the map value should be the data class to join to.", E_USER_ERROR);
}
$items = isset($items) ? array_merge($newItems, $items) : $newItems;
} }
} }
return isset($items) ? $items : null; return isset($items) ? $items : null;
} }
@ -2176,7 +2209,7 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
*/ */
function buildDataObjectSet($records, $containerClass = "DataObjectSet", $query = null, $baseClass = null) { function buildDataObjectSet($records, $containerClass = "DataObjectSet", $query = null, $baseClass = null) {
foreach($records as $record) { foreach($records as $record) {
if(!$record['RecordClassName']) { if(empty($record['RecordClassName'])) {
$record['RecordClassName'] = $record['ClassName']; $record['RecordClassName'] = $record['ClassName'];
} }
if(class_exists($record['RecordClassName'])) { if(class_exists($record['RecordClassName'])) {

View File

@ -103,6 +103,7 @@ class ErrorPage extends Page {
Requirements::clear(); Requirements::clear();
$controller = new ErrorPage_Controller($this); $controller = new ErrorPage_Controller($this);
$errorContent = $controller->handleRequest(new HTTPRequest('GET',''))->getBody(); $errorContent = $controller->handleRequest(new HTTPRequest('GET',''))->getBody();
Requirements::clear();
if(!file_exists(ASSETS_PATH)) { if(!file_exists(ASSETS_PATH)) {
mkdir(ASSETS_PATH, 02775); mkdir(ASSETS_PATH, 02775);

View File

@ -80,8 +80,8 @@ class SiteTree extends DataObject {
"ReportClass" => "Varchar", "ReportClass" => "Varchar",
"Priority" => "Float", "Priority" => "Float",
"CanViewType" => "Enum('Anyone, LoggedInUsers, OnlyTheseUsers, Inherit', 'Anyone')", "CanViewType" => "Enum('Anyone, LoggedInUsers, OnlyTheseUsers, Inherit', 'Inherit')",
"CanEditType" => "Enum('LoggedInUsers, OnlyTheseUsers, Inherit', 'OnlyTheseUsers')", "CanEditType" => "Enum('LoggedInUsers, OnlyTheseUsers, Inherit', 'Inherit')",
// Simple task tracking // Simple task tracking
"ToDo" => "Text", "ToDo" => "Text",
@ -123,8 +123,8 @@ class SiteTree extends DataObject {
"ShowInMenus" => 1, "ShowInMenus" => 1,
"ShowInSearch" => 1, "ShowInSearch" => 1,
"Status" => "New page", "Status" => "New page",
"CanViewType" => "Anyone", "CanViewType" => "Inherit",
"CanEditType" => "OnlyTheseUsers" "CanEditType" => "Inherit"
); );
static $has_one = array( static $has_one = array(
@ -609,14 +609,13 @@ class SiteTree extends DataObject {
if($results && is_array($results)) if(!min($results)) return false; if($results && is_array($results)) if(!min($results)) return false;
// check for empty spec // check for empty spec
if( if(!$this->CanViewType || $this->CanViewType == 'Anyone') return true;
!$this->CanViewType || $this->CanViewType == 'Anyone'
) return true;
// check for inherit // check for inherit
if( if($this->CanViewType == 'Inherit') {
$this->CanViewType == 'Inherit' && $this->Parent() if($this->ParentID) return $this->Parent()->canView($member);
) return $this->Parent()->canView($member); else return true;
}
// check for any logged-in users // check for any logged-in users
if( if(
@ -743,27 +742,19 @@ class SiteTree extends DataObject {
if(!$this->canView()) return false; if(!$this->canView()) return false;
// check for empty spec // check for empty spec
if( if(!$this->CanEditType || $this->CanEditType == 'Anyone') return true;
!$this->CanEditType || $this->CanEditType == 'Anyone'
) return true;
// check for inherit // check for inherit
if( if($this->CanEditType == 'Inherit') {
$this->CanEditType == 'Inherit' && $this->Parent() if($this->ParentID) return $this->Parent()->canEdit($member);
) return $this->Parent()->canEdit($member); else return Permission::checkMember($member, 'CMS_ACCESS_CMSMain');
}
// check for any logged-in users // check for any logged-in users
if( if($this->CanEditType == 'LoggedInUsers' && Permission::checkMember($member, 'CMS_ACCESS_CMSMain')) return true;
$this->CanEditType == 'LoggedInUsers'
&& Permission::checkMember($member, 'CMS_ACCESS_CMSMain')
) return true;
// check for specific groups // check for specific groups
if( if($this->CanEditType == 'OnlyTheseUsers' && $member && $member->inGroups($this->EditorGroups())) return true;
$this->CanEditType == 'OnlyTheseUsers'
&& $member
&& $member->inGroups($this->EditorGroups())
) return true;
return false; return false;
} }
@ -1527,6 +1518,8 @@ class SiteTree extends DataObject {
$result[$class] = ($class == $this->class) $result[$class] = ($class == $this->class)
? _t('SiteTree.CURRENTLY', 'Currently').' '.$addAction ? _t('SiteTree.CURRENTLY', 'Currently').' '.$addAction
: _t('SiteTree.CHANGETO', 'Change to').' '.$addAction; : _t('SiteTree.CHANGETO', 'Change to').' '.$addAction;
$currentAddAction = null;
$currentClass = null;
} }
} }
@ -1703,6 +1696,9 @@ class SiteTree extends DataObject {
if(!$this->canEdit() && !$this->canAddChildren()) if(!$this->canEdit() && !$this->canAddChildren())
$classes .= " disabled"; $classes .= " disabled";
if(!$this->ShowInMenus)
$classes .= " notinmenu";
$classes .= $this->markingClasses(); $classes .= $this->markingClasses();
return $classes; return $classes;

View File

@ -96,6 +96,8 @@ class Text extends DBField {
*/ */
function FirstSentence() { function FirstSentence() {
$data = Convert::xml2raw( $this->value ); $data = Convert::xml2raw( $this->value );
if( !$data ) return "";
$sentences = explode( '.', $data ); $sentences = explode( '.', $data );

View File

@ -44,7 +44,7 @@ class CsvBulkLoader extends BulkLoader {
} }
foreach($csv as $row) { foreach($csv as $row) {
$this->processRecord($row, array(), $results, $preview); $this->processRecord($row, $this->columnMap, $results, $preview);
} }
return $results; return $results;
@ -100,8 +100,10 @@ class CsvBulkLoader extends BulkLoader {
// second run: save data // second run: save data
foreach($record as $fieldName => $val) { foreach($record as $fieldName => $val) {
if($this->isNullValue($val, $fieldName)) continue; if($this->isNullValue($val, $fieldName)) continue;
if(strpos($fieldName, '->') !== FALSE) {
if($obj->hasMethod("import{$fieldName}")) { $funcName = substr($fieldName, 2);
$this->$funcName($obj, $val, $record);
} else if($obj->hasMethod("import{$fieldName}")) {
$obj->{"import{$fieldName}"}($val, $record); $obj->{"import{$fieldName}"}($val, $record);
} else { } else {
$obj->update(array($fieldName => $val)); $obj->update(array($fieldName => $val));

View File

@ -75,7 +75,7 @@ class DevelopmentAdmin extends Controller {
function build() { function build() {
$renderer = new DebugView(); $renderer = new DebugView();
$renderer->writeHeader(); $renderer->writeHeader();
$renderer->writeInfo("Environment <i>re</i>Builder (formerly db/build)", Director::absoluteBaseURL()); $renderer->writeInfo("Environment Builder (formerly db/build)", Director::absoluteBaseURL());
echo "<div style=\"margin: 0 2em\">"; echo "<div style=\"margin: 0 2em\">";
$da = new DatabaseAdmin(); $da = new DatabaseAdmin();

View File

@ -79,7 +79,6 @@ Behaviour.register({
new Ajax.Request('{$url}?ajax=1&{$this->name}=' + encodeURIComponent(this.value), { new Ajax.Request('{$url}?ajax=1&{$this->name}=' + encodeURIComponent(this.value), {
method: 'get', method: 'get',
onSuccess: function(response) { onSuccess: function(response) {
console.debug(this);
if(response.responseText == 'ok') if(response.responseText == 'ok')
Element.removeClassName(this, 'inuse'); Element.removeClassName(this, 'inuse');
else { else {

View File

@ -130,6 +130,7 @@ TableListField.prototype = {
var el = $(this.id); var el = $(this.id);
} }
if(el.getAttribute('href')) {
new Ajax.Request( new Ajax.Request(
el.getAttribute('href'), el.getAttribute('href'),
{ {
@ -140,6 +141,7 @@ TableListField.prototype = {
}.bind(this) }.bind(this)
} }
); );
}
if(e) Event.stop(e); if(e) Event.stop(e);
return false; return false;

View File

@ -22,18 +22,24 @@
// Added by SRM: Initialise the loaded_list with the scripts included on first load // Added by SRM: Initialise the loaded_list with the scripts included on first load
initialiseJSLoadedList : function() { initialiseItemLoadedList : function() {
if(this.loaded_list == null) { if(this.loaded_list == null) {
$this = this; $this = this;
$this.loaded_list = []; $this.loaded_list = {};
$('script').each(function() { $('script').each(function() {
if($(this).attr('src')) $this.loaded_list[ $(this).attr('src') ] = 1; if($(this).attr('src')) $this.loaded_list[ $(this).attr('src') ] = 1;
}); });
$('link[@rel="stylesheet"]').each(function() {
if($(this).attr('href')) $this.loaded_list[ $(this).attr('href') ] = 1;
});
} }
}, },
isJsLoaded : function(scriptUrl) { /**
this.initialiseJSLoadedList(); * Returns true if the given CSS or JS script has already been loaded
*/
isItemLoaded : function(scriptUrl) {
this.initialiseItemLoadedList();
return this.loaded_list[scriptUrl] != undefined; return this.loaded_list[scriptUrl] != undefined;
}, },
@ -60,7 +66,7 @@
this.pending = _request; this.pending = _request;
this.initialiseJSLoadedList(); this.initialiseItemLoadedList();
if (this.loaded_list[this.pending.url] != undefined) { // if required file exists (by PGA) if (this.loaded_list[this.pending.url] != undefined) { // if required file exists (by PGA)
this.requestComplete(); // => request complete this.requestComplete(); // => request complete
@ -118,6 +124,9 @@
requireCss : function(styleUrl, media){ requireCss : function(styleUrl, media){
if(media == null) media = 'all'; if(media == null) media = 'all';
// Don't double up on loading scripts
if(this.isItemLoaded(styleUrl)) return;
if(document.createStyleSheet){ if(document.createStyleSheet){
var ss = document.createStyleSheet($.requireConfig.routeCss + styleUrl); var ss = document.createStyleSheet($.requireConfig.routeCss + styleUrl);
ss.media = media; ss.media = media;
@ -130,9 +139,10 @@
media : media, media : media,
rel : 'stylesheet' rel : 'stylesheet'
}).appendTo($('head').get(0)); }).appendTo($('head').get(0));
} }
this.loaded_list[styleUrl] = 1;
} }
}) })
@ -148,7 +158,8 @@
var _dataType = s.dataType; var _dataType = s.dataType;
// This replaces the usual ajax success & complete handlers. They are called after any on demand JS is loaded. // This replaces the usual ajax success & complete handlers. They are called after any on demand JS is loaded.
var _ondemandComplete = function(xml, status) { var _ondemandComplete = function(xml) {
var status = jQuery.httpSuccess(xml) ? 'success' : 'error';
if(status == 'success') { if(status == 'success') {
data = jQuery.httpData(xml, _dataType); data = jQuery.httpData(xml, _dataType);
if(_success) _success(data, status, xml); if(_success) _success(data, status, xml);
@ -159,7 +170,7 @@
// We remove the success handler and take care of calling it outselves within _ondemandComplete // We remove the success handler and take care of calling it outselves within _ondemandComplete
s.success = null; s.success = null;
s.complete = function(xml, status) { s.complete = function(xml, status) {
processOnDemandHeaders(xml); processOnDemandHeaders(xml, _ondemandComplete);
} }
_originalAjax(s); _originalAjax(s);
@ -172,14 +183,14 @@
* once we get rid of all uses of prototype, we can remove this * once we get rid of all uses of prototype, we can remove this
*/ */
function prototypeOnDemandHandler(xml, callback) { function prototypeOnDemandHandler(xml, callback) {
processOnDemandHandlers(xml, callback); processOnDemandHeaders(xml, callback);
} }
/** /**
* Process the X-Include-CSS and X-Include-JS headers provided by the Requirements class * Process the X-Include-CSS and X-Include-JS headers provided by the Requirements class
*/ */
function processOnDemandHandlers(xml, _ondemandComplete) { function processOnDemandHeaders(xml, _ondemandComplete) {
var i; var i;
// CSS // CSS
if(xml.getResponseHeader('X-Include-CSS')) { if(xml.getResponseHeader('X-Include-CSS')) {
@ -201,7 +212,7 @@ function processOnDemandHandlers(xml, _ondemandComplete) {
if(xml.getResponseHeader('X-Include-JS')) { if(xml.getResponseHeader('X-Include-JS')) {
var jsIncludes = xml.getResponseHeader('X-Include-JS').split(','); var jsIncludes = xml.getResponseHeader('X-Include-JS').split(',');
for(i=0;i<jsIncludes.length;i++) { for(i=0;i<jsIncludes.length;i++) {
if(!jQuery.isJsLoaded(jsIncludes[i])) { if(!jQuery.isItemLoaded(jsIncludes[i])) {
newIncludes.push(jsIncludes[i]); newIncludes.push(jsIncludes[i]);
} }
} }
@ -212,7 +223,7 @@ function processOnDemandHandlers(xml, _ondemandComplete) {
// be able to execute script in the new includes (such as a livequery update) // be able to execute script in the new includes (such as a livequery update)
if(newIncludes.length > 0) { if(newIncludes.length > 0) {
for(i=0;i<jsIncludes.length;i++) { for(i=0;i<jsIncludes.length;i++) {
jQuery.requireJs(jsIncludes[i], (i == jsIncludes.length-1) ? function() { _ondemandComplete(xml, status); } : null); jQuery.requireJs(jsIncludes[i], (i == jsIncludes.length-1) ? function() { _ondemandComplete(xml); } : null);
} }
// If there aren't any new includes, then we can just call the callbacks ourselves // If there aren't any new includes, then we can just call the callbacks ourselves

View File

@ -78,6 +78,13 @@ if (isset($_GET['debug_profile'])) {
// Connect to database // Connect to database
require_once("core/model/DB.php"); require_once("core/model/DB.php");
// Redirect to the installer if no database is selected
if(!isset($databaseConfig) || !isset($databaseConfig['database']) || !$databaseConfig['database']) {
$installURL = dirname(dirname($_SERVER['SCRIPT_NAME'])) . '/install.php';
header("Location: $installURL");
die();
}
if (isset($_GET['debug_profile'])) Profiler::mark('DB::connect'); if (isset($_GET['debug_profile'])) Profiler::mark('DB::connect');
DB::connect($databaseConfig); DB::connect($databaseConfig);
if (isset($_GET['debug_profile'])) Profiler::unmark('DB::connect'); if (isset($_GET['debug_profile'])) Profiler::unmark('DB::connect');

View File

@ -30,7 +30,7 @@ class Member extends DataObject {
); );
static $has_one = array(); static $has_one = array();
static $has_many = array();
static $many_many = array(); static $many_many = array();
static $many_many_extraFields = array(); static $many_many_extraFields = array();

View File

@ -119,6 +119,7 @@ class MemberLoginForm extends LoginForm {
Session::clear("BackURL"); Session::clear("BackURL");
Director::redirect($backURL); Director::redirect($backURL);
} else { } else {
$member=Member::CurrentUser();
$firstname = Convert::raw2xml($member->FirstName); $firstname = Convert::raw2xml($member->FirstName);
Session::set("Security.Message.message", Session::set("Security.Message.message",
sprintf(_t('Member.WELCOMEBACK', "Welcome Back, %s"), $firstname) sprintf(_t('Member.WELCOMEBACK', "Welcome Back, %s"), $firstname)

View File

@ -315,6 +315,11 @@ class Security extends Controller {
// with the tabstrip library otherwise // with the tabstrip library otherwise
$link_base = Director::absoluteURL($this->Link("login")); $link_base = Director::absoluteURL($this->Link("login"));
Requirements::javascript(THIRDPARTY_DIR . "/jquery/jquery.js");
Requirements::javascript(THIRDPARTY_DIR . '/jquery/plugins/livequery/jquery.livequery.js');
Requirements::javascript(THIRDPARTY_DIR . "/tabstrip/tabstrip.js");
Requirements::css(THIRDPARTY_DIR . "/tabstrip/tabstrip.css");
$content = '<div id="Form_EditForm">'; $content = '<div id="Form_EditForm">';
$content .= '<ul class="tabstrip">'; $content .= '<ul class="tabstrip">';
$content_forms = ''; $content_forms = '';

View File

@ -31,8 +31,8 @@ class UpgradeSiteTreePermissionSchemaTask extends BuildTask {
$pageIDs = DB::query("SELECT ID FROM SiteTree")->column('ID'); $pageIDs = DB::query("SELECT ID FROM SiteTree")->column('ID');
foreach($pageIDs as $pageID) { foreach($pageIDs as $pageID) {
$page = DataObject::get_by_id('SiteTree', $pageID); $page = DataObject::get_by_id('SiteTree', $pageID);
if($page->ViewersGroup) $page->ViewerGroups()->add($page->ViewersGroup); if($page->ViewersGroup && DataObject::get_by_id("Group", $page->ViewersGroup)) $page->ViewerGroups()->add($page->ViewersGroup);
if($page->EditorsGroup) $page->EditorGroups()->add($page->EditorsGroup); if($page->EditorsGroup && DataObject::get_by_id("Group", $page->EditorsGroup)) $page->EditorGroups()->add($page->EditorsGroup);
$page->destroy(); $page->destroy();
unset($page); unset($page);

View File

@ -136,6 +136,20 @@ class CsvBulkLoaderTest extends SapphireTest {
} }
function testLoadWithCustomImportMethods() {
$loader = new CsvBulkLoaderTest_CustomLoader('CsvBulkLoaderTest_Player');
$filepath = Director::baseFolder() . '/sapphire/tests/dev/CsvBulkLoaderTest_PlayersWithHeader.csv';
$loader->columnMap = array(
'FirstName' => '->importFirstName',
'Biography' => 'Biography',
'Birthday' => 'Birthday'
);
$results = $loader->load($filepath);
$player = DataObject::get_by_id('CsvBulkLoaderTest_Player', 1);
$this->assertEquals($player->FirstName, 'Customized John');
$this->assertEquals($player->Biography, "He's a good guy");
}
protected function getLineCount(&$file) { protected function getLineCount(&$file) {
$i = 0; $i = 0;
while(fgets($file) !== false) $i++; while(fgets($file) !== false) $i++;
@ -145,6 +159,12 @@ class CsvBulkLoaderTest extends SapphireTest {
} }
class CsvBulkLoaderTest_CustomLoader extends CsvBulkLoader implements TestOnly {
function importFirstName(&$obj, $val, $record) {
$obj->FirstName = "Customized {$val}";
}
}
class CsvBulkLoaderTest_Team extends DataObject implements TestOnly { class CsvBulkLoaderTest_Team extends DataObject implements TestOnly {
static $db = array( static $db = array(
@ -184,7 +204,7 @@ class CsvBulkLoaderTest_Player extends DataObject implements TestOnly {
* @param string $val * @param string $val
* @param array $record * @param array $record
*/ */
public function setUSBirthday($val, $record) { public function setUSBirthday($val, $record = null) {
$this->Birthday = preg_replace('/^([0-9]{1,2})\/([0-9]{1,2})\/([0-90-9]{2,4})/', '\\3-\\1-\\2', $val); $this->Birthday = preg_replace('/^([0-9]{1,2})\/([0-9]{1,2})\/([0-90-9]{2,4})/', '\\3-\\1-\\2', $val);
} }
} }