Extension:WhoIsWatchingTabbed
WhoIsWatchingTabbed Release status: beta |
|||
---|---|---|---|
Implementation | User activity, Page action, Special page | ||
Description | Creates a tab to see who is watching a particular page. Or what pages a user is watching. | ||
Author(s) | Jack Bredberg and Danila Ulyanov | ||
Last version | 1.3.1 | ||
MediaWiki | 1.11.1 | ||
License | GPL v3+ | ||
Download | No link | ||
|
|||
Check usage (experimental) |
Contents |
[edit] What can this extension do?
When installed this extension will create a tab in the tab bar that has the text "Who's watching this? (X)" where X is the number of users watching the page. When the tab is viewed it will display a grid of users who are watching the page. Each result will display the username, user real name, and page name. Usernames are linked to the same watching page, but will display all pages that the user is watching. Page names are linked to the same page, but will display all users watching that page. This installation will provide access only to group sysop. An item will be added to the special page list for accessing this extension. Viewing the special page will display top watching users and top watched pages defaulted to 10 each but with ability to raise that limit.
[edit] Download instructions
Please cut and paste the code found below and place it in the correct file in the $IP/extensions/WhoIsWatchingTabbed/
directory. Note: $IP stands for the root directory of your MediaWiki installation, the same directory that holds LocalSettings.php.
[edit] Installation
To install this extension, add the following to LocalSettings.php:
$wgGroupPermissions['sysop']['whoiswatchingtabbed'] = true; require_once("$IP/extensions/WhoIsWatchingTabbed/WhoIsWatchingTabbed.php" );
[edit] User rights
If you want to modify the groups that can access/view the tab you should add them to the $wgGroupPermissionsArray where the second index is 'whoiswatchingtabbed'.
[edit] Code
To use this extension you will need to create a new directory in the extensions directory called, WhoIsWatchingTabbed. Inside of that directory you will need to create two files: WhoIsWatchingTabbed.php and WhoIsWatchingTabbed.i18n.php. You will find the contents for each file below, just copy and paste. Ensure that you have added the two lines above to LocalSettings.php.
[edit] WhoIsWatchingTabbed.php
<?php # # WhoIsWatchingTabbed Mediawiki extension # # Original by Jack Bredberg and Danila Ulyanov 05.05.2008 # # http://www.mediawiki.org/ # # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. /** * ChangeLog * * 10.02.2008 1.3.1 * - Added a join in some queries to ensure that the watchlist only counts users that still exist * * 06.30.2008 1.3.0 * - Added ability to view more than top 10 most watched pages and most watching users * * 05.20.2008 1.2.0 * - Queries now use the database functions built in * - An issue with the namespace constant for the project has been addressed * * 05.08.2008 1.1.0 * - Fixed namespace bugs * - Added special page for most watching persons and most watched pages * * 05.05.2008 1.0.0 * - First version release */ require_once "$IP/includes/SpecialPage.php"; /* Global variables */ $wgAllowAnonUsers = false; # set to false to deny access to anonymous users /* Extension variables */ $wgExtensionFunctions[] = "wfSetupWhoIsWatchingTabbed"; $wgExtensionCredits["specialpage"][] = array( "name" => "WhoIsWatchingTabbed", "description" => "Adds Who Is Watching tab and special page to see who is watching any page, as well as, what pages a user is watching.", "url" => "", "author" => "[http://www.bestwaytech.com/ Jack Bredberg]", "version" => "1.3.1" ); $namespace_titles = array( NS_MEDIA =>"Media", NS_SPECIAL =>"Special", NS_MAIN =>"Main", NS_USER =>"User", NS_IMAGE =>"Image", NS_MEDIAWIKI =>"MediaWiki", NS_TEMPLATE =>"Template", NS_HELP =>"Help", NS_CATEGORY =>"Category", NS_PROJECT =>str_replace(" ","_",$wgSitename) ); class WhoIsWatchingTabbed extends SpecialPage { // Constructor function WhoIsWatchingTabbed() { global $wgHooks, $wgSpecialPages, $wgWatchingMessages; # Add all our needed hooks $wgHooks["UnknownAction"][] = $this; $wgHooks["SkinTemplateTabs"][] = $this; SpecialPage::SpecialPage("WhoIsWatchingTabbed", "block"); } function getDescription() { global $wgMessageCache, $wgWatchingMessages; require_once("WhoIsWatchingTabbed.i18n.php"); foreach($wgWatchingMessages as $language_code => $message) { $wgMessageCache->addMessages($message, $language_code); } return wfMsg("special_page_link"); } function execute() { global $wgOut, $wgSitename, $wgCachePages, $wgUser, $wgTitle, $wgDenyAccessMessage, $wgAllowAnonUsers, $wgRequest, $wgMessageCache, $wgWatchingMessages, $wgDBtype, $namespace_titles; require_once("WhoIsWatchingTabbed.i18n.php"); foreach($wgWatchingMessages as $language_code => $message) { $wgMessageCache->addMessages($message, $language_code); } $wgOut->setPagetitle(wfMsg("special_page_link")); //Set the limit of rows returned $page_limit = $user_limit = 10; $limit_menu = array("10" => "10", "25" => "25", "100" => "100", "0" => "All"); if(isset($_REQUEST["page_limit"]) && ctype_digit((string) $_REQUEST["page_limit"])) { $page_limit = $_REQUEST["page_limit"]; } if(isset($_REQUEST["user_limit"]) && ctype_digit((string) $_REQUEST["user_limit"])) { $user_limit = $_REQUEST["user_limit"]; } $db = &wfGetDB(DB_SLAVE); $style = ' style="border-bottom: 2px solid #000;"'; $tableStyle = ' style="float: left; margin-left: 40px;"'; $output = ""; $tables = array("watchlist","user"); $columns = array("wl_title", "wl_namespace", "COUNT(1) AS users_watching_page"); $conditions = array("wl_user = user_id", "wl_namespace IN (".implode(", ", array_keys($namespace_titles)).")"); $fname = "Database::select"; $options = array( "GROUP BY" => "LOWER(wl_title), wl_namespace", "ORDER BY" => "COUNT(1) DESC", ); if ($page_limit > 0) { $options["LIMIT"] = $page_limit; } if (false == $result = $db->select($tables, $columns, $conditions, $fname, $options)) { $output .= '<p>Error accessing watchlist.</p>'; } else if($db->numRows($result) == 0) { $output .= '<p>Nobody is watching this page.</p>'; } else { $output .= ' <table'.$tableStyle.'> <tr> <th colspan="3"'.$style.'>'.$db->numRows($result).' Most Watched Pages</th> </tr> <tr> <th style="text-align: left;">Namespace</th> <th>Page</th> <th style="text-align: right;">Watchers</th> </tr>'; while ($row = $db->fetchRow($result)) { $output .= ' <tr> <td>'.$namespace_titles[$row["wl_namespace"]].'</td> <td><a href="'.$_SERVER["PHP_SELF"].'?title='.($row["wl_namespace"]!=0 ? $namespace_titles[$row["wl_namespace"]].':' : '').$row["wl_title"].'&action=watching">'.$row["wl_title"].'</a></td> <td style="text-align: right;">'.$row["users_watching_page"] .'</td> </tr>'; } $output .= ' <tr> <td colspan="3" align="right"> <form action="post" method="get" id="limit_form"> Number of Results: <select name="page_limit" onchange="form.submit();">'; foreach ($limit_menu as $value => $option) { $selected = ""; if ($page_limit == $value) { $selected = ' selected="selected"'; } $output .= ' <option value="'.$value.'"'.$selected.'>'.$option.'</option>'; } $output .= ' </select> <input type="hidden" name="title" value="Special:WhoIsWatchingTabbed" /> <input type="hidden" name="user_limit" value="'.$user_limit.'" /> </form> </td> </tr> </table>'; } //Get the users who are watching the most pages $tables = array("watchlist", "user"); $columns = array("user_name", "user_real_name", "COUNT(1) AS pages_watched_by_user"); $conditions = array("wl_user = user_id", "wl_namespace IN (".implode(", ", array_keys($namespace_titles)).")"); $fname = "Database::select"; $options = array( "GROUP BY" => "wl_user", "ORDER BY" => "COUNT(1) DESC", ); if ($user_limit > 0) { $options["LIMIT"] = $user_limit; } if (false == $result = $db->select($tables, $columns, $conditions, $fname, $options)) { $output .= '<p>Error accessing watchlist.</p>'; } else if($db->numRows($result) == 0) { $output .= '<p>Nobody is watching this page.</p>'; } else { $output .= ' <table'.$tableStyle.'> <tr> <th colspan="3"'.$style.'>'.$db->numRows($result).' Users Watching the Most Pages</th> </tr> <tr> <th style="text-align: left;">Name</th> <th>User</th> <th style="text-align: right;">Watches</th> </tr>'; while ($row = $db->fetchRow($result)) { $output .= ' <tr> <td>'.$row["user_real_name"].'</td> <td><a href="'.$_SERVER["PHP_SELF"].'?title=&user_name='.$row["user_name"].'&action=watching">'.$row["user_name"].'</a></td> <td style="text-align: right;">'.$row["pages_watched_by_user"].'</td> </tr>'; } $output .= ' <tr> <td colspan="3" align="right"> <form action="post" method="get" id="limit_form"> Number of Results: <select name="user_limit" onchange="form.submit();">'; foreach ($limit_menu as $value => $option) { $selected = ""; if ($user_limit == $value) { $selected = ' selected="selected"'; } $output .= ' <option value="'.$value.'"'.$selected.'>'.$option.'</option>'; } $output .= ' </select> <input type="hidden" name="title" value="Special:WhoIsWatchingTabbed" /> <input type="hidden" name="page_limit" value="'.$page_limit.'" /> </form> </td> </tr> </table>'; } $wgOut->addHTML($output); return false; } function onUnknownAction($action, $article) { global $wgOut, $wgSitename, $wgCachePages, $wgLang, $wgUser, $wgTitle, $wgDenyAccessMessage, $wgAllowAnonUsers, $wgRequest,$wgMessageCache, $wgWatchingMessages, $namespace_titles, $wgSitename; require_once("WhoIsWatchingTabbed.i18n.php"); $wgCachePages = false; // Gather all the messages from the language file. foreach($wgWatchingMessages as $language_code => $message) { $wgMessageCache->addMessages($message, $language_code); } //Verify that the action coming in is "watching" (not to be confused with the system action "watch/unwatch" if($action == "watching") { if (!$wgUser->isAllowed("whoiswatchingtabbed")) { $wgOut->permissionRequired("whoiswatchingtabbed"); return true; } //Determine the namespace and the title of the current page. $pt = explode(":",$_REQUEST["title"]); if(sizeof($pt)==1) { $page_namespace = 0; $page_title = $pt[0]; } else { //Check for namespace that is the NS_PROJECT name if(strtoupper($pt[0])==strtoupper(str_replace(" ","_",$wgSitename))) { $page_namespace = constant("NS_PROJECT"); } else { $page_namespace = constant("NS_".strtoupper($pt[0])); } $page_title = $pt[1]; } $db = &wfGetDB(DB_SLAVE); $tables = array("user", "watchlist"); $conditions = array("wl_user = user_id", "wl_namespace IN (".implode(", ", array_keys($namespace_titles)).")"); $fname = "Database::select"; //Determine which results are going to be shown and the appropriate columns if(isset($_REQUEST["user_name"])) { $wgOut->setPagetitle(wfMsg("pages_watched_by_user")); $columns = array("wl_namespace","wl_title"); $conditions[] = "LOWER(user_name) = " . $db->addQuotes(strtolower($_REQUEST["user_name"])); } else { $wgOut->setPagetitle(wfMsg("users_watching_page")); $columns = array("user_name", "user_real_name"); $conditions[] = "LOWER(wl_title) = " . $db->addQuotes(strtolower($page_title)); } $order_col = "user_name"; if(isset($_REQUEST["order_col"]) && in_array($_REQUEST["order_col"], $columns)) { $order_col = $_REQUEST["order_col"]; } //Change the way the results are ordered if(isset($_REQUEST["order_type"]) && $_REQUEST["order_type"] == "DESC") { $ordertype = "DESC"; $ordertypeR = "ASC"; } else { $ordertype = "ASC"; $ordertypeR = "DESC"; } $options = array("ORDER BY" => "$order_col $ordertype"); $output = ""; if (false == $result = $db->select($tables, $columns, $conditions, $fname, $options)) { $output .= '<p>Error accessing watchlist.</p>'; } else if($db->numRows($result) == 0) { $output .= '<p>Nobody is watching this page.</p>'; } else { $style = ' style="border-bottom:2px solid #000; text-align:left;"'; $output .= '<table cellspacing="0" cellpadding="5"><tr>'; //Generate sortable column headings foreach($columns as $column){ $output .= '<th'.$style.'><a href="'.$_SERVER["PHP_SELF"].'?title='.$_REQUEST["title"].'&order_col='.$column.'&action=watching&order_type='.$ordertypeR. (isset($_REQUEST["user_name"]) ? '&user_name='.$_REQUEST["user_name"] : ''). (isset($_REQUEST["user_real_name"]) ? '&user_real_name='.$_REQUEST["user_real_name"] : '').'">'.wfMsg($column).'</a></th>'; } $output .= '</tr>'; //Display the data--display some data differently than others. while ($row = $db->fetchRow($result)) { $output .= '<tr>'; foreach($columns as $column){ $output .= "<td>"; if ($column == "user_name") { $output .= '<a href="'.$_SERVER["PHP_SELF"].'?title='.$_REQUEST["title"].'&action=watching&user_name='.$row[$column].'">'.$row[$column]; } elseif ($column == "user_real_name") { $output .= $row[$column]; } elseif ($column == "wl_title") { $output .= '<a href="'.$_SERVER["PHP_SELF"].'?title='.($row["wl_namespace"]!=0 ? $namespace_titles[$row["wl_namespace"]].':' : '').$row[$column].'&action=watching">'.$row[$column].'</a>'; } elseif ($column == "wl_namespace") { $output .= $namespace_titles[$row[$column]]; } else { $output .= htmlspecialchars($row[$column]).' '; } $output .= "</td>"; } $output .= '</tr>'; } $output .= '</table>'; } $wgOut->addHTML($output); return false; } else { return true; } } function onSkinTemplateTabs(&$skin, &$content_actions) { global $wgRequest, $wgUser, $wgSitename; if (!$wgUser->isAllowed("whoiswatchingtabbed")) { return false; } $action = $wgRequest->getText("action"); $db = &wfGetDB(DB_SLAVE); $page_title = $_REQUEST["title"]; $page_namespace = 0; $pt = explode(":",$_REQUEST["title"]); if(sizeof($pt)>1) { if(strtoupper($pt[0])==strtoupper(str_replace(" ","_",$wgSitename))) { $page_namespace = constant("NS_PROJECT"); } else { $page_namespace = constant("NS_".strtoupper($pt[0])); } $page_title = $pt[1]; } $tables = array("watchlist","user"); $columns = array("COUNT(1) AS users_watching_page"); $conditions = array("wl_user = user_id", "LOWER(wl_title) = ". $db->addQuotes(strtolower($page_title)),"wl_namespace=".$page_namespace); $fname = "Database::select"; $watcherCount = 0; if (false == $result = $db->select($tables, $columns, $conditions, $fname)) { $output .= '<p>Error accessing watchlist.</p>'; } else { $row = $db->fetchRow($result); $watcherCount = $row["users_watching_page"]; $content_actions["watching"] = array( "class" => ($action == "watching") ? "selected" : false, "text" => "who is watching this? (".$watcherCount.")", "href" => $skin->mTitle->getLocalURL("action=watching") ); } //tab links return false; } } //end class /* Global function */ # Called from $wgExtensionFunctions array when initialising extensions function wfSetupWhoIsWatchingTabbed() { global $wgUser; SpecialPage::addPage( new WhoIsWatchingTabbed ); if ($wgUser->isAllowed("whoiswatchingtabbed")) { global $wgWhoIsWatchingTabbed; $wgWhoIsWatchingTabbed = new WhoIsWatchingTabbed(); } }
[edit] WhoIsWatchingTabbed.i18n.php
<?php $user_name = "Unknown User"; if(isset($_REQUEST["user_name"])) { $user_name = $_REQUEST["user_name"]; } $page_title = "Unknown Page"; if(isset($_REQUEST["title"])) { $page_title = $_REQUEST["title"]; } $wgWatchingMessages['en'] = array( 'pages_watched_by_user' => "Pages watched by ".$user_name, 'users_watching_page' => "Users watching ".$page_title, 'special_page_link' => "Who is Watching Statistics", 'user_name' => 'Username', 'user_real_name' => 'Real name', 'page_title' => 'Page Title', 'page_namespace' => 'Page Namespace' ); $wgWatchingMessages['zh-tw'] = array( 'pages_watched_by_user' => "受".$user_name."監視的頁面", 'users_watching_page' => "「".$page_title ."」頁面監視者", 'special_page_link' => "監視頁面統計", 'user_name' => '用戶名稱', 'user_real_name' => '真實名稱', 'page_title' => '頁面標題', 'page_namespace' => '頁面名字空間', );
[edit] Known Issues
- In MediaWiki 1.10.0 it has been found that this extension will break the Special:Version page for sysops. This issue is not present in 1.11.1.
- The language file isn't entirely useful. There is some logic and text initializations occurring outside of the rest of the array/message initializations.
[edit] Revisions
- 2008.06.30 - Cleaned up last revision.
- 2008.06.27 - Added limit selection to top ten lists on the special page.
- 2008.05.08 - Fixed namespace issues and added the link to the special page list.
- 2008.05.05 - Initial version released.
[edit] See also
Extensions that are similar in goal or style:
- Extension:Chat - A lovely extension that adds chat support via a new tab.
- Extension:WatchLog - Logs user watches. However, depends on Extension:StubManager extension.
- Extension:WhoIsWatching - Adds the number of users watching to the footer.