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

src/Protection/EditProtectionUpdater.php (1 issue)

super-globals are not used.

Coding Style Minor

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
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
__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 );
158
		}
159
160
		return array( $isEditProtected, $isAnnotationBySystem );
161
	}
162
163
	private function doUpdateRestrictions( $isEditProtected ) {
164
165
		$protections = array();
166
		$expiry = array();
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(
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