Completed
Push — master ( 3abc67...80e892 )
by mw
207:38 queued 172:37
created

EditProtectionUpdater::doUpdateFrom()   C

Complexity

Conditions 12
Paths 6

Size

Total Lines 33
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 15
nc 6
nop 1
dl 0
loc 33
rs 5.1612
c 0
b 0
f 0

How to fix   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
namespace SMW\Protection;
4
5
use SMW\Message;
6
use SMW\SemanticData;
7
use SMW\DIProperty;
8
use SMW\PropertyAnnotators\EditProtectedPropertyAnnotator;
9
use SMW\MediaWiki\Hooks\ArticleProtectComplete;
10
use Psr\Log\LoggerInterface;
11
use Psr\Log\LoggerAwareInterface;
12
use WikiPage;
13
use User;
14
15
/**
16
 * @license GNU GPL v2+
17
 * @since 2.5
18
 *
19
 * @author mwjames
20
 */
21
class EditProtectionUpdater implements LoggerAwareInterface {
22
23
	/**
24
	 * @var WikiPage
25
	 */
26
	private $wikiPage;
27
28
	/**
29
	 * @var User
30
	 */
31
	private $user;
32
33
	/**
34
	 * @var boolean
35
	 */
36
	private $isRestrictedUpdate = false;
37
38
	/**
39
	 * @var boolean|string
40
	 */
41
	private $editProtectionRight = false;
42
43
	/**
44
	 * LoggerInterface
45
	 */
46
	private $logger;
47
48
	/**
49
	 * @since 2.5
50
	 *
51
	 * @param WikiPage $wikiPage
52
	 * @param User|null $user
53
	 */
54
	public function __construct( WikiPage $wikiPage, User $user = null ) {
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...
55
		$this->wikiPage = $wikiPage;
56
		$this->user = $user;
57
58
		if ( $this->user === null ) {
59
			$this->user = $GLOBALS['wgUser'];
60
		}
61
	}
62
63
	/**
64
	 * @see LoggerAwareInterface::setLogger
65
	 *
66
	 * @since 2.5
67
	 *
68
	 * @param LoggerInterface $logger
69
	 */
70
	public function setLogger( LoggerInterface $logger ) {
71
		$this->logger = $logger;
72
	}
73
74
	/**
75
	 * @since 2.5
76
	 *
77
	 * @param string|boolean $editProtectionRight
78
	 */
79
	public function setEditProtectionRight( $editProtectionRight ) {
80
		$this->editProtectionRight = $editProtectionRight;
81
	}
82
83
	/**
84
	 * @since 2.5
85
	 *
86
	 * @return boolean
87
	 */
88
	public function isRestrictedUpdate() {
89
		return $this->isRestrictedUpdate;
90
	}
91
92
	/**
93
	 * @since 2.5
94
	 *
95
	 * @param SemanticData $semanticData
96
	 */
97
	public function doUpdateFrom( SemanticData $semanticData ) {
98
99
		// Do nothing
100
		if ( $this->editProtectionRight === false ) {
101
			return;
102
		}
103
104
		list( $isEditProtected, $isAnnotationBySystem ) = $this->fetchEditProtectedInfo( $semanticData );
105
106
		$title = $this->wikiPage->getTitle();
107
108
		if ( $title === null ) {
109
			return;
110
		}
111
112
		$restrictions = array_flip( $title->getRestrictions( 'edit' ) );
113
114
		// No `Is edit protected` was found and the restriction doesn't contain
115
		// a matchable `editProtectionRight`
116
		if ( $isEditProtected === null && !isset( $restrictions[$this->editProtectionRight] ) ) {
117
			return $this->log( __METHOD__ . ' no update required' );
118
		}
119
120
		if ( $isEditProtected && !isset( $restrictions[$this->editProtectionRight] ) && !$isAnnotationBySystem ) {
121
			return $this->doUpdateRestrictions( $isEditProtected );
122
		}
123
124
		if ( $isEditProtected && $title->isProtected( 'edit' ) || !$isEditProtected && !$title->isProtected( 'edit' ) ) {
125
			return $this->log( __METHOD__ . ' Status already set, no update required' );
126
		}
127
128
		$this->doUpdateRestrictions( $isEditProtected );
129
	}
130
131
	private function fetchEditProtectedInfo( $semanticData ) {
132
133
		// Whether or not the update was invoked by the ArticleProtectComplete hook
134
		$this->isRestrictedUpdate = $semanticData->getOption( ArticleProtectComplete::RESTRICTED_UPDATE ) === true;
135
		$property = new DIProperty( '_EDIP' );
136
137
		$isEditProtected = null;
138
		$isAnnotationBySystem = false;
139
140
		$dataItems = $semanticData->getPropertyValues(
141
			$property
142
		);
143
144
		if ( $dataItems !== array() ) {
145
			$isEditProtected = false;
146
147
			// In case of two competing values, true always wins
148
			foreach ( $dataItems as $dataItem ) {
149
150
				$isEditProtected = $dataItem->getBoolean();
151
152
				if ( $isEditProtected ) {
153
					break;
154
				}
155
			}
156
157
			$isAnnotationBySystem = $dataItem->getOption( EditProtectedPropertyAnnotator::SYSTEM_ANNOTATION );
0 ignored issues
show
Bug introduced by
The variable $dataItem seems to be defined by a foreach iteration on line 148. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
158
		}
159
160
		return array( $isEditProtected, $isAnnotationBySystem );
161
	}
162
163
	private function doUpdateRestrictions( $isEditProtected ) {
164
165
		$protections = array();
0 ignored issues
show
Unused Code introduced by
$protections is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
166
		$expiry = array();
0 ignored issues
show
Unused Code introduced by
$expiry is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
167
168
		if ( $isEditProtected ) {
169
			$this->log( __METHOD__ . ' add protection on edit, move' );
170
171
			$protections = array(
172
				'edit' => $this->editProtectionRight,
173
				'move' => $this->editProtectionRight
174
			);
175
176
			$expiry = array(
177
				'edit' => 'infinity',
178
				'move' => 'infinity'
179
			);
180
		} else {
181
			$this->log( __METHOD__ . ' remove protection on edit, move' );
182
			$protections = array();
183
			$expiry = array();
184
		}
185
186
		$reason = Message::get( 'smw-edit-protection-auto-update' );
187
		$cascade = false;
188
189
		$status = $this->wikiPage->doUpdateRestrictions(
0 ignored issues
show
Unused Code introduced by
$status is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
190
			$protections,
191
			$expiry,
192
			$cascade,
193
			$reason,
194
			$this->user
195
		);
196
	}
197
198
	private function log( $message, $context = array() ) {
199
200
		if ( $this->logger === null ) {
201
			return;
202
		}
203
204
		$this->logger->info( $message, $context );
205
	}
206
207
}
208