Completed
Push — master ( bfc7b3...a85dc6 )
by mw
33:41
created

CodeStringValueFormatter::formatAsPrettyJson()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SMW\DataValues\ValueFormatters;
4
5
use SMWDataValue as DataValue;
6
use SMWOutputs as Outputs;
7
8
/**
9
 * @license GNU GPL v2+
10
 * @since 2.4
11
 *
12
 * @author mwjames
13
 */
14
class CodeStringValueFormatter extends StringValueFormatter {
15
16
	/**
17
	 * @since 2.4
18
	 *
19
	 * {@inheritDoc}
20
	 */
21 172
	public function isFormatterFor( DataValue $dataValue ) {
22 172
		return $dataValue->getTypeID() === '_cod';
23
	}
24
25
	/**
26
	 * @see StringValueFormatter::doFormatFinalOutputFor
27
	 */
28 9
	protected function doFormatFinalOutputFor( $type, $linker ) {
29
30 9
		$abbreviate = $type === self::WIKI_LONG || $type === self::HTML_LONG;
31 9
		$text = $this->dataValue->getDataItem()->getString();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SMWDataItem as the method getString() does only exist in the following sub-classes of SMWDataItem: SMWDIBlob, SMWDIError, SMWDIString. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
32
33
		// Escape and wrap values of type Code. The result is escaped to be
34
		// HTML-safe (it will also work in wiki context). The result will
35
		// contain mark-up that must not be escaped again.
36
37 9
		Outputs::requireResource( 'ext.smw.style' );
38
39
		if ( $this->isJson( $text ) ) {
40 9
			$result = self::formatAsPrettyJson( $text );
41 9
		} else {
42 9
			// This disables all active wiki and HTML markup:
43
			$result = str_replace(
44
				array( '<', '>', ' ', '[', '{', '=', "'", ':', "\n" ),
45 9
				array( '&lt;', '&gt;', '&#160;', '&#x005B;', '&#x007B;', '&#x003D;', '&#x0027;', '&#58;', "<br />" ),
46 6
				$text
47
			);
48
		}
49 9
50
		if ( $abbreviate ) {
51
			$result = "<div style=\"min-height:5em; overflow:auto;\">$result</div>";
52
		}
53
54
		return "<div class=\"smwpre\">$result</div>";
55
	}
56
57
	/**
58
	 * @since 2.5
59
	 *
60
	 * @param string $string
61
	 *
62
	 * @return string
63
	 */
64
	public static function formatAsPrettyJson( $string ) {
65
		return defined( 'JSON_PRETTY_PRINT' ) ? json_encode( json_decode( $string ), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) : $string;
66
	}
67
68
	private function isJson( $string ) {
69
70
		// Don't bother
71
		if ( substr( $string, 0, 1 ) !== '{' ) {
72
			return false;
73
		}
74
75
		json_decode( $string );
76
77
		return ( json_last_error() == JSON_ERROR_NONE );
78
	}
79
80
}
81