21 * Initialize private variables
23 * @param string $title
25 function LinksUpdate( $id, $title ) {
27 $this->mTitle
= $title;
31 * Update link tables with outgoing links from an updated article
32 * Relies on the 'link cache' to be filled out.
36 global $wgUseDumbLinkUpdate, $wgLinkCache, $wgDBtransactions;
37 global $wgEnablePersistentLC, $wgUseCategoryMagic;
39 if ( $wgUseDumbLinkUpdate ) {
40 $this->doDumbUpdate();
44 $fname = 'LinksUpdate::doUpdate';
45 wfProfileIn( $fname );
50 $dbw =& wfGetDB( DB_MASTER
);
51 $pagelinks = $dbw->tableName( 'pagelinks' );
52 $imagelinks = $dbw->tableName( 'imagelinks' );
53 $categorylinks = $dbw->tableName( 'categorylinks' );
55 #------------------------------------------------------------------------------
58 if ( $wgLinkCache->incrementalSetup( LINKCACHE_PAGE
, $del, $add ) ) {
59 # Delete where necessary
60 if ( count( $del ) ) {
61 $batch = new LinkBatch( $del );
62 $set = $batch->constructSet( 'pl', $dbw );
64 $sql = "DELETE FROM $pagelinks WHERE pl_from={$this->mId} AND ($set)";
65 $dbw->query( $sql, $fname );
70 $dbw->delete( 'pagelinks', array( 'pl_from' => $this->mId
), $fname );
72 # Get the addition list
73 $add = $wgLinkCache->getGoodLinks();
77 if( 0 != count( $add ) ) {
79 foreach( $add as $lt => $target ) {
80 array_push( $arr, array(
81 'pl_from' => $this->mId
,
82 'pl_namespace' => $target->getNamespace(),
83 'pl_title' => $target->getDbKey() ) );
86 # The link cache was constructed without FOR UPDATE, so there may be collisions
87 # Ignoring for now, I'm not sure if that causes problems or not, but I'm fairly
88 # sure it's better than without IGNORE
89 $dbw->insert( 'pagelinks', $arr, $fname, array( 'IGNORE' ) );
92 #------------------------------------------------------------------------------
94 $dbw->delete('imagelinks',array('il_from'=>$this->mId
),$fname);
97 $add = $wgLinkCache->getImageLinks();
102 if ( 0 != count ( $add ) ) {
104 foreach ($add as $iname => $val ) {
105 $nt = Title
::makeTitle( $image, $iname );
107 $nt->invalidateCache();
108 array_push( $arr, array(
109 'il_from' => $this->mId
,
110 'il_to' => $iname ) );
112 $dbw->insert('imagelinks', $arr, $fname, array('IGNORE'));
115 #------------------------------------------------------------------------------
117 if( $wgUseCategoryMagic ) {
118 global $messageMemc, $wgDBname;
121 $add = $wgLinkCache->getCategoryLinks();
123 # select existing catlinks for this page
124 $res = $dbw->select( 'categorylinks',
125 array( 'cl_to', 'cl_sortkey' ),
126 array( 'cl_from' => $this->mId
),
131 if( 0 != $dbw->numRows( $res ) ) {
132 while( $row = $dbw->fetchObject( $res ) ) {
133 if( !isset( $add[$row->cl_to
] ) ||
$add[$row->cl_to
] != $row->cl_sortkey
) {
134 // in the db, but no longer in the page
135 // or sortkey has changed -> delete
136 $del[] = $row->cl_to
;
138 // remove already existing category memberships
139 // from the add array
140 unset( $add[$row->cl_to
] );
145 // delete any removed categorylinks
146 if( count( $del ) > 0) {
148 $dbw->delete( 'categorylinks',
150 'cl_from' => $this->mId
,
153 foreach( $del as $cname ){
154 $nt = Title
::makeTitle( NS_CATEGORY
, $cname );
155 $nt->invalidateCache();
156 // update the timestamp which indicates when the last article
157 // was added or removed to/from this article
158 $key = $wgDBname . ':Category:' . md5( $nt->getDBkey() ) . ':adddeltimestamp';
159 $messageMemc->set( $key , wfTimestamp( TS_MW
), 24*3600 );
163 // add any new category memberships
164 if( count( $add ) > 0 ) {
166 foreach( $add as $cname => $sortkey ) {
167 $nt = Title
::makeTitle( NS_CATEGORY
, $cname );
168 $nt->invalidateCache();
169 // update the timestamp which indicates when the last article
170 // was added or removed to/from this article
171 $key = $wgDBname . ':Category:' . md5( $nt->getDBkey() ) . ':adddeltimestamp';
172 $messageMemc->set( $key , wfTimestamp( TS_MW
), 24*3600 );
173 array_push( $arr, array(
174 'cl_from' => $this->mId
,
176 'cl_sortkey' => $sortkey ) );
178 // do the actual sql insertion
179 $dbw->insert( 'categorylinks', $arr, $fname, array( 'IGNORE' ) );
183 wfProfileOut( $fname );
187 * Link update which clears the previous entries and inserts new ones
188 * May be slower or faster depending on level of lock contention and write speed of DB
189 * Also useful where link table corruption needs to be repaired, e.g. in refreshLinks.php
191 function doDumbUpdate() {
192 global $wgLinkCache, $wgDBtransactions, $wgUseCategoryMagic;
193 $fname = 'LinksUpdate::doDumbUpdate';
194 wfProfileIn( $fname );
197 $dbw =& wfGetDB( DB_MASTER
);
198 $pagelinks = $dbw->tableName( 'pagelinks' );
199 $imagelinks = $dbw->tableName( 'imagelinks' );
200 $categorylinks = $dbw->tableName( 'categorylinks' );
202 $dbw->delete('pagelinks', array('pl_from'=>$this->mId
),$fname);
204 $a = $wgLinkCache->getPageLinks();
205 if ( 0 != count( $a ) ) {
207 foreach( $a as $lt => $target ) {
208 array_push( $arr, array(
209 'pl_from' => $this->mId
,
210 'pl_namespace' => $target->getNamespace(),
211 'pl_title' => $target->getDBkey() ) );
213 $dbw->insert( 'pagelinks', $arr, $fname, array( 'IGNORE' ) );
216 $dbw->delete('imagelinks', array('il_from'=>$this->mId
),$fname);
218 $a = $wgLinkCache->getImageLinks();
220 if ( 0 != count ( $a ) ) {
222 foreach( $a as $iname => $val )
223 array_push( $arr, array(
224 'il_from' => $this->mId
,
225 'il_to' => $iname ) );
226 $dbw->insert( 'imagelinks', $arr, $fname, array( 'IGNORE' ) );
229 if( $wgUseCategoryMagic ) {
230 $dbw->delete('categorylinks', array('cl_from'=>$this->mId
),$fname);
233 $add = $wgLinkCache->getCategoryLinks();
237 if ( 0 != count ( $add ) ) {
239 foreach( $add as $cname => $sortkey ) {
240 # FIXME: Change all this to avoid unnecessary duplication
241 $nt = Title
::makeTitle( NS_CATEGORY
, $cname );
243 $nt->invalidateCache();
244 array_push( $arr, array(
245 'cl_from' => $this->mId
,
247 'cl_sortkey' => $sortkey ) );
249 $dbw->insert( 'categorylinks', $arr, $fname, array( 'IGNORE' ) );
252 wfProfileOut( $fname );