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" : "");
}
/**
* @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.
* @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_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:
* - SS_ENVIRONMENT_TYPE: The environment type: dev, test or live.
*
@ -31,25 +37,42 @@
/*
* _ss_environment.php handler
*/
foreach(array(
'SS_DATABASE_PASSWORD',
'SS_DATABASE_USERNAME',
'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('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(
'SS_DATABASE_PASSWORD',
'SS_DATABASE_USERNAME',
'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);
}
}
Director::set_environment_type(SS_ENVIRONMENT_TYPE);
global $databaseConfig;
$databaseConfig = array(
"type" => "MySQLDatabase",
"server" => defined('SS_DATABASE_SERVER') ? SS_DATABASE_SERVER : 'localhost',
"username" => SS_DATABASE_USERNAME,
"password" => SS_DATABASE_PASSWORD,
"database" => (defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : '')
. $database
. (defined('SS_DATABASE_SUFFIX') ? SS_DATABASE_SUFFIX : ''),
);
if(defined('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;
$databaseConfig = array(
"type" => "MySQLDatabase",
"server" => defined('SS_DATABASE_SERVER') ? SS_DATABASE_SERVER : 'localhost',
"username" => SS_DATABASE_USERNAME,
"password" => SS_DATABASE_PASSWORD,
"database" => (defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : '')
. $database
. (defined('SS_DATABASE_SUFFIX') ? SS_DATABASE_SUFFIX : ''),
);
}
if(defined('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');
foreach($envFiles as $envFile) {
if(file_exists($envFile)) {
define('SS_ENVIRONMENT_FILE', $envFile);
include_once($envFile);
break;
}
@ -257,6 +258,7 @@ function getClassFile($className) {
function singleton($className) {
static $_SINGLETONS;
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(!class_exists($className)) user_error("Bad class to singleton() - $className", E_USER_ERROR);
$_SINGLETONS[$className] = Object::strong_create($className,null, true);

View File

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

View File

@ -343,18 +343,11 @@ class Object {
if($builtIn) {
$val = $this->stat($name);
$val2 = null;
try {
// The reflection doesn't work properly in 5.1.2
if(phpversion() == '5.1.2') {
$val2 = eval('return ' . get_parent_class($this) . "::\$$name;");
} 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!
}
// isset() can handle the case where a variable isn't defined; more reliable than reflection
$propertyName = get_parent_class($this) . "::\$$name";
$val2 = eval("return isset($propertyName) ? $propertyName : 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
$base = Director::baseFolder() . '/';
foreach(array_diff_key($combinedFiles,$this->blocked) as $combinedFile => $dummy) {
@ -834,11 +829,35 @@ class Requirements_Backend {
if(!file_exists(dirname($base . $combinedFile))) {
Filesytem::makeFolder(dirname($base . $combinedFile));
}
$successfulWrite = false;
$fh = fopen($base . $combinedFile, 'w');
fwrite($fh, $combinedData);
fclose($fh);
unset($fh);
if($fh) {
if(fwrite($fh, $combinedData) == strlen($combinedData)) $successfulWrite = true;
fclose($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() {

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($_GET['debug_profile'])) {
Profiler::mark("template($fieldName)", " on $this->class object");
@ -981,7 +981,7 @@ class ViewableData_Customised extends ViewableData {
return $val;
} 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()}.
*/
static function isDev() {
if(self::$environment_type) return self::$environment_type == 'dev';
// Use ?isDev=1 to get development access on the live server
if(isset($_GET['isDev'])) {
if(Security::database_is_ready()) {
@ -688,8 +686,10 @@ class Director {
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
if(in_array($_SERVER['HTTP_HOST'], Director::$dev_servers)) {
@ -710,6 +710,8 @@ class Director {
* For information about environment types, see {@link Director::set_environment_type()}.
*/
static function isTest() {
if(self::isDev()) return false;
if(self::$environment_type) {
return self::$environment_type == 'test';
}

View File

@ -132,7 +132,8 @@ class DB {
* @return boolean
*/
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;
}
} 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;
@ -1282,7 +1288,13 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
return $candidate;
}
} 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;
}
} 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);
}
} else {
eval("\$items = isset(\$items) ? array_merge((array){$class}::\$many_many, (array)\$items) : (array){$class}::\$many_many;");
eval("\$items = array_merge((array){$class}::\$belongs_many_many, (array)\$items);");
$newItems = eval("return (array){$class}::\$many_many;");
// 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;
}
@ -2176,7 +2209,7 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
*/
function buildDataObjectSet($records, $containerClass = "DataObjectSet", $query = null, $baseClass = null) {
foreach($records as $record) {
if(!$record['RecordClassName']) {
if(empty($record['RecordClassName'])) {
$record['RecordClassName'] = $record['ClassName'];
}
if(class_exists($record['RecordClassName'])) {

View File

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

View File

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

View File

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

View File

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

View File

@ -75,7 +75,7 @@ class DevelopmentAdmin extends Controller {
function build() {
$renderer = new DebugView();
$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\">";
$da = new DatabaseAdmin();

View File

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

View File

@ -129,17 +129,19 @@ TableListField.prototype = {
} else {
var el = $(this.id);
}
new Ajax.Request(
el.getAttribute('href'),
{
postBody: 'update=1',
onComplete: function(response) {
Element.replace(this.id, response.responseText)
Behaviour.apply($(this.id))
}.bind(this)
}
);
if(el.getAttribute('href')) {
new Ajax.Request(
el.getAttribute('href'),
{
postBody: 'update=1',
onComplete: function(response) {
Element.replace(this.id, response.responseText)
Behaviour.apply($(this.id))
}.bind(this)
}
);
}
if(e) Event.stop(e);
return false;

View File

@ -22,18 +22,24 @@
// Added by SRM: Initialise the loaded_list with the scripts included on first load
initialiseJSLoadedList : function() {
initialiseItemLoadedList : function() {
if(this.loaded_list == null) {
$this = this;
$this.loaded_list = [];
$this.loaded_list = {};
$('script').each(function() {
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;
},
@ -60,7 +66,7 @@
this.pending = _request;
this.initialiseJSLoadedList();
this.initialiseItemLoadedList();
if (this.loaded_list[this.pending.url] != undefined) { // if required file exists (by PGA)
this.requestComplete(); // => request complete
@ -118,6 +124,9 @@
requireCss : function(styleUrl, media){
if(media == null) media = 'all';
// Don't double up on loading scripts
if(this.isItemLoaded(styleUrl)) return;
if(document.createStyleSheet){
var ss = document.createStyleSheet($.requireConfig.routeCss + styleUrl);
ss.media = media;
@ -130,8 +139,9 @@
media : media,
rel : 'stylesheet'
}).appendTo($('head').get(0));
}
this.loaded_list[styleUrl] = 1;
}
@ -148,7 +158,8 @@
var _dataType = s.dataType;
// 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') {
data = jQuery.httpData(xml, _dataType);
if(_success) _success(data, status, xml);
@ -159,9 +170,9 @@
// We remove the success handler and take care of calling it outselves within _ondemandComplete
s.success = null;
s.complete = function(xml, status) {
processOnDemandHeaders(xml);
processOnDemandHeaders(xml, _ondemandComplete);
}
_originalAjax(s);
}
@ -172,14 +183,14 @@
* once we get rid of all uses of prototype, we can remove this
*/
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
*/
function processOnDemandHandlers(xml, _ondemandComplete) {
function processOnDemandHeaders(xml, _ondemandComplete) {
var i;
// CSS
if(xml.getResponseHeader('X-Include-CSS')) {
@ -201,7 +212,7 @@ function processOnDemandHandlers(xml, _ondemandComplete) {
if(xml.getResponseHeader('X-Include-JS')) {
var jsIncludes = xml.getResponseHeader('X-Include-JS').split(',');
for(i=0;i<jsIncludes.length;i++) {
if(!jQuery.isJsLoaded(jsIncludes[i])) {
if(!jQuery.isItemLoaded(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)
if(newIncludes.length > 0) {
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

View File

@ -78,6 +78,13 @@ if (isset($_GET['debug_profile'])) {
// Connect to database
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');
DB::connect($databaseConfig);
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_many = array();
static $many_many = array();
static $many_many_extraFields = array();

View File

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

View File

@ -314,7 +314,12 @@ class Security extends Controller {
// Needed because the <base href=".."> in the template makes problems
// with the tabstrip library otherwise
$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 .= '<ul class="tabstrip">';
$content_forms = '';

View File

@ -31,8 +31,8 @@ class UpgradeSiteTreePermissionSchemaTask extends BuildTask {
$pageIDs = DB::query("SELECT ID FROM SiteTree")->column('ID');
foreach($pageIDs as $pageID) {
$page = DataObject::get_by_id('SiteTree', $pageID);
if($page->ViewersGroup) $page->ViewerGroups()->add($page->ViewersGroup);
if($page->EditorsGroup) $page->EditorGroups()->add($page->EditorsGroup);
if($page->ViewersGroup && DataObject::get_by_id("Group", $page->ViewersGroup)) $page->ViewerGroups()->add($page->ViewersGroup);
if($page->EditorsGroup && DataObject::get_by_id("Group", $page->EditorsGroup)) $page->EditorGroups()->add($page->EditorsGroup);
$page->destroy();
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) {
$i = 0;
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 {
static $db = array(
@ -184,7 +204,7 @@ class CsvBulkLoaderTest_Player extends DataObject implements TestOnly {
* @param string $val
* @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);
}
}