Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
TranslatableBundle
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
20
0.00% covered (danger)
0.00%
0 / 1
 getTitle
n/a
0 / 0
n/a
0 / 0
0
 getMessageGroupId
n/a
0 / 0
n/a
0 / 0
0
 getTranslationPages
n/a
0 / 0
n/a
0 / 0
0
 getTranslationUnitPages
n/a
0 / 0
n/a
0 / 0
0
 isMoveable
n/a
0 / 0
n/a
0 / 0
0
 isDeletable
n/a
0 / 0
n/a
0 / 0
0
 getTranslationUnitPagesByTitle
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\MessageGroupProcessing;
5
6use MediaWiki\Extension\Translate\MessageLoading\MessageHandle;
7use MediaWiki\MediaWikiServices;
8use MediaWiki\Page\PageReference;
9use MediaWiki\Title\Title;
10
11/**
12 * Translatable bundle represents a message group where its translatable content is
13 * defined on a wiki page.
14 *
15 * This interface was created to support moving message bundles using the code developed for
16 * moving translatable pages.
17 *
18 * See also WikiMessageGroup which is not considered to be a translatable bundle.
19 * @author Abijeet Patro
20 * @author Niklas Laxström
21 * @since 2022.03
22 * @license GPL-2.0-or-later
23 */
24abstract class TranslatableBundle {
25    /** Return the title of the page where the translatable bundle is defined */
26    abstract public function getTitle(): Title;
27
28    /**
29     * Return the message group id for the bundle
30     * Note that the message group id may refer to a message group that does not exist.
31     */
32    abstract public function getMessageGroupId(): string;
33
34    /**
35     * Return the available translation pages for the bundle
36     * @see Translation page: https://www.mediawiki.org/wiki/Help:Extension:Translate/Glossary
37     * @return Title[]
38     */
39    abstract public function getTranslationPages(): array;
40
41    /**
42     * Return the available translation units for the bundle
43     * @see Translation unit: https://www.mediawiki.org/wiki/Help:Extension:Translate/Glossary
44     * @return Title[]
45     */
46    abstract public function getTranslationUnitPages( ?string $code = null ): array;
47
48    /** Check if this translatable bundle is moveable */
49    abstract public function isMoveable(): bool;
50
51    /** Check if this is a deletable translatable bundle */
52    abstract public function isDeletable(): bool;
53
54    protected function getTranslationUnitPagesByTitle( PageReference $title, ?string $code = null ): array {
55        $mwServices = MediaWikiServices::getInstance();
56
57        $dbw = $mwServices->getDBLoadBalancer()->getConnection( DB_PRIMARY );
58        $base = $mwServices->getTitleFormatter()->getPrefixedDBkey( $title );
59        // Including the / used as separator
60        $baseLength = strlen( $base ) + 1;
61
62        if ( $code === null ) {
63            $like = $dbw->buildLike( "$base/", $dbw->anyString() );
64        } else {
65            $like = $dbw->buildLike( "$base/", $dbw->anyString(), "/$code" );
66        }
67
68        $res = $dbw->newSelectQueryBuilder()
69            ->select( [ 'page_namespace', 'page_title' ] )
70            ->from( 'page' )
71            ->where( [
72                'page_namespace' => NS_TRANSLATIONS,
73                'page_title ' . $like
74            ] )
75            ->caller( __METHOD__ )
76            ->fetchResultSet();
77
78        // Only include pages which belong to this translatable page.
79        // Problematic cases are when pages Foo and Foo/bar are both
80        // translatable. Then when querying for Foo, we also get units
81        // belonging to Foo/bar.
82        $units = [];
83        foreach ( $res as $row ) {
84            $title = Title::newFromRow( $row );
85
86            // Strip the language code and the name of the
87            // translatable to get plain translation unit id
88            $handle = new MessageHandle( $title );
89            $key = substr( $handle->getKey(), $baseLength );
90            if ( str_contains( $key, '/' ) ) {
91                // Probably belongs to translatable subpage
92                continue;
93            }
94
95            // We have a match :)
96            $units[] = $title;
97        }
98
99        return $units;
100    }
101}