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\Dumpers; |
||
4 | |||
5 | use InvalidArgumentException; |
||
6 | use MWContentSerializationException; |
||
7 | use PageProps; |
||
8 | use Wikibase\DataModel\Entity\EntityId; |
||
9 | use Wikibase\DataModel\Services\Entity\EntityPrefetcher; |
||
10 | use Wikibase\DataModel\Services\Lookup\EntityLookupException; |
||
11 | use Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup; |
||
12 | use Wikibase\DataModel\Services\Lookup\RedirectResolvingEntityLookup; |
||
13 | use Wikibase\Lib\Store\EntityRevisionLookup; |
||
14 | use Wikibase\Lib\Store\EntityTitleLookup; |
||
15 | use Wikibase\Lib\Store\RevisionedUnresolvedRedirectException; |
||
16 | use Wikibase\Lib\Store\StorageException; |
||
17 | use Wikibase\Repo\Rdf\EntityRdfBuilderFactory; |
||
18 | use Wikibase\Repo\Rdf\HashDedupeBag; |
||
19 | use Wikibase\Repo\Rdf\RdfBuilder; |
||
20 | use Wikibase\Repo\Rdf\RdfProducer; |
||
21 | use Wikibase\Repo\Rdf\RdfVocabulary; |
||
22 | use Wikibase\Repo\Rdf\ValueSnakRdfBuilderFactory; |
||
23 | use Wikimedia\Purtle\BNodeLabeler; |
||
24 | use Wikimedia\Purtle\RdfWriterFactory; |
||
25 | |||
26 | /** |
||
27 | * RdfDumpGenerator generates an RDF dump of a given set of entities, excluding |
||
28 | * redirects. |
||
29 | * |
||
30 | * @license GPL-2.0-or-later |
||
31 | * @author Daniel Kinzler |
||
32 | * @author Stas Malyshev |
||
33 | */ |
||
34 | class RdfDumpGenerator extends DumpGenerator { |
||
35 | |||
36 | /** |
||
37 | * @var RdfBuilder |
||
38 | */ |
||
39 | private $rdfBuilder; |
||
40 | |||
41 | /** |
||
42 | * @var EntityRevisionLookup |
||
43 | */ |
||
44 | private $entityRevisionLookup; |
||
45 | |||
46 | /** |
||
47 | * @var int Fixed timestamp for tests. |
||
48 | */ |
||
49 | private $timestamp; |
||
50 | |||
51 | /** |
||
52 | * @var PageProps |
||
53 | */ |
||
54 | private $pageProps; |
||
55 | |||
56 | /** |
||
57 | * @var EntityTitleLookup |
||
58 | */ |
||
59 | private $titleLookup; |
||
60 | |||
61 | /** |
||
62 | * @param resource $out |
||
63 | * @param EntityRevisionLookup $lookup Must not resolve redirects |
||
64 | * @param RdfBuilder $rdfBuilder |
||
65 | * @param EntityPrefetcher $entityPrefetcher |
||
66 | * @param EntityTitleLookup $titleLookup |
||
67 | */ |
||
68 | public function __construct( |
||
69 | $out, |
||
70 | EntityRevisionLookup $lookup, |
||
71 | RdfBuilder $rdfBuilder, |
||
72 | EntityPrefetcher $entityPrefetcher, |
||
73 | EntityTitleLookup $titleLookup |
||
74 | ) { |
||
75 | parent::__construct( $out, $entityPrefetcher ); |
||
76 | |||
77 | if ( $lookup instanceof RedirectResolvingEntityLookup ) { |
||
78 | throw new InvalidArgumentException( '$lookup must not resolve redirects!' ); |
||
79 | } |
||
80 | |||
81 | $this->rdfBuilder = $rdfBuilder; |
||
82 | $this->entityRevisionLookup = $lookup; |
||
83 | $this->titleLookup = $titleLookup; |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Do something before dumping data |
||
88 | */ |
||
89 | protected function preDump() { |
||
90 | $this->pageProps = PageProps::getInstance(); |
||
91 | $this->pageProps->ensureCacheSize( $this->batchSize ); |
||
92 | $this->rdfBuilder->setPageProps( $this->pageProps ); |
||
93 | |||
94 | $this->rdfBuilder->startDocument(); |
||
95 | $this->rdfBuilder->addDumpHeader( $this->timestamp ); |
||
96 | |||
97 | $header = $this->rdfBuilder->getRDF(); |
||
98 | $this->writeToDump( $header ); |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * Do something after dumping data |
||
103 | */ |
||
104 | protected function postDump() { |
||
105 | $this->rdfBuilder->finishDocument(); |
||
106 | |||
107 | $footer = $this->rdfBuilder->getRDF(); |
||
108 | $this->writeToDump( $footer ); |
||
109 | } |
||
110 | |||
111 | /** |
||
112 | * Do something before dumping a batch of entities |
||
113 | * @param EntityId[] $entities |
||
114 | */ |
||
115 | protected function preBatchDump( $entities ) { |
||
116 | parent::preBatchDump( $entities ); |
||
117 | $titles = $this->titleLookup->getTitlesForIds( $entities ); |
||
118 | $props = array_keys( $this->rdfBuilder->getPageProperties() ); |
||
119 | // Prefetch page props |
||
120 | if ( $titles && $props ) { |
||
0 ignored issues
–
show
The expression
$titles of type Title[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
121 | $this->pageProps->getProperties( $titles, $props ); |
||
122 | } |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * Produces RDF dump of the entity |
||
127 | * |
||
128 | * @param EntityId $entityId |
||
129 | * |
||
130 | * @throws EntityLookupException |
||
131 | * @throws StorageException |
||
132 | * @return string|null RDF |
||
133 | */ |
||
134 | protected function generateDumpForEntityId( EntityId $entityId ) { |
||
135 | try { |
||
136 | $entityRevision = $this->entityRevisionLookup->getEntityRevision( $entityId ); |
||
137 | |||
138 | if ( !$entityRevision ) { |
||
139 | throw new EntityLookupException( $entityId, 'Entity not found: ' . $entityId->getSerialization() ); |
||
140 | } |
||
141 | |||
142 | $this->rdfBuilder->addEntityRevisionInfo( |
||
143 | $entityRevision->getEntity()->getId(), |
||
144 | $entityRevision->getRevisionId(), |
||
145 | $entityRevision->getTimestamp() |
||
146 | ); |
||
147 | |||
148 | $this->rdfBuilder->addEntityPageProps( $entityRevision->getEntity()->getId() ); |
||
0 ignored issues
–
show
It seems like
$entityRevision->getEntity()->getId() can be null ; however, addEntityPageProps() does not accept null , maybe add an additional type check?
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: /** @return stdClass|null */
function mayReturnNull() { }
function doesNotAcceptNull(stdClass $x) { }
// With potential error.
function withoutCheck() {
$x = mayReturnNull();
doesNotAcceptNull($x); // Potential error here.
}
// Safe - Alternative 1
function withCheck1() {
$x = mayReturnNull();
if ( ! $x instanceof stdClass) {
throw new \LogicException('$x must be defined.');
}
doesNotAcceptNull($x);
}
// Safe - Alternative 2
function withCheck2() {
$x = mayReturnNull();
if ($x instanceof stdClass) {
doesNotAcceptNull($x);
}
}
Loading history...
|
|||
149 | |||
150 | $this->rdfBuilder->addEntity( |
||
151 | $entityRevision->getEntity() |
||
152 | ); |
||
153 | |||
154 | } catch ( MWContentSerializationException $ex ) { |
||
155 | throw new StorageException( 'Deserialization error for ' . $entityId->getSerialization() ); |
||
156 | } catch ( RevisionedUnresolvedRedirectException $e ) { |
||
157 | if ( $e->getRevisionId() > 0 ) { |
||
158 | $this->rdfBuilder->addEntityRevisionInfo( |
||
159 | $entityId, |
||
160 | $e->getRevisionId(), |
||
161 | $e->getRevisionTimestamp() |
||
162 | ); |
||
163 | } |
||
164 | |||
165 | $this->rdfBuilder->addEntityRedirect( |
||
166 | $entityId, |
||
167 | $e->getRedirectTargetId() |
||
168 | ); |
||
169 | } |
||
170 | |||
171 | $rdf = $this->rdfBuilder->getRDF(); |
||
172 | return $rdf; |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * @param int $timestamp |
||
177 | */ |
||
178 | public function setTimestamp( $timestamp ) { |
||
179 | $this->timestamp = (int)$timestamp; |
||
180 | } |
||
181 | |||
182 | private static function getRdfWriter( $name, BNodeLabeler $labeler = null ) { |
||
183 | $factory = new RdfWriterFactory(); |
||
184 | $format = $factory->getFormatName( $name ); |
||
185 | |||
186 | if ( !$format ) { |
||
187 | return null; |
||
188 | } |
||
189 | |||
190 | return $factory->getWriter( $format, $labeler ); |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * Get the producer setting for the given flavor. |
||
195 | * |
||
196 | * @param string|null $flavorName |
||
197 | * |
||
198 | * @return int |
||
199 | * @throws InvalidArgumentException |
||
200 | */ |
||
201 | private static function getFlavorFlags( $flavorName ) { |
||
202 | //Note: RdfProducer::PRODUCE_VERSION_INFO is not needed here as dumps |
||
203 | // include that per default. |
||
204 | |||
205 | switch ( $flavorName ) { |
||
206 | case 'full-dump': |
||
207 | return RdfProducer::PRODUCE_ALL_STATEMENTS |
||
208 | | RdfProducer::PRODUCE_TRUTHY_STATEMENTS |
||
209 | | RdfProducer::PRODUCE_QUALIFIERS |
||
210 | | RdfProducer::PRODUCE_REFERENCES |
||
211 | | RdfProducer::PRODUCE_SITELINKS |
||
212 | | RdfProducer::PRODUCE_FULL_VALUES |
||
213 | | RdfProducer::PRODUCE_PAGE_PROPS |
||
214 | | RdfProducer::PRODUCE_NORMALIZED_VALUES; |
||
215 | case 'truthy-dump': |
||
216 | // XXX: For partial dumps we might want this to also include entity stubs. |
||
217 | return RdfProducer::PRODUCE_TRUTHY_STATEMENTS; |
||
218 | } |
||
219 | |||
220 | throw new InvalidArgumentException( "Unsupported flavor: $flavorName" ); |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * @param string $format |
||
225 | * @param resource $output |
||
226 | * @param string $flavor Either "full" or "truthy" |
||
227 | * @param EntityRevisionLookup $entityRevisionLookup |
||
228 | * @param PropertyDataTypeLookup $propertyLookup |
||
229 | * @param ValueSnakRdfBuilderFactory $valueSnakRdfBuilderFactory |
||
230 | * @param EntityRdfBuilderFactory $entityRdfBuilderFactory |
||
231 | * @param EntityPrefetcher $entityPrefetcher |
||
232 | * @param RdfVocabulary $vocabulary |
||
233 | * @param EntityTitleLookup $titleLookup |
||
234 | * @param BNodeLabeler|null $labeler |
||
235 | * |
||
236 | * @return static |
||
237 | * @throws InvalidArgumentException |
||
238 | */ |
||
239 | public static function createDumpGenerator( |
||
240 | $format, |
||
241 | $output, |
||
242 | $flavor, |
||
243 | EntityRevisionLookup $entityRevisionLookup, |
||
244 | PropertyDataTypeLookup $propertyLookup, |
||
245 | ValueSnakRdfBuilderFactory $valueSnakRdfBuilderFactory, |
||
246 | EntityRdfBuilderFactory $entityRdfBuilderFactory, |
||
247 | EntityPrefetcher $entityPrefetcher, |
||
248 | RdfVocabulary $vocabulary, |
||
249 | EntityTitleLookup $titleLookup, |
||
250 | BNodeLabeler $labeler = null |
||
251 | ) { |
||
252 | $rdfWriter = self::getRdfWriter( $format, $labeler ); |
||
253 | if ( !$rdfWriter ) { |
||
254 | throw new InvalidArgumentException( "Unknown format: $format" ); |
||
255 | } |
||
256 | |||
257 | $rdfBuilder = new RdfBuilder( |
||
258 | $vocabulary, |
||
259 | $valueSnakRdfBuilderFactory, |
||
260 | $propertyLookup, |
||
261 | $entityRdfBuilderFactory, |
||
262 | self::getFlavorFlags( $flavor ), |
||
263 | $rdfWriter, |
||
264 | new HashDedupeBag(), |
||
265 | $titleLookup |
||
266 | ); |
||
267 | |||
268 | return new self( $output, $entityRevisionLookup, $rdfBuilder, $entityPrefetcher, $titleLookup ); |
||
269 | } |
||
270 | |||
271 | } |
||
272 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.