mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
ENHANCEMENT: Improved performance of admin/assets area.
BUGFIX: Fixed bug in 'sake interactive' error handling. BUGFIX: Fixed bugs with MSSQL and Windows support. API CHANGE: Added FormAction::setButtonContent() git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@80782 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
aaef41a122
commit
f41e2b474c
@ -33,7 +33,7 @@ class Convert extends Object {
|
|||||||
foreach($val as $k => $v) $val[$k] = self::raw2att($v);
|
foreach($val as $k => $v) $val[$k] = self::raw2att($v);
|
||||||
return $val;
|
return $val;
|
||||||
} else {
|
} else {
|
||||||
return str_replace(array('&','"',"'",'<','>'), array('&','"',''','<','>'), $val);
|
return str_replace(array('&','"',"'",'<','>'), array('&','"',''','<','>'), $val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ class Convert extends Object {
|
|||||||
foreach($val as $k => $v) $val[$k] = self::raw2xml($v);
|
foreach($val as $k => $v) $val[$k] = self::raw2xml($v);
|
||||||
return $val;
|
return $val;
|
||||||
} else {
|
} else {
|
||||||
return str_replace(array('&','<','>',"\n",'"',"'"), array('&','<','>','<br />','"','''), $val);
|
return str_replace(array('&','<','>',"\n",'"',"'"), array('&','<','>','<br />','"','''), $val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ class Convert extends Object {
|
|||||||
// More complex text needs to use html2raw instead
|
// More complex text needs to use html2raw instead
|
||||||
if(strpos($val,'<') !== false) return self::html2raw($val);
|
if(strpos($val,'<') !== false) return self::html2raw($val);
|
||||||
|
|
||||||
$converted = str_replace(array('&','<','>','"','''), array('&','<','>','"',"'"), $val);
|
$converted = str_replace(array('&','<','>','"',''', '''), array('&','<','>','"',"'", "'"), $val);
|
||||||
$converted = ereg_replace('&#[0-9]+;', '', $converted);
|
$converted = ereg_replace('&#[0-9]+;', '', $converted);
|
||||||
return $converted;
|
return $converted;
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,9 @@ class Session {
|
|||||||
|
|
||||||
if(!session_id() && !headers_sent()) {
|
if(!session_id() && !headers_sent()) {
|
||||||
session_set_cookie_params(self::$timeout, Director::baseURL());
|
session_set_cookie_params(self::$timeout, Director::baseURL());
|
||||||
session_start();
|
// @ is to supress win32 warnings/notices when session wasn't cleaned up properly
|
||||||
|
// There's nothing we can do about this, because it's an operating system function!
|
||||||
|
@session_start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,8 +262,14 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
$this->class = get_class($this);
|
$this->class = get_class($this);
|
||||||
foreach($record as $k => $v) {
|
foreach($record as $k => $v) {
|
||||||
if($v) {
|
if($v) {
|
||||||
|
if($k == 'Created' || $k == 'LastEdited') {
|
||||||
|
$fieldtype = 'SSDatetime';
|
||||||
|
} else {
|
||||||
|
$fieldtype = $this->db($k);
|
||||||
|
}
|
||||||
|
|
||||||
// MSSQLDatabase::date() uses datetime for the data type for "Date" and "SSDatetime"
|
// MSSQLDatabase::date() uses datetime for the data type for "Date" and "SSDatetime"
|
||||||
switch($this->db($k)) {
|
switch($fieldtype) {
|
||||||
case "Date":
|
case "Date":
|
||||||
$v = preg_replace('/:[0-9][0-9][0-9]([ap]m)$/i', ' \\1', $v);
|
$v = preg_replace('/:[0-9][0-9][0-9]([ap]m)$/i', ' \\1', $v);
|
||||||
$record[$k] = date('Y-m-d', strtotime($v));
|
$record[$k] = date('Y-m-d', strtotime($v));
|
||||||
|
@ -429,66 +429,18 @@ class Hierarchy extends DataObjectDecorator {
|
|||||||
$stageChildren = $this->owner->stageChildren(true);
|
$stageChildren = $this->owner->stageChildren(true);
|
||||||
$this->_cache_allChildrenIncludingDeleted = $stageChildren;
|
$this->_cache_allChildrenIncludingDeleted = $stageChildren;
|
||||||
|
|
||||||
$this->owner->extend("augmentAllChildrenIncludingDeleted", $stageChildren, $context);
|
// Add live site content that doesn't exist on the stage site, 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
|
|
||||||
$liveChildren = $this->owner->liveChildren(true);
|
|
||||||
|
|
||||||
if(isset($stageChildren)) {
|
|
||||||
foreach($stageChildren as $child) {
|
|
||||||
$idxStageChildren[$child->ID] = $child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($liveChildren)) {
|
|
||||||
foreach($liveChildren as $child) {
|
|
||||||
$idxLiveChildren[$child->ID] = $child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DataObject::disable_subclass_access();
|
|
||||||
if($idxStageChildren) {
|
|
||||||
$foundInLive = Versioned::get_by_stage( $baseClass, 'Live', "\"{$baseClass}\".\"ID\" IN (" . implode(",", array_keys($idxStageChildren)) . ")", "" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if($idxLiveChildren) {
|
|
||||||
$foundInStage = Versioned::get_by_stage( $baseClass, 'Stage', "\"{$baseClass}\".\"ID\" IN (" . implode(",", array_keys($idxLiveChildren)) . ")", "" );
|
|
||||||
}
|
|
||||||
DataObject::enable_subclass_access();
|
|
||||||
|
|
||||||
if(isset($foundInLive)) {
|
|
||||||
foreach($foundInLive as $child) {
|
|
||||||
$idxFoundInLive[$child->ID] = $child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($foundInStage)) {
|
|
||||||
foreach($foundInStage as $child) {
|
|
||||||
$idxFoundInStage[$child->ID] = $child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->_cache_allChildrenIncludingDeleted = new DataObjectSet();
|
|
||||||
|
|
||||||
// First, go through the stage children. They will all be listed but may be different colours
|
|
||||||
if($stageChildren) {
|
|
||||||
foreach($stageChildren as $child) {
|
|
||||||
$this->_cache_allChildrenIncludingDeleted->push($child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next, go through the live children. Only some of these will be listed
|
// Next, go through the live children. Only some of these will be listed
|
||||||
|
$liveChildren = $this->owner->liveChildren(true, true);
|
||||||
if($liveChildren) {
|
if($liveChildren) {
|
||||||
foreach($liveChildren as $child) {
|
foreach($liveChildren as $child) {
|
||||||
// Not found on stage = deleted page. Anything else is ignored
|
|
||||||
if(!isset($idxFoundInStage[$child->ID])) {
|
|
||||||
$this->_cache_allChildrenIncludingDeleted->push($child);
|
$this->_cache_allChildrenIncludingDeleted->push($child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
$this->owner->extend("augmentAllChildrenIncludingDeleted", $stageChildren, $context);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
user_error("Hierarchy::AllChildren() Couldn't determine base class for '{$this->owner->class}'", E_USER_ERROR);
|
user_error("Hierarchy::AllChildren() Couldn't determine base class for '{$this->owner->class}'", E_USER_ERROR);
|
||||||
@ -529,7 +481,10 @@ class Hierarchy extends DataObjectDecorator {
|
|||||||
$extraFilter = $showAll ? '' : " AND \"ShowInMenus\"=1";
|
$extraFilter = $showAll ? '' : " AND \"ShowInMenus\"=1";
|
||||||
$baseClass = ClassInfo::baseDataClass($this->owner->class);
|
$baseClass = ClassInfo::baseDataClass($this->owner->class);
|
||||||
|
|
||||||
$staged = 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();
|
if(!$staged) $staged = new DataObjectSet();
|
||||||
$this->owner->extend("augmentStageChildren", $staged, $showAll);
|
$this->owner->extend("augmentStageChildren", $staged, $showAll);
|
||||||
return $staged;
|
return $staged;
|
||||||
@ -538,12 +493,28 @@ class Hierarchy extends DataObjectDecorator {
|
|||||||
/**
|
/**
|
||||||
* Return children from the live site, if it exists.
|
* Return children from the live site, if it exists.
|
||||||
* @param boolean $showAll Include all of the elements, even those not shown in the menus.
|
* @param boolean $showAll Include all of the elements, even those not shown in the menus.
|
||||||
|
* @param boolean $onlyDeletedFromStage Only return items that have been deleted from stage
|
||||||
* @return DataObjectSet
|
* @return DataObjectSet
|
||||||
*/
|
*/
|
||||||
public function liveChildren($showAll = false) {
|
public function liveChildren($showAll = false, $onlyDeletedFromStage = false) {
|
||||||
$extraFilter = $showAll ? '' : " AND \"ShowInMenus\"=1";
|
$extraFilter = $showAll ? '' : " AND \"ShowInMenus\"=1";
|
||||||
|
$join = "";
|
||||||
|
|
||||||
$baseClass = ClassInfo::baseDataClass($this->owner->class);
|
$baseClass = ClassInfo::baseDataClass($this->owner->class);
|
||||||
return Versioned::get_by_stage($baseClass, "Live", "\"{$baseClass}\".\"ParentID\" = " . (int)$this->owner->ID . " AND \"{$baseClass}\".\"ID\" != " . (int)$this->owner->ID. $extraFilter, "");
|
|
||||||
|
if($onlyDeletedFromStage) {
|
||||||
|
// Note that the lack of double-quotes around $baseClass are the only thing preventing
|
||||||
|
// it from being rewritten to {$baseClass}_Live. This is brittle, won't work in
|
||||||
|
// postgres, and will need to be fixed *somehow*. Also, this code should probably be
|
||||||
|
// refactored to be pushed into Versioned somehow; perhaps a "doesn't exist on stage X"
|
||||||
|
// option for get_by_stage.
|
||||||
|
$join = "LEFT JOIN {$baseClass} ON {$baseClass}.\"ID\" = \"{$baseClass}\".\"ID\"";
|
||||||
|
$extraFilter .= " AND {$baseClass}.\"ID\" IS NULL";
|
||||||
|
}
|
||||||
|
|
||||||
|
return Versioned::get_by_stage($baseClass, "Live", "\"{$baseClass}\".\"ParentID\" = "
|
||||||
|
. (int)$this->owner->ID . " AND \"{$baseClass}\".\"ID\" != " . (int)$this->owner->ID
|
||||||
|
. $extraFilter, null, $join);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -442,7 +442,12 @@ class Versioned extends DataObjectDecorator {
|
|||||||
|
|
||||||
$oldStage = Versioned::$reading_stage;
|
$oldStage = Versioned::$reading_stage;
|
||||||
Versioned::$reading_stage = $toStage;
|
Versioned::$reading_stage = $toStage;
|
||||||
|
|
||||||
|
$conn = DB::getConn();
|
||||||
|
if($conn->hasMethod('allowPrimaryKeyEditing')) $conn->allowPrimaryKeyEditing($baseClass, true);
|
||||||
$from->write();
|
$from->write();
|
||||||
|
if($conn->hasMethod('allowPrimaryKeyEditing')) $conn->allowPrimaryKeyEditing($baseClass, false);
|
||||||
|
|
||||||
$from->destroy();
|
$from->destroy();
|
||||||
|
|
||||||
Versioned::$reading_stage = $oldStage;
|
Versioned::$reading_stage = $oldStage;
|
||||||
|
@ -123,7 +123,7 @@ class Date extends DBField {
|
|||||||
*/
|
*/
|
||||||
function Ago() {
|
function Ago() {
|
||||||
if($this->value) {
|
if($this->value) {
|
||||||
if(time() > strtotime($this->value)) {
|
if(strtotime($this->value) == time() || time() > strtotime($this->value)) {
|
||||||
return sprintf(
|
return sprintf(
|
||||||
_t(
|
_t(
|
||||||
'Date.TIMEDIFFAGO',
|
'Date.TIMEDIFFAGO',
|
||||||
|
@ -44,7 +44,9 @@ class HTMLText extends Text {
|
|||||||
|
|
||||||
/* Catch warnings thrown by loadHTML and turn them into a failure boolean rather than a SilverStripe error */
|
/* Catch warnings thrown by loadHTML and turn them into a failure boolean rather than a SilverStripe error */
|
||||||
set_error_handler(create_function('$no, $str', 'throw new Exception("HTML Parse Error: ".$str);'), E_ALL);
|
set_error_handler(create_function('$no, $str', 'throw new Exception("HTML Parse Error: ".$str);'), E_ALL);
|
||||||
try { $res = $doc->loadHTML('<meta content="text/html; charset=utf-8" http-equiv="Content-type"/>' . $this->value); }
|
// Nonbreaking spaces get converted into weird characters, so strip them
|
||||||
|
$value = str_replace(' ', ' ', $this->value);
|
||||||
|
try { $res = $doc->loadHTML('<meta content="text/html; charset=utf-8" http-equiv="Content-type"/>' . $value); }
|
||||||
catch (Exception $e) { $res = false; }
|
catch (Exception $e) { $res = false; }
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ define('30719',E_ALL);
|
|||||||
*/
|
*/
|
||||||
class SapphireREPL extends Controller {
|
class SapphireREPL extends Controller {
|
||||||
|
|
||||||
private function error_handler( $errno, $errstr, $errfile, $errline, $errctx ) {
|
public function error_handler( $errno, $errstr, $errfile, $errline, $errctx ) {
|
||||||
// Ignore unless important error
|
// Ignore unless important error
|
||||||
if ( ($errno & ~( 2048 | 8192 | 16384 )) == 0 ) return ;
|
if ( ($errno & ~( 2048 | 8192 | 16384 )) == 0 ) return ;
|
||||||
// Otherwise throw exception to handle in REPL loop
|
// Otherwise throw exception to handle in REPL loop
|
||||||
|
@ -191,11 +191,15 @@ class Folder extends File {
|
|||||||
if($oldFile == $file && $i > 2) user_error("Couldn't fix $file with $i", E_USER_ERROR);
|
if($oldFile == $file && $i > 2) user_error("Couldn't fix $file with $i", E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(file_exists($tmpFile['tmp_name']) && copy($tmpFile['tmp_name'], "$base/$file")) {
|
//$fullFilename = "$base/$file";
|
||||||
|
$fullFilename = $base . DIRECTORY_SEPARATOR . str_replace(array("\\","/") , DIRECTORY_SEPARATOR, $file );
|
||||||
|
|
||||||
|
if(file_exists($tmpFile['tmp_name']) && copy($tmpFile['tmp_name'], $fullFilename)) {
|
||||||
// Update with the new image
|
// Update with the new image
|
||||||
return $this->constructChild(basename($file));
|
return $this->constructChild(basename($file));
|
||||||
} else {
|
} else {
|
||||||
user_error("Folder::addUploadToFolder: Couldn't copy '$tmpFile[tmp_name]' to '$file'", E_USER_ERROR);
|
if(!file_exists($tmpFile['tmp_name'])) user_error("Folder::addUploadToFolder: '$tmpFile[tmp_name]' doesn't exist", E_USER_ERROR);
|
||||||
|
else user_error("Folder::addUploadToFolder: Couldn't copy '$tmpFile[tmp_name]' to '$fullFilename'", E_USER_ERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,7 +264,18 @@ 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->ID && $this->myChildren() && $this->myChildren()->Count() > 0;
|
return (bool)DB::query("SELECT COUNT(*) FROM \"File\" WHERE ParentID = "
|
||||||
|
. (int)$this->ID)->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this folder has children
|
||||||
|
*/
|
||||||
|
public function hasChildFolders() {
|
||||||
|
$SQL_folderClasses = Convert::raw2sql(ClassInfo::subclassesFor('Folder'));
|
||||||
|
|
||||||
|
return (bool)DB::query("SELECT COUNT(*) FROM \"File\" WHERE ParentID = " . (int)$this->ID
|
||||||
|
. " AND \"ClassName\" IN ('" . implode("','", $SQL_folderClasses) . "')")->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -311,7 +326,6 @@ class Folder extends File {
|
|||||||
*/
|
*/
|
||||||
function getCMSFields() {
|
function getCMSFields() {
|
||||||
$nameField = ($this->ID > 0) ? new TextField("Name") : new HiddenField("Name");
|
$nameField = ($this->ID > 0) ? new TextField("Name") : new HiddenField("Name");
|
||||||
|
|
||||||
$fileList = new AssetTableField(
|
$fileList = new AssetTableField(
|
||||||
$this,
|
$this,
|
||||||
"Files",
|
"Files",
|
||||||
@ -350,10 +364,10 @@ class Folder extends File {
|
|||||||
new LiteralField("UploadIframe",
|
new LiteralField("UploadIframe",
|
||||||
$this->getUploadIframe()
|
$this->getUploadIframe()
|
||||||
)
|
)
|
||||||
),
|
)/*,
|
||||||
new Tab("UnusedFiles", _t('Folder.UNUSEDFILESTAB', "Unused files"),
|
new Tab("UnusedFiles", _t('Folder.UNUSEDFILESTAB', "Unused files"),
|
||||||
new Folder_UnusedAssetsField($this)
|
new Folder_UnusedAssetsField($this)
|
||||||
)
|
)*/
|
||||||
),
|
),
|
||||||
new HiddenField("ID")
|
new HiddenField("ID")
|
||||||
);
|
);
|
||||||
@ -422,6 +436,12 @@ class Folder extends File {
|
|||||||
HTML;
|
HTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the children of this folder that are also folders.
|
||||||
|
*/
|
||||||
|
function ChildFolders() {
|
||||||
|
return DataObject::get("Folder", "ParentID = " . (int)$this->ID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Folder_UnusedAssetsField extends CompositeField {
|
class Folder_UnusedAssetsField extends CompositeField {
|
||||||
|
@ -19,6 +19,16 @@ class FormAction extends FormField {
|
|||||||
*/
|
*/
|
||||||
public $useButtonTag = false;
|
public $useButtonTag = false;
|
||||||
|
|
||||||
|
private $buttonContent = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add content inside a button field.
|
||||||
|
*/
|
||||||
|
function setButtonContent($content) {
|
||||||
|
$this->buttonContent = (string) $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new action button.
|
* Create a new action button.
|
||||||
* @param action The method to call when the button is clicked
|
* @param action The method to call when the button is clicked
|
||||||
@ -74,7 +84,7 @@ class FormAction extends FormField {
|
|||||||
$attributes['class'] = $attributes['class'] . ' disabled';
|
$attributes['class'] = $attributes['class'] . ' disabled';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->createTag('button', $attributes, $this->attrTitle());
|
return $this->createTag('button', $attributes, $this->buttonContent ? $this->buttonContent : $this->attrTitle());
|
||||||
} else {
|
} else {
|
||||||
$attributes = array(
|
$attributes = array(
|
||||||
'class' => 'action' . ($this->extraClass() ? $this->extraClass() : ''),
|
'class' => 'action' . ($this->extraClass() ? $this->extraClass() : ''),
|
||||||
|
Loading…
Reference in New Issue
Block a user