2009-10-23 03:29:55 +02:00
|
|
|
<?php
|
2015-08-30 07:02:55 +02:00
|
|
|
|
2016-06-15 06:03:16 +02:00
|
|
|
namespace SilverStripe\ORM\FieldType;
|
2015-08-30 07:02:55 +02:00
|
|
|
|
|
|
|
use Convert;
|
|
|
|
|
2009-10-23 03:29:55 +02:00
|
|
|
/**
|
|
|
|
* An abstract base class for the string field types (i.e. Varchar and Text)
|
2013-04-05 10:57:54 +02:00
|
|
|
*
|
2012-04-12 08:02:46 +02:00
|
|
|
* @package framework
|
2016-06-15 06:03:16 +02:00
|
|
|
* @subpackage orm
|
2009-10-23 03:29:55 +02:00
|
|
|
*/
|
2015-08-30 07:02:55 +02:00
|
|
|
abstract class DBString extends DBField {
|
2013-04-05 10:57:54 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var boolean
|
|
|
|
*/
|
2009-10-23 03:29:55 +02:00
|
|
|
protected $nullifyEmpty = true;
|
|
|
|
|
2013-04-05 10:57:54 +02:00
|
|
|
/**
|
|
|
|
* @var array
|
|
|
|
*/
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $casting = array(
|
2012-01-31 01:07:24 +01:00
|
|
|
"LimitCharacters" => "Text",
|
2014-10-17 11:41:28 +02:00
|
|
|
"LimitCharactersToClosestWord" => "Text",
|
2013-04-05 10:57:54 +02:00
|
|
|
'LimitWordCount' => 'Text',
|
2012-01-31 11:44:16 +01:00
|
|
|
"LowerCase" => "Text",
|
|
|
|
"UpperCase" => "Text",
|
2014-09-27 22:32:35 +02:00
|
|
|
'NoHTML' => 'Text',
|
2012-01-31 01:07:24 +01:00
|
|
|
);
|
|
|
|
|
2009-10-23 03:29:55 +02:00
|
|
|
/**
|
2013-04-05 10:57:54 +02:00
|
|
|
* Construct a string type field with a set of optional parameters.
|
|
|
|
*
|
2016-06-03 10:51:02 +02:00
|
|
|
* @param string $name string The name of the field
|
|
|
|
* @param array $options array An array of options e.g. array('nullifyEmpty'=>false). See
|
2012-09-26 23:34:00 +02:00
|
|
|
* {@link StringField::setOptions()} for information on the available options
|
2009-10-23 03:29:55 +02:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function __construct($name = null, $options = array()) {
|
2016-06-03 10:51:02 +02:00
|
|
|
$options = $this->parseConstructorOptions($options);
|
|
|
|
if($options) {
|
2009-10-23 03:29:55 +02:00
|
|
|
$this->setOptions($options);
|
|
|
|
}
|
2013-04-05 10:57:54 +02:00
|
|
|
|
2009-10-23 03:29:55 +02:00
|
|
|
parent::__construct($name);
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2016-06-03 10:51:02 +02:00
|
|
|
/**
|
|
|
|
* Parses the "options" parameter passed to the constructor. This could be a
|
|
|
|
* string value, or an array of options. Config specification might also
|
|
|
|
* encode "key=value" pairs in non-associative strings.
|
|
|
|
*
|
|
|
|
* @param mixed $options
|
|
|
|
* @return array The list of parsed options, or empty if there are none
|
|
|
|
*/
|
|
|
|
protected function parseConstructorOptions($options) {
|
|
|
|
if(is_string($options)) {
|
|
|
|
$options = [$options];
|
|
|
|
}
|
|
|
|
if(!is_array($options)) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
$parsed = [];
|
|
|
|
foreach($options as $option => $value) {
|
|
|
|
// Workaround for inability for config args to support associative arrays
|
|
|
|
if(is_numeric($option) && strpos($value, '=') !== false) {
|
|
|
|
list($option, $value) = explode('=', $value);
|
|
|
|
$option = trim($option);
|
|
|
|
$value = trim($value);
|
|
|
|
}
|
|
|
|
// Convert bool values
|
|
|
|
if(strcasecmp($value, 'true') === 0) {
|
|
|
|
$value = true;
|
|
|
|
} elseif(strcasecmp($value, 'false') === 0) {
|
|
|
|
$value = false;
|
|
|
|
}
|
|
|
|
$parsed[$option] = $value;
|
|
|
|
}
|
|
|
|
return $parsed;
|
|
|
|
}
|
|
|
|
|
2009-10-23 03:29:55 +02:00
|
|
|
/**
|
|
|
|
* Update the optional parameters for this field.
|
2016-06-03 10:51:02 +02:00
|
|
|
*
|
|
|
|
* @param array $options Array of options
|
2009-10-23 03:29:55 +02:00
|
|
|
* The options allowed are:
|
|
|
|
* <ul><li>"nullifyEmpty"
|
|
|
|
* This is a boolean flag.
|
2012-09-26 23:34:00 +02:00
|
|
|
* 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.
|
2009-10-23 03:29:55 +02:00
|
|
|
* </li></ul>
|
2016-06-03 10:51:02 +02:00
|
|
|
* @return $this
|
2009-10-23 03:29:55 +02:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function setOptions(array $options = array()) {
|
2009-10-23 03:29:55 +02:00
|
|
|
if(array_key_exists("nullifyEmpty", $options)) {
|
|
|
|
$this->nullifyEmpty = $options["nullifyEmpty"] ? true : false;
|
|
|
|
}
|
2016-06-03 10:51:02 +02:00
|
|
|
return $this;
|
2009-10-23 03:29:55 +02:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-10-23 03:29:55 +02:00
|
|
|
/**
|
2013-04-05 10:57:54 +02:00
|
|
|
* Set whether this field stores empty strings rather than converting
|
|
|
|
* them to null.
|
|
|
|
*
|
2009-10-23 03:29:55 +02:00
|
|
|
* @param $value boolean True if empty strings are to be converted to null
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function setNullifyEmpty($value) {
|
2010-10-19 02:53:46 +02:00
|
|
|
$this->nullifyEmpty = ($value ? true : false);
|
2009-10-23 03:29:55 +02:00
|
|
|
}
|
2013-04-05 10:57:54 +02:00
|
|
|
|
2009-10-23 03:29:55 +02:00
|
|
|
/**
|
2013-04-05 10:57:54 +02:00
|
|
|
* 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
|
2009-10-23 03:29:55 +02:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function getNullifyEmpty() {
|
2009-10-23 03:29:55 +02:00
|
|
|
return $this->nullifyEmpty;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* (non-PHPdoc)
|
2012-04-11 04:48:06 +02:00
|
|
|
* @see core/model/fieldtypes/DBField#exists()
|
2009-10-23 03:29:55 +02:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function exists() {
|
2016-06-30 16:54:44 +02:00
|
|
|
$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
|
2009-10-23 03:29:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* (non-PHPdoc)
|
|
|
|
* @see core/model/fieldtypes/DBField#prepValueForDB($value)
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function prepValueForDB($value) {
|
2012-03-20 09:20:35 +01:00
|
|
|
if(!$this->nullifyEmpty && $value === '') {
|
2013-06-21 00:32:08 +02:00
|
|
|
return $value;
|
2009-10-23 03:29:55 +02:00
|
|
|
} else {
|
|
|
|
return parent::prepValueForDB($value);
|
|
|
|
}
|
|
|
|
}
|
2013-05-30 10:26:58 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function forTemplate() {
|
2016-06-03 10:51:02 +02:00
|
|
|
return nl2br(parent::forTemplate());
|
2013-05-30 10:26:58 +02:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2011-12-17 00:27:14 +01:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function LimitCharacters($limit = 20, $add = '...') {
|
2016-06-30 16:54:44 +02:00
|
|
|
$value = trim($this->RAW());
|
2011-12-17 00:27:14 +01:00
|
|
|
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;
|
|
|
|
}
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2014-10-17 11:41:28 +02:00
|
|
|
/**
|
|
|
|
* Limit this field's content by a number of characters and truncate
|
2016-01-06 00:34:58 +01:00
|
|
|
* the field to the closest complete word. All HTML tags are stripped
|
2014-10-17 11:41:28 +02:00
|
|
|
* 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
|
2016-06-30 16:54:44 +02:00
|
|
|
$value = strip_tags($this->RAW());
|
2014-10-17 11:41:28 +02:00
|
|
|
|
|
|
|
// Determine if value exceeds limit before limiting characters
|
2016-06-30 16:54:44 +02:00
|
|
|
$exceedsLimit = mb_strlen($value) > $limit;
|
2012-01-31 11:44:16 +01:00
|
|
|
|
2014-10-17 11:41:28 +02:00
|
|
|
// Limit to character limit
|
2016-06-30 16:54:44 +02:00
|
|
|
$value = DBField::create_field(get_class($this), $value)->LimitCharacters($limit, '');
|
2014-10-17 11:41:28 +02:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
2013-04-05 10:57:54 +02:00
|
|
|
|
2012-01-31 11:44:16 +01:00
|
|
|
/**
|
2013-04-05 10:57:54 +02:00
|
|
|
* Limit this field's content by a number of words.
|
|
|
|
*
|
|
|
|
* @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 = '...') {
|
2016-06-30 16:54:44 +02:00
|
|
|
$value = trim(Convert::xml2raw($this->RAW()));
|
|
|
|
$ret = explode(' ', $value, $numWords + 1);
|
2013-04-05 10:57:54 +02:00
|
|
|
|
|
|
|
if(count($ret) <= $numWords - 1) {
|
2016-06-30 16:54:44 +02:00
|
|
|
$ret = $value;
|
2013-04-05 10:57:54 +02:00
|
|
|
} else {
|
|
|
|
array_pop($ret);
|
|
|
|
$ret = implode(' ', $ret) . $add;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts the current value for this StringField to lowercase.
|
|
|
|
*
|
2012-01-31 11:44:16 +01:00
|
|
|
* @return string
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function LowerCase() {
|
2016-06-30 16:54:44 +02:00
|
|
|
return mb_strtolower($this->RAW());
|
2012-01-31 11:44:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-04-05 10:57:54 +02:00
|
|
|
* Converts the current value for this StringField to uppercase.
|
2016-06-03 10:51:02 +02:00
|
|
|
*
|
2014-08-15 08:53:05 +02:00
|
|
|
* @return string
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function UpperCase() {
|
2016-06-30 16:54:44 +02:00
|
|
|
return mb_strtoupper($this->RAW());
|
2009-11-21 02:41:24 +01:00
|
|
|
}
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2014-09-27 22:32:35 +02:00
|
|
|
/**
|
2016-06-03 10:51:02 +02:00
|
|
|
* Plain text version of this string
|
2014-09-27 22:32:35 +02:00
|
|
|
*
|
2016-06-03 10:51:02 +02:00
|
|
|
* @return string Plain text
|
2014-09-27 22:32:35 +02:00
|
|
|
*/
|
|
|
|
public function NoHTML() {
|
2016-06-03 10:51:02 +02:00
|
|
|
return $this->RAW();
|
2014-09-27 22:32:35 +02:00
|
|
|
}
|
2009-10-23 03:29:55 +02:00
|
|
|
}
|