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, $wgUseCategoryMagic;
38 if ( $wgUseDumbLinkUpdate ) {
39 $this->doDumbUpdate();
43 $fname = 'LinksUpdate::doUpdate';
44 wfProfileIn( $fname );
49 $dbw =& wfGetDB( DB_MASTER
);
50 $pagelinks = $dbw->tableName( 'pagelinks' );
51 $imagelinks = $dbw->tableName( 'imagelinks' );
52 $categorylinks = $dbw->tableName( 'categorylinks' );
54 #------------------------------------------------------------------------------
57 if ( $wgLinkCache->incrementalSetup( LINKCACHE_PAGE
, $del, $add ) ) {
58 # Delete where necessary
59 if ( count( $del ) ) {
60 $batch = new LinkBatch( $del );
61 $set = $batch->constructSet( 'pl', $dbw );
63 $sql = "DELETE FROM $pagelinks WHERE pl_from={$this->mId} AND ($set)";
64 $dbw->query( $sql, $fname );
69 $dbw->delete( 'pagelinks', array( 'pl_from' => $this->mId
), $fname );
71 # Get the addition list
72 $add = $wgLinkCache->getPageLinks();
76 if( 0 != count( $add ) ) {
78 foreach( $add as $lt => $target ) {
79 array_push( $arr, array(
80 'pl_from' => $this->mId
,
81 'pl_namespace' => $target->getNamespace(),
82 'pl_title' => $target->getDbKey() ) );
85 # The link cache was constructed without FOR UPDATE, so there may be collisions
86 # Ignoring for now, I'm not sure if that causes problems or not, but I'm fairly
87 # sure it's better than without IGNORE
88 $dbw->insert( 'pagelinks', $arr, $fname, array( 'IGNORE' ) );
91 #------------------------------------------------------------------------------
93 $dbw->delete('imagelinks',array('il_from'=>$this->mId
),$fname);
96 $add = $wgLinkCache->getImageLinks();
101 if ( 0 != count ( $add ) ) {
103 foreach ($add as $iname => $val ) {
104 $nt = Title
::makeTitle( $image, $iname );
106 $nt->invalidateCache();
107 array_push( $arr, array(
108 'il_from' => $this->mId
,
109 'il_to' => $iname ) );
111 $dbw->insert('imagelinks', $arr, $fname, array('IGNORE'));
114 #------------------------------------------------------------------------------
116 if( $wgUseCategoryMagic ) {
117 global $messageMemc, $wgDBname;
120 $add = $wgLinkCache->getCategoryLinks();
122 # select existing catlinks for this page
123 $res = $dbw->select( 'categorylinks',
124 array( 'cl_to', 'cl_sortkey' ),
125 array( 'cl_from' => $this->mId
),
130 if( 0 != $dbw->numRows( $res ) ) {
131 while( $row = $dbw->fetchObject( $res ) ) {
132 if( !isset( $add[$row->cl_to
] ) ||
$add[$row->cl_to
] != $row->cl_sortkey
) {
133 // in the db, but no longer in the page
134 // or sortkey has changed -> delete
135 $del[] = $row->cl_to
;
137 // remove already existing category memberships
138 // from the add array
139 unset( $add[$row->cl_to
] );
144 // delete any removed categorylinks
145 if( count( $del ) > 0) {
147 $dbw->delete( 'categorylinks',
149 'cl_from' => $this->mId
,
152 foreach( $del as $cname ){
153 $nt = Title
::makeTitle( NS_CATEGORY
, $cname );
154 $nt->invalidateCache();
155 // update the timestamp which indicates when the last article
156 // was added or removed to/from this article
157 $key = $wgDBname . ':Category:' . md5( $nt->getDBkey() ) . ':adddeltimestamp';
158 $messageMemc->set( $key , wfTimestamp( TS_MW
), 24*3600 );
162 // add any new category memberships
163 if( count( $add ) > 0 ) {
165 foreach( $add as $cname => $sortkey ) {
166 $nt = Title
::makeTitle( NS_CATEGORY
, $cname );
167 $nt->invalidateCache();
168 // update the timestamp which indicates when the last article
169 // was added or removed to/from this article
170 $key = $wgDBname . ':Category:' . md5( $nt->getDBkey() ) . ':adddeltimestamp';
171 $messageMemc->set( $key , wfTimestamp( TS_MW
), 24*3600 );
172 array_push( $arr, array(
173 'cl_from' => $this->mId
,
175 'cl_sortkey' => $sortkey ) );
177 // do the actual sql insertion
178 $dbw->insert( 'categorylinks', $arr, $fname, array( 'IGNORE' ) );
182 wfProfileOut( $fname );
186 * Link update which clears the previous entries and inserts new ones
187 * May be slower or faster depending on level of lock contention and write speed of DB
188 * Also useful where link table corruption needs to be repaired, e.g. in refreshLinks.php
190 function doDumbUpdate() {
191 global $wgLinkCache, $wgUseCategoryMagic;
192 $fname = 'LinksUpdate::doDumbUpdate';
193 wfProfileIn( $fname );
196 $dbw =& wfGetDB( DB_MASTER
);
197 $pagelinks = $dbw->tableName( 'pagelinks' );
198 $imagelinks = $dbw->tableName( 'imagelinks' );
199 $categorylinks = $dbw->tableName( 'categorylinks' );
201 $dbw->delete('pagelinks', array('pl_from'=>$this->mId
),$fname);
203 $a = $wgLinkCache->getPageLinks();
204 if ( 0 != count( $a ) ) {
206 foreach( $a as $lt => $target ) {
207 array_push( $arr, array(
208 'pl_from' => $this->mId
,
209 'pl_namespace' => $target->getNamespace(),
210 'pl_title' => $target->getDBkey() ) );
212 $dbw->insert( 'pagelinks', $arr, $fname, array( 'IGNORE' ) );
215 $dbw->delete('imagelinks', array('il_from'=>$this->mId
),$fname);
217 $a = $wgLinkCache->getImageLinks();
219 if ( 0 != count ( $a ) ) {
221 foreach( $a as $iname => $val )
222 array_push( $arr, array(
223 'il_from' => $this->mId
,
224 'il_to' => $iname ) );
225 $dbw->insert( 'imagelinks', $arr, $fname, array( 'IGNORE' ) );
228 if( $wgUseCategoryMagic ) {
229 $dbw->delete('categorylinks', array('cl_from'=>$this->mId
),$fname);
232 $add = $wgLinkCache->getCategoryLinks();
236 if ( 0 != count ( $add ) ) {
238 foreach( $add as $cname => $sortkey ) {
239 # FIXME: Change all this to avoid unnecessary duplication
240 $nt = Title
::makeTitle( NS_CATEGORY
, $cname );
242 $nt->invalidateCache();
243 array_push( $arr, array(
244 'cl_from' => $this->mId
,
246 'cl_sortkey' => $sortkey ) );
248 $dbw->insert( 'categorylinks', $arr, $fname, array( 'IGNORE' ) );
251 wfProfileOut( $fname );