Merged from 2.3

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@72453 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Andrew O'Neil 2009-03-04 03:44:11 +00:00
parent 334cfc8f3e
commit 635e2c3df6
30 changed files with 221 additions and 111 deletions

View File

@ -54,10 +54,16 @@ class SapphireSoapServer extends Controller {
}
function index() {
$s = new SoapServer($this->getWSDLURL());
$s->setClass($this->class);
$s->handle();
$wsdl = $this->getViewer('wsdl')->process($this);
$wsdlFile = TEMP_FOLDER . '/sapphire-wsdl-' . $this->class;
$fh = fopen($wsdlFile, 'w');
fwrite($fh, $wsdl);
fclose($fh);
$s = new SoapServer($wsdlFile);
$s->setClass($this->class);
$s->handle();
}
}
?>
?>

View File

@ -26,6 +26,7 @@
* You can configure the default admin with these defines
* - SS_DEFAULT_ADMIN_USERNAME: The username of the default admin - this is a non-database user with administrative privileges.
* - SS_DEFAULT_ADMIN_PASSWORD: The password of the default admin.
* - SS_USE_BASIC_AUTH: Protect the site with basic auth (good for test sites)
*
* Email:
* - SS_SEND_ALL_EMAILS_TO: If you set this define, all emails will be redirected to this address.
@ -82,7 +83,10 @@ if(defined('SS_DEFAULT_ADMIN_USERNAME')) {
if(!defined('SS_DEFAULT_ADMIN_PASSWORD')) user_error("SS_DEFAULT_ADMIN_PASSWORD must be defined in your _ss_environment.php, if SS_DEFAULT_ADMIN_USERNAME is defined. See http://doc.silverstripe.com/doku.php?id=environment-management for more infomration", E_USER_ERROR);
Security::setDefaultAdmin(SS_DEFAULT_ADMIN_USERNAME, SS_DEFAULT_ADMIN_PASSWORD);
}
if(defined('SS_USE_BASIC_AUTH') && SS_USE_BASIC_AUTH) {
BasicAuth::enable();
}
if(defined('SS_ERROR_LOG')) {
Debug::log_errors_to(SS_ERROR_LOG);
}
}

View File

@ -32,6 +32,7 @@ class ArrayData extends ViewableData {
E_USER_WARNING
);
}
parent::__construct();
}
public function getField($f) {

View File

@ -24,12 +24,23 @@ class ClassInfo {
return isset($_ALL_CLASSES['exists'][$class]) ? $_ALL_CLASSES['exists'][$class] : null;
}
/**
* Cache for {@link hasTable()}
*/
private static $_cache_all_tables = null;
/**
* @todo Move this to Database or DB
*/
static function hasTable($class) {
if(DB::isActive()) {
return DB::getConn()->hasTable($class);
// Cache the list of all table names to reduce on DB traffic
if(self::$_cache_all_tables === null) {
self::$_cache_all_tables = array();
$tables = DB::query("SHOW TABLES")->column();
foreach($tables as $table) self::$_cache_all_tables[strtolower($table)] = true;
}
return isset(self::$_cache_all_tables[strtolower($class)]);
} else {
return false;
}
@ -191,4 +202,4 @@ class ClassInfo {
}
}
?>
?>

View File

@ -7,6 +7,20 @@
* @subpackage view
*/
class Requirements {
/**
* Enable combining of css/javascript files.
*
* @var boolean
*/
private static $combined_files_enabled = true;
public static function set_combined_files_enabled($enable) {
self::$combined_files_enabled = (bool) $enable;
}
public static function get_combined_files_enabled() {
return self::$combined_files_enabled;
}
/**
* Instance of requirements for storage
*
@ -777,7 +791,7 @@ class Requirements_Backend {
*/
function process_combined_files() {
if(Director::isDev() && !SapphireTest::is_running_test()) {
if((Director::isDev() && !SapphireTest::is_running_test()) || !Requirements::get_combined_files_enabled()) {
return;
}

View File

@ -369,7 +369,7 @@ class SSViewer extends Object {
static function parseTemplateContent($content, $template="") {
// Add template filename comments on dev sites
if(Director::isDev() && self::$source_file_comments && $template) {
if(Director::isDev() && self::$source_file_comments && $template && stripos($content, "<?xml") === false) {
// If this template is a full HTML page, then put the comments just inside the HTML tag to prevent any IE glitches
if(stripos($content, "<html") !== false) {
$content = preg_replace('/(<html[^>]*>)/i', "\\1<!-- template $template -->", $content);

View File

@ -244,17 +244,17 @@ JS
$archiveLink = "<a class=\"current\">". _t('ContentController.ARCHIVEDSITE', 'Archived Site') ."</a>";
$liveLink = "<a href=\"$thisPage?stage=Live\" target=\"site\" style=\"left : -3px;\">". _t('ContentController.PUBLISHEDSITE', 'Published Site') ."</a>";
$stageLink = "<a href=\"$thisPage?stage=Stage\" target=\"site\" style=\"left : -1px;\">". _t('ContentController.DRAFTSITE', 'Draft Site') ."</a>";
$message = "<div id=\"SilverStripeNavigatorMessage\" title='". _t('ContentControl.NOTEWONTBESHOWN', 'Note: this message won\'t be shown to your visitors') ."'>". _t('ContentController.ARCHIVEDSITEFROM', 'Archived site from') ."<br>" . $dateObj->Nice() . "</div>";
$message = "<div id=\"SilverStripeNavigatorMessage\" title='". _t('ContentControl.NOTEWONTBESHOWN', 'Note: this message will not be shown to your visitors') ."'>". _t('ContentController.ARCHIVEDSITEFROM', 'Archived site from') ."<br>" . $dateObj->Nice() . "</div>";
} else if(Versioned::current_stage() == 'Stage') {
$stageLink = "<a class=\"current\">". _t('ContentController.DRAFTSITE', 'Draft Site') ."</a>";
$liveLink = "<a href=\"$thisPage?stage=Live\" target=\"site\" style=\"left : -3px;\">". _t('ContentController.PUBLISHEDSITE', 'Published Site') ."</a>";
$message = "<div id=\"SilverStripeNavigatorMessage\" title='". _t('ContentControl.NOTEWONTBESHOWN', 'Note: this message won\'t be shown to your visitors') ."'>". _t('ContentController.DRAFTSITE', 'Draft Site') ."</div>";
$message = "<div id=\"SilverStripeNavigatorMessage\" title='". _t('ContentControl.NOTEWONTBESHOWN', 'Note: this message will not be shown to your visitors') ."'>". _t('ContentController.DRAFTSITE', 'Draft Site') ."</div>";
} else {
$liveLink = "<a class=\"current\">". _t('ContentController.PUBLISHEDSITE', 'Published Site') ."</a>";
$stageLink = "<a href=\"$thisPage?stage=Stage\" target=\"site\" style=\"left : -1px;\">". _t('ContentController.DRAFTSITE', 'Draft Site') ."</a>";
$message = "<div id=\"SilverStripeNavigatorMessage\" title='". _t('ContentControl.NOTEWONTBESHOWN', 'Note: this message won\'t be shown to your visitors') ."'>". _t('ContentController.PUBLISHEDSITE', 'Published Site') ."</div>";
$message = "<div id=\"SilverStripeNavigatorMessage\" title='". _t('ContentControl.NOTEWONTBESHOWN', 'Note: this message will not be shown to your visitors') ."'>". _t('ContentController.PUBLISHEDSITE', 'Published Site') ."</div>";
}
if($member) {

View File

@ -38,11 +38,11 @@ class ModelAsController extends Controller implements NestedController {
$url = Controller::join_links(
Director::baseURL(),
$child->URLSegment,
(isset($this->urlParams['Action'])) ? $this->urlParams['Action'] : null,
(isset($this->urlParams['ID'])) ? $this->urlParams['ID'] : null,
(isset($this->urlParams['OtherID'])) ? $this->urlParams['OtherID'] : null
isset($this->urlParams['Action']) ? $this->urlParams['Action'] : null,
isset($this->urlParams['ID']) ? $this->urlParams['ID'] : null,
isset($this->urlParams['OtherID']) ? $this->urlParams['OtherID'] : null
);
$response = new HTTPResponse();
$response->redirect($url, 301);
return $response;
@ -80,17 +80,32 @@ class ModelAsController extends Controller implements NestedController {
}
protected function findOldPage($urlSegment) {
$versionedQuery = new SQLQuery (
'"RecordID"', '"SiteTree_versions"',
"\"WasPublished\" AND \"URLSegment\" = '$urlSegment'",
'"LastEdited" DESC, "WasPublished"',
null, null, 1
);
// Build the query by replacing `SiteTree` with `SiteTree_versions` in a regular query.
// Note that this should *really* be handled by a more full-featured data mapper; as it stands
// this is a bit of a hack.
$origStage = Versioned::current_stage();
Versioned::reading_stage('Stage');
$versionedQuery = singleton('SiteTree')->extendedSQL('');
Versioned::reading_stage($origStage);
foreach($versionedQuery->from as $k => $v) {
$versionedQuery->renameTable($k, $k . '_versions');
}
$versionedQuery->select = array("`SiteTree_versions`.RecordID");
$versionedQuery->where[] = "`SiteTree_versions`.`WasPublished` = 1 AND `URLSegment` = '$urlSegment'";
$versionedQuery->orderby = '`LastEdited` DESC, `SiteTree_versions`.`WasPublished`';
$versionedQuery->limit = 1;
$result = $versionedQuery->execute();
if($result->numRecords() == 1 && $redirectPage = $result->nextRecord()) {
if($redirectObj = DataObject::get_by_id('SiteTree', $redirectPage['RecordID'])) return $redirectObj;
$redirectObj = DataObject::get_by_id('SiteTree', $redirectPage['RecordID']);
if($redirectObj) {
// Double-check by querying this page in the same way that getNestedController() does. This
// will prevent query muck-ups from modules such as subsites
$doubleCheck = SiteTree::get_by_url($redirectObj->URLSegment);
if($doubleCheck) return $redirectObj;
}
}
return false;
@ -102,4 +117,4 @@ class ModelAsController extends Controller implements NestedController {
}
}
?>
?>

View File

@ -1103,6 +1103,9 @@ class i18n extends Object {
static function include_by_locale($locale) {
$topLevel = scandir(Director::baseFolder());
foreach($topLevel as $module) {
//$topLevel is the website root, some server is configurated not to allow excess website root's parent level
//and we don't need to check website root's parent level and websit root level for its lang folder, so we skip these 2 levels checking.
if($module == ".." || $module == ".") continue;
if (file_exists(Director::getAbsFile("$module/_config.php")) &&
file_exists($file = Director::getAbsFile("$module/lang/$locale.php"))) {
include_once($file);

View File

@ -206,7 +206,7 @@ class i18nTextCollector extends Object {
$entitiesArr = array_merge($entitiesArr,(array)$this->collectFromTemplate($includeContent, $module, $includeFileName));
}
// @todo respect template tags (<% _t() %> instead of _t())
// @todo respect template tags (< % _t() % > instead of _t())
$regexRule = '_t[[:space:]]*\(' .
'[[:space:]]*("[^"]*"|\\\'[^\']*\\\')[[:space:]]*,' . # namespace.entity
'[[:space:]]*("([^"]|\\\")*"|\'([^\']|\\\\\')*\')([[:space:]]*,' . # value
@ -366,7 +366,7 @@ class i18nTextCollector extends Object {
user_error('i18nTextCollector->writeMasterStringFile(): Invalid PHP language file. Error: ' . $e->toString(), E_USER_ERROR);
}
fwrite($fh, "<?php\n\nglobal \$lang;\n\n" . $php . "\n?>");
fwrite($fh, "<"."?php\n\nglobal \$lang;\n\n" . $php . "\n?".">");
fclose($fh);
//Debug::message("Created file: $langFolder/" . $this->defaultLocale . ".php", false);

View File

@ -105,6 +105,29 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
* @todo Define the options that can be set here
*/
static $api_access = false;
/**
* Should dataobjects be validated before they are written?
*/
private static $validation_enabled = true;
/**
* Returns when validation on DataObjects is enabled.
* @return bool
*/
static function get_validation_enabled() {
return self::$validation_enabled;
}
/**
* Set whether DataObjects should be validated before they are written.
* @param $enable bool
* @see DataObject::validate()
*/
static function set_validation_enabled($enable) {
self::$validation_enabled = (bool) $enable;
}
/**
* Construct a new DataObject.
@ -165,6 +188,9 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
$this->extension_instances = null;
$this->components = null;
$this->destroyed = true;
$this->record = null;
$this->orignal = null;
$this->changed = null;
$this->flushCache();
}
@ -692,12 +718,14 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
$this->brokenOnWrite = true;
$isNewRecord = false;
$valid = $this->validate();
if(!$valid->valid()) {
throw new ValidationException($valid, "Validation error writing a $this->class object: " . $valid->message() . ". Object not written.", E_USER_WARNING);
return false;
if(self::get_validation_enabled()) {
$valid = $this->validate();
if(!$valid->valid()) {
throw new ValidationException($valid, "Validation error writing a $this->class object: " . $valid->message() . ". Object not written.", E_USER_WARNING);
return false;
}
}
$this->onBeforeWrite();
if($this->brokenOnWrite) {
user_error("$this->class has a broken onBeforeWrite() function. Make sure that you call parent::onBeforeWrite().", E_USER_ERROR);

View File

@ -158,13 +158,16 @@ class DatabaseAdmin extends Controller {
$conn = DB::getConn();
$conn->beginSchemaUpdate();
foreach($dataClasses as $dataClass) {
$SNG = singleton($dataClass);
if($testMode || !($SNG instanceof TestOnly)) {
if(!$quiet) {
if(Director::is_cli()) echo " * $dataClass\n";
else echo "<li>$dataClass</li>\n";
// Check if class exists before trying to instantiate - this sidesteps any manifest weirdness
if(class_exists($dataClass)) {
$SNG = singleton($dataClass);
if($testMode || !($SNG instanceof TestOnly)) {
if(!$quiet) {
if(Director::is_cli()) echo " * $dataClass\n";
else echo "<li>$dataClass</li>\n";
}
$SNG->requireTable();
}
$SNG->requireTable();
}
}
$conn->endSchemaUpdate();
@ -176,9 +179,9 @@ class DatabaseAdmin extends Controller {
}
foreach($dataClasses as $dataClass) {
// Check if class exists before trying to instantiate - this sidesteps any manifest weirdness
// Test_ indicates that it's the data class is part of testing system
if(strpos($dataClass,'Test_') === false) {
if(strpos($dataClass,'Test_') === false && class_exists($dataClass)) {
if(!$quiet) {
if(Director::is_cli()) echo " * $dataClass\n";
else echo "<li>$dataClass</li>\n";
@ -266,4 +269,4 @@ class DatabaseAdmin extends Controller {
}
?>
?>

View File

@ -272,6 +272,8 @@ class MySQLDatabase extends Database {
}
}
private static $_cache_collation_info = array();
public function fieldList($table) {
$fields = DB::query("SHOW FULL FIELDS IN \"$table\"");
foreach($fields as $field) {
@ -281,7 +283,11 @@ class MySQLDatabase extends Database {
}
if($field['Collation'] && $field['Collation'] != 'NULL') {
$collInfo = DB::query("SHOW COLLATION LIKE '$field[Collation]'")->record();
// Cache collation info to cut down on database traffic
if(!isset(self::$_cache_collation_info[$field['Collation']])) {
self::$_cache_collation_info[$field['Collation']] = DB::query("SHOW COLLATION LIKE '$field[Collation]'")->record();
}
$collInfo = self::$_cache_collation_info[$field['Collation']];
$fieldSpec .= " character set $collInfo[Charset] collate $field[Collation]";
}

View File

@ -74,6 +74,16 @@ class Date extends DBField {
if($this->value) return date($formattingString, strtotime($this->value));
}
/**
* Return the date formatted using the given strftime formatting string.
*
* strftime obeyes the current LC_TIME/LC_ALL when printing lexical values
* like day- and month-names
*/
function FormatI18N($formattingString) {
if($this->value) return strftime($formattingString, strtotime($this->value));
}
/*
* Return a string in the form "12 - 16 Sept" or "12 Aug - 16 Sept"
*/

View File

@ -40,7 +40,7 @@ table.CMSList thead th {
height : 24px;
border-right : 1px solid #aca899;
border-left : 1px solid #ffffff;
padding-left : 5px;
padding-left : 0 5px;
}
table.TableField thead th span,
@ -75,8 +75,8 @@ table.TableField tfoot td,
.TableListField table.data tfoot td,
table.CMSList tbody td,
table.CMSList tfoot td {
border : 1px solid #f1efe2;
padding-left : 5px;
border: 1px solid #f1efe2;
padding: 5px;
}
.TableListField table.data tfoot tr.addtogrouprow td {

View File

@ -128,9 +128,9 @@ abstract class BulkLoader extends ViewableData {
*
* @return BulkLoader_Result See {@link self::processAll()}
*/
public function load($filepath) {
public function load($filepath, $memory_limit='512M') {
ini_set('max_execution_time', 3600);
ini_set('memory_limit', '512M');
ini_set('memory_limit', $memory_limit);
return $this->processAll($filepath);
}

View File

@ -86,6 +86,7 @@ class CsvBulkLoader extends BulkLoader {
$obj->setComponent($relationName, $relationObj);
$obj->{"{$relationName}ID"} = $relationObj->ID;
$obj->write();
$obj->flushCache(); // avoid relation caching confusion
} elseif(strpos($fieldName, '.') !== false) {
// we have a relation column with dot notation
@ -95,11 +96,10 @@ class CsvBulkLoader extends BulkLoader {
$relationObj->write();
$obj->{"{$relationName}ID"} = $relationObj->ID;
$obj->write();
$obj->flushCache(); // avoid relation caching confusion
}
$obj->flushCache(); // avoid relation caching confusion
}
$id = ($preview) ? 0 : $obj->write();
// second run: save data
foreach($record as $fieldName => $val) {
@ -127,9 +127,15 @@ class CsvBulkLoader extends BulkLoader {
$results->addCreated($obj, $message);
}
$objID = $obj->ID;
$obj->destroy();
// memory usage
unset($existingObj);
unset($obj);
return $objID;
}
/**

View File

@ -66,9 +66,15 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
$dbadmin = new DatabaseAdmin();
$dbadmin->clearAllData();
// We have to disable validation while we import the fixtures, as the order in
// which they are imported doesnt guarantee valid relations until after the
// import is complete.
$validationenabled = DataObject::get_validation_enabled();
DataObject::set_validation_enabled(false);
$this->fixture = new YamlFixture($fixtureFile);
$this->fixture->saveIntoDatabase();
DataObject::set_validation_enabled($validationenabled);
}
// Set up email
@ -236,4 +242,4 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
}
}
?>
?>

View File

@ -133,6 +133,9 @@ class TestRunner extends Controller {
}
function runTests($classList, $coverage = false) {
// XDEBUG seem to cause problems with test execution :-(
if(function_exists('xdebug_disable')) xdebug_disable();
ini_set('max_execution_time', 0);
$this->setUp();

View File

@ -238,8 +238,8 @@ class Email extends ViewableData {
if($headerName == 'Cc') $this->cc = $headerValue;
else if($headerName == 'Bcc') $this->bcc = $headerValue;
else {
if($this->customHeaders[$headerName]) $this->customHeaders[$headerName] .= ", ";
$this->customHeaders[$headerName] .= $headerValue;
if(isset($this->customHeaders[$headerName])) $this->customHeaders[$headerName] .= ", " . $headerValue;
else $this->customHeaders[$headerName] = $headerValue;
}
}
@ -746,6 +746,8 @@ class Email_BounceRecord extends DataObject {
static $defaults = array();
static $singular_name = 'Email Bounce Record';
/**
* a record of Email_BounceRecord can't be created manually. Instead, it should be

View File

@ -40,7 +40,7 @@ class ComplexTableField extends TableListField {
protected $detailFormFields;
protected $viewAction, $sourceJoin, $sourceItems, $unpagedSourceItems;
protected $viewAction, $sourceJoin, $sourceItems;
/**
* @var Controller
@ -825,9 +825,7 @@ class ComplexTableField_ItemRequest extends RequestHandler {
if(!isset($_REQUEST['ctf']['start']) || !is_numeric($_REQUEST['ctf']['start']) || $_REQUEST['ctf']['start'] == 0) {
return null;
}
// We never use $item afterwards in the function, where we have it here? disable it!
//$item = $this->unpagedSourceItems->First();
$start = 0;
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
}
@ -837,8 +835,6 @@ class ComplexTableField_ItemRequest extends RequestHandler {
return null;
}
// We never use $item afterwards in the function, where we have it here? disable it!
// $item = $this->unpagedSourceItems->Last();
$start = $this->totalCount - 1;
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
}
@ -848,9 +844,6 @@ class ComplexTableField_ItemRequest extends RequestHandler {
return null;
}
// We never use $item afterwards in the function, where we have it here? disable it!
//$item = $this->unpagedSourceItems->getIterator()->getOffset($_REQUEST['ctf']['start'] + 1);
$start = $_REQUEST['ctf']['start'] + 1;
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
}
@ -860,9 +853,6 @@ class ComplexTableField_ItemRequest extends RequestHandler {
return null;
}
// We never use $item afterwards in the function, where we have it here? disable it!
//$item = $this->unpagedSourceItems->getIterator()->getOffset($_REQUEST['ctf']['start'] - 1);
$start = $_REQUEST['ctf']['start'] - 1;
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
}
@ -887,7 +877,6 @@ class ComplexTableField_ItemRequest extends RequestHandler {
}
for($i = $offset;$i <= $offset + $this->pageSize && $i <= $this->totalCount;$i++) {
$start = $i - 1;
$item = $this->unpagedSourceItems->getIterator()->getOffset($i-1);
$links['link'] = Controller::join_links($this->Link() . "$this->methodName?ctf[start]={$start}");
$links['number'] = $i;
$links['active'] = $i == $currentItem ? false : true;

View File

@ -54,6 +54,8 @@ class HtmlEditorField extends TextareaField {
} else if($link[0] == '/') {
$broken = true;
} else if(ereg('^assets/',$link)) {
$link = str_replace(array('%20', '%5C', '%27'), array(' ', '\\', '\''), $link);
$link = Convert::raw2sql($link);
if(!DataObject::get_one("File", "\"Filename\" = '$link'", false)) {
$broken = true;
}

View File

@ -54,13 +54,14 @@ class RequiredFields extends Validator{
function javascript() {
$js = "";
$fields = $this->form->Fields();
foreach($this->form->Fields()->dataFields() as $field) {
//if the field type has some special specific specification for validation of itself
$validationFunc = $field->jsValidation();
if($validationFunc) $js .= $validationFunc . "\n";
$dataFields = $this->form->Fields()->dataFields();
if($dataFields) {
foreach($dataFields as $field) {
// if the field type has some special specific specification for validation of itself
$validationFunc = $field->jsValidation();
if($validationFunc) $js .= $validationFunc . "\n";
}
}
$useLabels = $this->useLabels ? 'true' : 'false';
if($this->required) {

View File

@ -1,7 +1,4 @@
var checkedListNameArray = null;
var checkedListEndName = 'CheckedList';
var checkedListField = 'selected';
var checkedArray = null;
Event.observe( window, 'load', function() {
if($('sitetree')){
@ -15,9 +12,12 @@ Event.observe( window, 'load', function() {
} );
RelationComplexTableField = Class.create();
RelationComplexTableField.prototype = {
RelationComplexTableField.prototype = {
initialize: function() {
var checkedListNameArray = null;
var checkedListEndName = 'CheckedList';
var checkedListField = 'selected';
var checkedArray = null;
// 1) Find The Hidden Field Where The IDs Will Be Stored

View File

@ -173,7 +173,7 @@
processOnDemandHeaders(xml, _ondemandComplete);
}
_originalAjax(s);
return _originalAjax(s);
}
})(jQuery);

View File

@ -105,16 +105,12 @@ class SearchContext extends Object {
public function getQuery($searchParams, $sort = false, $limit = false, $existingQuery = null) {
$model = singleton($this->modelClass);
$fields = $this->applyBaseTableFields($model);
if($existingQuery) {
$query = $existingQuery;
} else {
$query = $model->buildSQL();
}
$query->select = array_merge($query->select,$fields);
$SQL_limit = Convert::raw2sql($limit);
$query->limit($SQL_limit);

View File

@ -64,9 +64,9 @@ class Member extends DataObject {
);
static $summary_fields = array(
'FirstName',
'Surname',
'Email',
'FirstName' => 'First Name',
'Surname' => 'Last Name',
'Email' => 'Email',
);
/**
@ -453,7 +453,6 @@ class Member extends DataObject {
*/
function onBeforeWrite() {
if($this->SetPassword) $this->Password = $this->SetPassword;
$identifierField = self::$unique_identifier_field;
if($this->$identifierField) {
$idClause = ($this->ID) ? " AND \"Member\".\"ID\" <> $this->ID" : '';
@ -471,6 +470,7 @@ class Member extends DataObject {
foreach($existingRecord->getAllFields() as $k => $v) {
if(!isset($this->changed[$k]) || !$this->changed[$k]) $this->record[$k] = $v;
}
$existingRecord->destroy();
}
}

View File

@ -273,6 +273,18 @@ class Security extends Controller {
* @return string Returns the "login" page as HTML code.
*/
public function login() {
// Event handler for pre-login, with an option to let it break you out of the login form
$eventResults = $this->extend('onBeforeSecurityLogin');
// If there was a redirection, return
if(Director::redirected_to()) return;
// If there was an HTTPResponse object returned, then return that
else if($eventResults) {
foreach($eventResults as $result) {
if($result instanceof HTTPResponse) return $result;
}
}
$customCSS = project() . '/css/tabs.css';
if(Director::fileExists($customCSS)) {
Requirements::css($customCSS);

View File

@ -1,9 +1,10 @@
<?xml version="1.0"?>
<rss version="2.0">
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>$Title</title>
<link>$Link</link>
<% if Description %><description>$Description.XML</description><% end_if %>
<atom:link href="$Link" rel="self" type="application/rss+xml" />
<description>$Description.XML</description>
<% control Entries %>
<item>
@ -12,10 +13,10 @@
<% if Description %><description>$Description.AbsoluteLinks.EscapeXML</description><% end_if %>
<% if Date %><pubDate>$Date.Rfc822</pubDate>
<% else %><pubDate>$Created.Rfc822</pubDate><% end_if %>
<% if Author %><author>$Author.XML</author><% end_if %>
<% if Author %><dc:creator>$Author.XML</dc:creator><% end_if %>
<guid>$AbsoluteLink</guid>
</item>
<% end_control %>
</channel>
</rss>
</rss>

View File

@ -5,7 +5,7 @@
*/
class DataObjectTest extends SapphireTest {
static $fixture_file = 'sapphire/tests/DataObjectTest.yml';
/**
* Test deletion of DataObjects
* - Deleting using delete() on the DataObject
@ -479,29 +479,20 @@ class DataObjectTest extends SapphireTest {
$reloadedTeam1 = $this->objFromFixture('DataObjectTest_Team', 'team1');
$this->assertEquals('New and improved team 1', $reloadedTeam1->Title);
}
public function testDataObjectValidation() {
public function testWritingInvalidDataObjectThrowsException() {
$validatedObject = new DataObjectTest_ValidatedObject();
$this->setExpectedException('ValidationException');
$validatedObject->write();
}
public function testWritingValidDataObjectDoesntThrowException() {
$validatedObject = new DataObjectTest_ValidatedObject();
try {
$validatedObject->write();
// If write doesn't throw an exception, this line is executed and the test fails.
$this->assertTrue(false, "Validated object did not throw a ValidationException when saving with DataObject::write");
} catch (ValidationException $validationException) {
// ValidationException wraps a ValidationResult. This result should be invalid
$this->assertFalse($validationException->getResult()->valid(), "ValidationException thrown by DataObject::write contains a valid ValidationResult. The result should be invalid.");
}
$validatedObject->Name = "Mr. Jones";
try {
$validatedObject->write();
$this->assertTrue($validatedObject->isInDB(), "Validated object was not saved to database");
} catch (Exception $exception) {
$this->assertTrue(false, "Validated object threw an unexpected exception of type " . get_class($exception) . " from DataObject::write: " . $exception->getMessage());
}
$validatedObject->write();
$this->assertTrue($validatedObject->isInDB(), "Validated object was not saved to database");
}
public function testSubclassCreation() {