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@69856 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
d32d4d5204
commit
0747fc6d52
15
_config.php
15
_config.php
@ -60,21 +60,6 @@ set_include_path(get_include_path() . PATH_SEPARATOR . $path);
|
|||||||
*/
|
*/
|
||||||
define('MCE_ROOT', 'jsparty/tiny_mce2/');
|
define('MCE_ROOT', 'jsparty/tiny_mce2/');
|
||||||
|
|
||||||
/**
|
|
||||||
* Should passwords be encrypted (TRUE) or stored in clear text (FALSE)?
|
|
||||||
*/
|
|
||||||
Security::encrypt_passwords(true);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Which algorithm should be used to encrypt? Should a salt be used to
|
|
||||||
* increase the security?
|
|
||||||
*
|
|
||||||
* You can get a list of supported algorithms by calling
|
|
||||||
* {@link Security::get_encryption_algorithms()}
|
|
||||||
*/
|
|
||||||
Security::set_password_encryption_algorithm('sha1', true);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The secret key that needs to be sent along with pings to /Email_BounceHandler
|
* The secret key that needs to be sent along with pings to /Email_BounceHandler
|
||||||
*
|
*
|
||||||
|
@ -73,15 +73,12 @@ class HTTP {
|
|||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function setGetVar($varname, $varvalue, $currentURL = null) {
|
public static function setGetVar($varname, $varvalue, $currentURL = null) {
|
||||||
$currentURL = $currentURL ? $currentURL : $_SERVER['REQUEST_URI'];
|
$scriptbase = $currentURL ? $currentURL : $_SERVER['REQUEST_URI'];
|
||||||
|
|
||||||
$scriptbase = $currentURL;
|
$scriptbase = str_replace('&', '&', $scriptbase);
|
||||||
$scriptbase = str_replace('&','&',$scriptbase);
|
$scriptbase = preg_replace('/\?' . quotemeta($varname) . '=([^&]*)&/', '?', $scriptbase);
|
||||||
|
$scriptbase = preg_replace('/([\?&]+)' . quotemeta($varname) . '=([^&]*)/', null, $scriptbase);
|
||||||
$scriptbase = ereg_replace("&$varname=[^&]*",'',$scriptbase);
|
|
||||||
$scriptbase = ereg_replace("\?$varname=[^&]*&",'?',$scriptbase);
|
|
||||||
$scriptbase = ereg_replace("\?$varname=[^&]*",'',$scriptbase);
|
|
||||||
|
|
||||||
$suffix = '';
|
$suffix = '';
|
||||||
if(($hashPos = strpos($scriptbase,'#')) !== false) {
|
if(($hashPos = strpos($scriptbase,'#')) !== false) {
|
||||||
@ -136,7 +133,7 @@ class HTTP {
|
|||||||
* Outputs appropriate header for downloading a file
|
* Outputs appropriate header for downloading a file
|
||||||
* exits() after the call, so that no further output is given.
|
* exits() after the call, so that no further output is given.
|
||||||
*
|
*
|
||||||
* @deprecated 2.3 Return a HTTPResponse::send_file() object instead
|
* @deprecated 2.3 Return a HTTPRequest::send_file() object instead
|
||||||
*/
|
*/
|
||||||
static function sendFileToBrowser($fileData, $fileName, $mimeType = false) {
|
static function sendFileToBrowser($fileData, $fileName, $mimeType = false) {
|
||||||
user_error("HTTP::sendFileToBrowser() deprecated; return a HTTPRequest::send_file() object instead", E_USER_NOTICE);
|
user_error("HTTP::sendFileToBrowser() deprecated; return a HTTPRequest::send_file() object instead", E_USER_NOTICE);
|
||||||
|
@ -52,7 +52,7 @@ class Director {
|
|||||||
* page.
|
* page.
|
||||||
*/
|
*/
|
||||||
static function history($pagesBack = 1) {
|
static function history($pagesBack = 1) {
|
||||||
return Session::get('history.' . sizeof(Session::get('history')) - $pagesBack - 1);
|
return Session::get('history.' . intval(sizeof(Session::get('history')) - $pagesBack - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -159,6 +159,7 @@ class Director {
|
|||||||
|
|
||||||
if(!$httpMethod) $httpMethod = ($postVars || is_array($postVars)) ? "POST" : "GET";
|
if(!$httpMethod) $httpMethod = ($postVars || is_array($postVars)) ? "POST" : "GET";
|
||||||
|
|
||||||
|
$urlWithQuerystring = $url;
|
||||||
if(strpos($url, '?') !== false) {
|
if(strpos($url, '?') !== false) {
|
||||||
list($url, $getVarsEncoded) = explode('?', $url, 2);
|
list($url, $getVarsEncoded) = explode('?', $url, 2);
|
||||||
parse_str($getVarsEncoded, $getVars);
|
parse_str($getVarsEncoded, $getVars);
|
||||||
@ -172,11 +173,11 @@ class Director {
|
|||||||
$existingPostVars = $_POST;
|
$existingPostVars = $_POST;
|
||||||
$existingSessionVars = $_SESSION;
|
$existingSessionVars = $_SESSION;
|
||||||
$existingCookies = $_COOKIE;
|
$existingCookies = $_COOKIE;
|
||||||
|
$existingServer = $_SERVER;
|
||||||
$existingCookieReportErrors = Cookie::report_errors();
|
$existingCookieReportErrors = Cookie::report_errors();
|
||||||
Cookie::set_report_errors(false);
|
|
||||||
|
|
||||||
$existingRequirementsBackend = Requirements::backend();
|
$existingRequirementsBackend = Requirements::backend();
|
||||||
|
|
||||||
|
Cookie::set_report_errors(false);
|
||||||
Requirements::set_backend(new Requirements_Backend());
|
Requirements::set_backend(new Requirements_Backend());
|
||||||
|
|
||||||
// Replace the superglobals with appropriate test values
|
// Replace the superglobals with appropriate test values
|
||||||
@ -185,6 +186,7 @@ class Director {
|
|||||||
$_POST = (array)$postVars;
|
$_POST = (array)$postVars;
|
||||||
$_SESSION = $session ? $session->inst_getAll() : array();
|
$_SESSION = $session ? $session->inst_getAll() : array();
|
||||||
$_COOKIE = array();
|
$_COOKIE = array();
|
||||||
|
$_SERVER['REQUEST_URI'] = Director::baseURL() . $urlWithQuerystring;
|
||||||
|
|
||||||
$req = new HTTPRequest($httpMethod, $url, $getVars, $postVars, $body);
|
$req = new HTTPRequest($httpMethod, $url, $getVars, $postVars, $body);
|
||||||
if($headers) foreach($headers as $k => $v) $req->addHeader($k, $v);
|
if($headers) foreach($headers as $k => $v) $req->addHeader($k, $v);
|
||||||
@ -196,6 +198,8 @@ class Director {
|
|||||||
$_POST = $existingPostVars;
|
$_POST = $existingPostVars;
|
||||||
$_SESSION = $existingSessionVars;
|
$_SESSION = $existingSessionVars;
|
||||||
$_COOKIE = $existingCookies;
|
$_COOKIE = $existingCookies;
|
||||||
|
$_SERVER = $existingServer;
|
||||||
|
|
||||||
Cookie::set_report_errors($existingCookieReportErrors);
|
Cookie::set_report_errors($existingCookieReportErrors);
|
||||||
Requirements::set_backend($existingRequirementsBackend);
|
Requirements::set_backend($existingRequirementsBackend);
|
||||||
|
|
||||||
|
@ -45,6 +45,13 @@ class DB {
|
|||||||
$_SESSION["alternativeDatabaseName"] = $dbname;
|
$_SESSION["alternativeDatabaseName"] = $dbname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the database in use
|
||||||
|
*/
|
||||||
|
static function get_alternative_database_name() {
|
||||||
|
return $_SESSION["alternativeDatabaseName"];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to a database.
|
* Connect to a database.
|
||||||
* Given the database configuration, this method will create the correct subclass of Database,
|
* Given the database configuration, this method will create the correct subclass of Database,
|
||||||
|
@ -126,8 +126,8 @@ class MySQLDatabase extends Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function createDatabase() {
|
public function createDatabase() {
|
||||||
$this->query("CREATE DATABASE $this->database");
|
$this->query("CREATE DATABASE `$this->database`");
|
||||||
$this->query("USE $this->database");
|
$this->query("USE `$this->database`");
|
||||||
|
|
||||||
$this->tableList = $this->fieldList = $this->indexList = null;
|
$this->tableList = $this->fieldList = $this->indexList = null;
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@
|
|||||||
<label for="mysql_password">MySQL password:</label>
|
<label for="mysql_password">MySQL password:</label>
|
||||||
<span class="middleColumn"><input id="mysql_password" class="text" type="password" name="mysql[password]" value="<?php echo $databaseConfig['password']; ?>" /></span>
|
<span class="middleColumn"><input id="mysql_password" class="text" type="password" name="mysql[password]" value="<?php echo $databaseConfig['password']; ?>" /></span>
|
||||||
<label for="mysql_database">MySQL database:</label>
|
<label for="mysql_database">MySQL database:</label>
|
||||||
<span class="middleColumn"><input id="mysql_database" class="text" type="text" name="mysql[database]" value="<?php echo $databaseConfig['database']; ?>" onchange="this.value = this.value.replace(/[^A-Za-z0-9_]+/g,'');" /></span>
|
<span class="middleColumn"><input id="mysql_database" class="text" type="text" name="mysql[database]" value="<?php echo $databaseConfig['database']; ?>" onchange="this.value = this.value.replace(/[\/\\:*?"<>|. \t]+/g,'');" /></span>
|
||||||
<input type="submit" class="action" value="Re-check requirements" />
|
<input type="submit" class="action" value="Re-check requirements" />
|
||||||
</p>
|
</p>
|
||||||
<p class="mysql">SilverStripe stores its content in a MySQL database. Please provide the username and password to connect to the server here. If this account has permission to create databases, then we will create the database for you; otherwise, you must give the name of a database that already exists.</p>
|
<p class="mysql">SilverStripe stores its content in a MySQL database. Please provide the username and password to connect to the server here. If this account has permission to create databases, then we will create the database for you; otherwise, you must give the name of a database that already exists.</p>
|
||||||
|
@ -18,6 +18,13 @@
|
|||||||
* If you want to process the submitted data in any way, please use {@link getData()} rather than
|
* If you want to process the submitted data in any way, please use {@link getData()} rather than
|
||||||
* the raw request data.
|
* the raw request data.
|
||||||
*
|
*
|
||||||
|
* Validation
|
||||||
|
* Each form needs some form of {@link Validator} to trigger the {@link FormField->validate()} methods for each field.
|
||||||
|
* You can't disable validator for security reasons, because crucial behaviour like extension checks for file uploads depend on it.
|
||||||
|
* The default validator is an instance of {@link RequiredFields}.
|
||||||
|
* If you want to enforce serverside-validation to be ignored for a specific {@link FormField},
|
||||||
|
* you need to subclass it.
|
||||||
|
*
|
||||||
* @package forms
|
* @package forms
|
||||||
* @subpackage core
|
* @subpackage core
|
||||||
*/
|
*/
|
||||||
@ -96,10 +103,11 @@ class Form extends RequestHandler {
|
|||||||
/**
|
/**
|
||||||
* Create a new form, with the given fields an action buttons.
|
* Create a new form, with the given fields an action buttons.
|
||||||
*
|
*
|
||||||
* @param controller The parent controller, necessary to create the appropriate form action tag.
|
* @param Controller $controller The parent controller, necessary to create the appropriate form action tag.
|
||||||
* @param name The method on the controller that will return this form object.
|
* @param String $name The method on the controller that will return this form object.
|
||||||
* @param fields All of the fields in the form - a {@link FieldSet} of {@link FormField} objects.
|
* @param FieldSet $fields All of the fields in the form - a {@link FieldSet} of {@link FormField} objects.
|
||||||
* @param actions All of the action buttons in the form - a {@link FieldSet} of {@link FormAction} objects
|
* @param FieldSet $actions All of the action buttons in the form - a {@link FieldSet} of {@link FormAction} objects
|
||||||
|
* @param Validator $validator Override the default validator instance (Default: {@link RequiredFields})
|
||||||
*/
|
*/
|
||||||
function __construct($controller, $name, FieldSet $fields, FieldSet $actions, $validator = null) {
|
function __construct($controller, $name, FieldSet $fields, FieldSet $actions, $validator = null) {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
@ -115,10 +123,8 @@ class Form extends RequestHandler {
|
|||||||
if(!$this->controller) user_error("$this->class form created without a controller", E_USER_ERROR);
|
if(!$this->controller) user_error("$this->class form created without a controller", E_USER_ERROR);
|
||||||
|
|
||||||
// Form validation
|
// Form validation
|
||||||
if($validator) {
|
$this->validator = ($validator) ? $validator : new RequiredFields();
|
||||||
$this->validator = $validator;
|
$this->validator->setForm($this);
|
||||||
$this->validator->setForm($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Form error controls
|
// Form error controls
|
||||||
$errorInfo = Session::get("FormInfo.{$this->FormName()}");
|
$errorInfo = Session::get("FormInfo.{$this->FormName()}");
|
||||||
|
@ -32,6 +32,7 @@ class HasManyComplexTableField extends ComplexTableField {
|
|||||||
|
|
||||||
if($controllerClass = $this->controllerClass()) {
|
if($controllerClass = $this->controllerClass()) {
|
||||||
$this->joinField = $this->getParentIdName($controllerClass, $this->sourceClass);
|
$this->joinField = $this->getParentIdName($controllerClass, $this->sourceClass);
|
||||||
|
if(!$this->joinField) user_error("Can't find a has_one relationship from '$this->sourceClass' to '$controllerClass'", E_USER_WARNING);
|
||||||
} else {
|
} else {
|
||||||
user_error("Can't figure out the data class of $controller", E_USER_WARNING);
|
user_error("Can't figure out the data class of $controller", E_USER_WARNING);
|
||||||
}
|
}
|
||||||
@ -148,6 +149,11 @@ class HasManyComplexTableField_Item extends ComplexTableField_Item {
|
|||||||
function MarkingCheckbox() {
|
function MarkingCheckbox() {
|
||||||
$name = $this->parent->Name() . '[]';
|
$name = $this->parent->Name() . '[]';
|
||||||
|
|
||||||
|
if(!$this->parent->joinField) {
|
||||||
|
user_error("joinField not set in HasManyComplexTableField '{$this->parent->name}'", E_USER_WARNING);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
$joinVal = $this->item->{$this->parent->joinField};
|
$joinVal = $this->item->{$this->parent->joinField};
|
||||||
$parentID = $this->parent->getControllerID();
|
$parentID = $this->parent->getControllerID();
|
||||||
|
|
||||||
|
@ -18,7 +18,9 @@ class HeaderField extends DatalessField {
|
|||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
if(!isset($args[1]) || is_numeric($args[1])) {
|
if(!isset($args[1]) || is_numeric($args[1])) {
|
||||||
$title = (isset($args[0])) ? $args[0] : null;
|
$title = (isset($args[0])) ? $args[0] : null;
|
||||||
$name = $title; // this means i18nized fields won't be easily accessible through fieldByName()
|
// Use "HeaderField(title)" as the default field name for a HeaderField; if it's just set to title then we risk
|
||||||
|
// causing accidental duplicate-field creation.
|
||||||
|
$name = 'HeaderField' . $title; // this means i18nized fields won't be easily accessible through fieldByName()
|
||||||
$headingLevel = (isset($args[1])) ? $args[1] : null;
|
$headingLevel = (isset($args[1])) ? $args[1] : null;
|
||||||
$allowHTML = (isset($args[2])) ? $args[2] : null;
|
$allowHTML = (isset($args[2])) ? $args[2] : null;
|
||||||
$form = (isset($args[3])) ? $args[3] : null;
|
$form = (isset($args[3])) ? $args[3] : null;
|
||||||
|
@ -423,6 +423,7 @@ class HtmlEditorField_Toolbar extends RequestHandler {
|
|||||||
new TextField('getimagesSearch', _t('HtmlEditorField.SEARCHFILENAME', 'Search by file name')),
|
new TextField('getimagesSearch', _t('HtmlEditorField.SEARCHFILENAME', 'Search by file name')),
|
||||||
new ThumbnailStripField('Image', 'FolderID', 'getimages'),
|
new ThumbnailStripField('Image', 'FolderID', 'getimages'),
|
||||||
new TextField('AltText', _t('HtmlEditorField.ALTTEXT', 'Description'), '', 80),
|
new TextField('AltText', _t('HtmlEditorField.ALTTEXT', 'Description'), '', 80),
|
||||||
|
new CheckboxField('Caption', _t('HtmlEditorField.CAPTION', 'Include as Caption')),
|
||||||
new HiddenField('CSSClass', _t('HtmlEditorField.CSSCLASS', 'Alignment / style')),
|
new HiddenField('CSSClass', _t('HtmlEditorField.CSSCLASS', 'Alignment / style')),
|
||||||
new LiteralField('AlignmentStyle', '<div id="ImageAligmentStyle" class="field text"><label>Alignment / style</label>'),
|
new LiteralField('AlignmentStyle', '<div id="ImageAligmentStyle" class="field text"><label>Alignment / style</label>'),
|
||||||
new LiteralField('AlignmentStyleLinks', '
|
new LiteralField('AlignmentStyleLinks', '
|
||||||
|
@ -40,7 +40,7 @@ class TreeDropdownField extends FormField {
|
|||||||
Requirements::javascript(SAPPHIRE_DIR . "/javascript/TreeSelectorField.js");
|
Requirements::javascript(SAPPHIRE_DIR . "/javascript/TreeSelectorField.js");
|
||||||
|
|
||||||
if($this->value) {
|
if($this->value) {
|
||||||
$record = DataObject::get_by_id($this->sourceObject, $this->value);
|
$record = $this->getByKey($this->value);
|
||||||
$title = ($record) ? $record->Title : _t('DropdownField.CHOOSE', "(Choose)", PR_MEDIUM, 'Start-value of a dropdown');
|
$title = ($record) ? $record->Title : _t('DropdownField.CHOOSE', "(Choose)", PR_MEDIUM, 'Start-value of a dropdown');
|
||||||
} else {
|
} else {
|
||||||
$title = _t('DropdownField.CHOOSE', "(Choose)", PR_MEDIUM, 'Start-value of a dropdown');
|
$title = _t('DropdownField.CHOOSE', "(Choose)", PR_MEDIUM, 'Start-value of a dropdown');
|
||||||
@ -65,7 +65,6 @@ HTML;
|
|||||||
if($this->treeBaseID) $obj = DataObject::get_by_id($this->sourceObject, $this->treeBaseID);
|
if($this->treeBaseID) $obj = DataObject::get_by_id($this->sourceObject, $this->treeBaseID);
|
||||||
else $obj = singleton($this->sourceObject);
|
else $obj = singleton($this->sourceObject);
|
||||||
|
|
||||||
|
|
||||||
if($this->filterFunc) $obj->setMarkingFilterFunction($this->filterFunc);
|
if($this->filterFunc) $obj->setMarkingFilterFunction($this->filterFunc);
|
||||||
else if($this->sourceObject == 'Folder') $obj->setMarkingFilter('ClassName', 'Folder');
|
else if($this->sourceObject == 'Folder') $obj->setMarkingFilter('ClassName', 'Folder');
|
||||||
$obj->markPartialTree();
|
$obj->markPartialTree();
|
||||||
@ -86,11 +85,12 @@ HTML;
|
|||||||
* Return a subtree via Ajax
|
* Return a subtree via Ajax
|
||||||
*/
|
*/
|
||||||
public function getsubtree() {
|
public function getsubtree() {
|
||||||
if($this->keyField == "ID") $obj = DataObject::get_by_id($this->sourceObject, $_REQUEST['SubtreeRootID']);
|
$obj = $this->getByKey($_REQUEST['SubtreeRootID']);
|
||||||
else $obj = DataObject::get_one($this->sourceObject, "\"$this->keyField\" = '$_REQUEST[SubtreeRootID]'");
|
|
||||||
|
|
||||||
if(!$obj) user_error("Can't find database record $this->sourceObject with $this->keyField = $_REQUEST[SubtreeRootID]", E_USER_ERROR);
|
if(!$obj) user_error("Can't find database record $this->sourceObject with $this->keyField = $_REQUEST[SubtreeRootID]", E_USER_ERROR);
|
||||||
|
|
||||||
if($this->filterFunc) $obj->setMarkingFilterFunction($this->filterFunc);
|
if($this->filterFunc) $obj->setMarkingFilterFunction($this->filterFunc);
|
||||||
|
else if($this->sourceObject == 'Folder') $obj->setMarkingFilter('ClassName', 'Folder');
|
||||||
$obj->markPartialTree();
|
$obj->markPartialTree();
|
||||||
|
|
||||||
$eval = '"<li id=\"selector-' . $this->name . '-$child->' . $this->keyField . '\" class=\"$child->class" . $child->markingClasses() . "\"><a>" . $child->' . $this->labelField . ' . "</a>"';
|
$eval = '"<li id=\"selector-' . $this->name . '-$child->' . $this->keyField . '\" class=\"$child->class" . $child->markingClasses() . "\"><a>" . $child->' . $this->labelField . ' . "</a>"';
|
||||||
@ -99,14 +99,11 @@ HTML;
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getByKey($key) {
|
public function getByKey($key) {
|
||||||
if(!is_numeric($key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->keyField == 'ID') {
|
if($this->keyField == 'ID') {
|
||||||
return DataObject::get_by_id($this->sourceObject, $key);
|
return DataObject::get_by_id($this->sourceObject, $key);
|
||||||
} else {
|
} else {
|
||||||
return DataObject::get_one($this->sourceObject, "\"$this->keyField\" = '$key'");
|
$SQL_key = Convert::raw2sql($key);
|
||||||
|
return DataObject::get_one($this->sourceObject, "\"$this->keyField\" = '$SQL_key'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,8 +111,7 @@ HTML;
|
|||||||
* Return the stack of values to be traversed to find the given key in the database
|
* Return the stack of values to be traversed to find the given key in the database
|
||||||
*/
|
*/
|
||||||
public function getstack() {
|
public function getstack() {
|
||||||
if($this->keyField == "ID") $page = DataObject::get_by_id($this->sourceObject, $_REQUEST['SubtreeRootID']);
|
$page = $this->getByKey($_REQUEST['SubtreeRootID']);
|
||||||
else $page = $this->getByKey($_REQUEST['SubtreeRootID']);
|
|
||||||
|
|
||||||
while($page->ParentID) {
|
while($page->ParentID) {
|
||||||
echo $ids[] = $page->ID;
|
echo $ids[] = $page->ID;
|
||||||
|
@ -54,7 +54,7 @@ abstract class Validator extends Object {
|
|||||||
public function __construct() {
|
public function __construct() {
|
||||||
if(self::$javascript_validation_handler) $this->setJavascriptValidationHandler(self::$javascript_validation_handler);
|
if(self::$javascript_validation_handler) $this->setJavascriptValidationHandler(self::$javascript_validation_handler);
|
||||||
|
|
||||||
if($this->javascriptValidationHandler) {
|
if($this->javascriptValidationHandler && $this->javascriptValidationHandler != 'none') {
|
||||||
Requirements::javascript(SAPPHIRE_DIR . '/javascript/Validator.js');
|
Requirements::javascript(SAPPHIRE_DIR . '/javascript/Validator.js');
|
||||||
}
|
}
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
BIN
images/smilies/confused.gif
Normal file
BIN
images/smilies/confused.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 700 B |
BIN
images/smilies/cool.gif
Normal file
BIN
images/smilies/cool.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 703 B |
BIN
images/smilies/grin.gif
Normal file
BIN
images/smilies/grin.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 688 B |
BIN
images/smilies/sad.gif
Normal file
BIN
images/smilies/sad.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 704 B |
BIN
images/smilies/smile.gif
Normal file
BIN
images/smilies/smile.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 699 B |
BIN
images/smilies/tongue.gif
Normal file
BIN
images/smilies/tongue.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 706 B |
@ -16,8 +16,32 @@ unset($options);
|
|||||||
*/
|
*/
|
||||||
class BBCodeParser extends TextParser {
|
class BBCodeParser extends TextParser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether phrases starting with http:// or www. are automatically linked
|
||||||
|
* @var Boolean
|
||||||
|
*/
|
||||||
protected static $autolinkUrls = true;
|
protected static $autolinkUrls = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether similies :), :(, :P are converted to images
|
||||||
|
* @var Boolean
|
||||||
|
*/
|
||||||
|
protected static $allowSimilies = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the location of the smiles folder. By default use the ones in sapphire
|
||||||
|
* but this can be overridden by setting BBCodeParser::set_icon_folder('themes/yourtheme/images/');
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected static $smilies_location = 'sapphire/images/smilies';
|
||||||
|
|
||||||
|
static function smilies_location() {
|
||||||
|
return BBCodeParser::$smilies_location;
|
||||||
|
}
|
||||||
|
static function set_icon_folder($path) {
|
||||||
|
BBCodeParser::$smilies_location = $path;
|
||||||
|
}
|
||||||
|
|
||||||
static function autolinkUrls() {
|
static function autolinkUrls() {
|
||||||
return (self::$autolinkUrls != null) ? true : false;
|
return (self::$autolinkUrls != null) ? true : false;
|
||||||
}
|
}
|
||||||
@ -26,6 +50,15 @@ class BBCodeParser extends TextParser {
|
|||||||
BBCodeParser::$autolinkUrls = $autolink;
|
BBCodeParser::$autolinkUrls = $autolink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function smiliesAllowed() {
|
||||||
|
return (self::$allowSimilies != null) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function enable_smilies() {
|
||||||
|
BBCodeParser::$allowSimilies = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static function usable_tags() {
|
static function usable_tags() {
|
||||||
return new DataObjectSet(
|
return new DataObjectSet(
|
||||||
new ArrayData(array(
|
new ArrayData(array(
|
||||||
@ -98,6 +131,12 @@ class BBCodeParser extends TextParser {
|
|||||||
return $useabletags."</ul>";
|
return $useabletags."</ul>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main BBCode parser method. This takes plain jane content and
|
||||||
|
* runs it through so many filters
|
||||||
|
*
|
||||||
|
* @return Text
|
||||||
|
*/
|
||||||
function parse() {
|
function parse() {
|
||||||
$this->content = str_replace(array('&', '<', '>'), array('&', '<', '>'), $this->content);
|
$this->content = str_replace(array('&', '<', '>'), array('&', '<', '>'), $this->content);
|
||||||
$this->content = SSHTMLBBCodeParser::staticQparse($this->content);
|
$this->content = SSHTMLBBCodeParser::staticQparse($this->content);
|
||||||
@ -108,6 +147,20 @@ class BBCodeParser extends TextParser {
|
|||||||
|
|
||||||
$this->content = preg_replace("/\n\s*\n/", "</p><p>", $this->content);
|
$this->content = preg_replace("/\n\s*\n/", "</p><p>", $this->content);
|
||||||
$this->content = str_replace("\n", "<br />", $this->content);
|
$this->content = str_replace("\n", "<br />", $this->content);
|
||||||
|
|
||||||
|
if(BBCodeParser::smiliesAllowed()) {
|
||||||
|
$smilies = array(
|
||||||
|
'#(?<!\w):D(?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/grin.gif'> ", // :D
|
||||||
|
'#(?<!\w):\)(?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/smile.gif'> ", // :)
|
||||||
|
'#(?<!\w):-\)(?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/smile.gif'> ", // :-)
|
||||||
|
'#(?<!\w):\((?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/sad.gif'> ", // :(
|
||||||
|
'#(?<!\w):-\((?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/sad.gif'> ", // :-(
|
||||||
|
'#(?<!\w):p(?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/tongue.gif'> ", // :p
|
||||||
|
'#(?<!\w)8-\)(?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/cool.gif'> ", // 8-)
|
||||||
|
'#(?<!\w):\^\)(?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/confused.gif'> " // :^)
|
||||||
|
);
|
||||||
|
$this->content = preg_replace(array_keys($smilies), array_values($smilies), $this->content);
|
||||||
|
}
|
||||||
return $this->content;
|
return $this->content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -933,11 +933,13 @@ class Security extends Controller {
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function database_is_ready() {
|
public static function database_is_ready() {
|
||||||
return
|
$requiredTables = ClassInfo::dataClassesFor('Member');
|
||||||
ClassInfo::hasTable('Member') &&
|
$requiredTables[] = 'Group';
|
||||||
ClassInfo::hasTable('Group') &&
|
$requiredTables[] = 'Permission';
|
||||||
ClassInfo::hasTable('Permission') &&
|
|
||||||
(($permissionFields = DB::fieldList('Permission')) && isset($permissionFields['Type'])) &&
|
foreach($requiredTables as $table) if(!ClassInfo::hasTable($table)) return false;
|
||||||
|
|
||||||
|
return (($permissionFields = DB::fieldList('Permission')) && isset($permissionFields['Type'])) &&
|
||||||
(($memberFields = DB::fieldList('Member')) && isset($memberFields['RememberLoginToken']));
|
(($memberFields = DB::fieldList('Member')) && isset($memberFields['RememberLoginToken']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
tests/HTTPTest.php
Normal file
29
tests/HTTPTest.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Tests the {@link HTTP} class
|
||||||
|
*
|
||||||
|
* @package sapphire
|
||||||
|
* @subpackage tests
|
||||||
|
*/
|
||||||
|
class HTTPTest extends SapphireTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests {@link HTTP::setGetVar()}
|
||||||
|
*/
|
||||||
|
public function testSetGetVar() {
|
||||||
|
$expected = array (
|
||||||
|
'/?foo=bar' => array('foo', 'bar', '/'),
|
||||||
|
'/?baz=buz&foo=bar' => array('foo', 'bar', '/?baz=buz'),
|
||||||
|
'/?buz=baz&foo=baz' => array('foo', 'baz', '/?foo=bar&buz=baz'),
|
||||||
|
'/?foo=var' => array('foo', 'var', '/?foo=&foo=bar'),
|
||||||
|
'/?foo[test]=var' => array('foo[test]', 'var', '/?foo[test]=another')
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach($expected as $result => $args) {
|
||||||
|
$this->assertEquals(
|
||||||
|
call_user_func_array(array('HTTP', 'setGetVar'), $args), str_replace('&', '&', $result)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
109
tests/SiteTreeActionsTest.php
Normal file
109
tests/SiteTreeActionsTest.php
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Possible actions:
|
||||||
|
* - action_save
|
||||||
|
* - action_publish
|
||||||
|
* - action_unpublish
|
||||||
|
* - action_delete
|
||||||
|
* - action_deletefromlive
|
||||||
|
* - action_rollback
|
||||||
|
* - action_revert
|
||||||
|
*
|
||||||
|
* @package sapphire
|
||||||
|
* @subpackage tests
|
||||||
|
*/
|
||||||
|
if(class_exists('SiteTreeCMSWorkflow')) {
|
||||||
|
class SiteTreeActionsTest extends FunctionalTest {
|
||||||
|
function testDummy() {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
class SiteTreeActionsTest extends FunctionalTest {
|
||||||
|
|
||||||
|
static $fixture_file = 'sapphire/tests/SiteTreeActionsTest.yml';
|
||||||
|
|
||||||
|
function testActionsNewPage() {
|
||||||
|
$className = 'Page';
|
||||||
|
$page = new $className();
|
||||||
|
$page->Title = 'New ' . $className;
|
||||||
|
$page->URLSegment = "new-" . strtolower($className);
|
||||||
|
$page->ClassName = $className;
|
||||||
|
$page->ParentID = 0;
|
||||||
|
$page->ID = 'new-Page-1';
|
||||||
|
|
||||||
|
$author = $this->objFromFixture('Member', 'cmseditor');
|
||||||
|
$this->session()->inst_set('loggedInAs', $author->ID);
|
||||||
|
|
||||||
|
$actionsArr = $page->getCMSActions()->column('Name');
|
||||||
|
|
||||||
|
$this->assertContains('action_save',$actionsArr);
|
||||||
|
$this->assertContains('action_publish',$actionsArr);
|
||||||
|
$this->assertNotContains('action_unpublish',$actionsArr);
|
||||||
|
$this->assertContains('action_delete',$actionsArr);
|
||||||
|
$this->assertNotContains('action_deletefromlive',$actionsArr);
|
||||||
|
$this->assertNotContains('action_rollback',$actionsArr);
|
||||||
|
$this->assertNotContains('action_revert',$actionsArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testActionsPublishedRecord() {
|
||||||
|
$page = new Page();
|
||||||
|
$page->write();
|
||||||
|
$page->publish('Stage', 'Live');
|
||||||
|
|
||||||
|
$author = $this->objFromFixture('Member', 'cmseditor');
|
||||||
|
$this->session()->inst_set('loggedInAs', $author->ID);
|
||||||
|
|
||||||
|
$actionsArr = $page->getCMSActions()->column('Name');
|
||||||
|
|
||||||
|
$this->assertContains('action_save',$actionsArr);
|
||||||
|
$this->assertContains('action_publish',$actionsArr);
|
||||||
|
$this->assertContains('action_unpublish',$actionsArr);
|
||||||
|
$this->assertContains('action_delete',$actionsArr);
|
||||||
|
$this->assertNotContains('action_deletefromlive',$actionsArr);
|
||||||
|
$this->assertNotContains('action_rollback',$actionsArr);
|
||||||
|
$this->assertNotContains('action_revert',$actionsArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testActionsDeletedFromStageRecord() {
|
||||||
|
$page = new Page();
|
||||||
|
$page->write();
|
||||||
|
$page->publish('Stage', 'Live');
|
||||||
|
$page->deleteFromStage('Stage');
|
||||||
|
|
||||||
|
$author = $this->objFromFixture('Member', 'cmseditor');
|
||||||
|
$this->session()->inst_set('loggedInAs', $author->ID);
|
||||||
|
|
||||||
|
$actionsArr = $page->getCMSActions()->column('Name');
|
||||||
|
|
||||||
|
$this->assertNotContains('action_save',$actionsArr);
|
||||||
|
$this->assertNotContains('action_publish',$actionsArr);
|
||||||
|
$this->assertNotContains('action_unpublish',$actionsArr);
|
||||||
|
$this->assertNotContains('action_delete',$actionsArr);
|
||||||
|
$this->assertContains('action_deletefromlive',$actionsArr);
|
||||||
|
$this->assertNotContains('action_rollback',$actionsArr);
|
||||||
|
$this->assertContains('action_revert',$actionsArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testActionsChangedOnStageRecord() {
|
||||||
|
$page = new Page();
|
||||||
|
$page->write();
|
||||||
|
$page->publish('Stage', 'Live');
|
||||||
|
$page->Content = 'Changed on Stage';
|
||||||
|
$page->write();
|
||||||
|
$page->flushCache();
|
||||||
|
|
||||||
|
$author = $this->objFromFixture('Member', 'cmseditor');
|
||||||
|
$this->session()->inst_set('loggedInAs', $author->ID);
|
||||||
|
|
||||||
|
$actionsArr = $page->getCMSActions()->column('Name');
|
||||||
|
|
||||||
|
$this->assertContains('action_save',$actionsArr);
|
||||||
|
$this->assertContains('action_publish',$actionsArr);
|
||||||
|
$this->assertContains('action_unpublish',$actionsArr);
|
||||||
|
$this->assertContains('action_delete',$actionsArr);
|
||||||
|
$this->assertNotContains('action_deletefromlive',$actionsArr);
|
||||||
|
$this->assertContains('action_rollback',$actionsArr);
|
||||||
|
$this->assertNotContains('action_revert',$actionsArr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
11
tests/SiteTreeActionsTest.yml
Normal file
11
tests/SiteTreeActionsTest.yml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Permission:
|
||||||
|
cmsmain:
|
||||||
|
Code: CMS_ACCESS_CMSMain
|
||||||
|
Group:
|
||||||
|
cmseditors:
|
||||||
|
Title: CMS Editors
|
||||||
|
Permissions: =>Permission.cmsmain
|
||||||
|
Member:
|
||||||
|
cmseditor:
|
||||||
|
Email: cmseditor@test.com
|
||||||
|
Groups: =>Group.cmseditors
|
Loading…
Reference in New Issue
Block a user