Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 105
0.00% covered (danger)
0.00%
0 / 14
CRAP
0.00% covered (danger)
0.00%
0 / 1
PersistentRootGraphLoader
0.00% covered (danger)
0.00%
0 / 105
0.00% covered (danger)
0.00%
0 / 14
1722
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getLoadedInstances
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 visitRoot
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 visitLanguage
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 visitManuscript
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 visitManuscriptDomain
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 visitManuscriptPrompt
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 visitRecording
0.00% covered (danger)
0.00%
0 / 79
0.00% covered (danger)
0.00%
0 / 1
756
 visitRecordingAnnotations
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 visitRecordingReview
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 visitSkippedManuscriptPrompt
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 visitUser
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 visitUserDialect
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 visitUserLanguageProficiencyLevel
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\WikispeechSpeechDataCollector\Crud;
4
5/**
6 * @file
7 * @ingroup Extensions
8 * @license GPL-2.0-or-later
9 */
10
11use ExternalStoreException;
12use InvalidArgumentException;
13use MediaWiki\WikispeechSpeechDataCollector\Crud\Mcr\RecordingAnnotationsCrud;
14use MediaWiki\WikispeechSpeechDataCollector\Crud\Rdbms\LanguageCrud;
15use MediaWiki\WikispeechSpeechDataCollector\Crud\Rdbms\ManuscriptCrud;
16use MediaWiki\WikispeechSpeechDataCollector\Crud\Rdbms\ManuscriptPromptCrud;
17use MediaWiki\WikispeechSpeechDataCollector\Crud\Rdbms\RecordingReviewCrud;
18use MediaWiki\WikispeechSpeechDataCollector\Crud\Rdbms\UserCrud;
19use MediaWiki\WikispeechSpeechDataCollector\Crud\Rdbms\UserDialectCrud;
20use MediaWiki\WikispeechSpeechDataCollector\Domain\Language;
21use MediaWiki\WikispeechSpeechDataCollector\Domain\Manuscript;
22use MediaWiki\WikispeechSpeechDataCollector\Domain\ManuscriptDomain;
23use MediaWiki\WikispeechSpeechDataCollector\Domain\ManuscriptPrompt;
24use MediaWiki\WikispeechSpeechDataCollector\Domain\Persistent;
25use MediaWiki\WikispeechSpeechDataCollector\Domain\PersistentSet;
26use MediaWiki\WikispeechSpeechDataCollector\Domain\PersistentVisitor;
27use MediaWiki\WikispeechSpeechDataCollector\Domain\Recording;
28use MediaWiki\WikispeechSpeechDataCollector\Domain\RecordingAnnotations;
29use MediaWiki\WikispeechSpeechDataCollector\Domain\RecordingReview;
30use MediaWiki\WikispeechSpeechDataCollector\Domain\SkippedManuscriptPrompt;
31use MediaWiki\WikispeechSpeechDataCollector\Domain\User;
32use MediaWiki\WikispeechSpeechDataCollector\Domain\UserDialect;
33use MediaWiki\WikispeechSpeechDataCollector\Domain\UserLanguageProficiencyLevel;
34
35/**
36 * Loads a graph of associated aggregated persistent objects per persistent class
37 * as defined by the code of this visitor.
38 *
39 * @since 0.1.0
40 */
41class PersistentRootGraphLoader implements PersistentVisitor {
42
43    /** @var PersistentSet */
44    private $loadedInstances;
45
46    /** @var CrudContext */
47    private $context;
48
49    /**
50     * @param CrudContext $context
51     * @param PersistentSet|null $loadedInstances
52     * @since 0.1.0
53     */
54    public function __construct(
55        CrudContext $context,
56        ?PersistentSet $loadedInstances = null
57    ) {
58        $this->context = $context;
59        $this->loadedInstances = $loadedInstances ?? new PersistentSet();
60    }
61
62    /**
63     * @return PersistentSet
64     * @since 0.1.0
65     */
66    public function getLoadedInstances(): PersistentSet {
67        return $this->loadedInstances;
68    }
69
70    /**
71     * @param Persistent $instance
72     * @throws InvalidArgumentException If identity is not set.
73     * @since 0.1.0
74     */
75    private function visitRoot( Persistent $instance ) {
76        if ( $instance->getIdentity() === null ) {
77            throw new InvalidArgumentException( 'Instance must be loaded.' );
78        }
79        $this->loadedInstances->add( $instance );
80    }
81
82    /**
83     * @param Language $language
84     * @return null
85     * @since 0.1.0
86     */
87    public function visitLanguage(
88        Language $language
89    ) {
90        $this->visitRoot( $language );
91        return null;
92    }
93
94    /**
95     * @param Manuscript $manuscript
96     * @return null
97     * @since 0.1.0
98     */
99    public function visitManuscript(
100        Manuscript $manuscript
101    ) {
102        $this->visitRoot( $manuscript );
103        return null;
104    }
105
106    /**
107     * @param ManuscriptDomain $manuscriptDomain
108     * @return null
109     * @since 0.1.0
110     */
111    public function visitManuscriptDomain(
112        ManuscriptDomain $manuscriptDomain
113    ) {
114        $this->visitRoot( $manuscriptDomain );
115        return null;
116    }
117
118    /**
119     * @param ManuscriptPrompt $manuscriptPrompt
120     * @return null
121     * @since 0.1.0
122     */
123    public function visitManuscriptPrompt(
124        ManuscriptPrompt $manuscriptPrompt
125    ) {
126        $this->visitRoot( $manuscriptPrompt );
127        return null;
128    }
129
130    /**
131     * Loads user voice of.
132     * Loads spoken dialect.
133     * Loads spoken dialect language
134     * Loads all reviews (but not the reviewer user).
135     * Loads annotations and annotation stereotypes.
136     * Loads manuscript prompt.
137     * Loads manuscript.
138     * Loads manuscript language.
139     * Loads manuscript domains recursive to manuscript domain root.
140     *
141     * @param Recording $recording
142     * @return null
143     * @throws ExternalStoreException If unable to load an aggregated instance.
144     * @since 0.1.0
145     */
146    public function visitRecording(
147        Recording $recording
148    ) {
149        $this->visitRoot( $recording );
150
151        if ( $recording->getSpokenDialect() ) {
152            $spokenDialect = new UserDialect();
153            $spokenDialect->setIdentity( $recording->getSpokenDialect() );
154            if ( !$this->loadedInstances->contains( $spokenDialect ) ) {
155                $userDialectCrud = new UserDialectCrud( $this->context );
156                if ( !$userDialectCrud->load( $spokenDialect ) ) {
157                    throw new ExternalStoreException( 'Unable to load ' . $spokenDialect );
158                }
159                $this->loadedInstances->add( $spokenDialect );
160            } else {
161                $spokenDialect = $this->loadedInstances->get( $spokenDialect );
162            }
163
164            if ( $spokenDialect->getLanguage() ) {
165                $language = new Language();
166                $language->setIdentity( $spokenDialect->getLanguage() );
167                if ( !$this->loadedInstances->contains( $language ) ) {
168                    $languageCrud = new LanguageCrud( $this->context );
169                    if ( !$languageCrud->load( $language ) ) {
170                        throw new ExternalStoreException( 'Unable to load ' . $language );
171                    }
172                    $this->loadedInstances->add( $language );
173                }
174            }
175        }
176
177        if ( $recording->getVoiceOf() ) {
178            $voiceOf = new User();
179            $voiceOf->setIdentity( $recording->getVoiceOf() );
180            if ( !$this->loadedInstances->contains( $voiceOf ) ) {
181                $userCrud = new UserCrud( $this->context );
182                if ( !$userCrud->load( $voiceOf ) ) {
183                    throw new ExternalStoreException( 'Unable to load ' . $voiceOf );
184                }
185                $this->loadedInstances->add( $voiceOf );
186            } else {
187                $voiceOf = $this->loadedInstances->get( $voiceOf );
188            }
189
190            // @todo load UserDialects and UserLanguageProficiencyLevels + languages
191            // that are matching the recorded manuscript prompt manuscript language
192        }
193
194        $reviewCrud = new RecordingReviewCrud( $this->context );
195        // @phan-suppress-next-line PhanTypeMismatchArgumentNullable
196        $reviews = $reviewCrud->listByRecording( $recording->getIdentity() );
197        if ( $reviews ) {
198            $this->loadedInstances->addAll( $reviews );
199        }
200
201        $recordingAnnotationsCrud = new RecordingAnnotationsCrud( $this->context );
202        $recordingAnnotations = $recordingAnnotationsCrud->read( $recording->getIdentity() );
203        if ( $recordingAnnotations !== null ) {
204            $this->loadedInstances->add( $recordingAnnotations );
205        }
206
207        if ( $recording->getManuscriptPrompt() ) {
208            $manuscriptPrompt = new ManuscriptPrompt();
209            $manuscriptPrompt->setIdentity( $recording->getManuscriptPrompt() );
210            if ( !$this->loadedInstances->contains( $manuscriptPrompt ) ) {
211                $manuscriptPromptCrud = new ManuscriptPromptCrud( $this->context );
212                if ( !$manuscriptPromptCrud->load( $manuscriptPrompt ) ) {
213                    throw new ExternalStoreException( 'Unable to load ' . $manuscriptPrompt );
214                }
215                $this->loadedInstances->add( $manuscriptPrompt );
216            } else {
217                $manuscriptPrompt = $this->loadedInstances->get( $manuscriptPrompt );
218            }
219
220            if ( $manuscriptPrompt->getManuscript() ) {
221                $manuscript = new Manuscript();
222                $manuscript->setIdentity( $manuscriptPrompt->getManuscript() );
223                if ( !$this->loadedInstances->contains( $manuscript ) ) {
224                    $manuscriptCrud = new ManuscriptCrud( $this->context );
225                    if ( !$manuscriptCrud->load( $manuscript ) ) {
226                        throw new ExternalStoreException( 'Unable to load ' . $manuscript );
227                    }
228                    $this->loadedInstances->add( $manuscript );
229                }
230
231                if ( $manuscript->getDomain() ) {
232                    $manuscriptDomain = new ManuscriptDomain();
233                    $manuscriptDomain->setIdentity( $manuscript->getDomain() );
234                    if ( !$this->loadedInstances->contains( $manuscriptDomain ) ) {
235                        $manuscriptDomainCrud = new ManuscriptCrud( $this->context );
236                        if ( !$manuscriptDomainCrud->load( $manuscriptDomain ) ) {
237                            throw new ExternalStoreException( 'Unable to load ' . $manuscriptDomain );
238                        }
239                        $this->loadedInstances->add( $manuscriptDomain );
240                    }
241
242                    // load parents to root
243                    while ( $manuscriptDomain->getParent() ) {
244                        $parentManuscriptDomain = new ManuscriptDomain();
245                        $parentManuscriptDomain->setIdentity( $manuscriptDomain->getParent() );
246                        if ( !$this->loadedInstances->contains( $parentManuscriptDomain ) ) {
247                            $manuscriptDomainCrud = new ManuscriptCrud( $this->context );
248                            if ( !$manuscriptDomainCrud->load( $parentManuscriptDomain ) ) {
249                                throw new ExternalStoreException( 'Unable to load ' . $parentManuscriptDomain );
250                            }
251                            $this->loadedInstances->add( $manuscriptDomain );
252                            $manuscriptDomain = $parentManuscriptDomain;
253                        } else {
254                            $manuscriptDomain = $this->loadedInstances->get( $parentManuscriptDomain );
255                        }
256                    }
257                }
258
259                if ( $manuscript->getLanguage() ) {
260                    $language = new Language();
261                    $language->setIdentity( $manuscript->getLanguage() );
262                    if ( !$this->loadedInstances->contains( $language ) ) {
263                        $languageCrud = new LanguageCrud( $this->context );
264                        if ( !$languageCrud->load( $language ) ) {
265                            throw new ExternalStoreException( 'Unable to load ' . $language );
266                        }
267                        $this->loadedInstances->add( $language );
268                    }
269                }
270            }
271        }
272
273        return null;
274    }
275
276    /**
277     * @param RecordingAnnotations $recordingAnnotations
278     * @return null
279     * @since 0.1.0
280     */
281    public function visitRecordingAnnotations(
282        RecordingAnnotations $recordingAnnotations
283    ) {
284        $this->visitRoot( $recordingAnnotations );
285        return null;
286    }
287
288    /**
289     * @param RecordingReview $recordingReview
290     * @return null
291     * @since 0.1.0
292     */
293    public function visitRecordingReview(
294        RecordingReview $recordingReview
295    ) {
296        $this->visitRoot( $recordingReview );
297        return null;
298    }
299
300    /**
301     * @param SkippedManuscriptPrompt $skippedManuscriptPrompt
302     * @return null
303     * @since 0.1.0
304     */
305    public function visitSkippedManuscriptPrompt(
306        SkippedManuscriptPrompt $skippedManuscriptPrompt
307    ) {
308        $this->visitRoot( $skippedManuscriptPrompt );
309        return null;
310    }
311
312    /**
313     * @param User $user
314     * @return null
315     * @since 0.1.0
316     */
317    public function visitUser(
318        User $user
319    ) {
320        $this->visitRoot( $user );
321        return null;
322    }
323
324    /**
325     * @param UserDialect $userDialect
326     * @return null
327     * @since 0.1.0
328     */
329    public function visitUserDialect(
330        UserDialect $userDialect
331    ) {
332        $this->visitRoot( $userDialect );
333        return null;
334    }
335
336    /**
337     * @param UserLanguageProficiencyLevel $languageProficiencyLevel
338     * @return null
339     * @since 0.1.0
340     */
341    public function visitUserLanguageProficiencyLevel(
342        UserLanguageProficiencyLevel $languageProficiencyLevel
343    ) {
344        $this->visitRoot( $languageProficiencyLevel );
345        return null;
346    }
347
348}