Completed
Push — 3 ( aecac8...3139b2 )
by Daniel
17:56
created

StringField::isPopulated()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 4
nc 7
nop 1
dl 0
loc 5
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * An abstract base class for the string field types (i.e. Varchar and Text)
4
 *
5
 * @package framework
6
 * @subpackage model
7
 */
8
abstract class StringField extends DBField {
9
10
	/**
11
	 * @var boolean
12
	 */
13
	protected $nullifyEmpty = true;
14
15
	/**
16
	 * @var array
17
	 */
18
	private static $casting = array(
19
		"LimitCharacters" => "Text",
20
		"LimitCharactersToClosestWord" => "Text",
21
		'LimitWordCount' => 'Text',
22
		'LimitWordCountXML' => 'HTMLText',
23
		"LowerCase" => "Text",
24
		"UpperCase" => "Text",
25
		'NoHTML' => 'Text',
26
	);
27
28
	/**
29
	 * Construct a string type field with a set of optional parameters.
30
	 *
31
	 * @param $name string The name of the field
32
	 * @param $options array An array of options e.g. array('nullifyEmpty'=>false).  See
33
	 *                       {@link StringField::setOptions()} for information on the available options
34
	 */
35
	public function __construct($name = null, $options = array()) {
36
		// Workaround: The singleton pattern calls this constructor with true/1 as the second parameter, so we
37
		// must ignore it
38
		if(is_array($options)){
39
			$this->setOptions($options);
40
		}
41
42
		parent::__construct($name);
43
	}
44
45
	/**
46
	 * Update the optional parameters for this field.
47
	 * @param $options array of options
48
	 * The options allowed are:
49
	 *   <ul><li>"nullifyEmpty"
50
	 *       This is a boolean flag.
51
	 *       True (the default) means that empty strings are automatically converted to nulls to be stored in
52
	 *       the database. Set it to false to ensure that nulls and empty strings are kept intact in the database.
53
	 *   </li></ul>
54
	 * @return unknown_type
55
	 */
56
	public function setOptions(array $options = array()) {
57
		if(array_key_exists("nullifyEmpty", $options)) {
58
			$this->nullifyEmpty = $options["nullifyEmpty"] ? true : false;
59
		}
60
	}
61
62
	/**
63
	 * Set whether this field stores empty strings rather than converting
64
	 * them to null.
65
	 *
66
	 * @param $value boolean True if empty strings are to be converted to null
67
	 */
68
	public function setNullifyEmpty($value) {
69
		$this->nullifyEmpty = ($value ? true : false);
70
	}
71
72
	/**
73
	 * Get whether this field stores empty strings rather than converting
74
	 * them to null
75
	 *
76
	 * @return boolean True if empty strings are to be converted to null
77
	 */
78
	public function getNullifyEmpty() {
79
		return $this->nullifyEmpty;
80
	}
81
82
	/**
83
	 * (non-PHPdoc)
84
	 * @see core/model/fieldtypes/DBField#exists()
85
	 */
86
	public function exists() {
87
		$value = $this->RAW();
88
		return $this->isPopulated($value);
89
	}
90
91
	/**
92
	 * (non-PHPdoc)
93
	 * @see core/model/fieldtypes/DBField#prepValueForDB($value)
94
	 */
95
	public function prepValueForDB($value) {
96
		if(!$this->nullifyEmpty && $value === '') {
97
			return $value;
98
		} else {
99
			return parent::prepValueForDB($value);
100
		}
101
	}
102
103
	/**
104
	 * @return string
105
	 */
106
	public function forTemplate() {
107
		return nl2br($this->XML());
108
	}
109
110
	/**
111
	 * Limit this field's content by a number of characters.
112
	 * This makes use of strip_tags() to avoid malforming the
113
	 * HTML tags in the string of text.
114
	 *
115
	 * @param int $limit Number of characters to limit by
116
	 * @param string $add Ellipsis to add to the end of truncated string
117
	 * @return string
118
	 */
119
	public function LimitCharacters($limit = 20, $add = '...') {
120
		$value = trim($this->RAW());
121
		if($this->stat('escape_type') == 'xml') {
122
			$value = strip_tags($value);
123
			$value = html_entity_decode($value, ENT_COMPAT, 'UTF-8');
124
			$value = (mb_strlen($value) > $limit) ? mb_substr($value, 0, $limit) . $add : $value;
125
			// Avoid encoding all multibyte characters as HTML entities by using htmlspecialchars().
126
			$value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
127
		} else {
128
			$value = (mb_strlen($value) > $limit) ? mb_substr($value, 0, $limit) . $add : $value;
129
		}
130
		return $value;
131
	}
132
133
	/**
134
	 * Limit this field's content by a number of characters and truncate
135
	 * the field to the closest complete word. All HTML tags are stripped
136
	 * from the field.
137
	 *
138
	 * @param int $limit Number of characters to limit by
139
	 * @param string $add Ellipsis to add to the end of truncated string
140
	 * @return string
141
	 */
142
	public function LimitCharactersToClosestWord($limit = 20, $add = '...') {
143
		// Strip HTML tags if they exist in the field
144
		$value = strip_tags($this->RAW());
145
146
		// Determine if value exceeds limit before limiting characters
147
		$exceedsLimit = mb_strlen($value) > $limit;
148
149
		// Limit to character limit
150
		$value = DBField::create_field(get_class($this), $value)->LimitCharacters($limit, '');
151
152
		// If value exceeds limit, strip punctuation off the end to the last space and apply ellipsis
153
		if($exceedsLimit) {
154
			$value = html_entity_decode($value, ENT_COMPAT, 'UTF-8');
155
156
			$value = rtrim(mb_substr($value, 0, mb_strrpos($value, " ")), "/[\.,-\/#!$%\^&\*;:{}=\-_`~()]\s") . $add;
157
158
			$value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
159
		}
160
161
		return $value;
162
	}
163
164
	/**
165
	 * Limit this field's content by a number of words.
166
	 *
167
	 * CAUTION: This is not XML safe. Please use
168
	 * {@link LimitWordCountXML()} instead.
169
	 *
170
	 * @param int $numWords Number of words to limit by.
171
	 * @param string $add Ellipsis to add to the end of truncated string.
172
	 *
173
	 * @return string
174
	 */
175
	public function LimitWordCount($numWords = 26, $add = '...') {
176
		$value = trim(Convert::xml2raw($this->RAW()));
177
		$ret = explode(' ', $value, $numWords + 1);
178
179
		if(count($ret) <= $numWords - 1) {
180
			$ret = $value;
181
		} else {
182
			array_pop($ret);
183
			$ret = implode(' ', $ret) . $add;
184
		}
185
186
		return $ret;
187
	}
188
189
	/**
190
	 * Limit the number of words of the current field's
191
	 * content. This is XML safe, so characters like &
192
	 * are converted to &amp;
193
	 *
194
	 * @param int $numWords Number of words to limit by.
195
	 * @param string $add Ellipsis to add to the end of truncated string.
196
	 *
197
	 * @return string
198
	 */
199
	public function LimitWordCountXML($numWords = 26, $add = '...') {
200
		$ret = $this->LimitWordCount($numWords, $add);
201
202
		return Convert::raw2xml($ret);
203
	}
204
205
	/**
206
	 * Converts the current value for this StringField to lowercase.
207
	 *
208
	 * @return string
209
	 */
210
	public function LowerCase() {
211
		return mb_strtolower($this->RAW());
212
	}
213
214
	/**
215
	 * Converts the current value for this StringField to uppercase.
216
	 * @return string
217
	 */
218
	public function UpperCase() {
219
		return mb_strtoupper($this->RAW());
220
	}
221
222
	/**
223
	 * Return the value of the field stripped of html tags.
224
	 *
225
	 * @return string
226
	 */
227
	public function NoHTML() {
228
		return strip_tags($this->RAW());
229
	}
230
231
    /**
232
     * Returns true if the value meets all the criteria of not being empty, as defined by
233
     * the class
234
     * @param $value
235
     * @return bool
236
     */
237
	protected function isPopulated($value) {
238
        return $value // All truthy values exist
239
            || (is_string($value) && strlen($value)) // non-empty strings exist ('0' but not (int)0)
240
            || (!$this->getNullifyEmpty() && $value === ''); // Remove this stupid exemption in 4.0
241
    }
242
}
243