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.
Passed
Pull Request — master (#52)
by Der Mundschenk
03:28
created

Dewidow_Fix::dewidow()   C

Complexity

Conditions 7
Paths 2

Size

Total Lines 31
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 0
cts 12
cp 0
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 13
nc 2
nop 6
crap 56
1
<?php
2
/**
3
 *  This file is part of PHP-Typography.
4
 *
5
 *  Copyright 2014-2017 Peter Putzer.
6
 *  Copyright 2009-2011 KINGdesk, LLC.
7
 *
8
 *  This program is free software; you can redistribute it and/or modify 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\Fixes\Node_Fixes;
29
30
use PHP_Typography\DOM;
31
use PHP_Typography\RE;
32
use PHP_Typography\Settings;
33
use PHP_Typography\Strings;
34
use PHP_Typography\U;
35
36
/**
37
 * Prevents widows (if enabled).
38
 *
39
 * @author Peter Putzer <[email protected]>
40
 *
41
 * @since 5.0.0
42
 */
43
class Dewidow_Fix extends Abstract_Node_Fix {
44
	const SPACE_BETWEEN = '[\s]+'; // \s includes all special spaces (but not ZWSP) with the u flag.
45
	const WIDOW         = '[\w\p{M}\-' . U::ZERO_WIDTH_SPACE . U::SOFT_HYPHEN . ']+?'; // \w includes all alphanumeric Unicode characters but not composed characters.
46
47
	// Mandatory UTF-8 modifer.
48
	const REGEX_START = '/
49
		(?:
50
			\A
51
			|
52
			(?:
53
				(?<space_before>            # subpattern 1: space before (note: ZWSP is not a space)
54
					[\s' . U::ZERO_WIDTH_SPACE . U::SOFT_HYPHEN . ']+
55
				)
56
				(?<neighbor>                # subpattern 2: neighbors widow (short as possible)
57
					[^\s' . U::ZERO_WIDTH_SPACE . U::SOFT_HYPHEN . ']+?
58
				)
59
			)
60
		)
61
		(?<space_between>                   # subpattern 3: space between
62
			' . self::SPACE_BETWEEN . '
63
		)
64
		(?<widow>                           # subpattern 4: widow
65
			' . self::WIDOW . '
66
			(?:
67
				' . self::SPACE_BETWEEN . self::WIDOW . '
68
			){0,'; // The maximum number of repetitions is missing.
69
70
	const REGEX_END =
71
		'})
72
		(?<trailing>                       # subpattern 5: any trailing punctuation or spaces
73
			[^\w\p{M}]*
74
		)
75
		\Z
76
	/Sxu';
77
78
	const MASKED_NARROW_SPACE = '__NO_BREAK_NARROW_SPACE__';
79
80
	/**
81
	 * Apply the fix to a given textnode.
82
	 *
83
	 * @param \DOMText $textnode Required.
84
	 * @param Settings $settings Required.
85
	 * @param bool     $is_title Optional. Default false.
86
	 */
87
	public function apply( \DOMText $textnode, Settings $settings, $is_title = false ) {
88
		// Intervening inline tags may interfere with widow identification, but that is a sacrifice of using the parser.
89
		// Intervening tags will only interfere if they separate the widow from previous or preceding whitespace.
90
		if ( empty( $settings['dewidow'] ) || empty( $settings['dewidowMaxPull'] ) || empty( $settings['dewidowMaxLength'] ) ) {
91
			return;
92
		}
93
94
		if ( '' === DOM::get_next_chr( $textnode ) ) {
95
			// We have the last type "text" child of a block level element.
96
			$textnode->data = $this->dewidow( $textnode->data, Strings::functions( $textnode->data ), $settings['dewidowMaxPull'], $settings['dewidowMaxLength'], $settings['dewidowWordNumber'], $settings->no_break_narrow_space() );
97
		}
98
	}
99
100
	/**
101
	 * Dewidow a given text fragment.
102
	 *
103
	 * @param  string $text         The text fragment to dewidow.
104
	 * @param  array  $func         An array of string functions.
105
	 * @param  int    $max_pull     Maximum number of characters pulled from previous line.
106
	 * @param  int    $max_length   Maximum widow length.
107
	 * @param  int    $word_number  Maximum number of words allowed in widow.
108
	 * @param  string $narrow_space The narrow no-break space character.
109
	 *
110
	 * @return string
111
	 */
112
	protected function dewidow( $text, array $func, $max_pull, $max_length, $word_number, $narrow_space ) {
113
		if ( $word_number < 1 ) {
114
			return $text; // We are done.
115
		}
116
117
		// Do what we have to do.
118
		return preg_replace_callback( self::REGEX_START . ( $word_number - 1 ) . self::REGEX_END, function( array $widow ) use ( $func, $max_pull, $max_length, $word_number, $narrow_space ) {
119
120
			// If we are here, we know that widows are being protected in some fashion
121
			// with that, we will assert that widows should never be hyphenated or wrapped
122
			// as such, we will strip soft hyphens and zero-width-spaces.
123
			$widow['widow']    = self::strip_breaking_characters( $widow['widow'] );
124
			$widow['trailing'] = self::strip_breaking_characters( self::make_space_nonbreaking( $widow['trailing'], $narrow_space, $func['u'] ) );
125
126
			if (
127
				// Eject if widows neighbor is proceeded by a no break space (the pulled text would be too long).
128
				'' === $widow['space_before'] || false !== \strpos( $widow['space_before'], U::NO_BREAK_SPACE ) ||
129
130
				// Eject if widows neighbor length exceeds the max allowed or widow length exceeds max allowed.
131
				$func['strlen']( $widow['neighbor'] ) > $max_pull || $func['strlen']( $widow['widow'] ) > $max_length ||
132
133
				// Never replace thin and hair spaces with &nbsp;.
134
				self::is_narrow_space( $widow['space_between'] )
135
			) {
136
				return $widow['space_before'] . $widow['neighbor'] . $this->dewidow( $widow['space_between'] . $widow['widow'] . $widow['trailing'], $func, $max_pull, $max_length, $word_number - 1, $narrow_space );
137
			}
138
139
			// Let's protect some widows!
140
			return $widow['space_before'] . $widow['neighbor'] . U::NO_BREAK_SPACE . self::make_space_nonbreaking( $widow['widow'], $narrow_space, $func['u'] ) . $widow['trailing'];
141
		}, $text );
142
	}
143
144
	/**
145
	 * Strip zero-width space and soft hyphens from the given string.
146
	 *
147
	 * @param  string $string Required.
148
	 *
149
	 * @return string
150
	 */
151
	protected static function strip_breaking_characters( $string ) {
152
		return str_replace( [ U::ZERO_WIDTH_SPACE, U::SOFT_HYPHEN ], '', $string );
153
	}
154
155
	/**
156
	 * Is the given string one of the narrow space characters?
157
	 *
158
	 * @since 6.0.0
159
	 *
160
	 * @param  string $string The whitespace to test.
161
	 *
162
	 * @return bool
163
	 */
164
	protected static function is_narrow_space( $string ) {
165
		return U::THIN_SPACE === $string || U::HAIR_SPACE === $string || U::NO_BREAK_NARROW_SPACE === $string;
166
	}
167
168
	/**
169
	 * Strip zero-width space and soft hyphens from the given string.
170
	 *
171
	 * @param  string $string       Required.
172
	 * @param  string $narrow_space The narrow no-break space character.
173
	 * @param  string $u            Either 'u' or the empty string.
174
	 *
175
	 * @return string
176
	 */
177
	protected static function make_space_nonbreaking( $string, $narrow_space, $u ) {
178
		return preg_replace(
179
			[
180
				'/\s*' . U::THIN_SPACE . '\s*/u',
181
				'/\s*' . U::NO_BREAK_NARROW_SPACE . '\s*/u',
182
				"/\\s+/$u",
183
				'/' . self::MASKED_NARROW_SPACE . "/$u",
184
			], [
185
				self::MASKED_NARROW_SPACE,
186
				self::MASKED_NARROW_SPACE,
187
				U::NO_BREAK_SPACE,
188
				$narrow_space,
189
			], $string
190
		);
191
	}
192
}
193