Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
92.98% |
53 / 57 |
|
66.67% |
4 / 6 |
CRAP | |
0.00% |
0 / 1 |
CognateRepo | |
92.98% |
53 / 57 |
|
66.67% |
4 / 6 |
11.04 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
setStatsdDataFactory | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
savePage | |
90.00% |
18 / 20 |
|
0.00% |
0 / 1 |
3.01 | |||
deletePage | |
77.78% |
7 / 9 |
|
0.00% |
0 / 1 |
3.10 | |||
getLinksForPage | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
2 | |||
invalidateAllSitesForPage | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace Cognate; |
4 | |
5 | use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface; |
6 | use MediaWiki\Linker\LinkTarget; |
7 | use MediaWiki\Title\TitleFormatter; |
8 | use Psr\Log\LoggerInterface; |
9 | use Wikimedia\Rdbms\DBReadOnlyError; |
10 | use Wikimedia\Stats\NullStatsdDataFactory; |
11 | use Wikimedia\Stats\StatsdAwareInterface; |
12 | |
13 | /** |
14 | * @license GPL-2.0-or-later |
15 | * @author Addshore |
16 | */ |
17 | class CognateRepo implements StatsdAwareInterface { |
18 | |
19 | /** |
20 | * @var CognateStore |
21 | */ |
22 | private $store; |
23 | |
24 | /** |
25 | * @var CacheInvalidator |
26 | */ |
27 | private $cacheInvalidator; |
28 | |
29 | /** |
30 | * @var TitleFormatter |
31 | */ |
32 | private $titleFormatter; |
33 | |
34 | /** |
35 | * @var LoggerInterface |
36 | */ |
37 | private $logger; |
38 | |
39 | /** |
40 | * @var StatsdDataFactoryInterface |
41 | */ |
42 | private $stats; |
43 | |
44 | /** |
45 | * @param CognateStore $store |
46 | * @param CacheInvalidator $cacheInvalidator |
47 | * @param TitleFormatter $titleFormatter |
48 | * @param LoggerInterface $logger |
49 | */ |
50 | public function __construct( |
51 | CognateStore $store, |
52 | CacheInvalidator $cacheInvalidator, |
53 | TitleFormatter $titleFormatter, |
54 | LoggerInterface $logger |
55 | ) { |
56 | $this->store = $store; |
57 | $this->cacheInvalidator = $cacheInvalidator; |
58 | $this->titleFormatter = $titleFormatter; |
59 | $this->logger = $logger; |
60 | $this->stats = new NullStatsdDataFactory(); |
61 | } |
62 | |
63 | /** |
64 | * @param StatsdDataFactoryInterface $statsFactory |
65 | */ |
66 | public function setStatsdDataFactory( StatsdDataFactoryInterface $statsFactory ) { |
67 | $this->stats = $statsFactory; |
68 | } |
69 | |
70 | /** |
71 | * @param string $dbName The dbName for the site |
72 | * @param LinkTarget $linkTarget |
73 | * |
74 | * @return bool |
75 | */ |
76 | public function savePage( $dbName, LinkTarget $linkTarget ) { |
77 | $this->stats->increment( 'Cognate.Repo.savePage' ); |
78 | |
79 | try { |
80 | $start = microtime( true ); |
81 | $success = $this->store->insertPage( $dbName, $linkTarget ); |
82 | $this->stats->timing( 'Cognate.Repo.savePage.time', 1000 * ( microtime( true ) - $start ) ); |
83 | $this->stats->gauge( 'Cognate.Repo.savePage.inserts', $success ); |
84 | } catch ( DBReadOnlyError $e ) { |
85 | return false; |
86 | } |
87 | |
88 | if ( $success ) { |
89 | $this->invalidateAllSitesForPage( $dbName, $linkTarget ); |
90 | } else { |
91 | $dbKey = $linkTarget->getDBkey(); |
92 | $namespace = $linkTarget->getNamespace(); |
93 | $this->logger->error( |
94 | 'Probable duplicate hash for dbKey: \'' . $dbKey . '\'', |
95 | [ |
96 | 'dbName' => $dbName, |
97 | 'namespace' => $namespace, |
98 | 'dbKey' => $dbKey, |
99 | ] |
100 | ); |
101 | } |
102 | |
103 | return (bool)$success; |
104 | } |
105 | |
106 | /** |
107 | * @param string $dbName The dbName for the site |
108 | * @param LinkTarget $linkTarget |
109 | * |
110 | * @return bool |
111 | */ |
112 | public function deletePage( $dbName, LinkTarget $linkTarget ) { |
113 | $this->stats->increment( 'Cognate.Repo.deletePage' ); |
114 | |
115 | try { |
116 | $start = microtime( true ); |
117 | $success = $this->store->deletePage( $dbName, $linkTarget ); |
118 | $this->stats->timing( 'Cognate.Repo.deletePage.time', 1000 * ( microtime( true ) - $start ) ); |
119 | } catch ( DBReadOnlyError $e ) { |
120 | return false; |
121 | } |
122 | |
123 | if ( $success ) { |
124 | $this->invalidateAllSitesForPage( $dbName, $linkTarget ); |
125 | } |
126 | |
127 | return $success; |
128 | } |
129 | |
130 | /** |
131 | * @param string $dbName The dbName of the site being linked from |
132 | * @param LinkTarget $linkTarget of the page the links should be retrieved for |
133 | * |
134 | * @return string[] interwiki links |
135 | */ |
136 | public function getLinksForPage( $dbName, LinkTarget $linkTarget ) { |
137 | $this->stats->increment( 'Cognate.Repo.getLinksForPage' ); |
138 | |
139 | $start = microtime( true ); |
140 | $linkDetails = $this->store->selectLinkDetailsForPage( $dbName, $linkTarget ); |
141 | $time = 1000 * ( microtime( true ) - $start ); |
142 | $this->stats->timing( 'Cognate.Repo.getLinksForPage.time', $time ); |
143 | |
144 | $links = []; |
145 | foreach ( $linkDetails as $data ) { |
146 | $links[] = $this->titleFormatter->formatTitle( |
147 | $data['namespaceID'], |
148 | $data['title'], |
149 | '', |
150 | $data['interwiki'] |
151 | ); |
152 | } |
153 | return $links; |
154 | } |
155 | |
156 | /** |
157 | * @param string $dbName |
158 | * @param LinkTarget $linkTarget |
159 | */ |
160 | private function invalidateAllSitesForPage( $dbName, LinkTarget $linkTarget ) { |
161 | $this->stats->increment( 'Cognate.Repo.selectSitesForPage' ); |
162 | |
163 | $start = microtime( true ); |
164 | $sites = $this->store->selectSitesForPage( $linkTarget ); |
165 | $time = 1000 * ( microtime( true ) - $start ); |
166 | $this->stats->timing( 'Cognate.Repo.selectSitesForPage.time', $time ); |
167 | |
168 | // In the case of a delete causing cache invalidations we need to add the local site |
169 | // back to the list as it has already been removed from the database. |
170 | $sites[] = $dbName; |
171 | $sites = array_values( array_unique( $sites ) ); |
172 | |
173 | $this->cacheInvalidator->invalidate( $sites, $linkTarget ); |
174 | } |
175 | |
176 | } |