This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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 Wikibase\Repo\ChangeOp; |
||
4 | |||
5 | use InvalidArgumentException; |
||
6 | use OutOfBoundsException; |
||
7 | use ValueValidators\Result; |
||
8 | use Wikibase\DataModel\ByPropertyIdArray; |
||
9 | use Wikibase\DataModel\Entity\EntityDocument; |
||
10 | use Wikibase\DataModel\Entity\EntityId; |
||
11 | use Wikibase\DataModel\Services\Statement\GuidGenerator; |
||
12 | use Wikibase\DataModel\Services\Statement\StatementGuidParser; |
||
13 | use Wikibase\DataModel\Services\Statement\StatementGuidParsingException; |
||
14 | use Wikibase\DataModel\Services\Statement\StatementGuidValidator; |
||
15 | use Wikibase\DataModel\Statement\Statement; |
||
16 | use Wikibase\DataModel\Statement\StatementList; |
||
17 | use Wikibase\DataModel\Statement\StatementListProvider; |
||
18 | use Wikibase\Lib\Summary; |
||
19 | use Wikibase\Repo\Validators\SnakValidator; |
||
20 | |||
21 | /** |
||
22 | * Class for statement modification operations |
||
23 | * |
||
24 | * @license GPL-2.0-or-later |
||
25 | */ |
||
26 | class ChangeOpStatement extends ChangeOpBase { |
||
27 | |||
28 | /** |
||
29 | * @var Statement |
||
30 | */ |
||
31 | private $statement; |
||
32 | |||
33 | /** |
||
34 | * @var GuidGenerator |
||
35 | */ |
||
36 | private $guidGenerator; |
||
37 | |||
38 | /** |
||
39 | * @var StatementGuidValidator |
||
40 | */ |
||
41 | private $guidValidator; |
||
42 | |||
43 | /** |
||
44 | * @var StatementGuidParser |
||
45 | */ |
||
46 | private $guidParser; |
||
47 | |||
48 | /** |
||
49 | * @var SnakValidator |
||
50 | */ |
||
51 | private $snakValidator; |
||
52 | |||
53 | /** |
||
54 | * @var int|null |
||
55 | */ |
||
56 | private $index; |
||
57 | |||
58 | /** |
||
59 | * @param Statement $statement |
||
60 | * @param GuidGenerator $guidGenerator |
||
61 | * @param StatementGuidValidator $guidValidator |
||
62 | * @param StatementGuidParser $guidParser |
||
63 | * @param SnakValidator $snakValidator |
||
64 | * @param int|null $index Where the statement should be placed among the other statements. |
||
65 | * |
||
66 | * @throws InvalidArgumentException |
||
67 | */ |
||
68 | public function __construct( |
||
69 | Statement $statement, |
||
70 | GuidGenerator $guidGenerator, |
||
71 | StatementGuidValidator $guidValidator, |
||
72 | StatementGuidParser $guidParser, |
||
73 | SnakValidator $snakValidator, |
||
74 | $index = null |
||
75 | ) { |
||
76 | if ( $index !== null && ( !is_int( $index ) || $index < 0 ) ) { |
||
77 | throw new InvalidArgumentException( '$index must be an non-negative integer or null' ); |
||
78 | } |
||
79 | |||
80 | $this->statement = $statement; |
||
81 | $this->guidGenerator = $guidGenerator; |
||
82 | $this->guidValidator = $guidValidator; |
||
83 | $this->guidParser = $guidParser; |
||
84 | $this->snakValidator = $snakValidator; |
||
85 | $this->index = $index; |
||
86 | } |
||
87 | |||
88 | /** |
||
89 | * @see ChangeOp::apply |
||
90 | * |
||
91 | * @param EntityDocument $entity |
||
92 | * @param Summary|null $summary |
||
93 | * |
||
94 | * @throws InvalidArgumentException |
||
95 | * @throws ChangeOpException |
||
96 | */ |
||
97 | public function apply( EntityDocument $entity, Summary $summary = null ) { |
||
98 | if ( !( $entity instanceof StatementListProvider ) ) { |
||
99 | throw new InvalidArgumentException( '$entity must be a StatementListProvider' ); |
||
100 | } |
||
101 | |||
102 | // @phan-suppress-next-line PhanUndeclaredMethod Phan is confused by intersection types |
||
103 | $entityId = $entity->getId(); |
||
104 | |||
105 | if ( $this->statement->getGuid() === null ) { |
||
106 | $this->statement->setGuid( $this->guidGenerator->newGuid( $entityId ) ); |
||
107 | } |
||
108 | |||
109 | $this->validateStatementGuid( $entityId ); |
||
110 | |||
111 | $entityStatements = $entity->getStatements(); |
||
112 | $oldIndex = $this->removeStatement( $entityStatements ); |
||
113 | |||
114 | if ( $this->index !== null ) { |
||
115 | $statements = $this->addStatementToGroup( $entityStatements, $this->index ); |
||
116 | $entityStatements->clear(); |
||
117 | foreach ( $statements as $statement ) { |
||
118 | $entityStatements->addStatement( $statement ); |
||
119 | } |
||
120 | } else { |
||
121 | $entityStatements->addStatement( $this->statement, $oldIndex ); |
||
122 | } |
||
123 | |||
124 | $this->updateSummary( $summary, $oldIndex === null ? 'create' : 'update' ); |
||
125 | |||
126 | return new GenericChangeOpResult( $entityId, true ); |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * @param EntityId $entityId |
||
131 | * |
||
132 | * @throws ChangeOpException |
||
133 | */ |
||
134 | private function validateStatementGuid( EntityId $entityId ) { |
||
135 | try { |
||
136 | $guid = $this->guidParser->parse( $this->statement->getGuid() ); |
||
137 | } catch ( StatementGuidParsingException $ex ) { |
||
138 | throw new ChangeOpException( 'Statement GUID can not be parsed' ); |
||
139 | } |
||
140 | |||
141 | if ( !$this->guidValidator->validate( $guid->getSerialization() ) ) { |
||
0 ignored issues
–
show
|
|||
142 | throw new ChangeOpException( 'Statement does not have a valid GUID' ); |
||
143 | } |
||
144 | |||
145 | if ( !$guid->getEntityId()->equals( $entityId ) ) { |
||
146 | throw new ChangeOpException( 'Statement GUID invalid for given entity' ); |
||
147 | } |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * @param StatementList $statements |
||
152 | * |
||
153 | * @return int|null |
||
154 | */ |
||
155 | private function removeStatement( StatementList $statements ) { |
||
156 | $guid = $this->statement->getGuid(); |
||
157 | $oldIndex = null; |
||
158 | $oldStatement = null; |
||
159 | |||
160 | foreach ( $statements->toArray() as $index => $statement ) { |
||
161 | if ( $statement->getGuid() === $guid ) { |
||
162 | $oldIndex = $index; |
||
163 | $oldStatement = $statement; |
||
164 | $statements->removeStatementsWithGuid( $guid ); |
||
165 | break; |
||
166 | } |
||
167 | } |
||
168 | |||
169 | if ( $oldStatement !== null ) { |
||
170 | $this->checkMainSnakUpdate( $oldStatement ); |
||
171 | } |
||
172 | |||
173 | return $oldIndex; |
||
174 | } |
||
175 | |||
176 | /** |
||
177 | * Checks that the update of the main snak is permissible. |
||
178 | * |
||
179 | * This checks that the main snaks of the old and the new statement |
||
180 | * refer to the same property. |
||
181 | * |
||
182 | * @param Statement $oldStatement |
||
183 | * |
||
184 | * @throws ChangeOpException If the main snak update is illegal. |
||
185 | */ |
||
186 | private function checkMainSnakUpdate( Statement $oldStatement ) { |
||
187 | $newMainSnak = $this->statement->getMainSnak(); |
||
188 | $oldPropertyId = $oldStatement->getPropertyId(); |
||
189 | |||
190 | if ( !$oldPropertyId->equals( $newMainSnak->getPropertyId() ) ) { |
||
191 | $guid = $this->statement->getGuid(); |
||
192 | throw new ChangeOpException( "Claim with GUID $guid uses property " |
||
193 | . $oldPropertyId . ", can't change to " |
||
194 | . $newMainSnak->getPropertyId() ); |
||
195 | } |
||
196 | } |
||
197 | |||
198 | /** |
||
199 | * @param StatementList $statements |
||
200 | * @param int $index |
||
201 | * |
||
202 | * @return Statement[] |
||
203 | */ |
||
204 | private function addStatementToGroup( StatementList $statements, $index ) { |
||
205 | // If we fail with the user supplied index and the index is greater than or equal 0 |
||
206 | // presume the user wants to have the index at the end of the list. |
||
207 | $indexedStatements = new ByPropertyIdArray( $statements->toArray() ); |
||
0 ignored issues
–
show
The class
Wikibase\DataModel\ByPropertyIdArray has been deprecated with message: since 5.0, use a DataModel Service instead
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead. ![]() |
|||
208 | $indexedStatements->buildIndex(); |
||
209 | |||
210 | try { |
||
211 | $indexedStatements->addObjectAtIndex( $this->statement, $index ); |
||
212 | } catch ( OutOfBoundsException $ex ) { |
||
213 | $statements->addStatement( $this->statement ); |
||
214 | return $statements->toArray(); |
||
215 | } |
||
216 | |||
217 | return $indexedStatements->toFlatArray(); |
||
218 | } |
||
219 | |||
220 | /** |
||
221 | * @see ChangeOp::validate |
||
222 | * |
||
223 | * @param EntityDocument $entity |
||
224 | * |
||
225 | * @return Result |
||
226 | */ |
||
227 | public function validate( EntityDocument $entity ) { |
||
228 | return $this->snakValidator->validateClaimSnaks( $this->statement ); |
||
229 | } |
||
230 | |||
231 | } |
||
232 |
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.