mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
MINOR Merged from branches/2.3
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@69957 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
c8200f67ac
commit
b7d394008e
@ -26,6 +26,15 @@ abstract class Extension extends Object {
|
||||
function setOwner(Object $owner) {
|
||||
$this->owner = $owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner of this decorator
|
||||
*
|
||||
* @return Object
|
||||
*/
|
||||
public function getOwner() {
|
||||
return $this->owner;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -40,7 +40,6 @@ class ManifestBuilder {
|
||||
'cli-script.php',
|
||||
'install.php',
|
||||
'index.php',
|
||||
'check-php.php',
|
||||
'rewritetest.php',
|
||||
);
|
||||
|
||||
|
@ -460,12 +460,15 @@ class Object {
|
||||
* @param string $funcName The name of the function.
|
||||
* @param mixed $arg An Argument to be passed to each of the extension functions.
|
||||
*/
|
||||
public function extend($funcName, &$arg=null) {
|
||||
public function extend($funcName, &$arg1=null, &$arg2=null, &$arg3=null, &$arg4=null, &$arg5=null, &$arg6=null, &$arg7=null) {
|
||||
$arguments = func_get_args();
|
||||
array_shift($arguments);
|
||||
|
||||
if($this->extension_instances) {
|
||||
$returnArr = array();
|
||||
foreach($this->extension_instances as $extension) {
|
||||
if($extension->hasMethod($funcName)) {
|
||||
$return = $extension->$funcName($arg);
|
||||
$return = $extension->$funcName($arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7);
|
||||
if($return !== NULL) $returnArr[] = $return;
|
||||
}
|
||||
}
|
||||
|
@ -377,7 +377,6 @@ HTML
|
||||
'index.php',
|
||||
'install.php',
|
||||
'rewritetest.php',
|
||||
'check-php.php',
|
||||
'config-form.css',
|
||||
'config-form.html',
|
||||
'index.html'
|
||||
|
@ -287,11 +287,8 @@ class Director {
|
||||
static function currentPage() {
|
||||
if(isset(Director::$urlParams['URLSegment'])) {
|
||||
$SQL_urlSegment = Convert::raw2sql(Director::$urlParams['URLSegment']);
|
||||
if (Translatable::is_enabled()) {
|
||||
return Translatable::get_one("SiteTree", "\"URLSegment\" = '$SQL_urlSegment'");
|
||||
} else {
|
||||
return DataObject::get_one("SiteTree", "\"URLSegment\" = '$SQL_urlSegment'");
|
||||
}
|
||||
|
||||
return SiteTree::get_by_url($SQL_urlSegment);
|
||||
} else {
|
||||
return Controller::curr();
|
||||
}
|
||||
|
@ -32,11 +32,8 @@ class ModelAsController extends Controller implements NestedController {
|
||||
public function getNestedController() {
|
||||
if($this->urlParams['URLSegment']) {
|
||||
$SQL_URLSegment = Convert::raw2sql($this->urlParams['URLSegment']);
|
||||
if (Translatable::is_enabled()) {
|
||||
$child = Translatable::get_one("SiteTree", "\"SiteTree\".\"URLSegment\" = '$SQL_URLSegment'", false);
|
||||
} else {
|
||||
$child = DataObject::get_one("SiteTree", "\"SiteTree\".\"URLSegment\" = '$SQL_URLSegment'", false);
|
||||
}
|
||||
$child = SiteTree::get_by_url($SQL_URLSegment);
|
||||
|
||||
if(!$child) {
|
||||
if($child = $this->findOldPage($SQL_URLSegment)) {
|
||||
$url = Controller::join_links(
|
||||
|
@ -853,26 +853,6 @@ class i18n extends Object {
|
||||
return self::$all_locales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of languages with at least one element translated in (including the default language)
|
||||
*
|
||||
* @param string $className Look for languages in elements of this class
|
||||
* @return array Map of languages in the form langCode => langName
|
||||
*/
|
||||
static function get_existing_content_languages($className = 'SiteTree', $where = '') {
|
||||
if(!Translatable::is_enabled()) return false;
|
||||
|
||||
$query = new SQLQuery('Lang',$className.'_lang',$where,"",'Lang');
|
||||
$dbLangs = $query->execute()->column();
|
||||
$langlist = array_merge((array)Translatable::default_lang(), (array)$dbLangs);
|
||||
$returnMap = array();
|
||||
$allCodes = array_merge(self::$all_locales, self::$common_languages);
|
||||
foreach ($langlist as $langCode) {
|
||||
$returnMap[$langCode] = (is_array($allCodes[$langCode]) ? $allCodes[$langCode][0] : $allCodes[$langCode]);
|
||||
}
|
||||
return $returnMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the root-directory for module-directories
|
||||
* (identified by having a _config.php on their first directory-level).
|
||||
|
@ -302,8 +302,7 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
|
||||
* @return string User friendly translated singular name of this DataObject
|
||||
*/
|
||||
function i18n_singular_name() {
|
||||
$name = (!empty($this->add_action)) ? $this->add_action : $this->singular_name();
|
||||
return _t($this->class.'.SINGULARNAME', $name);
|
||||
return _t($this->class.'.SINGULARNAME', $this->singular_name());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2245,6 +2244,9 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
|
||||
}
|
||||
|
||||
$query = $this->extendedSQL($filter, $sort, $limit, $join);
|
||||
|
||||
$this->extend('augmentSQL', $query);
|
||||
|
||||
$records = $query->execute();
|
||||
|
||||
$ret = $this->buildDataObjectSet($records, $containerClass, $query, $this->class);
|
||||
|
@ -381,6 +381,21 @@ class DataObjectSet extends ViewableData implements IteratorAggregate {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces $itemOld with $itemNew
|
||||
*
|
||||
* @param DataObject $itemOld
|
||||
* @param DataObject $itemNew
|
||||
*/
|
||||
public function replace($itemOld, $itemNew) {
|
||||
foreach($this->items as $key => $item) {
|
||||
if($item === $itemOld) {
|
||||
$this->items[$key] = $itemNew;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge another set onto the end of this set.
|
||||
* @param DataObjectSet $anotherSet Set to mege onto this set.
|
||||
|
@ -33,7 +33,7 @@ class Hierarchy extends DataObjectDecorator {
|
||||
$this->markingFinished();
|
||||
}
|
||||
|
||||
$children = $this->owner->AllChildrenIncludingDeleted();
|
||||
$children = $this->owner->AllChildrenIncludingDeleted($extraArg);
|
||||
|
||||
if($children) {
|
||||
if($attributes) {
|
||||
@ -69,13 +69,13 @@ class Hierarchy extends DataObjectDecorator {
|
||||
* @param int $minCount The minimum amount of nodes to mark.
|
||||
* @return int The actual number of nodes marked.
|
||||
*/
|
||||
public function markPartialTree($minCount = 30) {
|
||||
public function markPartialTree($minCount = 30, $context = null) {
|
||||
$this->markedNodes = array($this->owner->ID => $this->owner);
|
||||
$this->owner->markUnexpanded();
|
||||
|
||||
// foreach can't handle an ever-growing $nodes list
|
||||
while(list($id, $node) = each($this->markedNodes)) {
|
||||
$this->markChildren($node);
|
||||
$this->markChildren($node, $context);
|
||||
|
||||
if($minCount && sizeof($this->markedNodes) >= $minCount) {
|
||||
break;
|
||||
@ -139,8 +139,8 @@ class Hierarchy extends DataObjectDecorator {
|
||||
* Mark all children of the given node that match the marking filter.
|
||||
* @param DataObject $node Parent node.
|
||||
*/
|
||||
public function markChildren($node) {
|
||||
$children = $node->AllChildrenIncludingDeleted();
|
||||
public function markChildren($node, $context = null) {
|
||||
$children = $node->AllChildrenIncludingDeleted($context);
|
||||
$node->markExpanded();
|
||||
if($children) {
|
||||
foreach($children as $child) {
|
||||
@ -381,7 +381,17 @@ class Hierarchy extends DataObjectDecorator {
|
||||
* Everything else has "SameOnStage" set, as an indicator that this information has been looked up.
|
||||
* @return DataObjectSet
|
||||
*/
|
||||
public function AllChildrenIncludingDeleted() {
|
||||
public function AllChildrenIncludingDeleted($context = null) {
|
||||
return $this->doAllChildrenIncludingDeleted($context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AllChildrenIncludingDeleted
|
||||
*
|
||||
* @param unknown_type $context
|
||||
* @return DataObjectSet
|
||||
*/
|
||||
public function doAllChildrenIncludingDeleted($context = null) {
|
||||
// Cache the allChildren data, so that future requests will return the references to the same
|
||||
// object. This allows the mark..() system to work appropriately.
|
||||
|
||||
@ -391,6 +401,8 @@ class Hierarchy extends DataObjectDecorator {
|
||||
$stageChildren = $this->owner->stageChildren(true);
|
||||
$this->allChildrenIncludingDeleted = $stageChildren;
|
||||
|
||||
$this->owner->extend("augmentAllChildrenIncludingDeleted", $stageChildren, $context);
|
||||
|
||||
// Add live site content, if required.
|
||||
if($this->owner->hasExtension('Versioned')) {
|
||||
// Get all the requisite data, and index it
|
||||
@ -467,6 +479,7 @@ class Hierarchy extends DataObjectDecorator {
|
||||
// We build the query in an extension-friendly way.
|
||||
$query = new SQLQuery("COUNT(*)","\"$baseClass\"","\"ParentID\" = " . (int)$this->owner->ID);
|
||||
$this->owner->extend('augmentSQL', $query);
|
||||
$this->owner->extend('augmentNumChildrenCountQuery', $query);
|
||||
return $query->execute()->value();
|
||||
}
|
||||
|
||||
@ -478,7 +491,11 @@ class Hierarchy extends DataObjectDecorator {
|
||||
public function stageChildren($showAll = false) {
|
||||
$extraFilter = $showAll ? '' : " AND \"ShowInMenus\"";
|
||||
$baseClass = ClassInfo::baseDataClass($this->owner->class);
|
||||
return DataObject::get($baseClass, "\"{$baseClass}\".\"ParentID\" = " . (int)$this->owner->ID . " AND \"{$baseClass}\".\"ID\" != " . (int)$this->owner->ID . $extraFilter, "");
|
||||
|
||||
$staged = DataObject::get($baseClass, "\"{$baseClass}\".\"ParentID\" = " . (int)$this->owner->ID . " AND \"{$baseClass}\".\"ID\" != " . (int)$this->owner->ID . $extraFilter, "");
|
||||
if(!$staged) $staged = new DataObjectSet();
|
||||
$this->owner->extend("augmentStageChildren", $staged, $showAll);
|
||||
return $staged;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6,6 +6,10 @@
|
||||
*/
|
||||
class Image extends File {
|
||||
|
||||
const ORIENTATION_SQUARE = 0;
|
||||
const ORIENTATION_PORTRAIT = 1;
|
||||
const ORIENTATION_LANDSCAPE = 2;
|
||||
|
||||
static $casting = array(
|
||||
'Tag' => 'HTMLText',
|
||||
);
|
||||
@ -383,6 +387,21 @@ class Image extends File {
|
||||
return $this->getDimensions(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the orientation of this image.
|
||||
* @return ORIENTATION_SQUARE | ORIENTATION_PORTRAIT | ORIENTATION_LANDSCAPE
|
||||
*/
|
||||
function getOrienation() {
|
||||
$width = $this->getWidth();
|
||||
$height = $this->getHeight();
|
||||
if($width > $height) {
|
||||
return self::ORIENTATION_LANDSCAPE;
|
||||
} elseif($height > $width) {
|
||||
return self::ORIENTATION_PORTRAIT;
|
||||
} else {
|
||||
return self::ORIENTATION_SQUARE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -467,7 +486,7 @@ class Image_Uploader extends Controller {
|
||||
|
||||
// set reading lang
|
||||
if(Translatable::is_enabled() && !Director::is_ajax()) {
|
||||
Translatable::choose_site_lang(array_keys(i18n::get_existing_content_languages('SiteTree')));
|
||||
Translatable::choose_site_lang(array_keys(Translatable::get_existing_content_languages('SiteTree')));
|
||||
}
|
||||
|
||||
parent::init();
|
||||
|
@ -398,12 +398,30 @@ class SQLQuery extends Object {
|
||||
|
||||
/**
|
||||
* Checks whether this query is for a specific ID in a table
|
||||
*
|
||||
* @todo Doesn't work with combined statements (e.g. "Foo='bar' AND ID=5")
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function filtersOnID() {
|
||||
return ($this->where &&
|
||||
(strpos($this->where[0], ".\"ID\" = ") || strpos($this->where[0], ".`ID` = ") || strpos($this->where[0], ".ID = ") || strpos($this->where[0], "ID = ") )
|
||||
return (
|
||||
$this->where
|
||||
&& count($this->where) == 1
|
||||
&& preg_match('/^(.*\.)?("|`)?ID("|`)?\s?=/', $this->where[0])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this query is filtering on a foreign key, ie finding a has_many relationship
|
||||
*
|
||||
* @todo Doesn't work with combined statements (e.g. "Foo='bar' AND ParentID=5")
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function filtersOnFK() {
|
||||
return (
|
||||
$this->where
|
||||
&& preg_match('/^(.*\.)?("|`)?[a-zA-Z]+ID("|`)?\s?=/', $this->where[0])
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -138,6 +138,8 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
||||
/**
|
||||
* The text shown in the create page dropdown. If
|
||||
* this is not set, default to "Create a ClassName".
|
||||
*
|
||||
* @deprecated 2.3 Use "<myclassname>.TITLE" in the i18n language tables instead
|
||||
* @var string
|
||||
*/
|
||||
static $add_action = null;
|
||||
@ -956,14 +958,12 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
||||
DataObject::set_context_obj($this);
|
||||
|
||||
// Ensure URLSegment is unique
|
||||
$idFilter = ($this->ID)
|
||||
? " AND \"SiteTree\".\"ID\" <> '$this->ID'" :
|
||||
'';
|
||||
$idFilter = ($this->ID) ? "\"SiteTree\".\"ID\" <> '$this->ID'" : '';
|
||||
|
||||
$count = 1;
|
||||
while (
|
||||
(class_exists($this->URLSegment) && is_subclass_of($this->URLSegment, 'RequestHandler')) ||
|
||||
DataObject::get_one("SiteTree", "\"URLSegment\" = '$this->URLSegment' $idFilter")
|
||||
SiteTree::get_by_url($this->URLSegment, $idFilter)
|
||||
) {
|
||||
$count++;
|
||||
$this->URLSegment = ereg_replace('-[0-9]+$','', $this->URLSegment) . "-$count";
|
||||
@ -1024,11 +1024,15 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
||||
* Return the SiteTree object with the given URL segment.
|
||||
*
|
||||
* @param string $urlSegment The URL segment, eg 'home'
|
||||
*
|
||||
* @param string $extraFilter
|
||||
* @param boolean $cache
|
||||
* @param string $orderby
|
||||
* @return SiteTree The object with the given URL segment
|
||||
*/
|
||||
public static function get_by_url($urlSegment) {
|
||||
return DataObject::get_one("SiteTree", "\"URLSegment\" = '" . addslashes((string) $urlSegment) . "'");
|
||||
public static function get_by_url($urlSegment, $extraFilter = "", $cache = true, $orderby = "") {
|
||||
$filter = sprintf("\"URLSegment\" = '%s'", Convert::raw2sql($urlSegment));
|
||||
if($extraFilter) $filter .= " AND $extraFilter";
|
||||
return DataObject::get_one("SiteTree", $filter, $cache, $orderby);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1721,6 +1725,9 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
||||
* @return boolean
|
||||
*/
|
||||
public function getIsModifiedOnStage() {
|
||||
// new unsaved pages could be never be published
|
||||
if($this->isNew()) return false;
|
||||
|
||||
$stageVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Stage', $this->ID);
|
||||
$liveVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Live', $this->ID);
|
||||
|
||||
@ -1735,6 +1742,9 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
||||
* @return boolean
|
||||
*/
|
||||
public function getIsAddedToStage() {
|
||||
// new unsaved pages could be never be published
|
||||
if($this->isNew()) return false;
|
||||
|
||||
$stageVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Stage', $this->ID);
|
||||
$liveVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Live', $this->ID);
|
||||
|
||||
@ -1768,6 +1778,12 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
||||
);
|
||||
}
|
||||
|
||||
function i18n_singular_name() {
|
||||
$addAction = $this->stat('add_action');
|
||||
$name = (!empty($addAction)) ? $addAction : $this->singular_name();
|
||||
return _t($this->class.'.SINGULARNAME', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded to also provide entities for 'Page' class which is usually
|
||||
* located in custom code, hence textcollector picks it up for the wrong folder.
|
||||
|
@ -758,6 +758,27 @@ class Translatable extends DataObjectDecorator {
|
||||
}
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of languages with at least one element translated in (including the default language)
|
||||
*
|
||||
* @param string $className Look for languages in elements of this class
|
||||
* @return array Map of languages in the form langCode => langName
|
||||
*/
|
||||
static function get_existing_content_languages($className = 'SiteTree', $where = '') {
|
||||
if(!Translatable::is_enabled()) return false;
|
||||
$baseTable = ClassInfo::baseDataClass($className);
|
||||
$query = new SQLQuery('Lang',$baseTable.'_lang',$where,"",'Lang');
|
||||
$dbLangs = $query->execute()->column();
|
||||
$langlist = array_merge((array)Translatable::default_lang(), (array)$dbLangs);
|
||||
$returnMap = array();
|
||||
$allCodes = array_merge(i18n::$all_locales, i18n::$common_languages);
|
||||
foreach ($langlist as $langCode) {
|
||||
if($langCode)
|
||||
$returnMap[$langCode] = (is_array($allCodes[$langCode]) ? $allCodes[$langCode][0] : $allCodes[$langCode]);
|
||||
}
|
||||
return $returnMap;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
@ -210,7 +210,7 @@ class Folder extends File {
|
||||
|
||||
|
||||
function onBeforeDelete() {
|
||||
if($children = $this->AllChildren()) {
|
||||
if($this->ID && ($children = $this->AllChildren())) {
|
||||
foreach($children as $child) {
|
||||
if(!$this->Filename || !$this->Name || !file_exists($this->getFullPath())) {
|
||||
$child->setField('Name',null);
|
||||
@ -260,7 +260,7 @@ class Folder extends File {
|
||||
* Returns true if this folder has children
|
||||
*/
|
||||
public function hasChildren() {
|
||||
return $this->myChildren() && $this->myChildren()->Count() > 0;
|
||||
return $this->ID && $this->myChildren() && $this->myChildren()->Count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -269,7 +269,7 @@ class Folder extends File {
|
||||
public function autosetFilename() {
|
||||
parent::autosetFilename();
|
||||
|
||||
if($children = $this->AllChildren()) {
|
||||
if($this->ID && ($children = $this->AllChildren())) {
|
||||
$this->write();
|
||||
|
||||
foreach($children as $child) {
|
||||
@ -286,7 +286,7 @@ class Folder extends File {
|
||||
protected function resetFilename($renamePhysicalFile = true) {
|
||||
parent::resetFilename($renamePhysicalFile);
|
||||
|
||||
if($children = $this->AllChildren()) {
|
||||
if($this->ID && ($children = $this->AllChildren())) {
|
||||
$this->write();
|
||||
|
||||
foreach($children as $child) {
|
||||
|
@ -35,6 +35,9 @@ class ComplexTableField extends TableListField {
|
||||
* - A FieldSet object: Use that field set directly.
|
||||
* - A method name, eg, 'getCMSFields': Call that method on the child object to get the fields.
|
||||
*/
|
||||
|
||||
protected $addTitle;
|
||||
|
||||
protected $detailFormFields;
|
||||
|
||||
protected $viewAction, $sourceJoin, $sourceItems, $unpagedSourceItems;
|
||||
@ -302,6 +305,15 @@ JS;
|
||||
function setDetailFormValidator( Validator $validator ) {
|
||||
$this->detailFormValidator = $validator;
|
||||
}
|
||||
|
||||
function setAddTitle($addTitle) {
|
||||
if(is_string($addTitle))
|
||||
$this->addTitle = $addTitle;
|
||||
}
|
||||
|
||||
function Title() {
|
||||
return $this->addTitle ? $this->addTitle : parent::Title();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content of this formfield without surrounding layout. Triggered by Javascript
|
||||
@ -982,4 +994,4 @@ class ComplexTableField_Popup extends Form {
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
@ -127,29 +127,7 @@ class Form extends RequestHandler {
|
||||
$this->validator->setForm($this);
|
||||
|
||||
// Form error controls
|
||||
$errorInfo = Session::get("FormInfo.{$this->FormName()}");
|
||||
|
||||
if(isset($errorInfo['errors']) && is_array($errorInfo['errors'])){
|
||||
foreach($errorInfo['errors'] as $error){
|
||||
$field = $this->fields->dataFieldByName($error['fieldName']);
|
||||
|
||||
if(!$field){
|
||||
$errorInfo['message'] = $error['message'];
|
||||
$errorInfo['type'] = $error['messageType'];
|
||||
} else {
|
||||
$field->setError($error['message'],$error['messageType']);
|
||||
}
|
||||
}
|
||||
|
||||
// load data in from previous submission upon error
|
||||
if(isset($errorInfo['data']))
|
||||
$this->loadDataFrom($errorInfo['data']);
|
||||
|
||||
}
|
||||
|
||||
if(isset($errorInfo['message']) && isset($errorInfo['type'])) {
|
||||
$this->setMessage($errorInfo['message'],$errorInfo['type']);
|
||||
}
|
||||
$this->setupFormErrors();
|
||||
|
||||
$this->security = self::$default_security;
|
||||
}
|
||||
@ -161,6 +139,34 @@ class Form extends RequestHandler {
|
||||
'GET ' => 'httpSubmission',
|
||||
);
|
||||
|
||||
/**
|
||||
* Set up current form errors in session to
|
||||
* the current form if appropriate.
|
||||
*/
|
||||
function setupFormErrors() {
|
||||
$errorInfo = Session::get("FormInfo.{$this->FormName()}");
|
||||
|
||||
if(isset($errorInfo['errors']) && is_array($errorInfo['errors'])) {
|
||||
foreach($errorInfo['errors'] as $error) {
|
||||
$field = $this->fields->dataFieldByName($error['fieldName']);
|
||||
|
||||
if(!$field) {
|
||||
$errorInfo['message'] = $error['message'];
|
||||
$errorInfo['type'] = $error['messageType'];
|
||||
} else {
|
||||
$field->setError($error['message'], $error['messageType']);
|
||||
}
|
||||
}
|
||||
|
||||
// load data in from previous submission upon error
|
||||
if(isset($errorInfo['data'])) $this->loadDataFrom($errorInfo['data']);
|
||||
}
|
||||
|
||||
if(isset($errorInfo['message']) && isset($errorInfo['type'])) {
|
||||
$this->setMessage($errorInfo['message'], $errorInfo['type']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a form submission. GET and POST requests behave identically.
|
||||
* Populates the form with {@link loadDataFrom()}, calls {@link validate()},
|
||||
|
@ -445,8 +445,7 @@ class HtmlEditorField_Toolbar extends RequestHandler {
|
||||
)
|
||||
),
|
||||
new FieldSet(
|
||||
new FormAction('insertimage', _t('HtmlEditorField.BUTTONINSERTIMAGE', 'Insert image')),
|
||||
new FormAction('editimage', _t('HtmlEditorField.BUTTONEDITIMAGE', 'Edit image'))
|
||||
new FormAction('insertimage', _t('HtmlEditorField.BUTTONINSERTIMAGE', 'Insert image'))
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -17,7 +17,7 @@ class LanguageDropdownField extends GroupedDropdownField {
|
||||
*/
|
||||
function __construct($name, $title, $dontInclude = array(), $translatingClass = 'SiteTree', $list = 'Common-English' ) {
|
||||
$usedlangs = array_diff(
|
||||
i18n::get_existing_content_languages($translatingClass),
|
||||
Translatable::get_existing_content_languages($translatingClass),
|
||||
$dontInclude
|
||||
);
|
||||
// we accept in dontInclude both language codes and names, so another diff is required
|
||||
|
@ -233,7 +233,7 @@ class TableField extends TableListField {
|
||||
foreach($newitems as $k => $newitem){
|
||||
$fieldset = $this->FieldSetForRow();
|
||||
if($fieldset){
|
||||
$newitem[ID] = "new".$k;
|
||||
$newitem['ID'] = "new".$k;
|
||||
foreach($newitem as $k => $v){
|
||||
if($this->extraData && array_key_exists($k, $this->extraData)){
|
||||
unset($newitem[$k]);
|
||||
@ -563,7 +563,8 @@ JS;
|
||||
}
|
||||
}
|
||||
|
||||
function validate($validator){
|
||||
function validate($validator) {
|
||||
$errorMessage = '';
|
||||
$valid = true;
|
||||
$fields = $this->SubmittedFieldSet($sourceItemsNew);
|
||||
$fields = new FieldSet($fields);
|
||||
|
@ -50,23 +50,23 @@ class MemberLoginForm extends LoginForm {
|
||||
if(!$fields) {
|
||||
$fields = new FieldSet(
|
||||
new HiddenField("AuthenticationMethod", null, $this->authenticator_class, $this),
|
||||
new TextField("Email", _t('Member.EMAIL'),
|
||||
Session::get('SessionForms.MemberLoginForm.Email'), null, $this),
|
||||
new TextField("Email", _t('Member.EMAIL'), Session::get('SessionForms.MemberLoginForm.Email'), null, $this),
|
||||
new PasswordField("Password", _t('Member.PASSWORD'), null, $this)
|
||||
);
|
||||
if(Security::$autologin_enabled) {
|
||||
$fields->push(new CheckboxField(
|
||||
"Remember",
|
||||
_t('Member.REMEMBERME', "Remember me next time?"),
|
||||
Session::get('SessionForms.MemberLoginForm.Remember'),
|
||||
$this
|
||||
_t('Member.REMEMBERME', "Remember me next time?")
|
||||
));
|
||||
}
|
||||
}
|
||||
if(!$actions) {
|
||||
$actions = new FieldSet(
|
||||
new FormAction('dologin', _t('Member.BUTTONLOGIN', "Log in")),
|
||||
new LiteralField('forgotPassword', '<p id="ForgotPassword"><a href="Security/lostpassword">' . _t('Member.BUTTONLOSTPASSWORD', "I've lost my password") . '</a></p>')
|
||||
new LiteralField(
|
||||
'forgotPassword',
|
||||
'<p id="ForgotPassword"><a href="Security/lostpassword">' . _t('Member.BUTTONLOSTPASSWORD', "I've lost my password") . '</a></p>'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -78,7 +78,6 @@ class MemberLoginForm extends LoginForm {
|
||||
parent::__construct($controller, $name, $fields, $actions);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get message from session
|
||||
*/
|
||||
@ -113,8 +112,6 @@ class MemberLoginForm extends LoginForm {
|
||||
$cp->sessionMessage('Your password has expired. Please choose a new one.', 'good');
|
||||
|
||||
Director::redirect('Security/changepassword');
|
||||
|
||||
|
||||
} elseif(isset($_REQUEST['BackURL']) && $backURL = $_REQUEST['BackURL']) {
|
||||
Session::clear("BackURL");
|
||||
Director::redirect($backURL);
|
||||
@ -122,6 +119,14 @@ class MemberLoginForm extends LoginForm {
|
||||
$member = Member::currentUser();
|
||||
if($member) {
|
||||
$firstname = Convert::raw2xml($member->FirstName);
|
||||
|
||||
if(!empty($data['Remember'])) {
|
||||
Session::set('SessionForms.MemberLoginForm.Remember', '1');
|
||||
$member->logIn(true);
|
||||
} else {
|
||||
$member->logIn();
|
||||
}
|
||||
|
||||
Session::set('Security.Message.message',
|
||||
sprintf(_t('Member.WELCOMEBACK', "Welcome Back, %s"), $firstname)
|
||||
);
|
||||
|
@ -112,6 +112,88 @@ class SQLQueryTest extends SapphireTest {
|
||||
function testSelectWithComplexOrderbyClause() {
|
||||
// @todo Test "ORDER BY RANDOM() ASC,MyName DESC" etc.
|
||||
}
|
||||
|
||||
function testFiltersOnID() {
|
||||
$query = new SQLQuery();
|
||||
$query->where[] = "ID = 5";
|
||||
$this->assertTrue(
|
||||
$query->filtersOnID(),
|
||||
"filtersOnID() is true with simple unquoted column name"
|
||||
);
|
||||
|
||||
$query = new SQLQuery();
|
||||
$query->where[] = "ID=5";
|
||||
$this->assertTrue(
|
||||
$query->filtersOnID(),
|
||||
"filtersOnID() is true with simple unquoted column name and no spaces in equals sign"
|
||||
);
|
||||
/*
|
||||
$query = new SQLQuery();
|
||||
$query->where[] = "Foo='Bar' AND ID=5";
|
||||
$this->assertTrue(
|
||||
$query->filtersOnID(),
|
||||
"filtersOnID() is true with combined SQL statements"
|
||||
);
|
||||
*/
|
||||
|
||||
$query = new SQLQuery();
|
||||
$query->where[] = "Identifier = 5";
|
||||
$this->assertFalse(
|
||||
$query->filtersOnID(),
|
||||
"filtersOnID() is false with custom column name (starting with 'id')"
|
||||
);
|
||||
|
||||
$query = new SQLQuery();
|
||||
$query->where[] = "ParentID = 5";
|
||||
$this->assertFalse(
|
||||
$query->filtersOnID(),
|
||||
"filtersOnID() is false with column name ending in 'ID'"
|
||||
);
|
||||
|
||||
$query = new SQLQuery();
|
||||
$query->where[] = "MyTable.ID = 5";
|
||||
$this->assertTrue(
|
||||
$query->filtersOnID(),
|
||||
"filtersOnID() is true with table and column name"
|
||||
);
|
||||
|
||||
$query = new SQLQuery();
|
||||
$query->where[] = "MyTable.`ID`= 5";
|
||||
$this->assertTrue(
|
||||
$query->filtersOnID(),
|
||||
"filtersOnID() is true with table and quoted column name "
|
||||
);
|
||||
}
|
||||
|
||||
function testFiltersOnFK() {
|
||||
$query = new SQLQuery();
|
||||
$query->where[] = "ID = 5";
|
||||
$this->assertFalse(
|
||||
$query->filtersOnFK(),
|
||||
"filtersOnFK() is true with simple unquoted column name"
|
||||
);
|
||||
|
||||
$query = new SQLQuery();
|
||||
$query->where[] = "Identifier = 5";
|
||||
$this->assertFalse(
|
||||
$query->filtersOnFK(),
|
||||
"filtersOnFK() is false with custom column name (starting with 'id')"
|
||||
);
|
||||
|
||||
$query = new SQLQuery();
|
||||
$query->where[] = "MyTable.ParentID = 5";
|
||||
$this->assertTrue(
|
||||
$query->filtersOnFK(),
|
||||
"filtersOnFK() is true with table and column name"
|
||||
);
|
||||
|
||||
$query = new SQLQuery();
|
||||
$query->where[] = "MyTable.`ParentID`= 5";
|
||||
$this->assertTrue(
|
||||
$query->filtersOnFK(),
|
||||
"filtersOnFK() is true with table and quoted column name "
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SQLQueryTest_DO extends DataObject implements TestOnly {
|
||||
|
Loading…
x
Reference in New Issue
Block a user