wfTimestampNow()->Database::timestamp()
[lhc/web/wiklou.git] / includes / LinksUpdate.php
1 <?php
2 /**
3 * See deferred.doc
4 */
5
6 /**
7 * @todo document
8 */
9 class LinksUpdate {
10
11 /* private */ var $mId, $mTitle;
12
13 function LinksUpdate( $id, $title )
14 {
15 $this->mId = $id;
16 $this->mTitle = $title;
17 }
18
19
20 function doUpdate()
21 {
22 global $wgUseBetterLinksUpdate, $wgLinkCache, $wgDBtransactions;
23 global $wgEnablePersistentLC, $wgUseCategoryMagic;
24
25 /* Update link tables with outgoing links from an updated article */
26 /* Relies on the 'link cache' to be filled out */
27
28 $fname = 'LinksUpdate::doUpdate';
29 wfProfileIn( $fname );
30
31 $del = array();
32 $add = array();
33
34 $dbw =& wfGetDB( DB_MASTER );
35 $links = $dbw->tableName( 'links' );
36 $brokenlinks = $dbw->tableName( 'brokenlinks' );
37 $imagelinks = $dbw->tableName( 'imagelinks' );
38 $categorylinks = $dbw->tableName( 'categorylinks' );
39
40 #------------------------------------------------------------------------------
41 # Good links
42
43 if ( $wgLinkCache->incrementalSetup( LINKCACHE_GOOD, $del, $add ) ) {
44 # Delete where necessary
45 if ( count( $del ) ) {
46 $sql = "DELETE FROM $links WHERE l_from={$this->mId} AND l_to IN(".
47 implode( ',', $del ) . ')';
48 $dbw->query( $sql, $fname );
49 }
50 } else {
51 # Delete everything
52 $dbw->delete( 'links', array( 'l_from' => $this->mId ), $fname );
53
54 # Get the addition list
55 $add = $wgLinkCache->getGoodLinks();
56 }
57
58 # Do the insertion
59 if ( 0 != count( $add ) ) {
60 $arr=array();
61 foreach($add as $lt=>$lid)
62 array_push($arr,array(
63 'l_from'=>$this->mId,
64 'l_to'=>$lid));
65 # The link cache was constructed without FOR UPDATE, so there may be collisions
66 # Ignoring for now, I'm not sure if that causes problems or not, but I'm fairly
67 # sure it's better than without IGNORE
68 $dbw->insertArray('links', $arr, $fname, array('IGNORE'));
69 }
70
71 #------------------------------------------------------------------------------
72 # Bad links
73
74 if ( $wgLinkCache->incrementalSetup( LINKCACHE_BAD, $del, $add ) ) {
75 # Delete where necessary
76 if ( count( $del ) ) {
77 $sql = "DELETE FROM $brokenlinks WHERE bl_from={$this->mId} AND bl_to IN(";
78 $first = true;
79 foreach( $del as $badTitle ) {
80 if ( $first ) {
81 $first = false;
82 } else {
83 $sql .= ',';
84 }
85 $sql .= $dbw->addQuotes( $badTitle );
86 }
87 $sql .= ')';
88 $dbw->query( $sql, $fname );
89 }
90 } else {
91 # Delete all
92 $dbw->delete( 'brokenlinks', array( 'bl_from' => $this->mId ) );
93
94 # Get addition list
95 $add = $wgLinkCache->getBadLinks();
96 }
97
98 # Do additions
99 $sql = '';
100 if ( 0 != count ( $add ) ) {
101 $arr=array();
102 foreach( $add as $blt ) {
103 $blt = $dbw->strencode( $blt );
104 array_push($arr,array(
105 'bl_from'=>$this->mId,
106 'bl_to'=>$blt));
107 }
108 $dbw->insertArray( 'brokenlinks',$arr,$fname,array('IGNORE'));
109 }
110
111 #------------------------------------------------------------------------------
112 # Image links
113 $sql = "DELETE FROM $imagelinks WHERE il_from='{$this->mId}'";
114 $dbw->query( $sql, $fname );
115
116 # Get addition list
117 $add = $wgLinkCache->getImageLinks();
118
119 # Do the insertion
120 $sql = '';
121 $image = Namespace::getImage();
122 if ( 0 != count ( $add ) ) {
123 $arr = array();
124 foreach ($add as $iname => $val ) {
125 $nt = Title::makeTitle( $image, $iname );
126 if( !$nt ) continue;
127 $nt->invalidateCache();
128 $iname = $dbw->strencode( $iname );
129 array_push($arr,array(
130 'il_from'=>$this->mId,
131 'il_to'=>$iname));
132 }
133 $dbw->insertArray($imagelinks, $arr, $fname, array('IGNORE'));
134 }
135
136 #------------------------------------------------------------------------------
137 # Category links
138 if( $wgUseCategoryMagic ) {
139 $sql = "DELETE FROM $categorylinks WHERE cl_from='{$this->mId}'";
140 $dbw->query( $sql, $fname );
141
142 # Get addition list
143 $add = $wgLinkCache->getCategoryLinks();
144
145 # Do the insertion
146 $sql = '';
147 if ( 0 != count ( $add ) ) {
148 $arr=array();
149 foreach( $add as $cname => $sortkey ) {
150 $nt = Title::makeTitle( NS_CATEGORY, $cname );
151 if( !$nt ) continue;
152 $nt->invalidateCache();
153 array_push($arr,array(
154 'cl_from'=>$this->mId,
155 'cl_to'=>$dbw->strencode( $cname ),
156 'cl_sortkey'=>$dbw->strencode( $sortkey )));
157 }
158 $dbw->insertArray($categorylinks,$arr,$fname,array('IGNORE'));
159 }
160 }
161
162 $this->fixBrokenLinks();
163
164 wfProfileOut( $fname );
165 }
166
167 function doDumbUpdate()
168 {
169 # Old inefficient update function
170 # Used for rebuilding the link table
171 global $wgLinkCache, $wgDBtransactions, $wgUseCategoryMagic;
172 $fname = 'LinksUpdate::doDumbUpdate';
173 wfProfileIn( $fname );
174
175
176 $dbw =& wfGetDB( DB_MASTER );
177 $links = $dbw->tableName( 'links' );
178 $brokenlinks = $dbw->tableName( 'brokenlinks' );
179 $imagelinks = $dbw->tableName( 'imagelinks' );
180 $categorylinks = $dbw->tableName( 'categorylinks' );
181
182 $sql = "DELETE FROM $links WHERE l_from={$this->mId}";
183 $dbw->query( $sql, $fname );
184
185 $a = $wgLinkCache->getGoodLinks();
186 if ( 0 != count( $a ) ) {
187 $arr=array();
188 foreach( $a as $lt => $lid ) {
189 array_push($arr,array(
190 'l_from'=>$this->mId,
191 'l_to'=>$lid));
192 }
193 $dbw->insertArray($links,$arr,$fname,array('IGNORE'));
194 }
195
196 $sql = "DELETE FROM $brokenlinks WHERE bl_from={$this->mId}";
197 $dbw->query( $sql, $fname );
198
199 $a = $wgLinkCache->getBadLinks();
200 if ( 0 != count ( $a ) ) {
201 $arr=array();
202 foreach( $a as $blt ) {
203 $blt = $dbw->strencode( $blt );
204 array_push($arr,array(
205 'bl_from'=>$this->mId,
206 'bl_to'=>$blt));
207 }
208 $dbw->insertArray($brokenlinks,$arr,$fname,array('IGNORE'));
209 }
210
211 $sql = "DELETE FROM $imagelinks WHERE il_from={$this->mId}";
212 $dbw->query( $sql, $fname );
213
214 $a = $wgLinkCache->getImageLinks();
215 $sql = '';
216 if ( 0 != count ( $a ) ) {
217 $arr=array();
218 foreach( $a as $iname => $val )
219 array_push($arr,array(
220 'il_from'=>$this->mId,
221 'il_to'=>$dbw->strencode( $iname )));
222 $dbw->insertArray($imagelinks,$arr,$fname,array('IGNORE'));
223 }
224
225 if( $wgUseCategoryMagic ) {
226 $sql = "DELETE FROM $categorylinks WHERE cl_from='{$this->mId}'";
227 $dbw->query( $sql, $fname );
228
229 # Get addition list
230 $add = $wgLinkCache->getCategoryLinks();
231
232 # Do the insertion
233 $sql = '';
234 if ( 0 != count ( $add ) ) {
235 $arr=array();
236 foreach( $add as $cname => $sortkey ) {
237 # FIXME: Change all this to avoid unnecessary duplication
238 $nt = Title::makeTitle( NS_CATEGORY, $cname );
239 if( !$nt ) continue;
240 $nt->invalidateCache();
241 array_push($arr,array(
242 'cl_from'=>$this->mId,
243 'cl_to'=>$dbw->strencode( $cname ),
244 'cl_sortkey'=>$dbw->strencode( $sortkey )));
245 }
246 $dbw->insertArray($categorylinks,$arr,$fname,array('IGNORE'));
247 }
248 }
249 $this->fixBrokenLinks();
250 wfProfileOut( $fname );
251 }
252
253 function fixBrokenLinks() {
254 /* Update any brokenlinks *to* this page */
255 /* Call for a newly created page, or just to make sure state is consistent */
256 $fname = 'LinksUpdate::fixBrokenLinks';
257
258 $dbw =& wfGetDB( DB_MASTER );
259 $cur = $dbw->tableName( 'cur' );
260 $links = $dbw->tableName( 'links' );
261
262 $res = $dbw->select( 'brokenlinks', array( 'bl_from' ), array( 'bl_to' => $this->mTitle ),
263 $fname, 'FOR UPDATE' );
264 if ( 0 == $dbw->numRows( $res ) ) { return; }
265
266 # Ignore errors. If a link existed in both the brokenlinks table and the links
267 # table, that's an error which can be fixed at this stage by simply ignoring collisions
268 $arr=array();
269 $now = $dbw->timestamp();
270 $sql2 = "UPDATE $cur SET cur_touched='{$now}' WHERE cur_id IN (";
271 $first = true;
272 while ( $row = $dbw->fetchObject( $res ) ) {
273 if ( ! $first ) { $sql2 .= ","; }
274 $first = false;
275 array_push($arr,array('l_from'=>$row->bl_from,'l_to'=>$this->mId));
276 $sql2 .= $row->bl_from;
277 }
278 $sql2 .= ')';
279 $dbw->insertArray($links,$arr,$fname,array('IGNORE'));
280 $dbw->query( $sql2, $fname );
281 $dbw->delete( 'brokenlinks', array( 'bl_to' => $this->mTitle ), $fname );
282 }
283 }
284
285 ?>