]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/LinkCache.php
MediaWiki 1.17.4
[autoinstallsdev/mediawiki.git] / includes / LinkCache.php
1 <?php
2 /**
3  * Cache for article titles (prefixed DB keys) and ids linked from one source
4  *
5  * @ingroup Cache
6  */
7 class LinkCache {
8         // Increment $mClassVer whenever old serialized versions of this class
9         // becomes incompatible with the new version.
10         /* private */ var $mClassVer = 4;
11
12         /* private */ var $mGoodLinks, $mBadLinks;
13         /* private */ var $mForUpdate;
14
15         /**
16          * Get an instance of this class
17          */
18         static function &singleton() {
19                 static $instance;
20                 if ( !isset( $instance ) ) {
21                         $instance = new LinkCache;
22                 }
23                 return $instance;
24         }
25
26         function __construct() {
27                 $this->mForUpdate = false;
28                 $this->mGoodLinks = array();
29                 $this->mGoodLinkFields = array();
30                 $this->mBadLinks = array();
31         }
32
33         /**
34          * General accessor to get/set whether SELECT FOR UPDATE should be used
35          */
36         public function forUpdate( $update = null ) {
37                 return wfSetVar( $this->mForUpdate, $update );
38         }
39
40         public function getGoodLinkID( $title ) {
41                 if ( array_key_exists( $title, $this->mGoodLinks ) ) {
42                         return $this->mGoodLinks[$title];
43                 } else {
44                         return 0;
45                 }
46         }
47
48         /**
49          * Get a field of a title object from cache.
50          * If this link is not good, it will return NULL.
51          * @param $title Title
52          * @param $field String: ('length','redirect','revision')
53          * @return mixed
54          */
55         public function getGoodLinkFieldObj( $title, $field ) {
56                 $dbkey = $title->getPrefixedDbKey();
57                 if ( array_key_exists( $dbkey, $this->mGoodLinkFields ) ) {
58                         return $this->mGoodLinkFields[$dbkey][$field];
59                 } else {
60                         return null;
61                 }
62         }
63
64         public function isBadLink( $title ) {
65                 return array_key_exists( $title, $this->mBadLinks );
66         }
67
68         /**
69          * Add a link for the title to the link cache
70          *
71          * @param $id Integer: page's ID
72          * @param $title Title object
73          * @param $len Integer: text's length
74          * @param $redir Integer: whether the page is a redirect
75          * @param $revision Integer: latest revision's ID
76          */
77         public function addGoodLinkObj( $id, $title, $len = -1, $redir = null, $revision = false ) {
78                 $dbkey = $title->getPrefixedDbKey();
79                 $this->mGoodLinks[$dbkey] = intval( $id );
80                 $this->mGoodLinkFields[$dbkey] = array(
81                         'length' => intval( $len ),
82                         'redirect' => intval( $redir ),
83                         'revision' => intval( $revision ) );
84         }
85
86         public function addBadLinkObj( $title ) {
87                 $dbkey = $title->getPrefixedDbKey();
88                 if ( !$this->isBadLink( $dbkey ) ) {
89                         $this->mBadLinks[$dbkey] = 1;
90                 }
91         }
92
93         public function clearBadLink( $title ) {
94                 unset( $this->mBadLinks[$title] );
95         }
96
97         public function clearLink( $title ) {
98                 $dbkey = $title->getPrefixedDbKey();
99                 if( isset($this->mBadLinks[$dbkey]) ) {
100                         unset($this->mBadLinks[$dbkey]);
101                 }
102                 if( isset($this->mGoodLinks[$dbkey]) ) {
103                         unset($this->mGoodLinks[$dbkey]);
104                 }
105                 if( isset($this->mGoodLinkFields[$dbkey]) ) {
106                         unset($this->mGoodLinkFields[$dbkey]);
107                 }
108         }
109
110         public function getGoodLinks() { return $this->mGoodLinks; }
111         public function getBadLinks() { return array_keys( $this->mBadLinks ); }
112
113         /**
114          * Add a title to the link cache, return the page_id or zero if non-existent
115          *
116          * @param $title String: title to add
117          * @return Integer
118          */
119         public function addLink( $title ) {
120                 $nt = Title::newFromDBkey( $title );
121                 if( $nt ) {
122                         return $this->addLinkObj( $nt );
123                 } else {
124                         return 0;
125                 }
126         }
127
128         /**
129          * Add a title to the link cache, return the page_id or zero if non-existent
130          *
131          * @param $nt Title object to add
132          * @return Integer
133          */
134         public function addLinkObj( $nt ) {
135                 global $wgAntiLockFlags;
136                 wfProfileIn( __METHOD__ );
137
138                 $key = $nt->getPrefixedDBkey();
139                 if ( $this->isBadLink( $key ) ) {
140                         wfProfileOut( __METHOD__ );
141                         return 0;
142                 }
143                 $id = $this->getGoodLinkID( $key );
144                 if ( $id != 0 ) {
145                         wfProfileOut( __METHOD__ );
146                         return $id;
147                 }
148
149                 if ( $key === '' ) {
150                         wfProfileOut( __METHOD__ );
151                         return 0;
152                 }
153                 
154                 # Some fields heavily used for linking...
155                 if ( $this->mForUpdate ) {
156                         $db = wfGetDB( DB_MASTER );
157                         if ( !( $wgAntiLockFlags & ALF_NO_LINK_LOCK ) ) {
158                                 $options = array( 'FOR UPDATE' );
159                         } else {
160                                 $options = array();
161                         }
162                 } else {
163                         $db = wfGetDB( DB_SLAVE );
164                         $options = array();
165                 }
166
167                 $s = $db->selectRow( 'page', 
168                         array( 'page_id', 'page_len', 'page_is_redirect', 'page_latest' ),
169                         array( 'page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey() ),
170                         __METHOD__, $options );
171                 # Set fields...
172                 if ( $s !== false ) {
173                         $id = intval( $s->page_id );
174                         $len = intval( $s->page_len );
175                         $redirect = intval( $s->page_is_redirect );
176                         $revision = intval( $s->page_latest );
177                 } else {
178                         $id = 0;
179                         $len = -1;
180                         $redirect = 0;
181                         $revision = 0;
182                 }
183
184                 if ( $id == 0 ) {
185                         $this->addBadLinkObj( $nt );
186                 } else {
187                         $this->addGoodLinkObj( $id, $nt, $len, $redirect, $revision );
188                 }
189                 wfProfileOut( __METHOD__ );
190                 return $id;
191         }
192
193         /**
194          * Clears cache
195          */
196         public function clear() {
197                 $this->mGoodLinks = array();
198                 $this->mGoodLinkFields = array();
199                 $this->mBadLinks = array();
200         }
201 }