Completed
Pull Request — master (#22)
by mw
03:56
created

CitationReferenceValue::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 9.4286
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
3
namespace SCI\DataValues;
4
5
use SCI\CitationReferencePositionJournal;
6
use SMWStringValue as StringValue;
7
use SMWDIBlob as DIBlob;
8
use Html;
9
10
/**
11
 * @license GNU GPL v2+
12
 * @since 1.0
13
 *
14
 * @author mwjames
15
 */
16
class CitationReferenceValue extends StringValue {
17
18
	/**
19
	 * @var integer
20
	 */
21
	private $captionFormat;
22
23
	/**
24
	 * @var CitationReferencePositionJournal
25
	 */
26
	private $citationReferencePositionJournal;
27
28
	/**
29
	 * @var string
30
	 */
31
	private $reference;
32
33
	/**
34
	 * To display something like [[CiteRef::Foo, 1970|:50-52]] as [1]:50-52 for
35
	 * SCI_CITEREF_NUM
36
	 *
37
	 * @var boolean
38
	 */
39
	private $usesShortFormCaption = false;
40
41
	/**
42
	 * @param string $typeid
43
	 */
44 11
	public function __construct( $typeid = '' ) {
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
45 11
		parent::__construct( '_sci_ref' );
46
47
		// Currently there is no good way to inject the setting
48 11
		$this->captionFormat = $GLOBALS['scigCitationReferenceCaptionFormat'];
49 11
	}
50
51
	/**
52
	 * @since 1.0
53
	 *
54
	 * @param  integer $captionFormat
55
	 */
56
	public function setCaptionFormat( $captionFormat ) {
57
		$this->captionFormat = $captionFormat;
58
	}
59
60
	/**
61
	 * @see StringValue::parseUserValue
62
	 */
63 9
	protected function parseUserValue( $value ) {
64
65 9
		$this->citationReferencePositionJournal = $this->getExtraneousFunctionFor( '\SCI\CitationReferencePositionJournal' );
66
67 9
		$value = trim( $value );
68
69 9
		if ( $value === '' ) {
70 1
			$this->addError( wfMessage( 'sci-datavalue-empty-reference' )->inContentLanguage()->text() );
71 1
			$this->m_dataitem = new DIBlob( 'ERROR' );
72 1
			return;
73
		}
74
75 8
		if ( $this->m_contextPage === null ) {
76
			parent::parseUserValue( $value );
77
			return;
78
		}
79
80 8
		$this->reference = $value;
81
82 8
		if ( $this->m_caption && $this->captionFormat === SCI_CITEREF_NUM ) {
83 1
			$this->usesShortFormCaption = true;
84 1
		}
85
86 8
		if ( !$this->m_caption ) {
87 7
			$this->m_caption = $this->reference;
88 7
		}
89
90
		// This is where the magic happens, compute the position of
91
		// a reference relative to previous CiteRef annotations
92 8
		$this->citationReferencePositionJournal->addJournalEntryFor(
93 8
			$this->m_contextPage,
94 8
			$this->reference
95 8
		);
96
97 8
		parent::parseUserValue( $this->reference );
98 8
	}
99
100
	/**
101
	 * @see StringValue::parseUserValue
102
	 */
103 7
	public function getShortWikiText( $linked = null ) {
104
105 7
		$this->citationReferencePositionJournal = $this->getExtraneousFunctionFor( '\SCI\CitationReferencePositionJournal' );
106
107
		// We want the last entry here to get the major/minor
108
		// number that was internally recorded
109 7
		$referencePosition = $this->citationReferencePositionJournal->findLastReferencePositionEntryFor(
110 7
			$this->m_contextPage,
111 7
			$this->reference
112 7
		);
113
114 7
		if ( $referencePosition === null || $this->m_caption === false ) {
115
			return $this->m_dataitem->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...
116
		}
117
118 7
		$referenceHash = md5( $this->reference );
119
120 7
		if ( $this->captionFormat === SCI_CITEREF_NUM ) {
121 4
			list( $major, $minor ) = explode( '-', $referencePosition );
0 ignored issues
show
Unused Code introduced by
The assignment to $minor is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
122 4
			$caption = $major;
123 4
			$captionClass = 'number';
124
125
			// [[CiteRef::Foo, 1970|:50-52]] will add the caption to the outside
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% 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...
126 4
			$shortFormCaption = $this->usesShortFormCaption ? $this->m_caption : '';
127 4
		} else {
128 3
			$captionClass = 'key';
129 3
			$caption = $this->m_caption;
130 3
			$shortFormCaption = ''; // Never has a short form
131
		}
132
133 7
		if ( $shortFormCaption !== '' ) {
134 1
			$shortFormCaption = Html::rawElement(
135 1
				'span',
136 1
				array( 'class' => 'scite-citeref-shortcaption' ),
137
				$shortFormCaption
138 1
			);
139 1
		}
140
141
		// Build element with back and forth link anchor
142 7
		$html = Html::rawElement(
143 7
			'span',
144
			array(
145 7
				'id'    => 'scite-ref-'. $referenceHash . '-' . $referencePosition,
146 7
				'class' => 'scite-citeref-' . $captionClass,
147 7
				'data-reference' => $this->reference
148 7
			),
149 7
			'[[' .'#scite-' . $referenceHash . '|' . $caption . ']]'
150 7
		) . $shortFormCaption;
151
152 7
		return $html;
153
	}
154
155
}
156