mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02: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) {
|
function setOwner(Object $owner) {
|
||||||
$this->owner = $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',
|
'cli-script.php',
|
||||||
'install.php',
|
'install.php',
|
||||||
'index.php',
|
'index.php',
|
||||||
'check-php.php',
|
|
||||||
'rewritetest.php',
|
'rewritetest.php',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -460,12 +460,15 @@ class Object {
|
|||||||
* @param string $funcName The name of the function.
|
* @param string $funcName The name of the function.
|
||||||
* @param mixed $arg An Argument to be passed to each of the extension functions.
|
* @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) {
|
if($this->extension_instances) {
|
||||||
$returnArr = array();
|
$returnArr = array();
|
||||||
foreach($this->extension_instances as $extension) {
|
foreach($this->extension_instances as $extension) {
|
||||||
if($extension->hasMethod($funcName)) {
|
if($extension->hasMethod($funcName)) {
|
||||||
$return = $extension->$funcName($arg);
|
$return = $extension->$funcName($arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7);
|
||||||
if($return !== NULL) $returnArr[] = $return;
|
if($return !== NULL) $returnArr[] = $return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -377,7 +377,6 @@ HTML
|
|||||||
'index.php',
|
'index.php',
|
||||||
'install.php',
|
'install.php',
|
||||||
'rewritetest.php',
|
'rewritetest.php',
|
||||||
'check-php.php',
|
|
||||||
'config-form.css',
|
'config-form.css',
|
||||||
'config-form.html',
|
'config-form.html',
|
||||||
'index.html'
|
'index.html'
|
||||||
|
@ -287,11 +287,8 @@ class Director {
|
|||||||
static function currentPage() {
|
static function currentPage() {
|
||||||
if(isset(Director::$urlParams['URLSegment'])) {
|
if(isset(Director::$urlParams['URLSegment'])) {
|
||||||
$SQL_urlSegment = Convert::raw2sql(Director::$urlParams['URLSegment']);
|
$SQL_urlSegment = Convert::raw2sql(Director::$urlParams['URLSegment']);
|
||||||
if (Translatable::is_enabled()) {
|
|
||||||
return Translatable::get_one("SiteTree", "\"URLSegment\" = '$SQL_urlSegment'");
|
return SiteTree::get_by_url($SQL_urlSegment);
|
||||||
} else {
|
|
||||||
return DataObject::get_one("SiteTree", "\"URLSegment\" = '$SQL_urlSegment'");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return Controller::curr();
|
return Controller::curr();
|
||||||
}
|
}
|
||||||
|
@ -32,11 +32,8 @@ class ModelAsController extends Controller implements NestedController {
|
|||||||
public function getNestedController() {
|
public function getNestedController() {
|
||||||
if($this->urlParams['URLSegment']) {
|
if($this->urlParams['URLSegment']) {
|
||||||
$SQL_URLSegment = Convert::raw2sql($this->urlParams['URLSegment']);
|
$SQL_URLSegment = Convert::raw2sql($this->urlParams['URLSegment']);
|
||||||
if (Translatable::is_enabled()) {
|
$child = SiteTree::get_by_url($SQL_URLSegment);
|
||||||
$child = Translatable::get_one("SiteTree", "\"SiteTree\".\"URLSegment\" = '$SQL_URLSegment'", false);
|
|
||||||
} else {
|
|
||||||
$child = DataObject::get_one("SiteTree", "\"SiteTree\".\"URLSegment\" = '$SQL_URLSegment'", false);
|
|
||||||
}
|
|
||||||
if(!$child) {
|
if(!$child) {
|
||||||
if($child = $this->findOldPage($SQL_URLSegment)) {
|
if($child = $this->findOldPage($SQL_URLSegment)) {
|
||||||
$url = Controller::join_links(
|
$url = Controller::join_links(
|
||||||
|
@ -853,26 +853,6 @@ class i18n extends Object {
|
|||||||
return self::$all_locales;
|
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
|
* Searches the root-directory for module-directories
|
||||||
* (identified by having a _config.php on their first directory-level).
|
* (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
|
* @return string User friendly translated singular name of this DataObject
|
||||||
*/
|
*/
|
||||||
function i18n_singular_name() {
|
function i18n_singular_name() {
|
||||||
$name = (!empty($this->add_action)) ? $this->add_action : $this->singular_name();
|
return _t($this->class.'.SINGULARNAME', $this->singular_name());
|
||||||
return _t($this->class.'.SINGULARNAME', $name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2245,6 +2244,9 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
|
|||||||
}
|
}
|
||||||
|
|
||||||
$query = $this->extendedSQL($filter, $sort, $limit, $join);
|
$query = $this->extendedSQL($filter, $sort, $limit, $join);
|
||||||
|
|
||||||
|
$this->extend('augmentSQL', $query);
|
||||||
|
|
||||||
$records = $query->execute();
|
$records = $query->execute();
|
||||||
|
|
||||||
$ret = $this->buildDataObjectSet($records, $containerClass, $query, $this->class);
|
$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.
|
* Merge another set onto the end of this set.
|
||||||
* @param DataObjectSet $anotherSet Set to mege onto this set.
|
* @param DataObjectSet $anotherSet Set to mege onto this set.
|
||||||
|
@ -33,7 +33,7 @@ class Hierarchy extends DataObjectDecorator {
|
|||||||
$this->markingFinished();
|
$this->markingFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
$children = $this->owner->AllChildrenIncludingDeleted();
|
$children = $this->owner->AllChildrenIncludingDeleted($extraArg);
|
||||||
|
|
||||||
if($children) {
|
if($children) {
|
||||||
if($attributes) {
|
if($attributes) {
|
||||||
@ -69,13 +69,13 @@ class Hierarchy extends DataObjectDecorator {
|
|||||||
* @param int $minCount The minimum amount of nodes to mark.
|
* @param int $minCount The minimum amount of nodes to mark.
|
||||||
* @return int The actual number of nodes marked.
|
* @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->markedNodes = array($this->owner->ID => $this->owner);
|
||||||
$this->owner->markUnexpanded();
|
$this->owner->markUnexpanded();
|
||||||
|
|
||||||
// foreach can't handle an ever-growing $nodes list
|
// foreach can't handle an ever-growing $nodes list
|
||||||
while(list($id, $node) = each($this->markedNodes)) {
|
while(list($id, $node) = each($this->markedNodes)) {
|
||||||
$this->markChildren($node);
|
$this->markChildren($node, $context);
|
||||||
|
|
||||||
if($minCount && sizeof($this->markedNodes) >= $minCount) {
|
if($minCount && sizeof($this->markedNodes) >= $minCount) {
|
||||||
break;
|
break;
|
||||||
@ -139,8 +139,8 @@ class Hierarchy extends DataObjectDecorator {
|
|||||||
* Mark all children of the given node that match the marking filter.
|
* Mark all children of the given node that match the marking filter.
|
||||||
* @param DataObject $node Parent node.
|
* @param DataObject $node Parent node.
|
||||||
*/
|
*/
|
||||||
public function markChildren($node) {
|
public function markChildren($node, $context = null) {
|
||||||
$children = $node->AllChildrenIncludingDeleted();
|
$children = $node->AllChildrenIncludingDeleted($context);
|
||||||
$node->markExpanded();
|
$node->markExpanded();
|
||||||
if($children) {
|
if($children) {
|
||||||
foreach($children as $child) {
|
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.
|
* Everything else has "SameOnStage" set, as an indicator that this information has been looked up.
|
||||||
* @return DataObjectSet
|
* @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
|
// Cache the allChildren data, so that future requests will return the references to the same
|
||||||
// object. This allows the mark..() system to work appropriately.
|
// object. This allows the mark..() system to work appropriately.
|
||||||
|
|
||||||
@ -391,6 +401,8 @@ class Hierarchy extends DataObjectDecorator {
|
|||||||
$stageChildren = $this->owner->stageChildren(true);
|
$stageChildren = $this->owner->stageChildren(true);
|
||||||
$this->allChildrenIncludingDeleted = $stageChildren;
|
$this->allChildrenIncludingDeleted = $stageChildren;
|
||||||
|
|
||||||
|
$this->owner->extend("augmentAllChildrenIncludingDeleted", $stageChildren, $context);
|
||||||
|
|
||||||
// Add live site content, if required.
|
// Add live site content, if required.
|
||||||
if($this->owner->hasExtension('Versioned')) {
|
if($this->owner->hasExtension('Versioned')) {
|
||||||
// Get all the requisite data, and index it
|
// 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.
|
// We build the query in an extension-friendly way.
|
||||||
$query = new SQLQuery("COUNT(*)","\"$baseClass\"","\"ParentID\" = " . (int)$this->owner->ID);
|
$query = new SQLQuery("COUNT(*)","\"$baseClass\"","\"ParentID\" = " . (int)$this->owner->ID);
|
||||||
$this->owner->extend('augmentSQL', $query);
|
$this->owner->extend('augmentSQL', $query);
|
||||||
|
$this->owner->extend('augmentNumChildrenCountQuery', $query);
|
||||||
return $query->execute()->value();
|
return $query->execute()->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,7 +491,11 @@ class Hierarchy extends DataObjectDecorator {
|
|||||||
public function stageChildren($showAll = false) {
|
public function stageChildren($showAll = false) {
|
||||||
$extraFilter = $showAll ? '' : " AND \"ShowInMenus\"";
|
$extraFilter = $showAll ? '' : " AND \"ShowInMenus\"";
|
||||||
$baseClass = ClassInfo::baseDataClass($this->owner->class);
|
$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 {
|
class Image extends File {
|
||||||
|
|
||||||
|
const ORIENTATION_SQUARE = 0;
|
||||||
|
const ORIENTATION_PORTRAIT = 1;
|
||||||
|
const ORIENTATION_LANDSCAPE = 2;
|
||||||
|
|
||||||
static $casting = array(
|
static $casting = array(
|
||||||
'Tag' => 'HTMLText',
|
'Tag' => 'HTMLText',
|
||||||
);
|
);
|
||||||
@ -383,6 +387,21 @@ class Image extends File {
|
|||||||
return $this->getDimensions(1);
|
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
|
// set reading lang
|
||||||
if(Translatable::is_enabled() && !Director::is_ajax()) {
|
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();
|
parent::init();
|
||||||
|
@ -399,11 +399,29 @@ class SQLQuery extends Object {
|
|||||||
/**
|
/**
|
||||||
* Checks whether this query is for a specific ID in a table
|
* 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
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
function filtersOnID() {
|
function filtersOnID() {
|
||||||
return ($this->where &&
|
return (
|
||||||
(strpos($this->where[0], ".\"ID\" = ") || strpos($this->where[0], ".`ID` = ") || strpos($this->where[0], ".ID = ") || strpos($this->where[0], "ID = ") )
|
$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
|
* The text shown in the create page dropdown. If
|
||||||
* this is not set, default to "Create a ClassName".
|
* this is not set, default to "Create a ClassName".
|
||||||
|
*
|
||||||
|
* @deprecated 2.3 Use "<myclassname>.TITLE" in the i18n language tables instead
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
static $add_action = null;
|
static $add_action = null;
|
||||||
@ -956,14 +958,12 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
DataObject::set_context_obj($this);
|
DataObject::set_context_obj($this);
|
||||||
|
|
||||||
// Ensure URLSegment is unique
|
// Ensure URLSegment is unique
|
||||||
$idFilter = ($this->ID)
|
$idFilter = ($this->ID) ? "\"SiteTree\".\"ID\" <> '$this->ID'" : '';
|
||||||
? " AND \"SiteTree\".\"ID\" <> '$this->ID'" :
|
|
||||||
'';
|
|
||||||
|
|
||||||
$count = 1;
|
$count = 1;
|
||||||
while (
|
while (
|
||||||
(class_exists($this->URLSegment) && is_subclass_of($this->URLSegment, 'RequestHandler')) ||
|
(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++;
|
$count++;
|
||||||
$this->URLSegment = ereg_replace('-[0-9]+$','', $this->URLSegment) . "-$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.
|
* Return the SiteTree object with the given URL segment.
|
||||||
*
|
*
|
||||||
* @param string $urlSegment The URL segment, eg 'home'
|
* @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
|
* @return SiteTree The object with the given URL segment
|
||||||
*/
|
*/
|
||||||
public static function get_by_url($urlSegment) {
|
public static function get_by_url($urlSegment, $extraFilter = "", $cache = true, $orderby = "") {
|
||||||
return DataObject::get_one("SiteTree", "\"URLSegment\" = '" . addslashes((string) $urlSegment) . "'");
|
$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
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function getIsModifiedOnStage() {
|
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);
|
$stageVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Stage', $this->ID);
|
||||||
$liveVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Live', $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
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function getIsAddedToStage() {
|
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);
|
$stageVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Stage', $this->ID);
|
||||||
$liveVersion = Versioned::get_versionnumber_by_stage('SiteTree', 'Live', $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
|
* Overloaded to also provide entities for 'Page' class which is usually
|
||||||
* located in custom code, hence textcollector picks it up for the wrong folder.
|
* located in custom code, hence textcollector picks it up for the wrong folder.
|
||||||
|
@ -759,5 +759,26 @@ class Translatable extends DataObjectDecorator {
|
|||||||
return $table;
|
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() {
|
function onBeforeDelete() {
|
||||||
if($children = $this->AllChildren()) {
|
if($this->ID && ($children = $this->AllChildren())) {
|
||||||
foreach($children as $child) {
|
foreach($children as $child) {
|
||||||
if(!$this->Filename || !$this->Name || !file_exists($this->getFullPath())) {
|
if(!$this->Filename || !$this->Name || !file_exists($this->getFullPath())) {
|
||||||
$child->setField('Name',null);
|
$child->setField('Name',null);
|
||||||
@ -260,7 +260,7 @@ class Folder extends File {
|
|||||||
* Returns true if this folder has children
|
* Returns true if this folder has children
|
||||||
*/
|
*/
|
||||||
public function hasChildren() {
|
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() {
|
public function autosetFilename() {
|
||||||
parent::autosetFilename();
|
parent::autosetFilename();
|
||||||
|
|
||||||
if($children = $this->AllChildren()) {
|
if($this->ID && ($children = $this->AllChildren())) {
|
||||||
$this->write();
|
$this->write();
|
||||||
|
|
||||||
foreach($children as $child) {
|
foreach($children as $child) {
|
||||||
@ -286,7 +286,7 @@ class Folder extends File {
|
|||||||
protected function resetFilename($renamePhysicalFile = true) {
|
protected function resetFilename($renamePhysicalFile = true) {
|
||||||
parent::resetFilename($renamePhysicalFile);
|
parent::resetFilename($renamePhysicalFile);
|
||||||
|
|
||||||
if($children = $this->AllChildren()) {
|
if($this->ID && ($children = $this->AllChildren())) {
|
||||||
$this->write();
|
$this->write();
|
||||||
|
|
||||||
foreach($children as $child) {
|
foreach($children as $child) {
|
||||||
|
@ -35,6 +35,9 @@ class ComplexTableField extends TableListField {
|
|||||||
* - A FieldSet object: Use that field set directly.
|
* - A FieldSet object: Use that field set directly.
|
||||||
* - A method name, eg, 'getCMSFields': Call that method on the child object to get the fields.
|
* - A method name, eg, 'getCMSFields': Call that method on the child object to get the fields.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
protected $addTitle;
|
||||||
|
|
||||||
protected $detailFormFields;
|
protected $detailFormFields;
|
||||||
|
|
||||||
protected $viewAction, $sourceJoin, $sourceItems, $unpagedSourceItems;
|
protected $viewAction, $sourceJoin, $sourceItems, $unpagedSourceItems;
|
||||||
@ -303,6 +306,15 @@ JS;
|
|||||||
$this->detailFormValidator = $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
|
* Returns the content of this formfield without surrounding layout. Triggered by Javascript
|
||||||
* to update content after a DetailForm-save-action.
|
* to update content after a DetailForm-save-action.
|
||||||
|
@ -127,29 +127,7 @@ class Form extends RequestHandler {
|
|||||||
$this->validator->setForm($this);
|
$this->validator->setForm($this);
|
||||||
|
|
||||||
// Form error controls
|
// Form error controls
|
||||||
$errorInfo = Session::get("FormInfo.{$this->FormName()}");
|
$this->setupFormErrors();
|
||||||
|
|
||||||
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->security = self::$default_security;
|
$this->security = self::$default_security;
|
||||||
}
|
}
|
||||||
@ -161,6 +139,34 @@ class Form extends RequestHandler {
|
|||||||
'GET ' => 'httpSubmission',
|
'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.
|
* Handle a form submission. GET and POST requests behave identically.
|
||||||
* Populates the form with {@link loadDataFrom()}, calls {@link validate()},
|
* Populates the form with {@link loadDataFrom()}, calls {@link validate()},
|
||||||
|
@ -445,8 +445,7 @@ class HtmlEditorField_Toolbar extends RequestHandler {
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
new FieldSet(
|
new FieldSet(
|
||||||
new FormAction('insertimage', _t('HtmlEditorField.BUTTONINSERTIMAGE', 'Insert image')),
|
new FormAction('insertimage', _t('HtmlEditorField.BUTTONINSERTIMAGE', 'Insert image'))
|
||||||
new FormAction('editimage', _t('HtmlEditorField.BUTTONEDITIMAGE', 'Edit image'))
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class LanguageDropdownField extends GroupedDropdownField {
|
|||||||
*/
|
*/
|
||||||
function __construct($name, $title, $dontInclude = array(), $translatingClass = 'SiteTree', $list = 'Common-English' ) {
|
function __construct($name, $title, $dontInclude = array(), $translatingClass = 'SiteTree', $list = 'Common-English' ) {
|
||||||
$usedlangs = array_diff(
|
$usedlangs = array_diff(
|
||||||
i18n::get_existing_content_languages($translatingClass),
|
Translatable::get_existing_content_languages($translatingClass),
|
||||||
$dontInclude
|
$dontInclude
|
||||||
);
|
);
|
||||||
// we accept in dontInclude both language codes and names, so another diff is required
|
// 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){
|
foreach($newitems as $k => $newitem){
|
||||||
$fieldset = $this->FieldSetForRow();
|
$fieldset = $this->FieldSetForRow();
|
||||||
if($fieldset){
|
if($fieldset){
|
||||||
$newitem[ID] = "new".$k;
|
$newitem['ID'] = "new".$k;
|
||||||
foreach($newitem as $k => $v){
|
foreach($newitem as $k => $v){
|
||||||
if($this->extraData && array_key_exists($k, $this->extraData)){
|
if($this->extraData && array_key_exists($k, $this->extraData)){
|
||||||
unset($newitem[$k]);
|
unset($newitem[$k]);
|
||||||
@ -563,7 +563,8 @@ JS;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function validate($validator){
|
function validate($validator) {
|
||||||
|
$errorMessage = '';
|
||||||
$valid = true;
|
$valid = true;
|
||||||
$fields = $this->SubmittedFieldSet($sourceItemsNew);
|
$fields = $this->SubmittedFieldSet($sourceItemsNew);
|
||||||
$fields = new FieldSet($fields);
|
$fields = new FieldSet($fields);
|
||||||
|
@ -50,23 +50,23 @@ class MemberLoginForm extends LoginForm {
|
|||||||
if(!$fields) {
|
if(!$fields) {
|
||||||
$fields = new FieldSet(
|
$fields = new FieldSet(
|
||||||
new HiddenField("AuthenticationMethod", null, $this->authenticator_class, $this),
|
new HiddenField("AuthenticationMethod", null, $this->authenticator_class, $this),
|
||||||
new TextField("Email", _t('Member.EMAIL'),
|
new TextField("Email", _t('Member.EMAIL'), Session::get('SessionForms.MemberLoginForm.Email'), null, $this),
|
||||||
Session::get('SessionForms.MemberLoginForm.Email'), null, $this),
|
|
||||||
new PasswordField("Password", _t('Member.PASSWORD'), null, $this)
|
new PasswordField("Password", _t('Member.PASSWORD'), null, $this)
|
||||||
);
|
);
|
||||||
if(Security::$autologin_enabled) {
|
if(Security::$autologin_enabled) {
|
||||||
$fields->push(new CheckboxField(
|
$fields->push(new CheckboxField(
|
||||||
"Remember",
|
"Remember",
|
||||||
_t('Member.REMEMBERME', "Remember me next time?"),
|
_t('Member.REMEMBERME', "Remember me next time?")
|
||||||
Session::get('SessionForms.MemberLoginForm.Remember'),
|
|
||||||
$this
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!$actions) {
|
if(!$actions) {
|
||||||
$actions = new FieldSet(
|
$actions = new FieldSet(
|
||||||
new FormAction('dologin', _t('Member.BUTTONLOGIN', "Log in")),
|
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);
|
parent::__construct($controller, $name, $fields, $actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get message from session
|
* Get message from session
|
||||||
*/
|
*/
|
||||||
@ -113,8 +112,6 @@ class MemberLoginForm extends LoginForm {
|
|||||||
$cp->sessionMessage('Your password has expired. Please choose a new one.', 'good');
|
$cp->sessionMessage('Your password has expired. Please choose a new one.', 'good');
|
||||||
|
|
||||||
Director::redirect('Security/changepassword');
|
Director::redirect('Security/changepassword');
|
||||||
|
|
||||||
|
|
||||||
} elseif(isset($_REQUEST['BackURL']) && $backURL = $_REQUEST['BackURL']) {
|
} elseif(isset($_REQUEST['BackURL']) && $backURL = $_REQUEST['BackURL']) {
|
||||||
Session::clear("BackURL");
|
Session::clear("BackURL");
|
||||||
Director::redirect($backURL);
|
Director::redirect($backURL);
|
||||||
@ -122,6 +119,14 @@ class MemberLoginForm extends LoginForm {
|
|||||||
$member = Member::currentUser();
|
$member = Member::currentUser();
|
||||||
if($member) {
|
if($member) {
|
||||||
$firstname = Convert::raw2xml($member->FirstName);
|
$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',
|
Session::set('Security.Message.message',
|
||||||
sprintf(_t('Member.WELCOMEBACK', "Welcome Back, %s"), $firstname)
|
sprintf(_t('Member.WELCOMEBACK', "Welcome Back, %s"), $firstname)
|
||||||
);
|
);
|
||||||
|
@ -112,6 +112,88 @@ class SQLQueryTest extends SapphireTest {
|
|||||||
function testSelectWithComplexOrderbyClause() {
|
function testSelectWithComplexOrderbyClause() {
|
||||||
// @todo Test "ORDER BY RANDOM() ASC,MyName DESC" etc.
|
// @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 {
|
class SQLQueryTest_DO extends DataObject implements TestOnly {
|
||||||
|
Loading…
Reference in New Issue
Block a user