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.

Smart_Fractions_Fix::apply()   B
last analyzed

Complexity

Conditions 8
Paths 7

Size

Total Lines 39
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 18
dl 0
loc 39
ccs 18
cts 18
cp 1
rs 8.4444
c 1
b 0
f 0
cc 8
nc 7
nop 3
crap 8
1
<?php
2
/**
3
 *  This file is part of PHP-Typography.
4
 *
5
 *  Copyright 2017-2019 Peter Putzer.
6
 *
7
 *  This program is free software; you can redistribute it and/or modify modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License along
18
 *  with this program; if not, write to the Free Software Foundation, Inc.,
19
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
 *
21
 *  ***
22
 *
23
 *  @package mundschenk-at/php-typography
24
 *  @license http://www.gnu.org/licenses/gpl-2.0.html
25
 */
26
27
namespace PHP_Typography\Fixes\Node_Fixes;
28
29
use PHP_Typography\DOM;
30
use PHP_Typography\RE;
31
use PHP_Typography\Settings;
32
use PHP_Typography\U;
33
34
/**
35
 * Applies smart fractions (if enabled).
36
 *
37
 * Call before style_numbers, but after smart_ordinal_suffix.
38
 * Purposefully seperated from smart_math because of HTML code injection.
39
 *
40
 * @author Peter Putzer <[email protected]>
41
 *
42
 * @since 5.0.0
43
 */
44
class Smart_Fractions_Fix extends Abstract_Node_Fix {
45
46
	const SPACING = '/\b(\d+)\s(\d+\s?\/\s?\d+)\b/';
47
48
	const FRACTION_MATCHING = '/
49
		# lookbehind assertion: makes sure we are not messing up a url
50
		(?<=\A|\s|' . U::NO_BREAK_SPACE . '|' . U::NO_BREAK_NARROW_SPACE . ')
51
52
		(\d+)
53
54
		# strip out any zero-width spaces inserted by wrap_hard_hyphens
55
		(?:\s?\/\s?' . U::ZERO_WIDTH_SPACE . '?)
56
57
		(
58
			# lookahead assertion: do not make fractions from x:x if x > 1
59
			(?:
60
				# ignore x:x where x > 1
61
				(?!\1(?:[^0-9]|\Z)) |
62
63
				# but allow 1:1
64
				(?=\1)(?=1(?:[^0-9]|\Z))
65
			)
66
67
			# Any numbers, except those above
68
			\d+
69
		)
70
		(
71
			# handle fractions followed by prime symbols
72
			(?:' . U::SINGLE_PRIME . '|' . U::DOUBLE_PRIME . ')?
73
74
			# handle ordinals after fractions
75
			(?:\<sup\>(?:st|nd|rd|th)<\/sup\>)?
76
77
			# makes sure we are not messing up a url
78
			(?:\Z|\s|' . U::NO_BREAK_SPACE . '|' . U::NO_BREAK_NARROW_SPACE . '|\.|,|\!|\?|\)|\;|\:|\'|")
79
		)
80
		/Sxu';
81
82
	const ESCAPE_DATE_MM_YYYY = '/
83
			# capture valid one- or two-digit months
84
			( \b (?: 0?[1-9] | 1[0-2] ) )
85
86
			# capture any zero-width spaces inserted by wrap_hard_hyphens
87
			(\s?\/\s?' . U::ZERO_WIDTH_SPACE . '?)
88
89
			# handle 4-decimal years
90
			( [12][0-9]{3}\b )
91
92
		/Sxu';
93
94
	/**
95
	 * Regular expression matching consecutive years in the format YYYY/YYYY+1.
96
	 *
97
	 * @var string
98
	 */
99
	protected $escape_consecutive_years;
100
101
	/**
102
	 * Replacement expression including optional CSS classes.
103
	 *
104
	 * @var string
105
	 */
106
	protected $replacement;
107
108
	/**
109
	 * Creates a new fix instance.
110
	 *
111
	 * @param string $css_numerator   CSS class applied to the numerator part.
112
	 * @param string $css_denominator CSS class applied to the denominator part.
113
	 * @param bool   $feed_compatible Optional. Default false.
114
	 */
115 1
	public function __construct( $css_numerator, $css_denominator, $feed_compatible = false ) {
116 1
		parent::__construct( $feed_compatible );
117
118
		// Escape consecutive years.
119 1
		$year_regex = [];
120 1
		for ( $year = 1900; $year < 2100; ++$year ) {
121 1
			$year_regex[] = "(?: ( $year ) (\s?\/\s?" . U::ZERO_WIDTH_SPACE . '?) ( ' . ( $year + 1 ) . ' ) )';
122
		}
123 1
		$this->escape_consecutive_years = '/\b (?| ' . implode( '|', $year_regex ) . ' ) \b/Sxu';
124
125
		// Replace fractions.
126 1
		$numerator_css     = empty( $css_numerator ) ? '' : ' class="' . $css_numerator . '"';
127 1
		$denominator_css   = empty( $css_denominator ) ? '' : ' class="' . $css_denominator . '"';
128 1
		$this->replacement = RE::escape_tags( "<sup{$numerator_css}>\$1</sup>" . U::FRACTION_SLASH . "<sub{$denominator_css}>\$2</sub>\$3" );
129 1
	}
130
131
	/**
132
	 * Apply the fix to a given textnode.
133
	 *
134
	 * @param \DOMText $textnode Required.
135
	 * @param Settings $settings Required.
136
	 * @param bool     $is_title Optional. Default false.
137
	 */
138 33
	public function apply( \DOMText $textnode, Settings $settings, $is_title = false ) {
139 33
		if ( empty( $settings[ Settings::SMART_FRACTIONS ] ) && empty( $settings[ Settings::FRACTION_SPACING ] ) ) {
140 12
			return;
141
		}
142
143
		// Cache textnode content.
144 21
		$node_data = $textnode->data;
145
146 21
		if ( ! empty( $settings[ Settings::FRACTION_SPACING ] ) && ! empty( $settings[ Settings::SMART_FRACTIONS ] ) ) {
147 5
			$node_data = \preg_replace( self::SPACING, '$1' . U::NO_BREAK_NARROW_SPACE . '$2', $node_data );
148 16
		} elseif ( ! empty( $settings[ Settings::FRACTION_SPACING ] ) && empty( $settings[ Settings::SMART_FRACTIONS ] ) ) {
149 4
			$node_data = \preg_replace( self::SPACING, '$1' . U::NO_BREAK_SPACE . '$2', $node_data );
150
		}
151
152 21
		if ( ! empty( $settings[ Settings::SMART_FRACTIONS ] ) ) {
153 17
			$node_data = \preg_replace(
154
				[
155
					// Escape sequences we don't want fractionified.
156 17
					$this->escape_consecutive_years,
157 17
					self::ESCAPE_DATE_MM_YYYY,
158
159
					// Replace fractions.
160 17
					self::FRACTION_MATCHING,
161
				],
162
				[
163 17
					'$1' . RE::ESCAPE_MARKER . '$2$3',
164
					'$1' . RE::ESCAPE_MARKER . '$2$3',
165
166 17
					$this->replacement,
167
				],
168 17
				$node_data
169
			);
170
171
			// Unescape escaped sequences.
172 17
			$node_data = \str_replace( RE::ESCAPE_MARKER, '', $node_data );
173
		}
174
175
		// Restore textnode content.
176 21
		$textnode->data = $node_data;
177 21
	}
178
}
179