Completed
Push — master ( 14d2bd...06e609 )
by mw
81:37 queued 59:24
created

includes/dataitems/SMW_DI_URI.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
use SMW\DataItemException;
4
5
/**
6
 * This class implements URI data items.
7
 *
8
 * @since 1.6
9
 *
10
 * @author Markus Krötzsch
11
 * @ingroup SMWDataItems
12
 */
13
class SMWDIUri extends SMWDataItem {
14
15
	/**
16
	 * URI scheme such as "html" or "mailto".
17
	 * @var string
18
	 */
19
	protected $m_scheme;
20
	/**
21
	 * "Hierpart" of the URI (usually some authority and path).
22
	 * @var string
23
	 */
24
	protected $m_hierpart;
25
	/**
26
	 * Query part of the URI.
27
	 * @var string
28
	 */
29
	protected $m_query;
30
	/**
31
	 * Fragment part of the URI.
32
	 * @var string
33
	 */
34
	protected $m_fragment;
35
36
	/**
37
	 * Initialise a URI by providing its scheme (e.g. "html"), 'hierpart'
38
	 * following "scheme:" (e.g. "//[email protected]/path), query (e.g.
39
	 * "q=Search+term", and fragment (e.g. "section-one"). The complete URI
40
	 * with these examples would be
41
	 * http://[email protected]/path?q=Search+term#section-one
42
	 * @param $scheme string for the scheme
43
	 * @param $hierpart string for the "hierpart"
44
	 * @param $query string for the query
45
	 * @param $fragment string for the fragment
46
	 *
47
	 * @todo Implement more validation here.
48
	 */
49 131
	public function __construct( $scheme, $hierpart, $query, $fragment ) {
50 131
		if ( ( $scheme === '' ) || ( preg_match( '/[^a-zA-Z]/u', $scheme ) ) ) {
51
			throw new DataItemException( "Illegal URI scheme \"$scheme\"." );
52
		}
53 131
		if ( $hierpart === '' ) {
54
			throw new DataItemException( "Illegal URI hierpart \"$hierpart\"." );
55
		}
56 131
		$this->m_scheme   = $scheme;
57 131
		$this->m_hierpart = $hierpart;
58 131
		$this->m_query    = $query;
59 131
		$this->m_fragment = $fragment;
60 131
	}
61
62 131
	public function getDIType() {
63 131
		return SMWDataItem::TYPE_URI;
64
	}
65
66
	/// @todo This should be changed to the spelling getUri().
67 131
	public function getURI() {
68
		$schemesWithDoubleslesh = array(
69 131
			'http', 'https', 'ftp'
70
		);
71
72 131
		$uri = $this->m_scheme . ':'
73 131
			. ( in_array( $this->m_scheme, $schemesWithDoubleslesh ) ? '//' : '' )
74 131
			. $this->m_hierpart
75 131
			. ( $this->m_query ? '?' . $this->m_query : '' )
76 131
			. ( $this->m_fragment ? '#' . $this->m_fragment : '' );
77
78 131
		return $uri;
79
	}
80
81 19
	public function getScheme() {
82 19
		return $this->m_scheme;
83
	}
84
85 5
	public function getHierpart() {
86 5
		return $this->m_hierpart;
87
	}
88
89 5
	public function getQuery() {
90 5
		return $this->m_query;
91
	}
92
93 128
	public function getFragment() {
94 128
		return $this->m_fragment;
95
	}
96
97
	public function getSortKey() {
98
		return $this->getURI();
99
	}
100
101 131
	public function getSerialization() {
102 131
		return $this->getURI();
103
	}
104
105
	/**
106
	 * Create a data item from the provided serialization string and type
107
	 * ID.
108
	 * @return SMWDIUri
109
	 */
110 29
	public static function doUnserialize( $serialization ) {
111 29
		$parts = explode( ':', $serialization, 2 ); // try to split "schema:rest"
112 29
		if ( count( $parts ) <= 1 ) {
113
			throw new DataItemException( "Unserialization failed: the string \"$serialization\" is no valid URI." );
114
		}
115 29
		$scheme = $parts[0];
116 29
		$parts = explode( '?', $parts[1], 2 ); // try to split "hier-part?queryfrag"
117 29
		if ( count( $parts ) == 2 ) {
118
			$hierpart = $parts[0];
119
			$parts = explode( '#', $parts[1], 2 ); // try to split "query#frag"
120
			$query = $parts[0];
121
			$fragment = ( count( $parts ) == 2 ) ? $parts[1] : '';
122
		} else {
123 29
			$query = '';
124 29
			$parts = explode( '#', $parts[0], 2 ); // try to split "hier-part#frag"
125 29
			$hierpart = $parts[0];
126 29
			$fragment = ( count( $parts ) == 2 ) ? $parts[1] : '';
127
		}
128
129 29
		$hierpart = ltrim( $hierpart, '/' );
130
131 29
		return new SMWDIUri( $scheme, $hierpart, $query, $fragment );
132
	}
133
134 1
	public function equals( SMWDataItem $di ) {
135 1
		if ( $di->getDIType() !== SMWDataItem::TYPE_URI ) {
136
			return false;
137
		}
138
139 1
		return $di->getURI() === $this->getURI();
0 ignored issues
show
It seems like you code against a specific sub-type and not the parent class SMWDataItem as the method getURI() does only exist in the following sub-classes of SMWDataItem: SMWDIUri. 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...
140
	}
141
}
142