mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
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:
parent
334cfc8f3e
commit
635e2c3df6
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ class ArrayData extends ViewableData {
|
||||
E_USER_WARNING
|
||||
);
|
||||
}
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function getField($f) {
|
||||
|
@ -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 {
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
?>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
@ -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]";
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
*/
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
||||
|
@ -173,7 +173,7 @@
|
||||
processOnDemandHeaders(xml, _ondemandComplete);
|
||||
}
|
||||
|
||||
_originalAjax(s);
|
||||
return _originalAjax(s);
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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>
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user