Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#95)
by Der Mundschenk
03:41
created

Settings::no_break_narrow_space()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 2
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
/**
3
 *  This file is part of PHP-Typography.
4
 *
5
 *  Copyright 2014-2019 Peter Putzer.
6
 *  Copyright 2009-2011 KINGdesk, LLC.
7
 *
8
 *  This program is free software; you can redistribute it and/or modify
9
 *  it under the terms of the GNU General Public License as published by
10
 *  the Free Software Foundation; either version 2 of the License, or
11
 *  (at your option) any later version.
12
 *
13
 *  This program is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *  GNU General Public License for more details.
17
 *
18
 *  You should have received a copy of the GNU General Public License along
19
 *  with this program; if not, write to the Free Software Foundation, Inc.,
20
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
 *
22
 *  ***
23
 *
24
 *  @package mundschenk-at/php-typography
25
 *  @license http://www.gnu.org/licenses/gpl-2.0.html
26
 */
27
28
namespace PHP_Typography;
29
30
use PHP_Typography\Settings\Dash_Style;
31
use PHP_Typography\Settings\Quote_Style;
32
use PHP_Typography\Settings\Quotes;
33
34
/**
35
 * Store settings for the PHP_Typography class.
36
 *
37
 * @author Peter Putzer <[email protected]>
38
 *
39
 * @since 4.0.0
40
 * @since 6.5.0 The protected property $no_break_narrow_space has been deprecated.
41
 * @since 7.0.0 Deprecated properties and methods relating to $no_break_narrow_space have been removed.
42
 */
43
class Settings implements \ArrayAccess, \JsonSerializable {
44
45
	// General attributes.
46
	const IGNORE_TAGS    = 'ignoreTags';
47
	const IGNORE_CLASSES = 'ignoreClasses';
48
	const IGNORE_IDS     = 'ignoreIDs';
49
50
	// Smart characters.
51
	const SMART_QUOTES                        = 'smartQuotes';
52
	const SMART_QUOTES_EXCEPTIONS             = 'smartQuotesExceptions';
53
	const SMART_DASHES                        = 'smartDashes';
54
	const SMART_ELLIPSES                      = 'smartEllipses';
55
	const SMART_DIACRITICS                    = 'smartDiacritics';
56
	const DIACRITIC_LANGUAGE                  = 'diacriticLanguage';
57
	const DIACRITIC_WORDS                     = 'diacriticWords';
58
	const DIACRITIC_REPLACEMENT_DATA          = 'diacriticReplacement';
59
	const DIACRITIC_CUSTOM_REPLACEMENTS       = 'diacriticCustomReplacements';
60
	const SMART_MARKS                         = 'smartMarks';
61
	const SMART_ORDINAL_SUFFIX                = 'smartOrdinalSuffix';
62
	const SMART_ORDINAL_SUFFIX_ROMAN_NUMERALS = 'smartOrdinalSuffixRomanNumerals';
63
	const SMART_MATH                          = 'smartMath';
64
	const SMART_FRACTIONS                     = 'smartFractions';
65
	const SMART_EXPONENTS                     = 'smartExponents';
66
	const SMART_AREA_UNITS                    = 'smartAreaVolumeUnits';
67
68
	// Smart spacing.
69
	const SINGLE_CHARACTER_WORD_SPACING = 'singleCharacterWordSpacing';
70
	const FRACTION_SPACING              = 'fractionSpacing';
71
	const UNIT_SPACING                  = 'unitSpacing';
72
	const UNITS                         = 'units';
73
	const NUMBERED_ABBREVIATION_SPACING = 'numberedAbbreviationSpacing';
74
	const FRENCH_PUNCTUATION_SPACING    = 'frenchPunctuationSpacing';
75
	const DASH_SPACING                  = 'dashSpacing';
76
	const DEWIDOW                       = 'dewidow';
77
	const DEWIDOW_MAX_LENGTH            = 'dewidowMaxLength';
78
	const DEWIDOW_MAX_PULL              = 'dewidowMaxPull';
79
	const DEWIDOW_WORD_NUMBER           = 'dewidowWordNumber';
80
	const HYPHEN_HARD_WRAP              = 'hyphenHardWrap';
81
	const URL_WRAP                      = 'urlWrap';
82
	const URL_MIN_AFTER_WRAP            = 'urlMinAfterWrap';
83
	const EMAIL_WRAP                    = 'emailWrap';
84
	const SPACE_COLLAPSE                = 'spaceCollapse';
85
86
	// Character styling.
87
	const STYLE_AMPERSANDS          = 'styleAmpersands';
88
	const STYLE_CAPS                = 'styleCaps';
89
	const STYLE_INITIAL_QUOTES      = 'styleInitialQuotes';
90
	const INITIAL_QUOTE_TAGS        = 'initialQuoteTags';
91
	const STYLE_NUMBERS             = 'styleNumbers';
92
	const STYLE_HANGING_PUNCTUATION = 'styleHangingPunctuation';
93
94
	// Hyphenation.
95
	const HYPHENATION                   = 'hyphenation';
96
	const HYPHENATION_LANGUAGE          = 'hyphenLanguage';
97
	const HYPHENATION_MIN_LENGTH        = 'hyphenMinLength';
98
	const HYPHENATION_MIN_BEFORE        = 'hyphenMinBefore';
99
	const HYPHENATION_MIN_AFTER         = 'hyphenMinAfter';
100
	const HYPHENATION_CUSTOM_EXCEPTIONS = 'hyphenationCustomExceptions';
101
	const HYPHENATE_HEADINGS            = 'hyphenateTitle';
102
	const HYPHENATE_ALL_CAPS            = 'hyphenateAllCaps';
103
	const HYPHENATE_TITLE_CASE          = 'hyphenateTitleCase';
104
	const HYPHENATE_COMPOUNDS           = 'hyphenateCompounds';
105
106
	// Parser error handling.
107
	const PARSER_ERRORS_IGNORE  = 'parserErrorsIgnore';
108
	const PARSER_ERRORS_HANDLER = 'parserErrorsHandler';
109
110
	/**
111
	 * Primary quote style.
112
	 *
113
	 * @var Quotes
114
	 */
115
	protected $primary_quote_style;
116
117
	/**
118
	 * Secondary quote style.
119
	 *
120
	 * @var Quotes
121
	 */
122
	protected $secondary_quote_style;
123
124
	/**
125
	 * A regex pattern for custom units (or the empty string).
126
	 *
127
	 * @var string
128
	 */
129
	protected $custom_units = '';
130
131
	/**
132
	 * A hashmap of settings for the various typographic options.
133
	 *
134
	 * @var array
135
	 */
136
	protected $data = [];
137
138
	/**
139
	 * The current dash style.
140
	 *
141
	 * @var Settings\Dashes
142
	 */
143
	protected $dash_style;
144
145
	/**
146
	 * The Unicode character mapping (some characters still have compatibility issues).
147
	 *
148
	 * @since 6.5.0
149
	 *
150
	 * @var string[]
151
	 */
152
	protected $unicode_mapping;
153
154
	/**
155
	 * An array containing just remapped characters (for optimization).
156
	 *
157
	 * @since 6.5.0
158
	 *
159
	 * @var string[]
160
	 */
161
	protected $remapped_characters;
162
163
	/**
164
	 * Sets up a new Settings object.
165
	 *
166
	 * @since 6.0.0 If $set_defaults is `false`, the settings object is not fully
167
	 *              initialized unless `set_smart_quotes_primary`,
168
	 *              `set_smart_quotes_secondary`, `set_smart_dashes_style` and
169
	 *              `set_true_no_break_narrow_space` are called explicitly.
170
	 * @since 6.5.0 A (partial) character mapping can be given to remap certain
171
	 *              characters.
172
	 *
173
	 * @param bool     $set_defaults Optional. If true, set default values for various properties. Default true.
174
	 * @param string[] $mapping      Optional. Unicode characters to remap. The default maps the narrow no-break space to the normal NO-BREAK SPACE and the apostrophe to the RIGHT SINGLE QUOTATION MARK.
175
	 */
176 1
	public function __construct( $set_defaults = true, array $mapping = [ U::NO_BREAK_NARROW_SPACE => U::NO_BREAK_SPACE, U::APOSTROPHE => U::SINGLE_QUOTE_CLOSE ] ) { // phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing
177 1
		if ( $set_defaults ) {
178 1
			$this->set_defaults();
179
		}
180
181
		// Merge default character mapping with given mapping.
182 1
		$this->unicode_mapping = $mapping;
183 1
	}
184
185
	/**
186
	 * Provides access to named settings (object syntax).
187
	 *
188
	 * @param string $key The settings key.
189
	 *
190
	 * @return mixed
191
	 */
192 1
	public function &__get( $key ) {
193 1
		return $this->data[ $key ];
194
	}
195
196
	/**
197
	 * Changes a named setting (object syntax).
198
	 *
199
	 * @param string $key   The settings key.
200
	 * @param mixed  $value The settings value.
201
	 */
202 1
	public function __set( $key, $value ) {
203 1
		$this->data[ $key ] = $value;
204 1
	}
205
206
	/**
207
	 * Checks if a named setting exists (object syntax).
208
	 *
209
	 * @param string $key The settings key.
210
	 */
211 1
	public function __isset( $key ) {
212 1
		return isset( $this->data[ $key ] );
213
	}
214
215
	/**
216
	 * Unsets a named setting.
217
	 *
218
	 * @param string $key The settings key.
219
	 */
220 1
	public function __unset( $key ) {
221 1
		unset( $this->data[ $key ] );
222 1
	}
223
224
	/**
225
	 * Changes a named setting (array syntax).
226
	 *
227
	 * @param string $offset The settings key.
228
	 * @param mixed  $value  The settings value.
229
	 */
230 1
	public function offsetSet( $offset, $value ) {
231 1
		if ( ! empty( $offset ) ) {
232 1
			$this->data[ $offset ] = $value;
233
		}
234 1
	}
235
236
	/**
237
	 * Checks if a named setting exists (array syntax).
238
	 *
239
	 * @param string $offset The settings key.
240
	 */
241 1
	public function offsetExists( $offset ) {
242 1
		return isset( $this->data[ $offset ] );
243
	}
244
245
	/**
246
	 * Unsets a named setting (array syntax).
247
	 *
248
	 * @param string $offset The settings key.
249
	 */
250 1
	public function offsetUnset( $offset ) {
251 1
		unset( $this->data[ $offset ] );
252 1
	}
253
254
	/**
255
	 * Provides access to named settings (array syntax).
256
	 *
257
	 * @param string $offset The settings key.
258
	 *
259
	 * @return mixed
260
	 */
261 1
	public function offsetGet( $offset ) {
262 1
		return isset( $this->data[ $offset ] ) ? $this->data[ $offset ] : null;
263
	}
264
265
	/**
266
	 * Provides a JSON serialization of the settings.
267
	 *
268
	 * @return mixed
269
	 */
270 1
	public function jsonSerialize() {
271 1
		return \array_merge(
272 1
			$this->data,
273
			[
274 1
				'unicode_mapping'       => $this->unicode_mapping,
275 1
				'primary_quotes'        => "{$this->primary_quote_style->open()}|{$this->primary_quote_style->close()}",
276 1
				'secondary_quotes'      => "{$this->secondary_quote_style->open()}|{$this->secondary_quote_style->close()}",
277 1
				'dash_style'            => "{$this->dash_style->interval_dash()}|{$this->dash_style->interval_space()}|{$this->dash_style->parenthetical_dash()}|{$this->dash_style->parenthetical_space()}",
278 1
				'custom_units'          => $this->custom_units,
279
			]
280
		);
281
	}
282
283
	/**
284
	 * Remaps a unicode character to another one.
285
	 *
286
	 * @since 6.5.0
287
	 *
288
	 * @param  string $char     The remapped character.
289
	 * @param  string $new_char The character to actually use.
290
	 */
291 1
	public function remap_character( $char, $new_char ) {
292 1
		if ( $char !== $new_char ) {
293 1
			$this->unicode_mapping[ $char ] = $new_char;
294
		} else {
295 1
			unset( $this->unicode_mapping[ $char ] );
296
		}
297 1
	}
298
299
	/**
300
	 * Remaps one or more strings.
301
	 *
302
	 * @since 6.5.0
303
	 *
304
	 * @param  string|string[] $input The input string(s).
305
	 *
306
	 * @return string|string[]
307
	 */
308 4
	public function apply_character_mapping( $input ) {
309
310
		// Nothing for us to do.
311 4
		if ( empty( $input ) || empty( $this->unicode_mapping ) ) {
312 1
			return $input;
313
		}
314
315 3
		$native_array = \is_array( $input );
316 3
		$data         = (array) $input;
317
318 3
		foreach ( $data as $key => $string ) {
319 3
			$data[ $key ] = \strtr( $string, $this->unicode_mapping );
320
		}
321
322 3
		return $native_array ? $data : $data[0];
323
	}
324
325
	/**
326
	 * Retrieves the primary (double) quote style.
327
	 *
328
	 * @return Quotes
329
	 */
330 1
	public function primary_quote_style() {
331 1
		return $this->primary_quote_style;
332
	}
333
334
	/**
335
	 * Retrieves the secondary (single) quote style.
336
	 *
337
	 * @return Quotes
338
	 */
339 1
	public function secondary_quote_style() {
340 1
		return $this->secondary_quote_style;
341
	}
342
343
	/**
344
	 * Retrieves the dash style.
345
	 *
346
	 * @return Settings\Dashes
347
	 */
348 1
	public function dash_style() {
349 1
		return $this->dash_style;
350
	}
351
352
	/**
353
	 * Retrieves the custom units pattern.
354
	 *
355
	 * @return string The pattern is suitable for inclusion into a regular expression.
356
	 */
357 1
	public function custom_units() {
358 1
		return $this->custom_units;
359
	}
360
361
	/**
362
	 * (Re)set various options to their default values.
363
	 */
364 1
	public function set_defaults() {
365
		// General attributes.
366 1
		$this->set_tags_to_ignore();
367 1
		$this->set_classes_to_ignore();
368 1
		$this->set_ids_to_ignore();
369
370
		// Smart characters.
371 1
		$this->set_smart_quotes();
372 1
		$this->set_smart_quotes_primary();
373 1
		$this->set_smart_quotes_secondary();
374 1
		$this->set_smart_quotes_exceptions();
375 1
		$this->set_smart_dashes();
376 1
		$this->set_smart_dashes_style();
377 1
		$this->set_smart_ellipses();
378 1
		$this->set_smart_diacritics();
379 1
		$this->set_diacritic_language();
380 1
		$this->set_diacritic_custom_replacements();
381 1
		$this->set_smart_marks();
382 1
		$this->set_smart_ordinal_suffix();
383 1
		$this->set_smart_ordinal_suffix_match_roman_numerals();
384 1
		$this->set_smart_math();
385 1
		$this->set_smart_fractions();
386 1
		$this->set_smart_exponents();
387 1
		$this->set_smart_area_units();
388
389
		// Smart spacing.
390 1
		$this->set_single_character_word_spacing();
391 1
		$this->set_fraction_spacing();
392 1
		$this->set_unit_spacing();
393 1
		$this->set_french_punctuation_spacing();
394 1
		$this->set_units();
395 1
		$this->set_dash_spacing();
396 1
		$this->set_dewidow();
397 1
		$this->set_max_dewidow_length();
398 1
		$this->set_max_dewidow_pull();
399 1
		$this->set_dewidow_word_number();
400 1
		$this->set_wrap_hard_hyphens();
401 1
		$this->set_url_wrap();
402 1
		$this->set_email_wrap();
403 1
		$this->set_min_after_url_wrap();
404 1
		$this->set_space_collapse();
405
406
		// Character styling.
407 1
		$this->set_style_ampersands();
408 1
		$this->set_style_caps();
409 1
		$this->set_style_initial_quotes();
410 1
		$this->set_style_numbers();
411 1
		$this->set_style_hanging_punctuation();
412 1
		$this->set_initial_quote_tags();
413
414
		// Hyphenation.
415 1
		$this->set_hyphenation();
416 1
		$this->set_hyphenation_language();
417 1
		$this->set_min_length_hyphenation();
418 1
		$this->set_min_before_hyphenation();
419 1
		$this->set_min_after_hyphenation();
420 1
		$this->set_hyphenate_headings();
421 1
		$this->set_hyphenate_all_caps();
422 1
		$this->set_hyphenate_title_case();
423 1
		$this->set_hyphenate_compounds();
424 1
		$this->set_hyphenation_exceptions();
425
426
		// Parser error handling.
427 1
		$this->set_ignore_parser_errors();
428 1
	}
429
430
	/**
431
	 * Enable lenient parser error handling (HTML is "best guess" if enabled).
432
	 *
433
	 * @param bool $on Optional. Default false.
434
	 */
435 1
	public function set_ignore_parser_errors( $on = false ) {
436 1
		$this->data[ self::PARSER_ERRORS_IGNORE ] = $on;
437 1
	}
438
439
	/**
440
	 * Sets an optional handler for parser errors. Invalid callbacks will be silently ignored.
441
	 *
442
	 * @since 6.0.0. callable type is enforced via typehinting.
443
	 *
444
	 * @param callable|null $handler Optional. A callable that takes an array of error strings as its parameter. Default null.
445
	 */
446 2
	public function set_parser_errors_handler( callable $handler = null ) {
447 2
		$this->data[ self::PARSER_ERRORS_HANDLER ] = $handler;
448 2
	}
449
450
	/**
451
	 * Sets tags for which the typography of their children will be left untouched.
452
	 *
453
	 * @param string|array $tags A comma separated list or an array of tag names.
454
	 */
455 1
	public function set_tags_to_ignore( $tags = [ 'code', 'head', 'kbd', 'object', 'option', 'pre', 'samp', 'script', 'noscript', 'noembed', 'select', 'style', 'textarea', 'title', 'var', 'math' ] ) {
456
		// Ensure that we pass only lower-case tag names to XPath.
457 1
		$tags = array_filter( array_map( 'strtolower', Strings::maybe_split_parameters( $tags ) ), 'ctype_alnum' );
458
459 1
		$this->data[ self::IGNORE_TAGS ] = array_unique( array_merge( $tags, array_flip( DOM::inappropriate_tags() ) ) );
460 1
	}
461
462
	/**
463
	 * Sets classes for which the typography of their children will be left untouched.
464
	 *
465
	 * @param string|array $classes A comma separated list or an array of class names.
466
	 */
467 1
	public function set_classes_to_ignore( $classes = [ 'vcard', 'noTypo' ] ) {
468 1
		$this->data[ self::IGNORE_CLASSES ] = Strings::maybe_split_parameters( $classes );
469 1
	}
470
471
	/**
472
	 * Sets IDs for which the typography of their children will be left untouched.
473
	 *
474
	 * @param string|array $ids A comma separated list or an array of tag names.
475
	 */
476 1
	public function set_ids_to_ignore( $ids = [] ) {
477 1
		$this->data[ self::IGNORE_IDS ] = Strings::maybe_split_parameters( $ids );
478 1
	}
479
480
	/**
481
	 * Enables/disables typographic quotes.
482
	 *
483
	 * @param bool $on Optional. Default true.
484
	 */
485 1
	public function set_smart_quotes( $on = true ) {
486 1
		$this->data[ self::SMART_QUOTES ] = $on;
487 1
	}
488
489
	/**
490
	 * Sets the style for primary ('double') quotemarks.
491
	 *
492
	 * Allowed values for $style:
493
	 * "doubleCurled" => "&ldquo;foo&rdquo;",
494
	 * "doubleCurledReversed" => "&rdquo;foo&rdquo;",
495
	 * "doubleLow9" => "&bdquo;foo&rdquo;",
496
	 * "doubleLow9Reversed" => "&bdquo;foo&ldquo;",
497
	 * "singleCurled" => "&lsquo;foo&rsquo;",
498
	 * "singleCurledReversed" => "&rsquo;foo&rsquo;",
499
	 * "singleLow9" => "&sbquo;foo&rsquo;",
500
	 * "singleLow9Reversed" => "&sbquo;foo&lsquo;",
501
	 * "doubleGuillemetsFrench" => "&laquo;&nbsp;foo&nbsp;&raquo;",
502
	 * "doubleGuillemets" => "&laquo;foo&raquo;",
503
	 * "doubleGuillemetsReversed" => "&raquo;foo&laquo;",
504
	 * "singleGuillemets" => "&lsaquo;foo&rsaquo;",
505
	 * "singleGuillemetsReversed" => "&rsaquo;foo&lsaquo;",
506
	 * "cornerBrackets" => "&#x300c;foo&#x300d;",
507
	 * "whiteCornerBracket" => "&#x300e;foo&#x300f;"
508
	 *
509
	 * @param  Quotes|string $style Optional. A Quotes instance or a quote style constant. Defaults to 'doubleCurled'.
510
	 *
511
	 * @throws \DomainException Thrown if $style constant is invalid.
512
	 */
513 3
	public function set_smart_quotes_primary( $style = Quote_Style::DOUBLE_CURLED ) {
514 3
		$this->primary_quote_style = $this->get_quote_style( $style );
515 2
	}
516
517
	/**
518
	 * Sets the style for secondary ('single') quotemarks.
519
	 *
520
	 * Allowed values for $style:
521
	 * "doubleCurled" => "&ldquo;foo&rdquo;",
522
	 * "doubleCurledReversed" => "&rdquo;foo&rdquo;",
523
	 * "doubleLow9" => "&bdquo;foo&rdquo;",
524
	 * "doubleLow9Reversed" => "&bdquo;foo&ldquo;",
525
	 * "singleCurled" => "&lsquo;foo&rsquo;",
526
	 * "singleCurledReversed" => "&rsquo;foo&rsquo;",
527
	 * "singleLow9" => "&sbquo;foo&rsquo;",
528
	 * "singleLow9Reversed" => "&sbquo;foo&lsquo;",
529
	 * "doubleGuillemetsFrench" => "&laquo;&nbsp;foo&nbsp;&raquo;",
530
	 * "doubleGuillemets" => "&laquo;foo&raquo;",
531
	 * "doubleGuillemetsReversed" => "&raquo;foo&laquo;",
532
	 * "singleGuillemets" => "&lsaquo;foo&rsaquo;",
533
	 * "singleGuillemetsReversed" => "&rsaquo;foo&lsaquo;",
534
	 * "cornerBrackets" => "&#x300c;foo&#x300d;",
535
	 * "whiteCornerBracket" => "&#x300e;foo&#x300f;"
536
	 *
537
	 * @param  Quotes|string $style Optional. A Quotes instance or a quote style constant. Defaults to 'singleCurled'.
538
	 *
539
	 * @throws \DomainException Thrown if $style constant is invalid.
540
	 */
541 3
	public function set_smart_quotes_secondary( $style = Quote_Style::SINGLE_CURLED ) {
542 3
		$this->secondary_quote_style = $this->get_quote_style( $style );
543 2
	}
544
545
	/**
546
	 * Retrieves a Quotes instance from a given style.
547
	 *
548
	 * @param  Quotes|string $style A Quotes instance or a quote style constant.
549
	 *
550
	 * @throws \DomainException Thrown if $style constant is invalid.
551
	 *
552
	 * @return Quotes
553
	 */
554 6
	protected function get_quote_style( $style ) {
555 6
		return $this->get_style( $style, Quotes::class, [ Quote_Style::class, 'get_styled_quotes' ], 'quote' );
556
	}
557
558
	/**
559
	 * Sets the list of exceptional words for smart quotes replacement. Mainly,
560
	 * this is used for contractions beginning with an apostrophe.
561
	 *
562
	 * @param string[] $exceptions Optional. An array of replacements indexed by the ”non-smart" form.
563
	 *                             Default a list of English words beginning with an apostrophy.
564
	 */
565 1
	public function set_smart_quotes_exceptions( $exceptions = [
566
		"'tain't"   => U::APOSTROPHE . 'tain' . U::APOSTROPHE . 't',
567
		"'twere"    => U::APOSTROPHE . 'twere',
568
		"'twas"     => U::APOSTROPHE . 'twas',
569
		"'tis"      => U::APOSTROPHE . 'tis',
570
		"'til"      => U::APOSTROPHE . 'til',
571
		"'bout"     => U::APOSTROPHE . 'bout',
572
		"'nuff"     => U::APOSTROPHE . 'nuff',
573
		"'round"    => U::APOSTROPHE . 'round',
574
		"'cause"    => U::APOSTROPHE . 'cause',
575
		"'splainin" => U::APOSTROPHE . 'splainin',
576
		"'em'"      => U::APOSTROPHE . 'em',
577
	] ) {
578 1
		$this->data[ self::SMART_QUOTES_EXCEPTIONS ] = [
579 1
			'patterns'     => \array_keys( $exceptions ),
580 1
			'replacements' => \array_values( $exceptions ),
581
		];
582 1
	}
583
584
	/**
585
	 * Retrieves an object from a given style.
586
	 *
587
	 * @param  object|string $style          A style object instance or a style constant.
588
	 * @param  string        $expected_class A class name.
589
	 * @param  callable      $get_style      A function that returns a style object from a given style constant.
590
	 * @param  string        $description    Style description for the exception message.
591
	 *
592
	 * @throws \DomainException Thrown if $style constant is invalid.
593
	 *
594
	 * @return object An instance of $expected_class.
595
	 */
596 9
	protected function get_style( $style, $expected_class, callable $get_style, $description ) {
597 9
		if ( $style instanceof $expected_class ) {
598 3
			$object = $style;
599
		} else {
600 6
			$object = $get_style( $style );
601
		}
602
603 9
		if ( ! \is_object( $object ) || ! $object instanceof $expected_class ) {
604 3
			throw new \DomainException( "Invalid $description style $style." );
605
		}
606
607 6
		return $object;
608
	}
609
610
	/**
611
	 * Enables/disables replacement of "a--a" with En Dash " -- " and "---" with Em Dash.
612
	 *
613
	 * @param bool $on Optional. Default true.
614
	 */
615 1
	public function set_smart_dashes( $on = true ) {
616 1
		$this->data[ self::SMART_DASHES ] = $on;
617 1
	}
618
619
	/**
620
	 * Sets the typographical conventions used by smart_dashes.
621
	 *
622
	 * Allowed values for $style:
623
	 * - "traditionalUS"
624
	 * - "international"
625
	 *
626
	 * @param string|Settings\Dashes $style Optional. Default Dash_Style::TRADITIONAL_US.
627
	 *
628
	 * @throws \DomainException Thrown if $style constant is invalid.
629
	 */
630 3
	public function set_smart_dashes_style( $style = Dash_Style::TRADITIONAL_US ) {
631 3
		$this->dash_style = $this->get_style( $style, Settings\Dashes::class, [ Dash_Style::class, 'get_styled_dashes' ], 'dash' );
632 2
	}
633
634
	/**
635
	 * Enables/disables replacement of "..." with "…".
636
	 *
637
	 * @param bool $on Optional. Default true.
638
	 */
639 1
	public function set_smart_ellipses( $on = true ) {
640 1
		$this->data[ self::SMART_ELLIPSES ] = $on;
641 1
	}
642
643
	/**
644
	 * Enables/disables replacement "creme brulee" with "crème brûlée".
645
	 *
646
	 * @param bool $on Optional. Default true.
647
	 */
648 1
	public function set_smart_diacritics( $on = true ) {
649 1
		$this->data[ self::SMART_DIACRITICS ] = $on;
650 1
	}
651
652
	/**
653
	 * Sets the language used for diacritics replacements.
654
	 *
655
	 * @param string $lang Has to correspond to a filename in 'diacritics'. Optional. Default 'en-US'.
656
	 */
657 1
	public function set_diacritic_language( $lang = 'en-US' ) {
658 1
		if ( isset( $this->data[ self::DIACRITIC_LANGUAGE ] ) && $this->data[ self::DIACRITIC_LANGUAGE ] === $lang ) {
659 1
			return;
660
		}
661
662 1
		$this->data[ self::DIACRITIC_LANGUAGE ] = $lang;
663 1
		$language_file_name                     = \dirname( __FILE__ ) . '/diacritics/' . $lang . '.json';
664
665 1
		if ( \file_exists( $language_file_name ) ) {
666 1
			$diacritics_file                     = \json_decode( \file_get_contents( $language_file_name ), true );
667 1
			$this->data[ self::DIACRITIC_WORDS ] = $diacritics_file['diacritic_words'];
668
		} else {
669 1
			unset( $this->data[ self::DIACRITIC_WORDS ] );
670
		}
671
672 1
		$this->update_diacritics_replacement_arrays();
673 1
	}
674
675
	/**
676
	 * Sets up custom diacritics replacements.
677
	 *
678
	 * @param string|array $custom_replacements An array formatted [needle=>replacement, needle=>replacement...],
679
	 *                                          or a string formatted `"needle"=>"replacement","needle"=>"replacement",...
680
	 */
681 6
	public function set_diacritic_custom_replacements( $custom_replacements = [] ) {
682 6
		if ( ! \is_array( $custom_replacements ) ) {
683 3
			$custom_replacements = $this->parse_diacritics_replacement_string( $custom_replacements );
684
		}
685
686 6
		$this->data[ self::DIACRITIC_CUSTOM_REPLACEMENTS ] = self::array_map_assoc(
687
			function( $key, $replacement ) {
688 5
				$key         = \strip_tags( \trim( $key ) );
689 5
				$replacement = \strip_tags( \trim( $replacement ) );
690
691 5
				if ( ! empty( $key ) && ! empty( $replacement ) ) {
692 3
					return [ $key => $replacement ];
693
				} else {
694 2
					return [];
695
				}
696 6
			},
697
			$custom_replacements
698
		);
699
700 6
		$this->update_diacritics_replacement_arrays();
701 6
	}
702
703
	/**
704
	 * Parses a custom diacritics replacement string into an array.
705
	 *
706
	 * @param string $custom_replacements A string formatted `"needle"=>"replacement","needle"=>"replacement",...
707
	 *
708
	 * @return array
709
	 */
710 3
	private function parse_diacritics_replacement_string( $custom_replacements ) {
711 3
		return self::array_map_assoc(
712
			function( $key, $replacement ) {
713
				// Account for single and double quotes in keys in and values, discard everything else.
714 3
				if ( \preg_match( '/(?<kquo>"|\')(?<key>(?:(?!\k<kquo>).)+)\k<kquo>\s*=>\s*(?<rquo>"|\')(?<replacement>(?:(?!\k<rquo>).)+)\k<rquo>/', $replacement, $match ) ) {
715 2
					$key         = $match['key'];
716 2
					$replacement = $match['replacement'];
717
718 2
					return [ $key => $replacement ];
719
				}
720
721 1
				return [];
722 3
			},
723
			/** RE correct. @scrutinizer ignore-type */
724 3
			\preg_split( '/,/', $custom_replacements, -1, PREG_SPLIT_NO_EMPTY )
725
		);
726
	}
727
728
	/**
729
	 * Provides an array_map implementation with control over resulting array's keys.
730
	 *
731
	 * Based on https://gist.github.com/jasand-pereza/84ecec7907f003564584.
732
	 *
733
	 * @since 6.0.0
734
	 *
735
	 * @param  callable $callback A callback function that needs to return [ $key => $value ] pairs.
736
	 * @param  array    $array    The array.
737
	 *
738
	 * @return array
739
	 */
740 2
	protected static function array_map_assoc( callable $callback, array $array ) {
741 2
		$new = [];
742
743 2
		foreach ( $array as $k => $v ) {
744 2
			$u = $callback( $k, $v );
745
746 2
			if ( ! empty( $u ) ) {
747 1
				$new[ \key( $u ) ] = \current( $u );
748
			}
749
		}
750
751 2
		return $new;
752
	}
753
754
	/**
755
	 * Update the pattern and replacement arrays in $settings['diacriticReplacement'].
756
	 *
757
	 * Should be called whenever a new diacritics replacement language is selected or
758
	 * when the custom replacements are updated.
759
	 */
760 7
	private function update_diacritics_replacement_arrays() {
761 7
		$patterns     = [];
762 7
		$replacements = [];
763
764 7
		if ( ! empty( $this->data[ self::DIACRITIC_CUSTOM_REPLACEMENTS ] ) ) {
765 3
			$this->parse_diacritics_rules( $this->data[ self::DIACRITIC_CUSTOM_REPLACEMENTS ], $patterns, $replacements );
766
		}
767 7
		if ( ! empty( $this->data[ self::DIACRITIC_WORDS ] ) ) {
768 1
			$this->parse_diacritics_rules( $this->data[ self::DIACRITIC_WORDS ], $patterns, $replacements );
769
		}
770
771 7
		$this->data[ self::DIACRITIC_REPLACEMENT_DATA ] = [
772 7
			'patterns'     => $patterns,
773 7
			'replacements' => $replacements,
774
		];
775 7
	}
776
777
	/**
778
	 * Parse an array of diacritics rules.
779
	 *
780
	 * @param array $diacritics_rules The rules ( $word => $replacement ).
781
	 * @param array $patterns         Resulting patterns. Passed by reference.
782
	 * @param array $replacements     Resulting replacements. Passed by reference.
783
	 */
784 4
	private function parse_diacritics_rules( array $diacritics_rules, array &$patterns, array &$replacements ) {
785
786 4
		foreach ( $diacritics_rules as $needle => $replacement ) {
787 4
			$patterns[]              = '/\b(?<!\w[' . U::NO_BREAK_SPACE . U::SOFT_HYPHEN . '])' . $needle . '\b(?![' . U::NO_BREAK_SPACE . U::SOFT_HYPHEN . ']\w)/u';
788 4
			$replacements[ $needle ] = $replacement;
789
		}
790 4
	}
791
792
	/**
793
	 * Enables/disables replacement of (r) (c) (tm) (sm) (p) (R) (C) (TM) (SM) (P) with ® © ™ ℠ ℗.
794
	 *
795
	 * @param bool $on Optional. Default true.
796
	 */
797 1
	public function set_smart_marks( $on = true ) {
798 1
		$this->data[ self::SMART_MARKS ] = $on;
799 1
	}
800
801
	/**
802
	 * Enables/disables proper mathematical symbols.
803
	 *
804
	 * @param bool $on Optional. Default true.
805
	 */
806 1
	public function set_smart_math( $on = true ) {
807 1
		$this->data[ self::SMART_MATH ] = $on;
808 1
	}
809
810
	/**
811
	 * Enables/disables replacement of 2^2 with 2<sup>2</sup>
812
	 *
813
	 * @param bool $on Optional. Default true.
814
	 */
815 1
	public function set_smart_exponents( $on = true ) {
816 1
		$this->data[ self::SMART_EXPONENTS ] = $on;
817 1
	}
818
819
	/**
820
	 * Enables/disables replacement of 1/4 with <sup>1</sup>&#8260;<sub>4</sub>.
821
	 *
822
	 * @param bool $on Optional. Default true.
823
	 */
824 1
	public function set_smart_fractions( $on = true ) {
825 1
		$this->data[ self::SMART_FRACTIONS ] = $on;
826 1
	}
827
828
	/**
829
	 * Enables/disables replacement of 1st with 1<sup>st</sup>.
830
	 *
831
	 * @param bool $on Optional. Default true.
832
	 */
833 1
	public function set_smart_ordinal_suffix( $on = true ) {
834 1
		$this->data[ self::SMART_ORDINAL_SUFFIX ] = $on;
835 1
	}
836
837
	/**
838
	 * Enables/disables replacement of XXe with XX<sup>e</sup>.
839
	 *
840
	 * @since 6.5.0
841
	 *
842
	 * @param bool $on Optional. Default false.
843
	 */
844 1
	public function set_smart_ordinal_suffix_match_roman_numerals( $on = false ) {
845 1
		$this->data[ self::SMART_ORDINAL_SUFFIX_ROMAN_NUMERALS ] = $on;
846 1
	}
847
848
	/**
849
	 * Enables/disables replacement of m2 with m³ and m3 with m³.
850
	 *
851
	 * @param bool $on Optional. Default true.
852
	 */
853 1
	public function set_smart_area_units( $on = true ) {
854 1
		$this->data[ self::SMART_AREA_UNITS ] = $on;
855 1
	}
856
857
	/**
858
	 * Enables/disables forcing single character words to next line with the insertion of &nbsp;.
859
	 *
860
	 * @param bool $on Optional. Default true.
861
	 */
862 1
	public function set_single_character_word_spacing( $on = true ) {
863 1
		$this->data[ self::SINGLE_CHARACTER_WORD_SPACING ] = $on;
864 1
	}
865
866
	/**
867
	 * Enables/disables fraction spacing.
868
	 *
869
	 * @param bool $on Optional. Default true.
870
	 */
871 1
	public function set_fraction_spacing( $on = true ) {
872 1
		$this->data[ self::FRACTION_SPACING ] = $on;
873 1
	}
874
875
	/**
876
	 * Enables/disables keeping units and values together with the insertion of &nbsp;.
877
	 *
878
	 * @param bool $on Optional. Default true.
879
	 */
880 1
	public function set_unit_spacing( $on = true ) {
881 1
		$this->data[ self::UNIT_SPACING ] = $on;
882 1
	}
883
884
	/**
885
	 * Enables/disables numbered abbreviations like "ISO 9000" together with the insertion of &nbsp;.
886
	 *
887
	 * @param bool $on Optional. Default true.
888
	 */
889 1
	public function set_numbered_abbreviation_spacing( $on = true ) {
890 1
		$this->data[ self::NUMBERED_ABBREVIATION_SPACING ] = $on;
891 1
	}
892
893
	/**
894
	 * Enables/disables extra whitespace before certain punction marks, as is the French custom.
895
	 *
896
	 * @since 6.0.0 The default value is now `false`.`
897
	 *
898
	 * @param bool $on Optional. Default false.
899
	 */
900 1
	public function set_french_punctuation_spacing( $on = false ) {
901 1
		$this->data[ self::FRENCH_PUNCTUATION_SPACING ] = $on;
902 1
	}
903
904
	/**
905
	 * Sets the list of units to keep together with their values.
906
	 *
907
	 * @param string|array $units A comma separated list or an array of units.
908
	 */
909 1
	public function set_units( $units = [] ) {
910 1
		$this->data[ self::UNITS ] = Strings::maybe_split_parameters( $units );
911 1
		$this->custom_units        = $this->update_unit_pattern( $this->data[ self::UNITS ] );
912 1
	}
913
914
	/**
915
	 * Update pattern for matching custom units.
916
	 *
917
	 * @since 6.4.0 Visibility changed to protected, return value added.
918
	 *
919
	 * @param array $units An array of unit names.
920
	 *
921
	 * @return string
922
	 */
923 2
	protected function update_unit_pattern( array $units ) {
924
		// Update unit regex pattern.
925 2
		foreach ( $units as $index => $unit ) {
926 2
			$units[ $index ] = \preg_quote( $unit, '/' );
927
		}
928
929 2
		$custom_units  = \implode( '|', $units );
930 2
		$custom_units .= ! empty( $custom_units ) ? '|' : '';
931
932 2
		return $custom_units;
933
	}
934
935
	/**
936
	 * Enables/disables wrapping of Em and En dashes are in thin spaces.
937
	 *
938
	 * @param bool $on Optional. Default true.
939
	 */
940 1
	public function set_dash_spacing( $on = true ) {
941 1
		$this->data[ self::DASH_SPACING ] = $on;
942 1
	}
943
944
	/**
945
	 * Enables/disables removal of extra whitespace characters.
946
	 *
947
	 * @param bool $on Optional. Default true.
948
	 */
949 1
	public function set_space_collapse( $on = true ) {
950 1
		$this->data[ self::SPACE_COLLAPSE ] = $on;
951 1
	}
952
953
	/**
954
	 * Enables/disables widow handling.
955
	 *
956
	 * @param bool $on Optional. Default true.
957
	 */
958 1
	public function set_dewidow( $on = true ) {
959 1
		$this->data[ self::DEWIDOW ] = $on;
960 1
	}
961
962
	/**
963
	 * Sets the maximum length of widows that will be protected.
964
	 *
965
	 * @param int $length Defaults to 5. Trying to set the value to less than 2 resets the length to the default.
966
	 */
967 1
	public function set_max_dewidow_length( $length = 5 ) {
968 1
		$length = ( $length > 1 ) ? $length : 5;
969
970 1
		$this->data[ self::DEWIDOW_MAX_LENGTH ] = $length;
971 1
	}
972
973
	/**
974
	 * Sets the maximum number of words considered for dewidowing.
975
	 *
976
	 * @param int $number Defaults to 1. Only 1, 2 and 3 are valid.
977
	 */
978 1
	public function set_dewidow_word_number( $number = 1 ) {
979 1
		$number = ( $number > 3 || $number < 1 ) ? 1 : $number;
980
981 1
		$this->data[ self::DEWIDOW_WORD_NUMBER ] = $number;
982 1
	}
983
984
	/**
985
	 * Sets the maximum length of pulled text to keep widows company.
986
	 *
987
	 * @param int $length Defaults to 5. Trying to set the value to less than 2 resets the length to the default.
988
	 */
989 1
	public function set_max_dewidow_pull( $length = 5 ) {
990 1
		$length = ( $length > 1 ) ? $length : 5;
991
992 1
		$this->data[ self::DEWIDOW_MAX_PULL ] = $length;
993 1
	}
994
995
	/**
996
	 * Enables/disables wrapping at internal hard hyphens with the insertion of a zero-width-space.
997
	 *
998
	 * @param bool $on Optional. Default true.
999
	 */
1000 1
	public function set_wrap_hard_hyphens( $on = true ) {
1001 1
		$this->data[ self::HYPHEN_HARD_WRAP ] = $on;
1002 1
	}
1003
1004
	/**
1005
	 * Enables/disables wrapping of urls.
1006
	 *
1007
	 * @param bool $on Optional. Default true.
1008
	 */
1009 1
	public function set_url_wrap( $on = true ) {
1010 1
		$this->data[ self::URL_WRAP ] = $on;
1011 1
	}
1012
1013
	/**
1014
	 * Enables/disables wrapping of email addresses.
1015
	 *
1016
	 * @param bool $on Optional. Default true.
1017
	 */
1018 1
	public function set_email_wrap( $on = true ) {
1019 1
		$this->data[ self::EMAIL_WRAP ] = $on;
1020 1
	}
1021
1022
	/**
1023
	 * Sets the minimum character requirement after an URL wrapping point.
1024
	 *
1025
	 * @param int $length Defaults to 5. Trying to set the value to less than 1 resets the length to the default.
1026
	 */
1027 1
	public function set_min_after_url_wrap( $length = 5 ) {
1028 1
		$length = ( $length > 0 ) ? $length : 5;
1029
1030 1
		$this->data[ self::URL_MIN_AFTER_WRAP ] = $length;
1031 1
	}
1032
1033
	/**
1034
	 * Enables/disables wrapping of ampersands in <span class="amp">.
1035
	 *
1036
	 * @param bool $on Optional. Default true.
1037
	 */
1038 1
	public function set_style_ampersands( $on = true ) {
1039 1
		$this->data[ self::STYLE_AMPERSANDS ] = $on;
1040 1
	}
1041
1042
	/**
1043
	 * Enables/disables wrapping caps in <span class="caps">.
1044
	 *
1045
	 * @param bool $on Optional. Default true.
1046
	 */
1047 1
	public function set_style_caps( $on = true ) {
1048 1
		$this->data[ self::STYLE_CAPS ] = $on;
1049 1
	}
1050
1051
	/**
1052
	 * Enables/disables wrapping of initial quotes in <span class="quo"> or <span class="dquo">.
1053
	 *
1054
	 * @param bool $on Optional. Default true.
1055
	 */
1056 1
	public function set_style_initial_quotes( $on = true ) {
1057 1
		$this->data[ self::STYLE_INITIAL_QUOTES ] = $on;
1058 1
	}
1059
1060
	/**
1061
	 * Enables/disables wrapping of numbers in <span class="numbers">.
1062
	 *
1063
	 * @param bool $on Optional. Default true.
1064
	 */
1065 1
	public function set_style_numbers( $on = true ) {
1066 1
		$this->data[ self::STYLE_NUMBERS ] = $on;
1067 1
	}
1068
1069
	/**
1070
	 * Enables/disables wrapping of punctiation and wide characters in <span class="pull-*">.
1071
	 *
1072
	 * @param bool $on Optional. Default true.
1073
	 */
1074 1
	public function set_style_hanging_punctuation( $on = true ) {
1075 1
		$this->data[ self::STYLE_HANGING_PUNCTUATION ] = $on;
1076 1
	}
1077
1078
	/**
1079
	 * Sets the list of tags where initial quotes and guillemets should be styled.
1080
	 *
1081
	 * @param string|array $tags A comma separated list or an array of tag names.
1082
	 */
1083 1
	public function set_initial_quote_tags( $tags = [ 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'li', 'dd', 'dt' ] ) {
1084
		// Make array if handed a list of tags as a string.
1085 1
		if ( ! \is_array( $tags ) ) {
1086 1
			$tags = \preg_split( '/[^a-z0-9]+/', $tags, -1, PREG_SPLIT_NO_EMPTY );
1087
		}
1088
1089
		// Store the tag array inverted (with the tagName as its index for faster lookup).
1090 1
		$this->data[ self::INITIAL_QUOTE_TAGS ] = \array_change_key_case( \array_flip( /** Array. @scrutinizer ignore-type */ $tags ), CASE_LOWER );
1091 1
	}
1092
1093
	/**
1094
	 * Enables/disables hyphenation.
1095
	 *
1096
	 * @param bool $on Optional. Default true.
1097
	 */
1098 1
	public function set_hyphenation( $on = true ) {
1099 1
		$this->data[ self::HYPHENATION ] = $on;
1100 1
	}
1101
1102
	/**
1103
	 * Sets the hyphenation pattern language.
1104
	 *
1105
	 * @param string $lang Has to correspond to a filename in 'lang'. Optional. Default 'en-US'.
1106
	 */
1107 8
	public function set_hyphenation_language( $lang = 'en-US' ) {
1108 8
		if ( isset( $this->data[ self::HYPHENATION_LANGUAGE ] ) && $this->data[ self::HYPHENATION_LANGUAGE ] === $lang ) {
1109 3
			return; // Bail out, no need to do anything.
1110
		}
1111
1112 8
		$this->data[ self::HYPHENATION_LANGUAGE ] = $lang;
1113 8
	}
1114
1115
	/**
1116
	 * Sets the minimum length of a word that may be hyphenated.
1117
	 *
1118
	 * @param int $length Defaults to 5. Trying to set the value to less than 2 resets the length to the default.
1119
	 */
1120 1
	public function set_min_length_hyphenation( $length = 5 ) {
1121 1
		$length = ( $length > 1 ) ? $length : 5;
1122
1123 1
		$this->data[ self::HYPHENATION_MIN_LENGTH ] = $length;
1124 1
	}
1125
1126
	/**
1127
	 * Sets the minimum character requirement before a hyphenation point.
1128
	 *
1129
	 * @param int $length Defaults to 3. Trying to set the value to less than 1 resets the length to the default.
1130
	 */
1131 1
	public function set_min_before_hyphenation( $length = 3 ) {
1132 1
		$length = ( $length > 0 ) ? $length : 3;
1133
1134 1
		$this->data[ self::HYPHENATION_MIN_BEFORE ] = $length;
1135 1
	}
1136
1137
	/**
1138
	 * Sets the minimum character requirement after a hyphenation point.
1139
	 *
1140
	 * @param int $length Defaults to 2. Trying to set the value to less than 1 resets the length to the default.
1141
	 */
1142 1
	public function set_min_after_hyphenation( $length = 2 ) {
1143 1
		$length = ( $length > 0 ) ? $length : 2;
1144
1145 1
		$this->data[ self::HYPHENATION_MIN_AFTER ] = $length;
1146 1
	}
1147
1148
	/**
1149
	 * Enables/disables hyphenation of titles and headings.
1150
	 *
1151
	 * @param bool $on Optional. Default true.
1152
	 */
1153 1
	public function set_hyphenate_headings( $on = true ) {
1154 1
		$this->data[ self::HYPHENATE_HEADINGS ] = $on;
1155 1
	}
1156
1157
	/**
1158
	 * Enables/disables hyphenation of words set completely in capital letters.
1159
	 *
1160
	 * @param bool $on Optional. Default true.
1161
	 */
1162 1
	public function set_hyphenate_all_caps( $on = true ) {
1163 1
		$this->data[ self::HYPHENATE_ALL_CAPS ] = $on;
1164 1
	}
1165
1166
	/**
1167
	 * Enables/disables hyphenation of words starting with a capital letter.
1168
	 *
1169
	 * @param bool $on Optional. Default true.
1170
	 */
1171 1
	public function set_hyphenate_title_case( $on = true ) {
1172 1
		$this->data[ self::HYPHENATE_TITLE_CASE ] = $on;
1173 1
	}
1174
1175
	/**
1176
	 * Enables/disables hyphenation of compound words (e.g. "editor-in-chief").
1177
	 *
1178
	 * @param bool $on Optional. Default true.
1179
	 */
1180 1
	public function set_hyphenate_compounds( $on = true ) {
1181 1
		$this->data[ self::HYPHENATE_COMPOUNDS ] = $on;
1182 1
	}
1183
1184
	/**
1185
	 * Sets custom word hyphenations.
1186
	 *
1187
	 * @param string|array $exceptions An array of words with all hyphenation points marked with a hard hyphen (or a string list of such words).
1188
	 *        In the latter case, only alphanumeric characters and hyphens are recognized. The default is empty.
1189
	 */
1190 2
	public function set_hyphenation_exceptions( $exceptions = [] ) {
1191 2
		$this->data[ self::HYPHENATION_CUSTOM_EXCEPTIONS ] = Strings::maybe_split_parameters( $exceptions );
1192 2
	}
1193
1194
	/**
1195
	 * Retrieves a unique hash value for the current settings.
1196
	 *
1197
	 * @since 5.2.0 The new parameter $raw_output has been added.
1198
	 *
1199
	 * @param int  $max_length Optional. The maximum number of bytes returned (0 for unlimited). Default 16.
1200
	 * @param bool $raw_output Optional. Wether to return raw binary data for the hash. Default true.
1201
	 *
1202
	 * @return string A binary hash value for the current settings limited to $max_length.
1203
	 */
1204 1
	public function get_hash( $max_length = 16, $raw_output = true ) {
1205 1
		$hash = \md5( \json_encode( $this ), $raw_output );
1206
1207 1
		if ( $max_length < \strlen( $hash ) && $max_length > 0 ) {
1208 1
			$hash = \substr( $hash, 0, $max_length );
1209
		}
1210
1211 1
		return $hash;
1212
	}
1213
}
1214