mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge branch '3'
This commit is contained in:
commit
5776a03141
@ -102,7 +102,7 @@ class MySQLiConnector extends DBConnector {
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
if ($this->dbConn) {
|
||||
if (is_resource($this->dbConn)) {
|
||||
mysqli_close($this->dbConn);
|
||||
$this->dbConn = null;
|
||||
}
|
||||
|
@ -256,19 +256,19 @@ abstract class DBField extends ViewableData {
|
||||
}
|
||||
|
||||
public function HTMLATT() {
|
||||
return Convert::raw2htmlatt($this->value);
|
||||
return Convert::raw2htmlatt($this->RAW());
|
||||
}
|
||||
|
||||
public function URLATT() {
|
||||
return urlencode($this->value);
|
||||
return urlencode($this->RAW());
|
||||
}
|
||||
|
||||
public function RAWURLATT() {
|
||||
return rawurlencode($this->value);
|
||||
return rawurlencode($this->RAW());
|
||||
}
|
||||
|
||||
public function ATT() {
|
||||
return Convert::raw2att($this->value);
|
||||
return Convert::raw2att($this->RAW());
|
||||
}
|
||||
|
||||
public function RAW() {
|
||||
@ -276,7 +276,7 @@ abstract class DBField extends ViewableData {
|
||||
}
|
||||
|
||||
public function JS() {
|
||||
return Convert::raw2js($this->value);
|
||||
return Convert::raw2js($this->RAW());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -284,15 +284,15 @@ abstract class DBField extends ViewableData {
|
||||
* @return string
|
||||
*/
|
||||
public function JSON() {
|
||||
return Convert::raw2json($this->value);
|
||||
return Convert::raw2json($this->RAW());
|
||||
}
|
||||
|
||||
public function HTML(){
|
||||
return Convert::raw2xml($this->value);
|
||||
return Convert::raw2xml($this->RAW());
|
||||
}
|
||||
|
||||
public function XML(){
|
||||
return Convert::raw2xml($this->value);
|
||||
return Convert::raw2xml($this->RAW());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,7 +111,7 @@ class DBHTMLText extends DBText {
|
||||
// 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);
|
||||
// Nonbreaking spaces get converted into weird characters, so strip them
|
||||
$value = str_replace(' ', ' ', $this->value);
|
||||
$value = str_replace(' ', ' ', $this->RAW());
|
||||
try {
|
||||
$res = $doc->loadHTML('<meta content="text/html; charset=utf-8" http-equiv="Content-type"/>' . $value);
|
||||
}
|
||||
@ -186,6 +186,15 @@ class DBHTMLText extends DBText {
|
||||
return $this->Summary();
|
||||
}
|
||||
|
||||
public function RAW() {
|
||||
if ($this->processShortcodes) {
|
||||
return ShortcodeParser::get_active()->parse($this->value);
|
||||
}
|
||||
else {
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of the field with relative links converted to absolute urls (with placeholders parsed).
|
||||
* @return string
|
||||
@ -195,12 +204,7 @@ class DBHTMLText extends DBText {
|
||||
}
|
||||
|
||||
public function forTemplate() {
|
||||
if ($this->processShortcodes) {
|
||||
return ShortcodeParser::get_active()->parse($this->value);
|
||||
}
|
||||
else {
|
||||
return $this->value;
|
||||
}
|
||||
return $this->RAW();
|
||||
}
|
||||
|
||||
public function prepValueForDB($value) {
|
||||
@ -248,14 +252,16 @@ class DBHTMLText extends DBText {
|
||||
return false;
|
||||
}
|
||||
|
||||
$value = $this->RAW();
|
||||
|
||||
// If it's got a content tag
|
||||
if(preg_match('/<(img|embed|object|iframe|meta|source|link)[^>]*>/i', $this->value)) {
|
||||
if(preg_match('/<(img|embed|object|iframe|meta|source|link)[^>]*>/i', $value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If it's just one or two tags on its own (and not the above) it's empty.
|
||||
// This might be <p></p> or <h1></h1> or whatever.
|
||||
if(preg_match('/^[\\s]*(<[^>]+>[\\s]*){1,2}$/', $this->value)) {
|
||||
if(preg_match('/^[\\s]*(<[^>]+>[\\s]*){1,2}$/', $value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -28,16 +28,21 @@ class DBHTMLVarchar extends DBVarchar {
|
||||
}
|
||||
|
||||
public function forTemplate() {
|
||||
return $this->RAW();
|
||||
}
|
||||
|
||||
public function RAW() {
|
||||
if ($this->processShortcodes) {
|
||||
return ShortcodeParser::get_active()->parse($this->value);
|
||||
}
|
||||
else {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function exists() {
|
||||
return parent::exists() && $this->value != '<p></p>';
|
||||
return parent::exists() && $this->RAW() != '<p></p>';
|
||||
}
|
||||
|
||||
public function scaffoldFormField($title = null, $params = null) {
|
||||
|
@ -88,9 +88,10 @@ abstract class DBString extends DBField {
|
||||
* @see core/model/fieldtypes/DBField#exists()
|
||||
*/
|
||||
public function exists() {
|
||||
return $this->getValue() // All truthy values exist
|
||||
|| (is_string($this->getValue()) && strlen($this->getValue())) // non-empty strings exist ('0' but not (int)0)
|
||||
|| (!$this->getNullifyEmpty() && $this->getValue() === ''); // Remove this stupid exemption in 4.0
|
||||
$value = $this->RAW();
|
||||
return $value // All truthy values exist
|
||||
|| (is_string($value) && strlen($value)) // non-empty strings exist ('0' but not (int)0)
|
||||
|| (!$this->getNullifyEmpty() && $value === ''); // Remove this stupid exemption in 4.0
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,7 +123,7 @@ abstract class DBString extends DBField {
|
||||
* @return string
|
||||
*/
|
||||
public function LimitCharacters($limit = 20, $add = '...') {
|
||||
$value = trim($this->value);
|
||||
$value = trim($this->RAW());
|
||||
if($this->stat('escape_type') == 'xml') {
|
||||
$value = strip_tags($value);
|
||||
$value = html_entity_decode($value, ENT_COMPAT, 'UTF-8');
|
||||
@ -146,13 +147,13 @@ abstract class DBString extends DBField {
|
||||
*/
|
||||
public function LimitCharactersToClosestWord($limit = 20, $add = '...') {
|
||||
// Strip HTML tags if they exist in the field
|
||||
$this->value = strip_tags($this->value);
|
||||
$value = strip_tags($this->RAW());
|
||||
|
||||
// Determine if value exceeds limit before limiting characters
|
||||
$exceedsLimit = mb_strlen($this->value) > $limit;
|
||||
$exceedsLimit = mb_strlen($value) > $limit;
|
||||
|
||||
// Limit to character limit
|
||||
$value = $this->LimitCharacters($limit, '');
|
||||
$value = DBField::create_field(get_class($this), $value)->LimitCharacters($limit, '');
|
||||
|
||||
// If value exceeds limit, strip punctuation off the end to the last space and apply ellipsis
|
||||
if($exceedsLimit) {
|
||||
@ -178,11 +179,11 @@ abstract class DBString extends DBField {
|
||||
* @return string
|
||||
*/
|
||||
public function LimitWordCount($numWords = 26, $add = '...') {
|
||||
$this->value = trim(Convert::xml2raw($this->value));
|
||||
$ret = explode(' ', $this->value, $numWords + 1);
|
||||
$value = trim(Convert::xml2raw($this->RAW()));
|
||||
$ret = explode(' ', $value, $numWords + 1);
|
||||
|
||||
if(count($ret) <= $numWords - 1) {
|
||||
$ret = $this->value;
|
||||
$ret = $value;
|
||||
} else {
|
||||
array_pop($ret);
|
||||
$ret = implode(' ', $ret) . $add;
|
||||
@ -213,7 +214,7 @@ abstract class DBString extends DBField {
|
||||
* @return string
|
||||
*/
|
||||
public function LowerCase() {
|
||||
return mb_strtolower($this->value);
|
||||
return mb_strtolower($this->RAW());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -221,7 +222,7 @@ abstract class DBString extends DBField {
|
||||
* @return string
|
||||
*/
|
||||
public function UpperCase() {
|
||||
return mb_strtoupper($this->value);
|
||||
return mb_strtoupper($this->RAW());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -230,6 +231,6 @@ abstract class DBString extends DBField {
|
||||
* @return string
|
||||
*/
|
||||
public function NoHTML() {
|
||||
return strip_tags($this->value);
|
||||
return strip_tags($this->RAW());
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ class DBText extends DBString {
|
||||
* @return string
|
||||
*/
|
||||
public function AbsoluteLinks() {
|
||||
return HTTP::absoluteURLs($this->value);
|
||||
return HTTP::absoluteURLs($this->RAW());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,7 +86,7 @@ class DBText extends DBString {
|
||||
}
|
||||
|
||||
$output = array();
|
||||
$data = trim(Convert::xml2raw($this->value));
|
||||
$data = trim(Convert::xml2raw($this->RAW()));
|
||||
$sentences = explode('.', $data);
|
||||
|
||||
if ($sentCount == 0) return '';
|
||||
@ -106,7 +106,7 @@ class DBText extends DBString {
|
||||
* Caution: Not XML/HTML-safe - does not respect closing tags.
|
||||
*/
|
||||
public function FirstSentence() {
|
||||
$paragraph = Convert::xml2raw( $this->value );
|
||||
$paragraph = Convert::xml2raw( $this->RAW() );
|
||||
if( !$paragraph ) return "";
|
||||
|
||||
$words = preg_split('/\s+/', $paragraph);
|
||||
@ -127,7 +127,7 @@ class DBText extends DBString {
|
||||
public function Summary($maxWords = 50) {
|
||||
// get first sentence?
|
||||
// this needs to be more robust
|
||||
$value = Convert::xml2raw( $this->value /*, true*/ );
|
||||
$value = Convert::xml2raw( $this->RAW() /*, true*/ );
|
||||
if(!$value) return '';
|
||||
|
||||
// grab the first paragraph, or, failing that, the whole content
|
||||
@ -169,7 +169,7 @@ class DBText extends DBString {
|
||||
|
||||
// get first sentence?
|
||||
// this needs to be more robust
|
||||
$data = $plain ? Convert::xml2raw($this->value, true) : $this->value;
|
||||
$data = $plain ? Convert::xml2raw($this->RAW(), true) : $this->RAW();
|
||||
|
||||
if(!$data) return '';
|
||||
|
||||
@ -209,8 +209,9 @@ class DBText extends DBString {
|
||||
public function FirstParagraph($plain = 1) {
|
||||
// get first sentence?
|
||||
// this needs to be more robust
|
||||
$value = $this->RAW();
|
||||
if($plain && $plain != 'html') {
|
||||
$data = Convert::xml2raw($this->value);
|
||||
$data = Convert::xml2raw($value);
|
||||
if(!$data) return "";
|
||||
|
||||
// grab the first paragraph, or, failing that, the whole content
|
||||
@ -219,12 +220,12 @@ class DBText extends DBString {
|
||||
|
||||
return $data;
|
||||
} else {
|
||||
if(strpos($this->value, "</p>") === false) return $this->value;
|
||||
if(strpos($value, "</p>") === false) return $value;
|
||||
|
||||
$data = substr($this->value, 0, strpos($this->value, "</p>") + 4);
|
||||
$data = substr($value, 0, strpos($value, "</p>") + 4);
|
||||
|
||||
if(strlen($data) < 20 && strpos($this->value, "</p>", strlen($data))) {
|
||||
$data = substr($this->value, 0, strpos( $this->value, "</p>", strlen($data)) + 4 );
|
||||
if(strlen($data) < 20 && strpos($value, "</p>", strlen($data))) {
|
||||
$data = substr($value, 0, strpos( $value, "</p>", strlen($data)) + 4 );
|
||||
}
|
||||
|
||||
return $data;
|
||||
@ -253,7 +254,7 @@ class DBText extends DBString {
|
||||
}
|
||||
|
||||
// Remove HTML tags so we don't have to deal with matching tags
|
||||
$text = $striphtml ? $this->NoHTML() : $this->value;
|
||||
$text = $striphtml ? $this->NoHTML() : $this->RAW();
|
||||
|
||||
// Find the search string
|
||||
$position = (int) stripos($text, $string);
|
||||
@ -285,7 +286,7 @@ class DBText extends DBString {
|
||||
$summary = trim($summary);
|
||||
|
||||
if($position > 0) $summary = $prefix . $summary;
|
||||
if(strlen($this->value) > ($characters + $position)) $summary = $summary . $suffix;
|
||||
if(strlen($this->RAW()) > ($characters + $position)) $summary = $summary . $suffix;
|
||||
|
||||
return $summary;
|
||||
}
|
||||
@ -299,14 +300,14 @@ class DBText extends DBString {
|
||||
*/
|
||||
public function Parse($parser = "TextParser") {
|
||||
if($parser == "TextParser" || is_subclass_of($parser, "TextParser")) {
|
||||
$obj = new $parser($this->value);
|
||||
$obj = new $parser($this->RAW());
|
||||
return $obj->parse();
|
||||
} else {
|
||||
// Fallback to using raw2xml and show a warning
|
||||
// TODO Don't kill script execution, we can continue without losing complete control of the app
|
||||
user_error("Couldn't find an appropriate TextParser sub-class to create (Looked for '$parser')."
|
||||
. "Make sure it sub-classes TextParser and that you've done ?flush=1.", E_USER_WARNING);
|
||||
return Convert::raw2xml($this->value);
|
||||
return Convert::raw2xml($this->RAW());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,15 +80,19 @@ class DBVarchar extends DBString {
|
||||
* Return the first letter of the string followed by a .
|
||||
*/
|
||||
public function Initial() {
|
||||
if($this->exists()) return $this->value[0] . '.';
|
||||
if($this->exists()) {
|
||||
$value = $this->RAW();
|
||||
return $value[0] . '.';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the given value is an absolute URL.
|
||||
*/
|
||||
public function URL() {
|
||||
if(preg_match('#^[a-zA-Z]+://#', $this->value)) return $this->value;
|
||||
else return "http://" . $this->value;
|
||||
$value = $this->RAW();
|
||||
if(preg_match('#^[a-zA-Z]+://#', $value)) return $value;
|
||||
else return "http://" . $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,7 +100,7 @@ class DBVarchar extends DBString {
|
||||
* @return string
|
||||
*/
|
||||
public function RTF() {
|
||||
return str_replace("\n", '\par ', $this->value);
|
||||
return str_replace("\n", '\par ', $this->RAW());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,7 +129,7 @@ class MemberLoginForm extends LoginForm {
|
||||
FormAction::create('dologin', _t('Member.BUTTONLOGIN', "Log in")),
|
||||
LiteralField::create(
|
||||
'forgotPassword',
|
||||
'<p id="ForgotPassword"><a href="Security/lostpassword">'
|
||||
'<p id="ForgotPassword"><a href="' . Security::lost_password_url() . '">'
|
||||
. _t('Member.BUTTONLOSTPASSWORD', "I've lost my password") . '</a></p>'
|
||||
)
|
||||
);
|
||||
|
@ -201,10 +201,9 @@ class Permission extends DataObject implements TemplateGlobalProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (substr($permCode, 0, 11) === 'CMS_ACCESS_') {
|
||||
elseif (substr($permCode, 0, 11) === 'CMS_ACCESS_' && !in_array('CMS_ACCESS_LeftAndMain', $code)) {
|
||||
//cms_access_leftandmain means access to all CMS areas
|
||||
$code[] = 'CMS_ACCESS_LeftAndMain';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,6 +155,15 @@ class Security extends Controller implements TemplateGlobalProvider {
|
||||
*/
|
||||
private static $logout_url = "Security/logout";
|
||||
|
||||
/**
|
||||
* The default lost password URL
|
||||
*
|
||||
* @config
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $lost_password_url = "Security/lostpassword";
|
||||
|
||||
/**
|
||||
* Get location of word list file
|
||||
*
|
||||
@ -1159,7 +1168,7 @@ class Security extends Controller implements TemplateGlobalProvider {
|
||||
* @return string
|
||||
*/
|
||||
public static function login_url() {
|
||||
return self::config()->login_url;
|
||||
return Controller::join_links(Director::baseURL(), self::config()->login_url);
|
||||
}
|
||||
|
||||
|
||||
@ -1171,9 +1180,19 @@ class Security extends Controller implements TemplateGlobalProvider {
|
||||
* @return string
|
||||
*/
|
||||
public static function logout_url() {
|
||||
return self::config()->logout_url;
|
||||
return Controller::join_links(Director::baseURL(), self::config()->logout_url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL of the logout page.
|
||||
*
|
||||
* To update the logout url use the "Security.logout_url" config setting.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function lost_password_url() {
|
||||
return Controller::join_links(Director::baseURL(), self::config()->lost_password_url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines global accessible templates variables.
|
||||
@ -1184,6 +1203,7 @@ class Security extends Controller implements TemplateGlobalProvider {
|
||||
return array(
|
||||
"LoginURL" => "login_url",
|
||||
"LogoutURL" => "logout_url",
|
||||
"LostPasswordURL" => "lost_password_url",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ you will get an instance of [api:HasManyList] rather than the object.
|
||||
echo $player->FirstName;
|
||||
}
|
||||
|
||||
To specify multiple $has_manys to the same object you can use dot notation to distinguish them like below:
|
||||
To specify multiple `$has_many` to the same object you can use dot notation to distinguish them like below:
|
||||
|
||||
:::php
|
||||
<?php
|
||||
@ -172,15 +172,25 @@ To specify multiple $has_manys to the same object you can use dot notation to di
|
||||
Multiple `$has_one` relationships are okay if they aren't linking to the same object type. Otherwise, they have to be
|
||||
named.
|
||||
|
||||
If you're using the default scaffolded form fields with multiple `has_one` relationships, you will end up with a CMS field for each relation. If you don't want these you can remove them by their IDs:
|
||||
|
||||
:::php
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
$fields->removeByName(array('ManagerID', 'CleanerID'));
|
||||
return $fields;
|
||||
}
|
||||
|
||||
|
||||
## belongs_to
|
||||
|
||||
Defines a 1-to-1 relationship with another object, which declares the other end of the relationship with a
|
||||
corresponding $has_one. A single database column named `<relationship-name>ID` will be created in the object with the
|
||||
corresponding `$has_one`. A single database column named `<relationship-name>ID` will be created in the object with the
|
||||
`$has_one`, but the $belongs_to by itself will not create a database field. This field will hold the ID of the object
|
||||
declaring the `$belongs_to`.
|
||||
|
||||
Similarly with $has_many, dot notation can be used to explicitly specify the `$has_one` which refers to this relation.
|
||||
Similarly with `$has_many`, dot notation can be used to explicitly specify the `$has_one` which refers to this relation.
|
||||
This is not mandatory unless the relationship would be otherwise ambiguous.
|
||||
|
||||
:::php
|
||||
|
@ -75,6 +75,19 @@ Image methods are chainable. Example:
|
||||
:::ss
|
||||
<body style="background-image:url($Image.ScaleWidth(800).CropHeight(800).Link)">
|
||||
|
||||
### Padded Image Resize
|
||||
|
||||
The Pad method allows you to resize an image with existing ratio and will
|
||||
pad any surplus space. You can specify the color of the padding using a hex code such as FFFFFF or 000000.
|
||||
|
||||
You can also specify a level of transparency to apply to the padding color in a fourth param. This will only effect
|
||||
png images.
|
||||
|
||||
:::php
|
||||
$Image.Pad(80, 80, FFFFFF, 50) // white padding with 50% transparency
|
||||
$Image.Pad(80, 80, FFFFFF, 100) // white padding with 100% transparency
|
||||
$Image.Pad(80, 80, FFFFFF) // white padding with no transparency
|
||||
|
||||
### Manipulating images in PHP
|
||||
|
||||
The image manipulation functions can be used in your code with the same names, example: `$image->Fill(150,150)`.
|
||||
|
@ -150,19 +150,61 @@ class ImagickBackend extends Imagick implements Image_Backend {
|
||||
return $this->resize( $scale * $geometry["width"], $height );
|
||||
}
|
||||
|
||||
public function paddedResize($width, $height, $backgroundColor = "FFFFFF") {
|
||||
/**
|
||||
* paddedResize
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param int $transparencyPercent
|
||||
* @return Image_Backend
|
||||
*/
|
||||
public function paddedResize($width, $height, $backgroundColor = "FFFFFF", $transparencyPercent = 0) {
|
||||
if(!$this->valid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//keep the % within bounds of 0-100
|
||||
$transparencyPercent = min(100, max(0, $transparencyPercent));
|
||||
|
||||
$new = $this->resizeRatio($width, $height);
|
||||
$new->setImageBackgroundColor("#".$backgroundColor);
|
||||
if($transparencyPercent) {
|
||||
$alphaHex = $this->calculateAlphaHex($transparencyPercent);
|
||||
$new->setImageBackgroundColor("#{$backgroundColor}{$alphaHex}");
|
||||
} else {
|
||||
$new->setImageBackgroundColor("#{$backgroundColor}");
|
||||
}
|
||||
$w = $new->getImageWidth();
|
||||
$h = $new->getImageHeight();
|
||||
$new->extentImage($width,$height,($w-$width)/2,($h-$height)/2);
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a percentage (or 'true') to a two char hex code to signifiy the level of an alpha channel
|
||||
*
|
||||
* @param $percent
|
||||
* @return string
|
||||
*/
|
||||
public function calculateAlphaHex($percent) {
|
||||
if($percent > 100) {
|
||||
$percent = 100;
|
||||
}
|
||||
// unlike GD, this uses 255 instead of 127, and is reversed. Lower = more transparent
|
||||
$alphaHex = dechex(255 - floor(255 * bcdiv($percent, 100, 2)));
|
||||
if(strlen($alphaHex) == 1) {
|
||||
$alphaHex = '0' .$alphaHex;
|
||||
}
|
||||
return $alphaHex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* croppedResize
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @return Image_Backend
|
||||
*/
|
||||
public function croppedResize($width, $height) {
|
||||
if(!$this->valid()) {
|
||||
return null;
|
||||
|
@ -53,9 +53,7 @@ class CheckboxSetField extends MultiSelectField {
|
||||
'Options' => $this->getOptions()
|
||||
));
|
||||
|
||||
return $this->customise($properties)->renderWith(
|
||||
$this->getTemplates()
|
||||
);
|
||||
return FormField::Field($properties);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,11 +65,10 @@ class ListboxField extends MultiSelectField {
|
||||
*/
|
||||
public function Field($properties = array()) {
|
||||
$properties = array_merge($properties, array(
|
||||
'Options' => $this->getOptions()
|
||||
'Options' => $this->getOptions(),
|
||||
));
|
||||
return $this
|
||||
->customise($properties)
|
||||
->renderWith($this->getTemplates());
|
||||
|
||||
return FormField::Field($properties);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,9 +121,7 @@ class OptionsetField extends SingleSelectField {
|
||||
'Options' => new ArrayList($options)
|
||||
));
|
||||
|
||||
return $this->customise($properties)->renderWith(
|
||||
$this->getTemplates()
|
||||
);
|
||||
return FormField::Field($properties);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -261,7 +261,7 @@ class TreeDropdownField extends FormField {
|
||||
)
|
||||
);
|
||||
|
||||
return $this->customise($properties)->renderWith('TreeDropdownField');
|
||||
return parent::Field($properties);
|
||||
}
|
||||
|
||||
public function extraClass() {
|
||||
|
@ -145,7 +145,7 @@ class TreeMultiselectField extends TreeDropdownField {
|
||||
'Value' => $value
|
||||
)
|
||||
);
|
||||
return $this->customise($properties)->renderWith('TreeDropdownField');
|
||||
return FormField::Field($properties);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1016,11 +1016,11 @@ class UploadField extends FileField {
|
||||
}
|
||||
|
||||
$mergedConfig = array_merge($config, $this->ufConfig);
|
||||
return $this->customise(array(
|
||||
return parent::Field(array(
|
||||
'configString' => str_replace('"', """, Convert::raw2json($mergedConfig)),
|
||||
'config' => new ArrayData($mergedConfig),
|
||||
'multiple' => $allowedMaxFileNumber !== 1
|
||||
))->renderWith($this->getTemplates());
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -270,11 +270,18 @@ class ShortcodeParser extends Object {
|
||||
preg_match_all(static::attrrx(), $match['attrs'][0], $attrmatches, PREG_SET_ORDER);
|
||||
|
||||
foreach ($attrmatches as $attr) {
|
||||
list($whole, $name, $value) = array_values(array_filter($attr, function($attrPart) {
|
||||
return $attrPart !== '';
|
||||
}));
|
||||
$name = '';
|
||||
$value = '';
|
||||
$parts = array_values(array_filter($attr));
|
||||
//the first element in the array is the complete delcaration (`id=1`) - we don't need this
|
||||
array_shift($parts);
|
||||
|
||||
//the next two parts are what we care about (id and 1 from `id=1`)
|
||||
$name = array_shift($parts) ?: $name;
|
||||
$value = array_shift($parts) ?: $value;
|
||||
|
||||
$attrs[$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// And store the indexes, tag details, etc
|
||||
@ -553,6 +560,9 @@ class ShortcodeParser extends Object {
|
||||
// If no content, don't try and parse it
|
||||
if (!trim($content)) return $content;
|
||||
|
||||
// If no shortcode tag, don't try and parse it
|
||||
if (strpos($content, '[') === false) return $content;
|
||||
|
||||
// First we operate in text mode, replacing any shortcodes with marker elements so that later we can
|
||||
// use a proper DOM
|
||||
list($content, $tags) = $this->replaceElementTagsWithMarkers($content);
|
||||
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
class ConfigStaticManifestTestClassKeyword implements TestOnly {
|
||||
|
||||
private static $foo = 'bar';
|
||||
|
||||
public function __construct() {
|
||||
$this->inst = Injector::inst()->get(static::class);
|
||||
}
|
||||
|
||||
}
|
@ -199,4 +199,126 @@ class DBHTMLTextTest extends SapphireTest {
|
||||
'Removes any elements not in whitelist including text elements'
|
||||
);
|
||||
}
|
||||
|
||||
public function testShortCodeParsedInRAW() {
|
||||
$parser = ShortcodeParser::get('HTMLTextTest');
|
||||
$parser->register('shortcode', function($arguments, $content, $parser, $tagName, $extra) {
|
||||
return 'replaced';
|
||||
});
|
||||
ShortcodeParser::set_active('HTMLTextTest');
|
||||
/** @var DBHTMLText $field */
|
||||
$field = DBField::create_field('HTMLText', '<p>[shortcode]</p>');
|
||||
$this->assertEquals('<p>replaced</p>', $field->RAW());
|
||||
$this->assertEquals('<p>replaced</p>', (string)$field);
|
||||
|
||||
$field->setOptions(array(
|
||||
'shortcodes' => false,
|
||||
));
|
||||
|
||||
$this->assertEquals('<p>[shortcode]</p>', $field->RAW());
|
||||
$this->assertEquals('<p>[shortcode]</p>', (string)$field);
|
||||
|
||||
|
||||
ShortcodeParser::set_active('default');
|
||||
}
|
||||
|
||||
public function testShortCodeParsedInTemplateHelpers() {
|
||||
$parser = ShortcodeParser::get('HTMLTextTest');
|
||||
$parser->register('shortcode', function($arguments, $content, $parser, $tagName, $extra) {
|
||||
return 'Replaced short code with this. <a href="home">home</a>';
|
||||
});
|
||||
ShortcodeParser::set_active('HTMLTextTest');
|
||||
/** @var DBHTMLText $field */
|
||||
$field = DBField::create_field('HTMLText', '<p>[shortcode]</p>');
|
||||
|
||||
$this->assertEquals(
|
||||
'<p>Replaced short code with this. <a href="home">home</a></p>',
|
||||
$field->HTMLATT()
|
||||
);
|
||||
$this->assertEquals(
|
||||
'%3Cp%3EReplaced+short+code+with+this.+%3Ca+href%3D%22home%22%3Ehome%3C%2Fa%3E%3C%2Fp%3E',
|
||||
$field->URLATT()
|
||||
);
|
||||
$this->assertEquals(
|
||||
'%3Cp%3EReplaced%20short%20code%20with%20this.%20%3Ca%20href%3D%22home%22%3Ehome%3C%2Fa%3E%3C%2Fp%3E',
|
||||
$field->RAWURLATT()
|
||||
);
|
||||
$this->assertEquals(
|
||||
'<p>Replaced short code with this. <a href="home">home</a></p>',
|
||||
$field->ATT()
|
||||
);
|
||||
$this->assertEquals(
|
||||
'<p>Replaced short code with this. <a href="home">home</a></p>',
|
||||
$field->RAW()
|
||||
);
|
||||
$this->assertEquals(
|
||||
'\x3cp\x3eReplaced short code with this. \x3ca href=\"home\"\x3ehome\x3c/a\x3e\x3c/p\x3e',
|
||||
$field->JS()
|
||||
);
|
||||
$this->assertEquals(
|
||||
'<p>Replaced short code with this. <a href="home">home</a></p>',
|
||||
$field->HTML()
|
||||
);
|
||||
$this->assertEquals(
|
||||
'<p>Replaced short code with this. <a href="home">home</a></p>',
|
||||
$field->XML()
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Repl...',
|
||||
$field->LimitCharacters(4, '...')
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Replaced...',
|
||||
$field->LimitCharactersToClosestWord(10, '...')
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Replaced...',
|
||||
$field->LimitWordCount(1, '...')
|
||||
);
|
||||
$this->assertEquals(
|
||||
'<p>replaced short code with this. <a href="home">home</a></p>',
|
||||
$field->LowerCase()
|
||||
);
|
||||
$this->assertEquals(
|
||||
'<P>REPLACED SHORT CODE WITH THIS. <A HREF="HOME">HOME</A></P>',
|
||||
$field->UpperCase()
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Replaced short code with this. home',
|
||||
$field->NoHTML()
|
||||
);
|
||||
Config::nest();
|
||||
Config::inst()->update('Director', 'alternate_base_url', 'http://example.com/');
|
||||
$this->assertEquals(
|
||||
'<p>Replaced short code with this. <a href="http://example.com/home">home</a></p>',
|
||||
$field->AbsoluteLinks()
|
||||
);
|
||||
Config::unnest();
|
||||
$this->assertEquals(
|
||||
'Replaced short code with this.',
|
||||
$field->LimitSentences(1)
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Replaced short code with this.',
|
||||
$field->FirstSentence()
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Replaced short...',
|
||||
$field->Summary(2)
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Replaced short code with...',
|
||||
$field->BigSummary(4)
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Replaced short code with this. home[home]',
|
||||
$field->FirstParagraph()
|
||||
);
|
||||
$this->assertEquals(
|
||||
'Replaced <span class="highlight">short</span> <span class="highlight">code</span> with this. home',
|
||||
$field->ContextSummary(500, 'short code')
|
||||
);
|
||||
|
||||
ShortcodeParser::set_active('default');
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,12 @@ class ShortcodeParserTest extends SapphireTest {
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
ShortcodeParser::get('test')->unregister('test_shortcode');
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that valid short codes that have not been registered are not replaced.
|
||||
*/
|
||||
@ -218,6 +224,14 @@ class ShortcodeParserTest extends SapphireTest {
|
||||
);
|
||||
}
|
||||
|
||||
public function testFalseyArguments() {
|
||||
$this->parser->parse('<p>[test_shortcode falsey=0]');
|
||||
|
||||
$this->assertEquals(array(
|
||||
'falsey' => '',
|
||||
), $this->arguments);
|
||||
}
|
||||
|
||||
public function testNumericShortcodes() {
|
||||
$this->assertEqualsIgnoringWhitespace(
|
||||
'[2]',
|
||||
@ -240,6 +254,8 @@ class ShortcodeParserTest extends SapphireTest {
|
||||
'<script>this is 2</script>',
|
||||
$this->parser->parse('<script>[2]</script>')
|
||||
);
|
||||
|
||||
$this->parser->unregister('2');
|
||||
}
|
||||
|
||||
public function testExtraContext() {
|
||||
@ -250,6 +266,18 @@ class ShortcodeParserTest extends SapphireTest {
|
||||
$this->assertEquals($this->extra['element']->tagName, 'a');
|
||||
}
|
||||
|
||||
public function testNoParseAttemptIfNoCode() {
|
||||
$stub = $this->getMock('ShortcodeParser', array('replaceElementTagsWithMarkers'));
|
||||
$stub->register('test', function() {
|
||||
return '';
|
||||
});
|
||||
|
||||
$stub->expects($this->never())
|
||||
->method('replaceElementTagsWithMarkers')->will($this->returnValue(array('', '')));
|
||||
|
||||
$stub->parse('<p>test</p>');
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
@ -31,6 +31,8 @@ class PermissionTest extends SapphireTest {
|
||||
$members = Member::get()->byIDs($this->allFixtureIDs('SilverStripe\\Security\\Member'));
|
||||
foreach ($members as $member) {
|
||||
$this->assertTrue(Permission::checkMember($member, 'CMS_ACCESS'));
|
||||
$this->assertTrue(Permission::checkMember($member, array('CMS_ACCESS', 'CMS_ACCESS_Security')));
|
||||
$this->assertTrue(Permission::checkMember($member, array('CMS_ACCESS_Security', 'CMS_ACCESS')));
|
||||
}
|
||||
|
||||
$member = new Member();
|
||||
@ -41,6 +43,8 @@ class PermissionTest extends SapphireTest {
|
||||
));
|
||||
$member->write();
|
||||
$this->assertFalse(Permission::checkMember($member, 'CMS_ACCESS'));
|
||||
$this->assertFalse(Permission::checkMember($member, array('CMS_ACCESS', 'CMS_ACCESS_Security')));
|
||||
$this->assertFalse(Permission::checkMember($member, array('CMS_ACCESS_Security', 'CMS_ACCESS')));
|
||||
}
|
||||
|
||||
public function testLeftAndMainAccessAll() {
|
||||
|
Loading…
Reference in New Issue
Block a user