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
Push — master ( c5123c...361d02 )
by Der Mundschenk
13s
created

Dewidow_Fix::dewidow()   D

Complexity

Conditions 9
Paths 2

Size

Total Lines 31
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
rs 4.909
c 0
b 0
f 0
cc 9
eloc 13
nc 2
nop 6
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
	const REGEX_START = '/
48
		(?:
49
			\A
50
			|
51
			(?:
52
				(?<space_before>            # subpattern 1: space before (note: ZWSP is not a space)
53
					[\s' . U::ZERO_WIDTH_SPACE . U::SOFT_HYPHEN . ']+
54
				)
55
				(?<neighbor>                # subpattern 2: neighbors widow (short as possible)
56
					[^\s' . U::ZERO_WIDTH_SPACE . U::SOFT_HYPHEN . ']+?
57
				)
58
			)
59
		)
60
		(?<space_between>                   # subpattern 3: space between
61
			' . self::SPACE_BETWEEN . '
62
		)
63
		(?<widow>                           # subpattern 4: widow
64
			' . self::WIDOW . '
65
			(?:
66
				' . self::SPACE_BETWEEN . self::WIDOW . '
67
			){0,'; // The maximum number of repetitions is missing.
68
69
	const REGEX_END =
70
		'})
71
		(?<trailing>                       # subpattern 5: any trailing punctuation or spaces
72
			[^\w\p{M}]*
73
		)
74
		\Z
75
	/Sxu';
76
77
	const MASKED_NARROW_SPACE = '__NO_BREAK_NARROW_SPACE__';
78
79
	/**
80
	 * Apply the fix to a given textnode.
81
	 *
82
	 * @param \DOMText $textnode Required.
83
	 * @param Settings $settings Required.
84
	 * @param bool     $is_title Optional. Default false.
85
	 */
86
	public function apply( \DOMText $textnode, Settings $settings, $is_title = false ) {
87
		// Intervening inline tags may interfere with widow identification, but that is a sacrifice of using the parser.
88
		// Intervening tags will only interfere if they separate the widow from previous or preceding whitespace.
89
		if ( empty( $settings['dewidow'] ) || empty( $settings['dewidowMaxPull'] ) || empty( $settings['dewidowMaxLength'] ) ) {
90
			return;
91
		}
92
93
		if ( '' === DOM::get_next_chr( $textnode ) ) {
94
			// We have the last type "text" child of a block level element.
95
			$textnode->data = $this->dewidow( $textnode->data, Strings::functions( $textnode->data ), $settings['dewidowMaxPull'], $settings['dewidowMaxLength'], $settings['dewidowWordNumber'], $settings->no_break_narrow_space() );
96
		}
97
	}
98
99
	/**
100
	 * Dewidow a given text fragment.
101
	 *
102
	 * @param  string $text         The text fragment to dewidow.
103
	 * @param  array  $func         An array of string functions.
104
	 * @param  int    $max_pull     Maximum number of characters pulled from previous line.
105
	 * @param  int    $max_length   Maximum widow length.
106
	 * @param  int    $word_number  Maximum number of words allowed in widow.
107
	 * @param  string $narrow_space The narrow no-break space character.
108
	 *
109
	 * @return string
110
	 */
111
	protected function dewidow( $text, array $func, $max_pull, $max_length, $word_number, $narrow_space ) {
112
		if ( $word_number < 1 ) {
113
			return $text; // We are done.
114
		}
115
116
		// Do what we have to do.
117
		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 ) {
118
119
			// If we are here, we know that widows are being protected in some fashion
120
			// with that, we will assert that widows should never be hyphenated or wrapped
121
			// as such, we will strip soft hyphens and zero-width-spaces.
122
			$widow['widow']    = self::strip_breaking_characters( $widow['widow'] );
123
			$widow['trailing'] = self::strip_breaking_characters( self::make_space_nonbreaking( $widow['trailing'], $func['u'] ) );
124
125
			if (
126
				// Eject if widows neighbor is proceeded by a no break space (the pulled text would be too long).
127
				'' === $widow['space_before'] || strstr( U::NO_BREAK_SPACE, $widow['space_before'] ) ||
128
129
				// Eject if widows neighbor length exceeds the max allowed or widow length exceeds max allowed.
130
				$func['strlen']( $widow['neighbor'] ) > $max_pull || $func['strlen']( $widow['widow'] ) > $max_length ||
131
132
				// Never replace thin and hair spaces with &nbsp;.
133
				U::THIN_SPACE === $widow['space_between'] || U::HAIR_SPACE === $widow['space_between'] || U::NO_BREAK_NARROW_SPACE === $widow['space_between']
134
			) {
135
				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 );
136
			}
137
138
			// Let's protect some widows!
139
			return $widow['space_before'] . $widow['neighbor'] . U::NO_BREAK_SPACE . self::make_space_nonbreaking( $widow['widow'], $narrow_space ) . $widow['trailing'];
140
		}, $text );
141
	}
142
143
	/**
144
	 * Strip zero-width space and soft hyphens from the given string.
145
	 *
146
	 * @param  string $string Required.
147
	 *
148
	 * @return string
149
	 */
150
	protected static function strip_breaking_characters( $string ) {
151
		return str_replace( [ U::ZERO_WIDTH_SPACE, U::SOFT_HYPHEN ], '', $string );
152
	}
153
154
	/**
155
	 * Strip zero-width space and soft hyphens from the given string.
156
	 *
157
	 * @param  string $string       Required.
158
	 * @param  string $narrow_space The narrow no-break space character.
159
	 *
160
	 * @return string
161
	 */
162
	protected static function make_space_nonbreaking( $string, $narrow_space ) {
163
		return preg_replace( [
164
			'/\s*' . U::THIN_SPACE . '\s*/u',
165
			'/\s*' . U::NO_BREAK_NARROW_SPACE . '\s*/u',
166
			'/\s+/u',
167
			'/' . self::MASKED_NARROW_SPACE . '/',
168
		], [
169
			self::MASKED_NARROW_SPACE,
170
			self::MASKED_NARROW_SPACE,
171
			U::NO_BREAK_SPACE,
172
			$narrow_space,
173
		], $string );
174
	}
175
}
176