Merge "Fix SlotDiffRenderer documentation"
[lhc/web/wiklou.git] / includes / block / CompositeBlock.php
1 <?php
2 /**
3 * Class for blocks composed from multiple blocks.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 */
22
23 namespace MediaWiki\Block;
24
25 use IContextSource;
26 use Title;
27
28 /**
29 * Multiple Block class.
30 *
31 * Multiple blocks exist to enforce restrictions from more than one block, if several
32 * blocks apply to a user/IP. Multiple blocks are created temporarily on enforcement.
33 *
34 * @since 1.34
35 */
36 class CompositeBlock extends AbstractBlock {
37 /** @var AbstractBlock[] */
38 private $originalBlocks;
39
40 /**
41 * Create a new block with specified parameters on a user, IP or IP range.
42 *
43 * @param array $options Parameters of the block:
44 * originalBlocks Block[] Blocks that this block is composed from
45 */
46 public function __construct( array $options = [] ) {
47 parent::__construct( $options );
48
49 $defaults = [
50 'originalBlocks' => [],
51 ];
52
53 $options += $defaults;
54
55 $this->originalBlocks = $options[ 'originalBlocks' ];
56
57 $this->setHideName( $this->propHasValue( 'mHideName', true ) );
58 $this->isSitewide( $this->propHasValue( 'isSitewide', true ) );
59 $this->isEmailBlocked( $this->propHasValue( 'mBlockEmail', true ) );
60 $this->isCreateAccountBlocked( $this->propHasValue( 'blockCreateAccount', true ) );
61 $this->isUsertalkEditAllowed( !$this->propHasValue( 'allowUsertalk', false ) );
62 }
63
64 /**
65 * Determine whether any original blocks have a particular property set to a
66 * particular value.
67 *
68 * @param string $prop
69 * @param mixed $value
70 * @return bool At least one block has the property set to the value
71 */
72 private function propHasValue( $prop, $value ) {
73 foreach ( $this->originalBlocks as $block ) {
74 if ( $block->$prop == $value ) {
75 return true;
76 }
77 }
78 return false;
79 }
80
81 /**
82 * Determine whether any original blocks have a particular method returning a
83 * particular value.
84 *
85 * @param string $method
86 * @param mixed $value
87 * @param mixed ...$params
88 * @return bool At least one block has the method returning the value
89 */
90 private function methodReturnsValue( $method, $value, ...$params ) {
91 foreach ( $this->originalBlocks as $block ) {
92 if ( $block->$method( ...$params ) == $value ) {
93 return true;
94 }
95 }
96 return false;
97 }
98
99 /**
100 * Get the original blocks from which this block is composed
101 *
102 * @since 1.34
103 * @return AbstractBlock[]
104 */
105 public function getOriginalBlocks() {
106 return $this->originalBlocks;
107 }
108
109 /**
110 * @inheritDoc
111 */
112 public function getExpiry() {
113 $maxExpiry = null;
114 foreach ( $this->originalBlocks as $block ) {
115 $expiry = $block->getExpiry();
116 if ( $maxExpiry === null || $expiry === '' || $expiry > $maxExpiry ) {
117 $maxExpiry = $expiry;
118 }
119 }
120 return $maxExpiry;
121 }
122
123 /**
124 * Get the IDs for the original blocks, ignoring any that are null
125 *
126 * @return int[]
127 */
128 protected function getIds() {
129 $ids = [];
130 foreach ( $this->originalBlocks as $block ) {
131 $id = $block->getId();
132 if ( $id !== null ) {
133 $ids[] = $id;
134 }
135 }
136 return $ids;
137 }
138
139 /**
140 * @inheritDoc
141 */
142 public function getPermissionsError( IContextSource $context ) {
143 $params = $this->getBlockErrorParams( $context );
144
145 $ids = implode( ', ', array_map( function ( $id ) {
146 return '#' . $id;
147 }, $this->getIds() ) );
148 if ( $ids === '' ) {
149 $idsMsg = $context->msg( 'blockedtext-composite-no-ids' )->plain();
150 } else {
151 $idsMsg = $context->msg( 'blockedtext-composite-ids', [ $ids ] )->plain();
152 }
153
154 // TODO: Clean up error messages params so we don't have to do this (T227174)
155 $params[ 4 ] = $idsMsg;
156
157 $msg = 'blockedtext-composite';
158
159 array_unshift( $params, $msg );
160
161 return $params;
162 }
163
164 /**
165 * @inheritDoc
166 */
167 public function appliesToRight( $right ) {
168 return $this->methodReturnsValue( __FUNCTION__, true, $right );
169 }
170
171 /**
172 * @inheritDoc
173 */
174 public function appliesToUsertalk( Title $usertalk = null ) {
175 return $this->methodReturnsValue( __FUNCTION__, true, $usertalk );
176 }
177
178 /**
179 * @inheritDoc
180 */
181 public function appliesToTitle( Title $title ) {
182 return $this->methodReturnsValue( __FUNCTION__, true, $title );
183 }
184
185 /**
186 * @inheritDoc
187 */
188 public function appliesToNamespace( $ns ) {
189 return $this->methodReturnsValue( __FUNCTION__, true, $ns );
190 }
191
192 /**
193 * @inheritDoc
194 */
195 public function appliesToPage( $pageId ) {
196 return $this->methodReturnsValue( __FUNCTION__, true, $pageId );
197 }
198
199 /**
200 * @inheritDoc
201 */
202 public function appliesToPasswordReset() {
203 return $this->methodReturnsValue( __FUNCTION__, true );
204 }
205
206 }