00001 <?php
00002
00003 if( !defined( 'MEDIAWIKI' ) )
00004 die;
00005
00006 class ChangeTags {
00007 static function formatSummaryRow( $tags, $page ) {
00008 if( !$tags )
00009 return array( '', array() );
00010
00011 $classes = array();
00012
00013 $tags = explode( ',', $tags );
00014 $displayTags = array();
00015 foreach( $tags as $tag ) {
00016 $displayTags[] = Xml::tags(
00017 'span',
00018 array( 'class' => 'mw-tag-marker ' .
00019 Sanitizer::escapeClass( "mw-tag-marker-$tag" ) ),
00020 self::tagDescription( $tag )
00021 );
00022 $classes[] = Sanitizer::escapeClass( "mw-tag-$tag" );
00023 }
00024
00025 $markers = '(' . implode( ', ', $displayTags ) . ')';
00026 $markers = Xml::tags( 'span', array( 'class' => 'mw-tag-markers' ), $markers );
00027 return array( $markers, $classes );
00028 }
00029
00030 static function tagDescription( $tag ) {
00031 $msg = wfMsgExt( "tag-$tag", 'parseinline' );
00032 if ( wfEmptyMsg( "tag-$tag", $msg ) ) {
00033 return htmlspecialchars( $tag );
00034 }
00035 return $msg;
00036 }
00037
00038 ## Basic utility method to add tags to a particular change, given its rc_id, rev_id and/or log_id.
00039 static function addTags( $tags, $rc_id = null, $rev_id = null, $log_id = null, $params = null ) {
00040 if ( !is_array( $tags ) ) {
00041 $tags = array( $tags );
00042 }
00043
00044 $tags = array_filter( $tags );
00045
00046 if( !$rc_id && !$rev_id && !$log_id ) {
00047 throw new MWException( "At least one of: RCID, revision ID, and log ID MUST be specified when adding a tag to a change!" );
00048 }
00049
00050 $dbr = wfGetDB( DB_SLAVE );
00051
00052
00053 if( !$rc_id ) {
00054 $dbr = wfGetDB( DB_MASTER );
00055 if( $log_id ) {
00056 $rc_id = $dbr->selectField( 'recentchanges', 'rc_id', array( 'rc_logid' => $log_id ), __METHOD__ );
00057 } elseif( $rev_id ) {
00058 $rc_id = $dbr->selectField( 'recentchanges', 'rc_id', array( 'rc_this_oldid' => $rev_id ), __METHOD__ );
00059 }
00060 } elseif( !$log_id && !$rev_id ) {
00061 $dbr = wfGetDB( DB_MASTER );
00062 $log_id = $dbr->selectField( 'recentchanges', 'rc_logid', array( 'rc_id' => $rc_id ), __METHOD__ );
00063 $rev_id = $dbr->selectField( 'recentchanges', 'rc_this_oldid', array( 'rc_id' => $rc_id ), __METHOD__ );
00064 }
00065
00066 $tsConds = array_filter( array( 'ts_rc_id' => $rc_id, 'ts_rev_id' => $rev_id, 'ts_log_id' => $log_id ) );
00067
00068 ## Update the summary row.
00069 $prevTags = $dbr->selectField( 'tag_summary', 'ts_tags', $tsConds, __METHOD__ );
00070 $prevTags = $prevTags ? $prevTags : '';
00071 $prevTags = array_filter( explode( ',', $prevTags ) );
00072 $newTags = array_unique( array_merge( $prevTags, $tags ) );
00073 sort( $prevTags );
00074 sort( $newTags );
00075
00076 if ( $prevTags == $newTags ) {
00077
00078 return false;
00079 }
00080
00081 $dbw = wfGetDB( DB_MASTER );
00082 $dbw->replace(
00083 'tag_summary',
00084 array( 'ts_rev_id', 'ts_rc_id', 'ts_log_id' ),
00085 array_filter( array_merge( $tsConds, array( 'ts_tags' => implode( ',', $newTags ) ) ) ),
00086 __METHOD__
00087 );
00088
00089
00090 $tagsRows = array();
00091 foreach( $tags as $tag ) {
00092 $tagsRows[] = array_filter(
00093 array(
00094 'ct_tag' => $tag,
00095 'ct_rc_id' => $rc_id,
00096 'ct_log_id' => $log_id,
00097 'ct_rev_id' => $rev_id,
00098 'ct_params' => $params
00099 )
00100 );
00101 }
00102
00103 $dbw->insert( 'change_tag', $tagsRows, __METHOD__, array( 'IGNORE' ) );
00104
00105 return true;
00106 }
00107
00113 static function modifyDisplayQuery( &$tables, &$fields, &$conds,
00114 &$join_conds, &$options, $filter_tag = false ) {
00115 global $wgRequest, $wgUseTagFilter;
00116
00117 if( $filter_tag === false ) {
00118 $filter_tag = $wgRequest->getVal( 'tagfilter' );
00119 }
00120
00121
00122 $join_field = '';
00123 if ( in_array( 'recentchanges', $tables ) ) {
00124 $join_cond = 'rc_id';
00125 } elseif( in_array( 'logging', $tables ) ) {
00126 $join_cond = 'log_id';
00127 } elseif ( in_array( 'revision', $tables ) ) {
00128 $join_cond = 'rev_id';
00129 } else {
00130 throw new MWException( 'Unable to determine appropriate JOIN condition for tagging.' );
00131 }
00132
00133
00134 $tables[] = 'tag_summary';
00135 $join_conds['tag_summary'] = array( 'LEFT JOIN', "ts_$join_cond=$join_cond" );
00136 $fields[] = 'ts_tags';
00137
00138 if( $wgUseTagFilter && $filter_tag ) {
00139
00140
00141
00142
00143 global $wgOldChangeTagsIndex;
00144 $index = $wgOldChangeTagsIndex ? 'ct_tag' : 'change_tag_tag_id';
00145 $options['USE INDEX'] = array( 'change_tag' => $index );
00146 unset( $options['FORCE INDEX'] );
00147 $tables[] = 'change_tag';
00148 $join_conds['change_tag'] = array( 'INNER JOIN', "ct_$join_cond=$join_cond" );
00149 $conds['ct_tag'] = $filter_tag;
00150 }
00151 }
00152
00157 static function buildTagFilterSelector( $selected='', $fullForm = false ) {
00158 global $wgUseTagFilter;
00159
00160 if ( !$wgUseTagFilter || !count( self::listDefinedTags() ) )
00161 return $fullForm ? '' : array();
00162
00163 global $wgTitle;
00164
00165 $data = array( wfMsgExt( 'tag-filter', 'parseinline' ), Xml::input( 'tagfilter', 20, $selected ) );
00166
00167 if ( !$fullForm ) {
00168 return $data;
00169 }
00170
00171 $html = implode( ' ', $data );
00172 $html .= "\n" . Xml::element( 'input', array( 'type' => 'submit', 'value' => wfMsg( 'tag-filter-submit' ) ) );
00173 $html .= "\n" . Xml::hidden( 'title', $wgTitle-> getPrefixedText() );
00174 $html = Xml::tags( 'form', array( 'action' => $wgTitle->getLocalURL(), 'method' => 'get' ), $html );
00175
00176 return $html;
00177 }
00178
00180 static function listDefinedTags() {
00181
00182 global $wgMemc;
00183 $key = wfMemcKey( 'valid-tags' );
00184
00185 if ( $tags = $wgMemc->get( $key ) )
00186 return $tags;
00187
00188 $emptyTags = array();
00189
00190
00191 $dbr = wfGetDB( DB_SLAVE );
00192 $res = $dbr->select( 'valid_tag', 'vt_tag', array(), __METHOD__ );
00193 while( $row = $res->fetchObject() ) {
00194 $emptyTags[] = $row->vt_tag;
00195 }
00196
00197 wfRunHooks( 'ListDefinedTags', array( &$emptyTags ) );
00198
00199 $emptyTags = array_filter( array_unique( $emptyTags ) );
00200
00201
00202 $wgMemc->set( $key, $emptyTags, 300 );
00203 return $emptyTags;
00204 }
00205 }