Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
EntityUpdaterLexemeUpdater
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
7 / 7
19
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 create
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 update
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 generateStatementIdsForFormsAndSenses
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
7
 storeLexeme
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
5
 convertEditMetadata
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 convertToLexemeRevision
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
1<?php declare( strict_types = 1 );
2
3namespace Wikibase\Lexeme\DataAccess\Store;
4
5use InvalidArgumentException;
6use Wikibase\DataModel\Services\Statement\GuidGenerator;
7use Wikibase\Lexeme\DataAccess\CrudEditSummaryAdapter;
8use Wikibase\Lexeme\Domain\Model\EditMetadata;
9use Wikibase\Lexeme\Domain\Model\Exceptions\EditPrevented;
10use Wikibase\Lexeme\Domain\Model\Exceptions\RateLimitReached;
11use Wikibase\Lexeme\Domain\Model\Exceptions\ResourceTooLargeException;
12use Wikibase\Lexeme\Domain\Model\Exceptions\TempAccountCreationLimitReached;
13use Wikibase\Lexeme\Domain\Model\Lexeme as LexemeWriteModel;
14use Wikibase\Lexeme\Domain\Model\ReadModel\LexemeRevision;
15use Wikibase\Lexeme\Domain\Services\LexemeCreator;
16use Wikibase\Lexeme\Domain\Services\LexemeUpdater;
17use Wikibase\Lib\Store\EntityRevision;
18use Wikibase\Repo\Domains\Crud\Domain\Model\EditMetadata as CrudEditMetadata;
19use Wikibase\Repo\Domains\Crud\Domain\Services\Exceptions\EditPrevented as CrudEditPrevented;
20use Wikibase\Repo\Domains\Crud\Domain\Services\Exceptions\RateLimitReached as CrudRateLimitReached;
21use Wikibase\Repo\Domains\Crud\Domain\Services\Exceptions\ResourceTooLargeException as CrudResourceTooLargeException;
22use Wikibase\Repo\Domains\Crud\Domain\Services\Exceptions\TempAccountCreationLimitReached as CrudTempAccountException;
23use Wikibase\Repo\Domains\Crud\Infrastructure\DataAccess\EntityUpdater;
24
25/**
26 * @license GPL-2.0-or-later
27 */
28class EntityUpdaterLexemeUpdater implements LexemeCreator, LexemeUpdater {
29
30    public function __construct(
31        private EntityUpdater $entityUpdater,
32        private LexemeReadModelConverter $lexemeReadModelConverter,
33        private GuidGenerator $guidGenerator,
34    ) {
35    }
36
37    /**
38     * @inheritDoc
39     */
40    public function create( LexemeWriteModel $lexeme, EditMetadata $editMetadata ): LexemeRevision {
41        if ( $lexeme->getId() ) {
42            throw new InvalidArgumentException( 'New Lexeme must not have an ID' );
43        }
44
45        return $this->storeLexeme( fn () => $this->entityUpdater->create(
46            $lexeme,
47            $this->convertEditMetadata( $editMetadata ),
48        ) );
49    }
50
51    /**
52     * @inheritDoc
53     */
54    public function update( LexemeWriteModel $lexeme, EditMetadata $editMetadata ): LexemeRevision {
55        if ( !$lexeme->getId() ) {
56            throw new InvalidArgumentException( 'Cannot update a Lexeme without an ID' );
57        }
58        $this->generateStatementIdsForFormsAndSenses( $lexeme );
59
60        return $this->storeLexeme( fn () => $this->entityUpdater->update(
61            $lexeme,
62            $this->convertEditMetadata( $editMetadata ),
63        ) );
64    }
65
66    /**
67     * EntityUpdater only generates IDs for the statements of the Lexeme itself,
68     * so the statements of its Forms and Senses are dealt with here.
69     */
70    private function generateStatementIdsForFormsAndSenses( LexemeWriteModel $lexeme ): void {
71        foreach ( $lexeme->getForms()->toArray() as $form ) {
72            foreach ( $form->getStatements() as $statement ) {
73                if ( $statement->getGuid() === null ) {
74                    $statement->setGuid( $this->guidGenerator->newGuid( $form->getId() ) );
75                }
76            }
77        }
78
79        foreach ( $lexeme->getSenses()->toArray() as $sense ) {
80            foreach ( $sense->getStatements() as $statement ) {
81                if ( $statement->getGuid() === null ) {
82                    $statement->setGuid( $this->guidGenerator->newGuid( $sense->getId() ) );
83                }
84            }
85        }
86    }
87
88    /**
89     * @throws TempAccountCreationLimitReached
90     * @throws ResourceTooLargeException
91     * @throws RateLimitReached
92     * @throws EditPrevented
93     */
94    private function storeLexeme( callable $attemptStoringLexeme ): LexemeRevision {
95        try {
96            $entityRevision = $attemptStoringLexeme();
97        } catch ( CrudTempAccountException ) {
98            throw new TempAccountCreationLimitReached();
99        } catch ( CrudResourceTooLargeException $e ) {
100            throw new ResourceTooLargeException( $e->getResourceSizeLimit() );
101        } catch ( CrudRateLimitReached ) {
102            throw new RateLimitReached();
103        } catch ( CrudEditPrevented $e ) {
104            throw new EditPrevented( $e->getReason(), $e->getContext() );
105        }
106
107        return $this->convertToLexemeRevision( $entityRevision );
108    }
109
110    private function convertEditMetadata( EditMetadata $editMetadata ): CrudEditMetadata {
111        return new CrudEditMetadata(
112            $editMetadata->tags,
113            $editMetadata->isBot,
114            new CrudEditSummaryAdapter( $editMetadata->editSummary ),
115        );
116    }
117
118    private function convertToLexemeRevision( EntityRevision $entityRevision ): LexemeRevision {
119        /** @var LexemeWriteModel $lexeme */
120        $lexeme = $entityRevision->getEntity();
121        '@phan-var LexemeWriteModel $lexeme';
122
123        return new LexemeRevision(
124            $this->lexemeReadModelConverter->convert( $lexeme ),
125            $entityRevision->getRevisionId(),
126            $entityRevision->getTimestamp(),
127        );
128    }
129
130}