Merge branch '3.0'

Conflicts:
	admin/scss/ie7.scss
This commit is contained in:
Sam Minnee 2012-06-22 17:20:07 +12:00
commit 4aa4cd2c28
11 changed files with 139 additions and 29 deletions

View File

@ -28,6 +28,37 @@ abstract class CMSBatchAction extends Object {
*/ */
abstract function run(SS_List $objs); abstract function run(SS_List $objs);
/**
* Helper method for responding to a back action request
* @param $successMessage string - The message to return as a notification.
* Can have up to two %d's in it. The first will be replaced by the number of successful
* changes, the second by the number of failures
* @param $status array - A status array like batchactions builds. Should be
* key => value pairs, the key can be any string: "error" indicates errors, anything
* else indicates a type of success. The value is an array. We don't care what's in it,
* we just use count($value) to find the number of items that succeeded or failed
*/
public function response($successMessage, $status) {
$count = 0;
$errors = 0;
foreach($status as $k => $v) {
if ($k == 'errors') $errors = count($v);
else $count += count($v);
}
$response = Controller::curr()->getResponse();
if($response) {
$response->setStatusCode(
200,
sprintf($successMessage, $count, $errors)
);
}
return Convert::raw2json($status);
}
/** /**
* Helper method for processing batch actions. * Helper method for processing batch actions.
* Returns a set of status-updating JavaScript to return to the CMS. * Returns a set of status-updating JavaScript to return to the CMS.
@ -67,15 +98,7 @@ abstract class CMSBatchAction extends Object {
unset($obj); unset($obj);
} }
$response = Controller::curr()->getResponse(); return $this->response($successMessage, $status);
if($response) {
$response->setStatusCode(
200,
sprintf($successMessage, $objs->Count(), count($status['error']))
);
}
return Convert::raw2json($status);
} }

View File

@ -545,10 +545,14 @@ body.cms-dialog { overflow: auto; background: url("../images/textures/bg_cms_mai
/** -------------------------------------------- "Insert X" forms -------------------------------------------- */ /** -------------------------------------------- "Insert X" forms -------------------------------------------- */
.htmleditorfield-dialog.ui-dialog-content { padding: 0; position: relative; } .htmleditorfield-dialog.ui-dialog-content { padding: 0; position: relative; }
.htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb .CompositeField { overflow: hidden; *zoom: 1; } .htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb .CompositeField { overflow: hidden; *zoom: 1; }
.htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb #RemoteURL { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; width: 55%; float: left; } .htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb #RemoteURL { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; width: 55%; float: left; position: relative; }
.htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb #RemoteURL label { position: absolute; left: 8px; top: 0px; font-weight: normal; color: #888; }
.htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb #RemoteURL .middleColumn { margin-left: 0; }
.htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb #RemoteURL input.remoteurl { padding-left: 40px; }
.htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb button.add-url { padding-top: 15px; overflow: hidden; *zoom: 1; border: none; background: none; opacity: 0.8; cursor: hand; } .htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb button.add-url { padding-top: 15px; overflow: hidden; *zoom: 1; border: none; background: none; opacity: 0.8; cursor: hand; }
.htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb button.add-url .btn-icon-addMedia { width: 20px; height: 20px; } .htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb button.add-url .btn-icon-addMedia { width: 20px; height: 20px; }
.htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb button.add-url:hover, .htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb button.add-url:active { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; opacity: 1; } .htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb button.add-url:hover, .htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb button.add-url:active { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; opacity: 1; }
.htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb button.add-url.ui-state-disabled, .htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb button.add-url.ui-state-disabled:hover, .htmleditorfield-dialog #MediaFormInsertMediaTabs_Fromtheweb button.add-url.ui-state-disabled:active { opacity: 0.35; filter: Alpha(Opacity=35); }
.htmleditorfield-dialog .cms-content-header { padding: 0; width: 100%; height: 40px; } .htmleditorfield-dialog .cms-content-header { padding: 0; width: 100%; height: 40px; }
.htmleditorfield-dialog .cms-content-header h3 { padding: 0 8px; margin: 10px; } .htmleditorfield-dialog .cms-content-header h3 { padding: 0 8px; margin: 10px; }
.htmleditorfield-dialog .ui-tabs { position: static; } .htmleditorfield-dialog .ui-tabs { position: static; }

View File

@ -102,7 +102,7 @@
}); });
}) })
// Make some jstree events delegatable // Make some jstree events delegatable
.bind('select_node.jstree check_node.jstree', function(e, data) { .bind('select_node.jstree check_node.jstree uncheck_node.jstree', function(e, data) {
$(document).triggerHandler(e, data); $(document).triggerHandler(e, data);
}) })
}, },

View File

@ -1449,6 +1449,22 @@ body.cms-dialog {
@include box-shadow-none; @include box-shadow-none;
width:55%; width:55%;
float:left; float:left;
position: relative;
label {
position: absolute;
left: 8px;
top: 0px;
font-weight: normal; color: #888;
}
.middleColumn {
margin-left: 0;
}
input.remoteurl {
padding-left: 40px;
}
} }
button.add-url{ button.add-url{
padding-top:15px; padding-top:15px;
@ -1466,6 +1482,12 @@ body.cms-dialog {
@include box-shadow-none; @include box-shadow-none;
opacity:1; opacity:1;
} }
&.ui-state-disabled {
&, &:hover, &:active {
opacity: 0.35;
filter: Alpha(Opacity=35);
}
}
} }
} }

View File

@ -392,7 +392,7 @@ class HtmlEditorField_Toolbar extends RequestHandler {
$fromWeb = new CompositeField( $fromWeb = new CompositeField(
new LiteralField('headerURL', '<h4 class="field header-url">' . sprintf($numericLabelTmpl, '1', _t('HtmlEditorField.ADDURL', 'Add URL')) . '</h4>'), new LiteralField('headerURL', '<h4 class="field header-url">' . sprintf($numericLabelTmpl, '1', _t('HtmlEditorField.ADDURL', 'Add URL')) . '</h4>'),
$remoteURL = new TextField('RemoteURL', ''), $remoteURL = new TextField('RemoteURL', 'http://'),
new LiteralField('addURLImage', '<button class="action ui-action-constructive ui-button field add-url" data-icon="addMedia"></button>') new LiteralField('addURLImage', '<button class="action ui-action-constructive ui-button field add-url" data-icon="addMedia"></button>')
); );
$remoteURL->addExtraClass('remoteurl'); $remoteURL->addExtraClass('remoteurl');

View File

@ -871,17 +871,51 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
}); });
$('form.htmleditorfield-form.htmleditorfield-mediaform input.remoteurl').entwine({
onadd: function() {
this.validate();
},
onkeyup: function() {
this.validate();
},
onchange: function() {
this.validate();
},
getAddButton: function() {
return this.closest('.CompositeField').find('button.add-url');
},
validate: function() {
var val = this.val(), orig = val;
val = val.replace(/^https?:\/\//i, '');
if (orig !== val) this.val(val);
this.getAddButton().button(!!val ? 'enable' : 'disable');
return !!val;
}
});
/** /**
* Show the second step after adding a URL * Show the second step after adding a URL
*/ */
$('form.htmleditorfield-form.htmleditorfield-mediaform .add-url').entwine({ $('form.htmleditorfield-form.htmleditorfield-mediaform .add-url').entwine({
getURLField: function() {
return this.closest('.CompositeField').find('input.remoteurl');
},
onclick: function(e) { onclick: function(e) {
var urlField = this.getURLField();
if (urlField.validate()) {
var form = this.closest('form'); var form = this.closest('form');
form.showFileView('http://' + urlField.val());
var urlField = this.closest('.CompositeField').find('input.remoteurl');
form.showFileView(urlField.val());
form.redraw(); form.redraw();
}
return false; return false;
} }
}); });

View File

@ -461,7 +461,7 @@ function max($field) {
function whereAny($filter) { function whereAny($filter) {
if($filter) { if($filter) {
$clone = $this; $clone = $this;
$clone->query->whereAny($filter); $clone->query->addWhereAny($filter);
return $clone; return $clone;
} else { } else {
return $this; return $this;

View File

@ -738,15 +738,29 @@ class SQLQuery {
return $this->setWhere($where); return $this->setWhere($where);
} }
public function whereAny($where) {
Deprecation::notice('3.0', 'Please use setWhereAny() or setWhereAny() instead!');
return $this->setWhereAny($where);
}
/** /**
* @param String|array $filters Predicate(s) to set, as escaped SQL statements. * @param String|array $filters Predicate(s) to set, as escaped SQL statements.
*/ */
function whereAny($filters) { function setWhereAny($filters) {
if(is_string($filters)) $filters = func_get_args(); if(is_string($filters)) $filters = func_get_args();
$clause = implode(" OR ", $filters); $clause = implode(" OR ", $filters);
return $this->setWhere($clause); return $this->setWhere($clause);
} }
/**
* @param String|array $filters Predicate(s) to set, as escaped SQL statements.
*/
function addWhereAny($filters) {
if(is_string($filters)) $filters = func_get_args();
$clause = implode(" OR ", $filters);
return $this->addWhere($clause);
}
/** /**
* Use the disjunctive operator 'OR' to join filter expressions in the WHERE clause. * Use the disjunctive operator 'OR' to join filter expressions in the WHERE clause.
*/ */

View File

@ -438,6 +438,17 @@ class DataListTest extends SapphireTest {
$this->assertEquals(2, $list->count()); $this->assertEquals(2, $list->count());
} }
/**
* Test that if an exclude() is applied to a filter(), the filter() is still preserved.
*/
public function testExcludeOnFilter() {
$list = DataObjectTest_TeamComment::get();
$list = $list->filter('Comment', 'Phil is a unique guy, and comments on team2');
$list = $list->exclude('Name', 'Bob');
$this->assertContains('WHERE ("Comment" = \'Phil is a unique guy, and comments on team2\') AND ("Name" != \'Bob\')', $list->sql());
}
/** /**
* $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // exclude bob with Age 21 or 43 * $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // exclude bob with Age 21 or 43
*/ */

View File

@ -258,11 +258,11 @@ class SQLQueryTest extends SapphireTest {
); );
} }
public function testWhereAny() { public function testSetWhereAny() {
$query = new SQLQuery(); $query = new SQLQuery();
$query->setFrom('MyTable'); $query->setFrom('MyTable');
$query->whereAny(array("Monkey = 'Chimp'", "Color = 'Brown'")); $query->setWhereAny(array("Monkey = 'Chimp'", "Color = 'Brown'"));
$this->assertEquals("SELECT * FROM MyTable WHERE (Monkey = 'Chimp' OR Color = 'Brown')",$query->sql()); $this->assertEquals("SELECT * FROM MyTable WHERE (Monkey = 'Chimp' OR Color = 'Brown')",$query->sql());
} }

View File

@ -1074,16 +1074,18 @@ class Requirements_Backend {
* @see Requirements::themedCSS() * @see Requirements::themedCSS()
*/ */
public function themedCSS($name, $module = null, $media = null) { public function themedCSS($name, $module = null, $media = null) {
$theme = SSViewer::current_theme(); $path = SSViewer::get_theme_folder();
$path = SSViewer::get_theme_folder() . "/css/$name.css"; $abspath = BASE_PATH . DIRECTORY_SEPARATOR . $path;
$css = "/css/$name.css";
if (file_exists(BASE_PATH . '/' . $path)) { if ($module && file_exists($abspath.'_'.$module.$css)) {
$this->css($path, $media); $this->css($path.'_'.$module.$css, $media);
return;
} }
else if (file_exists($abspath.$css)) {
if ($module) { $this->css($path.$css, $media);
$this->css("$module/css/$name.css"); }
else if ($module) {
$this->css($module.$css);
} }
} }