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 (#15)
by Der Mundschenk
02:30
created

PHP_Typography_Testcase::assertSmartQuotesStyle()   D

Complexity

Conditions 16
Paths 16

Size

Total Lines 81
Code Lines 64

Duplication

Lines 56
Ratio 69.14 %

Importance

Changes 0
Metric Value
cc 16
eloc 64
nc 16
nop 3
dl 56
loc 81
rs 4.9906
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 *  This file is part of PHP-Typography.
4
 *
5
 *  Copyright 2017 Peter Putzer.
6
 *
7
 *  This program is free software; you can redistribute it and/or
8
 *  modify it under the terms of the GNU General Public License
9
 *  as published by the Free Software Foundation; either version 2
10
 *  of the License, or ( 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
18
 *  along with this program; if not, write to the Free Software
19
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
 *
21
 *  @package mundschenk-at/php-typography/tests
22
 *  @license http://www.gnu.org/licenses/gpl-2.0.html
23
 */
24
25
namespace PHP_Typography\Tests;
26
27
use \PHP_Typography\Strings;
28
29
/**
30
 * Abstract base class for \PHP_Typography\* unit tests.
31
 */
32
abstract class PHP_Typography_Testcase extends \PHPUnit\Framework\TestCase {
33
	/**
34
	 * Return encoded HTML string (everything except <>"').
35
	 *
36
	 * @param string $html A HTML fragment.
37
	 */
38
	protected function clean_html( $html ) {
39
		// Convert everything except Latin and Cyrillic and Thai.
40
		static $convmap = [
41
			// Simple Latin characters.
42
			0x80,   0x03ff,   0, 0xffffff, // @codingStandardsIgnoreLine.
43
			// Cyrillic characters.
44
			0x0514, 0x0dff, 0, 0xffffff, // @codingStandardsIgnoreLine.
45
			// Thai characters.
46
			0x0e7f, 0x10ffff, 0, 0xffffff, // @codingStandardsIgnoreLine.
47
		];
48
49
		return str_replace( [ '&lt;', '&gt;' ], [ '<', '>' ], mb_encode_numericentity( htmlentities( $html, ENT_NOQUOTES, 'UTF-8', false ), $convmap, 'UTF-8' ) );
50
	}
51
52
	/**
53
	 * Call protected/private method of a class.
54
	 *
55
	 * @param object $object      Instantiated object that we will run method on.
56
	 * @param string $method_name Method name to call.
57
	 * @param array  $parameters  Array of parameters to pass into method.
58
	 *
59
	 * @return mixed Method return.
60
	 */
61
	protected function invokeMethod( $object, $method_name, array $parameters = [] ) {
62
		$reflection = new \ReflectionClass( get_class( $object ) );
63
		$method = $reflection->getMethod( $method_name );
64
		$method->setAccessible( true );
65
66
		return $method->invokeArgs( $object, $parameters );
67
	}
68
69
	/**
70
	 * Call protected/private method of a class.
71
	 *
72
	 * @param string $classname   A class that we will run the method on.
73
	 * @param string $method_name Method name to call.
74
	 * @param array  $parameters  Array of parameters to pass into method.
75
	 *
76
	 * @return mixed Method return.
77
	 */
78
	protected function invokeStaticMethod( $classname, $method_name, array $parameters = [] ) {
79
		$reflection = new \ReflectionClass( $classname );
80
		$method = $reflection->getMethod( $method_name );
81
		$method->setAccessible( true );
82
83
		return $method->invokeArgs( null, $parameters );
84
	}
85
86
	/**
87
	 * Sets the value of a private/protected property of a class.
88
	 *
89
	 * @param string     $classname     A class whose property we will access.
90
	 * @param string     $property_name Property to set.
91
	 * @param mixed|null $value         The new value.
92
	 */
93
	protected function setStaticValue( $classname, $property_name, $value ) {
94
		$reflection = new \ReflectionClass( $classname );
95
		$property = $reflection->getProperty( $property_name );
96
		$property->setAccessible( true );
97
		$property->setValue( $value );
98
	}
99
100
	/**
101
	 * Sets the value of a private/protected property of a class.
102
	 *
103
	 * @param object     $object        Instantiated object that we will run method on.
104
	 * @param string     $property_name Property to set.
105
	 * @param mixed|null $value         The new value.
106
	 */
107
	protected function setValue( $object, $property_name, $value ) {
108
		$reflection = new \ReflectionClass( get_class( $object ) );
109
		$property = $reflection->getProperty( $property_name );
110
		$property->setAccessible( true );
111
		$property->setValue( $object, $value );
112
	}
113
114
	/**
115
	 * Retrieves the value of a private/protected property of a class.
116
	 *
117
	 * @param string $classname     A class whose property we will access.
118
	 * @param string $property_name Property to set.
119
	 *
120
	 * @return mixed
121
	 */
122
	protected function getStaticValue( $classname, $property_name ) {
123
		$reflection = new \ReflectionClass( $classname );
124
		$property = $reflection->getProperty( $property_name );
125
		$property->setAccessible( true );
126
127
		return $property->getValue();
128
	}
129
130
	/**
131
	 * Retrieves the value of a private/protected property of a class.
132
	 *
133
	 * @param object $object        Instantiated object that we will run method on.
134
	 * @param string $property_name Property to set.
135
	 *
136
	 * @return mixed
137
	 */
138
	protected function getValue( $object, $property_name ) {
139
		$reflection = new \ReflectionClass( get_class( $object ) );
140
		$property = $reflection->getProperty( $property_name );
141
		$property->setAccessible( true );
142
143
		return $property->getValue( $object );
144
	}
145
146
	/**
147
	 * Helper function to generate a valid token list from strings.
148
	 *
149
	 * @param string $value The string to tokenize.
150
	 * @param int    $type  Optional. Default 'word'.
151
	 *
152
	 * @return array
153
	 */
154
	protected function tokenize( $value, $type = \PHP_Typography\Text_Parser\Token::WORD ) {
155
		return [
156
			new \PHP_Typography\Text_Parser\Token( $value, $type ),
157
		];
158
	}
159
160
	/**
161
	 * Helper function to generate a valid word token list from strings.
162
	 *
163
	 * @param string $value Token value.
164
	 *
165
	 * @return array
166
	 */
167
	protected function tokenize_sentence( $value ) {
168
		$words = explode( ' ', $value );
169
		$tokens = [];
170
171
		foreach ( $words as $word ) {
172
			$tokens[] = new \PHP_Typography\Text_Parser\Token( $word, \PHP_Typography\Text_Parser\Token::WORD );
173
		}
174
175
		return $tokens;
176
	}
177
178
	/**
179
	 * Reports an error identified by $message if the combined token values differ from the expected value.
180
	 *
181
	 * @param string|array $expected_value Either a word/sentence or a token array.
182
	 * @param array        $actual_tokens  A token array.
183
	 * @param string       $message        Optional. Default ''.
184
	 */
185
	protected function assertTokensSame( $expected_value, array $actual_tokens, $message = '' ) {
186
		$this->assertContainsOnlyInstancesOf( \PHP_Typography\Text_Parser\Token::class, $actual_tokens, '$actual_tokens has to be an array of tokens.' );
187
		foreach ( $actual_tokens as $index => $token ) {
188
			$actual_tokens[ $index ] = $token->with_value( $this->clean_html( $token->value ) );
189
		}
190
191
		if ( is_scalar( $expected_value ) ) {
192
			if ( false !== strpos( $expected_value, ' ' ) ) {
193
				$expected_value = $this->tokenize_sentence( $expected_value );
194
			} else {
195
				$expected_value = $this->tokenize( $expected_value );
196
			}
197
		}
198
199
		// Ensure clean HTML even when a scalar was passed.
200
		$this->assertContainsOnlyInstancesOf( \PHP_Typography\Text_Parser\Token::class, $expected_value, '$expected_value has to be a string or an array of tokens.' );
201
		$expected = [];
202
		foreach ( $expected_value as $index => $token ) {
203
			$expected[ $index ] = $token->with_value( $this->clean_html( $token->value ) );
204
		}
205
206
		$this->assertSame( count( $expected ), count( $actual_tokens ) );
207
208
		foreach ( $actual_tokens as $key => $token ) {
209
			$this->assertSame( $expected[ $key ]->value, $token->value, $message );
210
			$this->assertSame( $expected[ $key ]->type,  $token->type,  $message );
211
		}
212
213
		return true;
214
	}
215
216
	/**
217
	 * Reports an error identified by $message if the combined token values do
218
	 * not differ from the expected value.
219
	 *
220
	 * @param string|array $expected_value Either a word/sentence or a token array.
221
	 * @param array        $actual_tokens  A token array.
222
	 * @param string       $message        Optional. Default ''.
223
	 */
224
	protected function assertTokensNotSame( $expected_value, array $actual_tokens, $message = '' ) {
225
		$this->assertContainsOnlyInstancesOf( \PHP_Typography\Text_Parser\Token::class, $actual_tokens, '$actual_tokens has to be an array of tokens.' );
226
		foreach ( $actual_tokens as $index => $token ) {
227
			$actual_tokens[ $index ] = $token->with_value( $this->clean_html( $token->value ) );
228
		}
229
230
		if ( is_scalar( $expected_value ) ) {
231
			if ( false !== strpos( $expected_value, ' ' ) ) {
232
				$expected = $this->tokenize_sentence( $expected_value );
233
			} else {
234
				$expected = $this->tokenize( $expected_value );
235
			}
236
		} else {
237
			$this->assertContainsOnlyInstancesOf( \PHP_Typography\Text_Parser\Token::class, (array) $expected_value, '$expected_value has to be a string or an array of tokens.' );
238
			$expected = $expected_value;
239
		}
240
241
		$this->assertSame( count( $expected ), count( $actual_tokens ) );
242
243
		$result = false;
244
		foreach ( $actual_tokens as $key => $token ) {
245
			if ( $expected[ $key ]->value !== $token->value || $expected[ $key ]->type !== $token->type ) {
246
				$result = true;
247
			}
248
		}
249
250
		return $this->assertTrue( $result, $message );
251
	}
252
253
	/**
254
	 * Reports an error identified by $message if $attribute in $object does not have the $key.
255
	 *
256
	 * @param string $key       The array key.
257
	 * @param string $attribute The attribute name.
258
	 * @param object $object    The object.
259
	 * @param string $message   Optional. Default ''.
260
	 */
261
	protected function assertAttributeArrayHasKey( $key, $attribute, $object, $message = '' ) {
262
		$ref = new \ReflectionClass( get_class( $object ) );
263
		$prop = $ref->getProperty( $attribute );
264
		$prop->setAccessible( true );
265
266
		return $this->assertArrayHasKey( $key, $prop->getValue( $object ), $message );
267
	}
268
269
	/**
270
	 * Reports an error identified by $message if $attribute in $object does have the $key.
271
	 *
272
	 * @param string $key       The array key.
273
	 * @param string $attribute The attribute name.
274
	 * @param object $object    The object.
275
	 * @param string $message   Optional. Default ''.
276
	 */
277
	protected function assertAttributeArrayNotHasKey( $key, $attribute, $object, $message = '' ) {
278
		$ref = new \ReflectionClass( get_class( $object ) );
279
		$prop = $ref->getProperty( $attribute );
280
		$prop->setAccessible( true );
281
282
		return $this->assertArrayNotHasKey( $key, $prop->getValue( $object ), $message );
283
	}
284
285
	/**
286
	 * Assert that the given quote styles match.
287
	 *
288
	 * @param string $style Style name.
289
	 * @param string $open  Opening quote character.
290
	 * @param string $close Closing quote character.
291
	 */
292
	protected function assertSmartQuotesStyle( $style, $open, $close ) {
293
		switch ( $style ) {
294
			case 'doubleCurled':
295
				$this->assertSame( Strings::_uchr( 8220 ), $open, "Opening quote $open did not match quote style $style." );
296
				$this->assertSame( Strings::_uchr( 8221 ), $close, "Closeing quote $close did not match quote style $style." );
297
				break;
298
299
			case 'doubleCurledReversed':
300
				$this->assertSame( Strings::_uchr( 8221 ), $open,  "Opening quote $open did not match quote style $style." );
301
				$this->assertSame( Strings::_uchr( 8221 ), $close, "Closeing quote $close did not match quote style $style." );
302
				break;
303
304
			case 'doubleLow9':
305
				$this->assertSame( Strings::_uchr( 8222 ), $open, "Opening quote $open did not match quote style $style." );
306
				$this->assertSame( Strings::_uchr( 8221 ), $close, "Closeing quote $close did not match quote style $style." );
307
				break;
308
309
			case 'doubleLow9Reversed':
310
				$this->assertSame( Strings::_uchr( 8222 ), $open, "Opening quote $open did not match quote style $style." );
311
				$this->assertSame( Strings::_uchr( 8220 ), $close, "Closeing quote $close did not match quote style $style." );
312
				break;
313
314
			case 'singleCurled':
315
				$this->assertSame( Strings::_uchr( 8216 ), $open, "Opening quote $open did not match quote style $style." );
316
				$this->assertSame( Strings::_uchr( 8217 ), $close, "Closeing quote $close did not match quote style $style." );
317
				break;
318
319
			case 'singleCurledReversed':
320
				$this->assertSame( Strings::_uchr( 8217 ), $open, "Opening quote $open did not match quote style $style." );
321
				$this->assertSame( Strings::_uchr( 8217 ), $close, "Closeing quote $close did not match quote style $style." );
322
				break;
323
324
			case 'singleLow9':
325
				$this->assertSame( Strings::_uchr( 8218 ), $open,  "Opening quote $open did not match quote style $style." );
326
				$this->assertSame( Strings::_uchr( 8217 ), $close, "Closeing quote $close did not match quote style $style." );
327
				break;
328
329
			case 'singleLow9Reversed':
330
				$this->assertSame( Strings::_uchr( 8218 ), $open, "Opening quote $open did not match quote style $style." );
331
				$this->assertSame( Strings::_uchr( 8216 ), $close, "Closeing quote $close did not match quote style $style." );
332
				break;
333
334
			case 'doubleGuillemetsFrench':
335
				$this->assertSame( Strings::_uchr( 171 ) . Strings::_uchr( 160 ), $open, "Opening quote $open did not match quote style $style." );
336
				$this->assertSame( Strings::_uchr( 160 ) . Strings::_uchr( 187 ), $close, "Closeing quote $close did not match quote style $style." );
337
				break;
338
339
			case 'doubleGuillemets':
340
				$this->assertSame( Strings::_uchr( 171 ), $open, "Opening quote $open did not match quote style $style." );
341
				$this->assertSame( Strings::_uchr( 187 ), $close, "Closeing quote $close did not match quote style $style." );
342
				break;
343
344
			case 'doubleGuillemetsReversed':
345
				$this->assertSame( Strings::_uchr( 187 ), $open, "Opening quote $open did not match quote style $style." );
346
				$this->assertSame( Strings::_uchr( 171 ), $close, "Closeing quote $close did not match quote style $style." );
347
				break;
348
349
			case 'singleGuillemets':
350
				$this->assertSame( Strings::_uchr( 8249 ), $open, "Opening quote $open did not match quote style $style." );
351
				$this->assertSame( Strings::_uchr( 8250 ), $close, "Closeing quote $close did not match quote style $style." );
352
				break;
353
354
			case 'singleGuillemetsReversed':
355
				$this->assertSame( Strings::_uchr( 8250 ), $open, "Opening quote $open did not match quote style $style." );
356
				$this->assertSame( Strings::_uchr( 8249 ), $close, "Closeing quote $close did not match quote style $style." );
357
				break;
358
359
			case 'cornerBrackets':
360
				$this->assertSame( Strings::_uchr( 12300 ), $open, "Opening quote $open did not match quote style $style." );
361
				$this->assertSame( Strings::_uchr( 12301 ), $close, "Closeing quote $close did not match quote style $style." );
362
				break;
363
364
			case 'whiteCornerBracket':
365
				$this->assertSame( Strings::_uchr( 12302 ), $open, "Opening quote $open did not match quote style $style." );
366
				$this->assertSame( Strings::_uchr( 12303 ), $close, "Closeing quote $close did not match quote style $style." );
367
				break;
368
369
			default:
370
				$this->assertTrue( false, "Invalid quote style $style." );
371
		}
372
	}
373
}
374