Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
61.54% |
16 / 26 |
|
66.67% |
2 / 3 |
CRAP | |
0.00% |
0 / 1 |
SectionPositionCalculator | |
61.54% |
16 / 26 |
|
66.67% |
2 / 3 |
15.69 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
calculateSectionPosition | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
5 | |||
fetchAppendixTitles | |
16.67% |
2 / 12 |
|
0.00% |
0 / 1 |
13.26 |
1 | <?php |
2 | declare( strict_types = 1 ); |
3 | |
4 | namespace ContentTranslation\Service; |
5 | |
6 | use ContentTranslation\SiteMapper; |
7 | use MediaWiki\Http\HttpRequestFactory; |
8 | use MediaWiki\Json\FormatJson; |
9 | use MediaWiki\Title\Title; |
10 | |
11 | class SectionPositionCalculator { |
12 | private const APPENDIX_TITLES = [ |
13 | "en" => [ |
14 | "Works", |
15 | "Publications", |
16 | "Bibliography", |
17 | "Discography", |
18 | "Filmography", |
19 | "See also", |
20 | "Notes", |
21 | "Citations", |
22 | "References", |
23 | "Further reading", |
24 | "External links" |
25 | ], |
26 | "es" => [ |
27 | "Bibliografía", |
28 | "Referencias", |
29 | "Citas", |
30 | "Discografía", |
31 | "Filmografía", |
32 | "Notas", |
33 | "Publicaciones", |
34 | "Obra", |
35 | "Enlaces externos", |
36 | "Otras lecturas", |
37 | "Lecturas relacionadas", |
38 | "Véase también" |
39 | ], |
40 | "bn" => [ |
41 | "গ্রন্থপঞ্জী", |
42 | "গ্রন্থপঞ্জি", |
43 | "তথ্যাবলি", |
44 | "উদ্ধৃতিসমূহ", |
45 | "বর্ণনসমূহ", |
46 | "উদ্ধৃতি", |
47 | "উদ্ধ্বৃতি", |
48 | "তথ্যসূত্র", |
49 | "ডিস্কোগ্রাফি", |
50 | "বহিঃসংযোগ", |
51 | "চলচ্চিত্রের তালিকা", |
52 | "আরও পড়ুন", |
53 | "আরও পড়ুন", |
54 | "আরো পড়ুন", |
55 | "টীকা", |
56 | "নোট", |
57 | "প্রকাশনা", |
58 | "প্রকাশিত গ্রন্থ", |
59 | "আরও দেখুন", |
60 | "আরো দেখুন", |
61 | "কাজ", |
62 | "কর্মজীবন" |
63 | ], |
64 | "fr" => [ |
65 | "Bibliographie", |
66 | "Références", |
67 | "Discographie", |
68 | "Filmographie", |
69 | "Travaux", |
70 | "Liens externes", |
71 | "Principales publications", |
72 | "Voir aussi" |
73 | ], |
74 | "de" => [ |
75 | "Literatur", |
76 | "Bibliographie", |
77 | "Anmerkungen", |
78 | "Zitate", |
79 | "Belege", |
80 | "Diskografie", |
81 | "Diskographie", |
82 | "Weblinks", |
83 | "Filmografie", |
84 | "Literatur", |
85 | "Einzelnachweise", |
86 | "Veröffentlichungen", |
87 | "Einzelnachweise", |
88 | "Arbeit", |
89 | "Siehe auch" |
90 | ] |
91 | ]; |
92 | |
93 | private HttpRequestFactory $httpRequestFactory; |
94 | private SectionTitleFetcher $sectionTitleFetcher; |
95 | |
96 | public function __construct( HttpRequestFactory $httpRequestFactory, SectionTitleFetcher $sectionTitleFetcher ) { |
97 | $this->httpRequestFactory = $httpRequestFactory; |
98 | $this->sectionTitleFetcher = $sectionTitleFetcher; |
99 | } |
100 | |
101 | /** |
102 | * This method returns the appropriate number indicating the position in |
103 | * which the new section should be published inside the target page, |
104 | * according to the following logic: |
105 | * |
106 | * 1. If the section is being published to user's sandbox, then the section |
107 | * position should be "new" |
108 | * 2. If section is a lead section then its position should be equal to 0. |
109 | * 3. If the section is neither a sandbox section nor a lead section: |
110 | * a. If at least one appendix section exists then it equals to the |
111 | * index of the first appendix section (in order of appearance) |
112 | * b. If not, it's equal to "new". |
113 | * |
114 | * @param Title $targetTitle |
115 | * @param string $targetLanguage |
116 | * @param bool $isSandbox |
117 | * @return int|string |
118 | */ |
119 | public function calculateSectionPosition( Title $targetTitle, string $targetLanguage, bool $isSandbox ) { |
120 | $sectionPosition = "new"; |
121 | if ( $isSandbox ) { |
122 | return $sectionPosition; |
123 | } |
124 | |
125 | $targetSectionTitles = $this->sectionTitleFetcher->fetchSectionTitles( $targetLanguage, $targetTitle ); |
126 | |
127 | // if target sections are null, this page doesn't exist, and this is a lead section |
128 | if ( $targetSectionTitles === null ) { |
129 | return 0; |
130 | } |
131 | |
132 | if ( $targetSectionTitles ) { |
133 | $appendixTitles = $this->fetchAppendixTitles( $targetLanguage ); |
134 | |
135 | $targetAppendixTitles = array_intersect( $targetSectionTitles, $appendixTitles ); |
136 | if ( $targetAppendixTitles ) { |
137 | $sectionPosition = array_key_first( $targetAppendixTitles ); |
138 | } |
139 | } |
140 | return $sectionPosition; |
141 | } |
142 | |
143 | /** |
144 | * Given a target language code, this method returns an array of |
145 | * strings containing the appendix section titles for this language. |
146 | * |
147 | * @param string $targetLanguage |
148 | * @return string[] |
149 | */ |
150 | public function fetchAppendixTitles( string $targetLanguage ): array { |
151 | if ( isset( self::APPENDIX_TITLES[$targetLanguage] ) ) { |
152 | return self::APPENDIX_TITLES[$targetLanguage]; |
153 | } |
154 | |
155 | $baseUrl = "/suggest/sections/titles/en/$targetLanguage"; |
156 | $params = [ 'titles' => implode( '|', self::APPENDIX_TITLES['en'] ) ]; |
157 | $cxServerUrl = SiteMapper::getCXServerUrl( $baseUrl, $params ); |
158 | try { |
159 | $response = $this->httpRequestFactory->get( $cxServerUrl, [], __METHOD__ ); |
160 | } catch ( \Exception $exception ) { |
161 | return []; |
162 | } |
163 | |
164 | if ( !$response ) { |
165 | return []; |
166 | } |
167 | |
168 | $json = FormatJson::decode( $response, true ); |
169 | return array_merge( ...array_values( $json ) ); |
170 | } |
171 | } |