silverstripe-framework/model/FieldType/DBString.php
Sam Minnee aeccb8b8e0 API: Move DBField subclasses into SilverStripe\Model\FieldType namespace
API: Deprecate SS_Datetime.

The DBField subclasses are have all been renamed to start with “DB” and
be in the SilverStripe\Model\FieldType namespace. To keep DataObject
definitions concise, the original short variations of their names are
preserved as service definitions. Most of the field generation code
doesn’t need to change, but where field classes are referenced directly,
changes will be needed.

SS_Datetime, which is commonly referenced outside the model system
itself, has been preserved as a subclass of DBDatetime. This has been
marked as deprecated and can be removed in SilverStripe 5.

A few places that referred to $db and $casting values weren’t using
the Injector to instantiate the relevant classes. This meant that the
remapping we have created as part of moving classes into a namespace
didn’t work.
2016-03-22 18:09:30 +13:00

237 lines
6.4 KiB
PHP

<?php
namespace SilverStripe\Model\FieldType;
use Convert;
/**
* An abstract base class for the string field types (i.e. Varchar and Text)
*
* @package framework
* @subpackage model
*/
abstract class DBString extends DBField {
/**
* @var boolean
*/
protected $nullifyEmpty = true;
/**
* @var array
*/
private static $casting = array(
"LimitCharacters" => "Text",
"LimitCharactersToClosestWord" => "Text",
'LimitWordCount' => 'Text',
'LimitWordCountXML' => 'HTMLText',
"LowerCase" => "Text",
"UpperCase" => "Text",
'NoHTML' => 'Text',
);
/**
* Construct a string type field with a set of optional parameters.
*
* @param $name string The name of the field
* @param $options array An array of options e.g. array('nullifyEmpty'=>false). See
* {@link StringField::setOptions()} for information on the available options
*/
public function __construct($name = null, $options = array()) {
// Workaround: The singleton pattern calls this constructor with true/1 as the second parameter, so we
// must ignore it
if(is_array($options)){
$this->setOptions($options);
}
parent::__construct($name);
}
/**
* Update the optional parameters for this field.
* @param $options array of options
* The options allowed are:
* <ul><li>"nullifyEmpty"
* This is a boolean flag.
* True (the default) means that empty strings are automatically converted to nulls to be stored in
* the database. Set it to false to ensure that nulls and empty strings are kept intact in the database.
* </li></ul>
* @return unknown_type
*/
public function setOptions(array $options = array()) {
if(array_key_exists("nullifyEmpty", $options)) {
$this->nullifyEmpty = $options["nullifyEmpty"] ? true : false;
}
}
/**
* Set whether this field stores empty strings rather than converting
* them to null.
*
* @param $value boolean True if empty strings are to be converted to null
*/
public function setNullifyEmpty($value) {
$this->nullifyEmpty = ($value ? true : false);
}
/**
* Get whether this field stores empty strings rather than converting
* them to null
*
* @return boolean True if empty strings are to be converted to null
*/
public function getNullifyEmpty() {
return $this->nullifyEmpty;
}
/**
* (non-PHPdoc)
* @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
}
/**
* (non-PHPdoc)
* @see core/model/fieldtypes/DBField#prepValueForDB($value)
*/
public function prepValueForDB($value) {
if(!$this->nullifyEmpty && $value === '') {
return $value;
} else {
return parent::prepValueForDB($value);
}
}
/**
* @return string
*/
public function forTemplate() {
return nl2br($this->XML());
}
/**
* Limit this field's content by a number of characters.
* This makes use of strip_tags() to avoid malforming the
* HTML tags in the string of text.
*
* @param int $limit Number of characters to limit by
* @param string $add Ellipsis to add to the end of truncated string
* @return string
*/
public function LimitCharacters($limit = 20, $add = '...') {
$value = trim($this->value);
if($this->stat('escape_type') == 'xml') {
$value = strip_tags($value);
$value = html_entity_decode($value, ENT_COMPAT, 'UTF-8');
$value = (mb_strlen($value) > $limit) ? mb_substr($value, 0, $limit) . $add : $value;
// Avoid encoding all multibyte characters as HTML entities by using htmlspecialchars().
$value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
} else {
$value = (mb_strlen($value) > $limit) ? mb_substr($value, 0, $limit) . $add : $value;
}
return $value;
}
/**
* Limit this field's content by a number of characters and truncate
* the field to the closest complete word. All HTML tags are stripped
* from the field.
*
* @param int $limit Number of characters to limit by
* @param string $add Ellipsis to add to the end of truncated string
* @return string
*/
public function LimitCharactersToClosestWord($limit = 20, $add = '...') {
// Strip HTML tags if they exist in the field
$this->value = strip_tags($this->value);
// Determine if value exceeds limit before limiting characters
$exceedsLimit = mb_strlen($this->value) > $limit;
// Limit to character limit
$value = $this->LimitCharacters($limit, '');
// If value exceeds limit, strip punctuation off the end to the last space and apply ellipsis
if($exceedsLimit) {
$value = html_entity_decode($value, ENT_COMPAT, 'UTF-8');
$value = rtrim(mb_substr($value, 0, mb_strrpos($value, " ")), "/[\.,-\/#!$%\^&\*;:{}=\-_`~()]\s") . $add;
$value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
}
return $value;
}
/**
* Limit this field's content by a number of words.
*
* CAUTION: This is not XML safe. Please use
* {@link LimitWordCountXML()} instead.
*
* @param int $numWords Number of words to limit by.
* @param string $add Ellipsis to add to the end of truncated string.
*
* @return string
*/
public function LimitWordCount($numWords = 26, $add = '...') {
$this->value = trim(Convert::xml2raw($this->value));
$ret = explode(' ', $this->value, $numWords + 1);
if(count($ret) <= $numWords - 1) {
$ret = $this->value;
} else {
array_pop($ret);
$ret = implode(' ', $ret) . $add;
}
return $ret;
}
/**
* Limit the number of words of the current field's
* content. This is XML safe, so characters like &
* are converted to &amp;
*
* @param int $numWords Number of words to limit by.
* @param string $add Ellipsis to add to the end of truncated string.
*
* @return string
*/
public function LimitWordCountXML($numWords = 26, $add = '...') {
$ret = $this->LimitWordCount($numWords, $add);
return Convert::raw2xml($ret);
}
/**
* Converts the current value for this StringField to lowercase.
*
* @return string
*/
public function LowerCase() {
return mb_strtolower($this->value);
}
/**
* Converts the current value for this StringField to uppercase.
* @return string
*/
public function UpperCase() {
return mb_strtoupper($this->value);
}
/**
* Return the value of the field stripped of html tags.
*
* @return string
*/
public function NoHTML() {
return strip_tags($this->value);
}
}