Completed
Push — master ( 7776a4...8c5813 )
by mw
35:00
created

doFormatFinalOutputFor()   C

Complexity

Conditions 8
Paths 9

Size

Total Lines 47
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 47
rs 5.7377
c 1
b 0
f 1
cc 8
eloc 24
nc 9
nop 2
1
<?php
2
3
namespace SMW\DataValues\ValueFormatters;
4
5
use SMW\DataValues\MonolingualTextValue;
6
use SMW\DataValueFactory;
7
use SMW\DIProperty;
8
use SMWDataValue as DataValue;
9
use RuntimeException;
10
11
/**
12
 * @license GNU GPL v2+
13
 * @since 2.4
14
 *
15
 * @author mwjames
16
 */
17
class MonolingualTextValueFormatter extends DataValueFormatter {
18
19
	/**
20
	 * @since 2.4
21
	 *
22
	 * {@inheritDoc}
23
	 */
24
	public function isFormatterFor( DataValue $dataValue ) {
25
		return $dataValue instanceOf MonolingualTextValue;
26
	}
27
28
	/**
29
	 * @since 2.4
30
	 *
31
	 * {@inheritDoc}
32
	 */
33
	public function format( $type, $linker = null ) {
34
35
		if ( !$this->dataValue instanceOf MonolingualTextValue ) {
36
			throw new RuntimeException( "The formatter is missing a valid MonolingualTextValue object" );
37
		}
38
39
		if (
40
			$this->dataValue->getCaption() !== false &&
41
			( $type === self::WIKI_SHORT || $type === self::HTML_SHORT ) ) {
42
			return $this->dataValue->getCaption();
43
		}
44
45
		return $this->getOutputText( $type, $linker );
46
	}
47
48
	protected function getOutputText( $type, $linker = null ) {
49
50
		if ( !$this->dataValue->isValid() ) {
51
			return ( ( $type == self::WIKI_SHORT ) || ( $type == self::HTML_SHORT ) ) ? '' : $this->dataValue->getErrorText();
52
		}
53
54
		// For the inverse case, return the subject that contains the reference
55
		// for Foo annotated with [[Bar::abc@en]] -> [[-Bar::Foo]]
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
56
		if ( $this->dataValue->getProperty() !== null && $this->dataValue->getProperty()->isInverse() ) {
57
58
			$dataItems = $this->dataValue->getDataItem()->getSemanticData()->getPropertyValues(
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 getSemanticData() does only exist in the following sub-classes of SMWDataItem: SMWDIContainer. 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...
59
				new DIProperty(  $this->dataValue->getProperty()->getKey() )
60
			);
61
62
			$dataItem = reset( $dataItems );
63
64
			if ( !$dataItem ) {
65
				return '';
66
			}
67
68
			return $dataItem->getDBKey();
69
		}
70
71
		return $this->doFormatFinalOutputFor( $type, $linker );
72
	}
73
74
	private function doFormatFinalOutputFor( $type, $linker ) {
75
76
		$text = '';
77
		$languagecode = '';
78
79
		foreach ( $this->dataValue->getPropertyDataItems() as $property ) {
0 ignored issues
show
Bug introduced by
The method getPropertyDataItems() does not exist on SMWDataValue. Did you maybe mean getProperty()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
80
81
			// If we wanted to omit the language code display for some outputs then
82
			// this is the point to make it happen
83
			if ( ( $type == self::HTML_LONG || $type == self::WIKI_SHORT ) && $property->getKey() === '_LCODE' ) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
84
			//continue;
85
			}
86
87
			$dataItems = $this->dataValue->getDataItem()->getSemanticData()->getPropertyValues( $property );
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 getSemanticData() does only exist in the following sub-classes of SMWDataItem: SMWDIContainer. 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...
88
89
			// Should not happen but just in case
90
			if ( !$dataItems === array() ) {
91
				$this->dataValue->addError( wfMessage( 'smw-datavalue-monolingual-dataitem-missing' )->text() );
92
				continue;
93
			}
94
95
			$dataItem = reset( $dataItems );
96
97
			if ( $dataItem === false ) {
98
				continue;
99
			}
100
101
			$dataValue = DataValueFactory::getInstance()->newDataItemValue(
102
				$dataItem,
103
				$property
104
			);
105
106
			$result = $this->findValueOutputFor(
107
				$type,
108
				$dataValue,
109
				$linker
110
			);
111
112
			if ( $property->getKey() === '_LCODE' ) {
113
				$languagecode = ' ' . wfMessage( 'smw-datavalue-monolingual-lcode-parenthesis', $result )->text();
114
			} else {
115
				$text = $result;
116
			}
117
		}
118
119
		return $text . $languagecode;
120
	}
121
122
	private function findValueOutputFor( $type, $dataValue, $linker ) {
123
		switch ( $type ) {
124
			case self::VALUE: return $dataValue->getWikiValue();
125
			case self::WIKI_SHORT: return $dataValue->getShortWikiText( $linker );
126
			case self::HTML_SHORT: return $dataValue->getShortHTMLText( $linker );
127
			case self::WIKI_LONG: return $dataValue->getShortWikiText( $linker );
128
			case self::HTML_LONG: return $dataValue->getShortHTMLText( $linker );
129
		}
130
	}
131
132
}
133