User:Diploid/ATS (Article Tagging System)/ATS Body.php
From MediaWiki.org
<?php /* Copyright (c) 2007 MediaWiki.org User: Diploid * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * ----------------------------------------------------------------------- */ # # The ATS ajax response (Article Tagging System) class # # used for producing tag clouds and all interactions with the ATS table class ATSajaxresponse { ##=========Configuration Variables========= #The Maximum Font Size of the Tag Cloud in the units selected bellow private $MaxFontSize = 21; private $MinFontSize = 12; #Units for the font size private $FontUnit = "px"; #Definate the default number of tags per tag cloud private $DefaultNofTags = 9; ##Defines the CSS Classes of various html elements of the Tag Cloud #Wrapper div for the tag cloud section private $cssClass_TagCloud = "tagcloud"; #Each individual tag's span element private $cssClass_Tag = "tag"; #Wrapper div for the add a tag section private $cssClass_AddTag = "addtag"; #The text input area for typing the name of your tag private $cssClass_Add_Text = "addtaginput"; #The button for adding your tag private $cssClass_Add_Button = "addtagbutton"; #The Add Tag and Tag Cloud titles private $HTMLtagCloudTitle = "<h2>Tags</h2>"; private $HTMLaddTagTitle = "<h2>Add Tag</h2>"; #Set the dbuser and dbpassword variables to give this script table create #permision for the wiki's database so that it can create the ATSTags table. private $dbuser=""; private $dbpassword=""; #database server name private $dbserver = "localhost"; #database name private $dbname = "wikidb"; #database mediawiki table prefix private $dbprefix = ""; //(make it the same as $wgDBprefix in local settings) private $MediaWikiInstallDirectory = ""; #Sets the default setting for tag clouds: # If true every page will have a tag cloud by default that can be removed #with {{#ATS: disable}} # If false pages will not have tag clouds by default but must be added #with {{#ATS: enable}} public $TagCloudEnable = true; #The Hash Key used for all ATS form data, set this to some random #characters for increased security public $FormHashData = ''; ##=====End of Configuration Variables===== ##Everything beyond this point should probably not be touched unless you wish #to modify the extension private $TagTableName = "atstags"; private $TagCountAlias = "NoOfTags"; #Time out (in seconds) for Session Data Stored in the atssession Memory Table in mysql #Note that this data is not particlularly valuable as it is only used to store a user validation key #from the time the user loads a ATS tagcloud to the time they add a tag to that cloud. private $SessionDataTimeout = 300; //default is 5 minute timeout ####Session Database Related Functions private function SessionEntryExists($user) { $query = "SELECT suser FROM ".$this->dbname.".".$this->dbprefix."atssessions " ."WHERE suser = '$user'"; if ($resultdata = $this->DBConnect($query)==false) return false; return true; } public function PostSessionData($sessiondata, $user) { foreach($sessiondata as $seskey => $sesvalue) { $query = "DELETE FROM $this->dbname.$this->dbprefix"."atssessions " ."WHERE suser = '$user' and skey = '$seskey'"; if ($this->DBConnect($query) == false) echo("ATS Session Deletion Error"); $servertime = time(); $query = "INSERT INTO ".$this->dbname.".".$this->dbprefix."atssessions" ." (suser, skey, svalue, timestamp)" ." VALUES ('$user', '$seskey', '$sesvalue','$servertime');"; if ($this->DBConnect($query) == false) echo("ATS Session Error"); } } public function GetSessionData($sessionkey, $user) { $query = "SELECT suser, svalue, skey FROM ".$this->dbname.".".$this->dbprefix."atssessions " ."WHERE skey = '$sessionkey' AND suser = '$user'"; $resultdata = $this->DBConnect($query); if ($resultdata==false) return false; $resultarray = $this->getSQLarray($resultdata); return $resultarray[(count($resultarray)-1)]['svalue']; } private function DeleteExpiredSessions() { #Deletes Entries older then the timeout period specified in the $SessionDataTimeout Variable $awhileback = time()-$this->SessionDataTimeout; $query = "DELETE FROM $this->dbname.$this->dbprefix"."atssessions " ."WHERE timestamp < $awhileback"; if ($this->DBConnect($query) == false) echo("ATS Session Deletion Error"); } private function SetupSession() { $query = "SELECT * FROM ".$this->dbname.".".$this->dbprefix."atssessions"; if ($this->DBConnect($query)==false) { $query = "CREATE TABLE ".$this->dbname.".".$this->dbprefix."atssessions" ."(" ."suser VARCHAR(100) NOT NULL, " ."skey VARCHAR(100) NOT NULL, " ."svalue VARCHAR(100) NOT NULL, " ."timestamp INTEGER UNSIGNED NOT NULL" .") ENGINE = MEMORY;"; if ($this->DBConnect($query)==false) echo ("ATS Fatal Error: Could Not Set Up Session Data"); } #Removing Expired Session Entries $this->DeleteExpiredSessions(); } ####Tag Creation Related Functions public function AddTag($pagename, $tag, $username, $hashtoken) { $tag = ucfirst($tag); $identicaltagcheck = $this->identicaltagcheck($pagename, $tag, $username); //Requires the user to be logged in and authorized (aka has a correct hash) if ($this->validateuser($pagename,$username,$hashtoken) == true and $identicaltagcheck==false and $pagename != null) { $pagename = ucfirst($pagename); ###### Adding to ATS Table #### //Updating the tag table $query = " INSERT INTO `".$this->dbname."`.`".$this->dbprefix.$this->TagTableName."` (Tag, Page, UserName) VALUES (\"".$tag."\",\"".$pagename."\",\"".$username."\")"; if($this->DBConnect($query)==false) { echo("Unknown ATS Error Please Try Again"); exit(); } ##### Adding to MediaWiki Tables ##### //Getting the page's number $_pagename = str_replace(" ", "_", $pagename); $query = "SELECT page_id FROM `".$this->dbname."`.`".$this->dbprefix."page` WHERE page_title = \"".$_pagename."\""; $pageiddata = $this->DBConnect($query); if ($pageiddata ==false) { echo("ATS Error While Getting Page ID Please Try Again"); exit(); } $pageidarray = $this->getSQLarray($pageiddata); $pageid = $pageidarray[count($pageidarray)-1]["page_id"]; //Updating the Media Wiki categorylinks table //cl_from, cl_to, cl_sortkey, cl_timestamp $timestamp = date("Y-m-d H:i:s"); $tag = str_replace(" ", "_", $tag); $query = " INSERT INTO `$this->dbname`.`$this->dbprefix"."categorylinks` (cl_from, cl_to, cl_sortkey, cl_timestamp) VALUES (\"".$pageid."\",\"".$tag."\",\"".$pagename."\",\"".$timestamp."\")"; if($this->DBConnect($query)==false) { echo("ATS Error While Interacting with the MediaWiki Table CategoryLinks Please Try Again"); exit(); } //Updating the Job List so that the category page is updated accordingly $query = " insert into ".$this->dbname.".".$this->dbprefix."job (job_cmd,job_namespace,job_title,job_params) VALUES ('refreshLinks',0,'".$_pagename."',''); "; if($this->DBConnect($query)==false) { echo("ATS Error While adding MediaWiki Job"); exit(); } } else { if ($identicaltagcheck == true) { echo("You can only tag this page once"); } else { echo("Your session has expired, please log in to add a tag"); } } } private function identicaltagcheck($page, $tag, $user) { $query = " SELECT Tag, Page, UserName FROM `".$this->dbname."`.`".$this->dbprefix.$this->TagTableName."` WHERE Tag = \"".$tag."\" and UserName = \"".$user."\" and Page = \"".$page."\" "; $result = $this->DBConnect($query); if ($result == false) return true; $resultarray = $this->getSQLarray($result); if (count($resultarray) == 1) { return false; } return true; } ####Tag Querying Functions private function QueryPageTags($page, $arg="orderbytagcount") { $orderby=""; if ($arg == "textonly" || $arg="orderbytagcount") $orderby = "ORDER BY Count(UserName) DESC"; //Querying the Database $query = " SELECT Tag, Count(UserName) AS ".$this->TagCountAlias." FROM `".$this->dbname."`.`".$this->dbprefix.$this->TagTableName."` WHERE Page = \"".$page."\" GROUP BY Tag ".$orderby; return $this->DBConnect($query); } public function GetTags_CommaSeperatedText($page) { $result = $this->QueryPageTags($page); if ($result == false) return false; return $this->getSQLcolumntext_CommaSeperated($result,"Tag"); } public function GetTags($page) { $result = $this->QueryPageTags($page); if ($result == false) return false; $resultarray = $this->getSQLarray($result); #Deleting the first, and for some reason always empty first row array_splice($resultarray, 0, 1); return $resultarray; } public function GetTaggedPages($tag) { $query = " SELECT Page, Count(UserName) AS tagcount FROM `".$this->dbname."`.`".$this->dbprefix.$this->TagTableName."` WHERE Tag = \"".$tag."\" GROUP BY Page ORDER BY Count(UserName) DESC " ; $result = $this->DBConnect($query); if ($result == false) return false; $resultarray = $this->getSQLarray($result); #Deleting the first, and for some reason always empty first row array_splice($resultarray, 0, 1); return $resultarray; } #This monster of a function generates Tag Clouds in both WikiText and HTML format public function MakeTagCloud($page,$NofTags = false, $user=false, $key) { if ($this->TagCloudEnable == true) { #Setting the defualt number of tags if it is not definaed here if ($NofTags==false) $NofTags = $this->DefaultNofTags; #Gets the tag data in array form $tagdata = $this->GetTags($page); $Path = $this->MediaWikiInstallDirectory; #Initializing the returned tag cloud HTML: $tagcloud var $tagcloud =$this->HTMLtagCloudTitle ."<div class=\"".$this->cssClass_TagCloud."\">"; #Getting the Size of the tagdata array $size = count($tagdata); #Checking that there are actually any tags returned for the page #before creating the tag cloud if ($tagdata!=false && $size != 0) { #Initializing a variety of variables if ($size < $NofTags) $NofTags = $size; $mosttags = $tagdata[0][$this->TagCountAlias]; $leasttags = $tagdata[$NofTags-1][$this->TagCountAlias]; $fontmultiplier = 1; if ($mosttags != $leasttags) { #Creating the font multiplier used to create the varying font sizes used in #the tag cloud to represent tag popularity $fontmultiplier = 1/($mosttags - $leasttags)* ($this->MaxFontSize - $this->MinFontSize); } #Get the first N Tags where N = $NofTags if ($size != $NofTags) array_splice($tagdata,$NofTags); $size = count($tagdata); #Order the first N Tags Alphabetically where N = $NofTags $this->OrderRowArrayAlphabetically($tagdata, "Tag"); #Creating each Tag's HTML for ($i=0; $i<$size; $i++) { #Generating the tag's font size relative to it's popularity and the #font multiplier $fontsize = (($tagdata[$i][$this->TagCountAlias]-$leasttags) *$fontmultiplier) + $this->MinFontSize; #Sets the URL of the Tag's Link $tagurl = $Path."/index.php?title=Category:".$tagdata[$i]["Tag"]; #Generating the Tag's HTML code and appending it to the output $tagcloud .= "<a href=\"".$tagurl."\" class = \"".$this->cssClass_Tag."\"" ." style=\"font-size:".$fontsize."".$this->FontUnit.";\">" .$tagdata[$i]["Tag"] ."</a>\n"; } } $tagcloud .= "</div>\n"; //End of the TagCloudSpan $tagcloud .= $this->HTMLaddTagTitle ."<div class = \"".$this->cssClass_AddTag."\">\n"; if ($this->validateuser($page, $user, $key) ==false) { $tagcloud .="Please Log in to add a tag"; } else { #Creating the Add Tag HTML $tagcloud .="" ."<input id=\"ATSaddtag-tagname\" type=\"text\" />\n" ."<input id=\"ATSaddtag-submit\" type=\"button\" value=\"Add\"" ."onClick=\"AsyncLoadATS(" ."document.getElementById('ATSaddtag-tagname').value)\"/>\n"; } $tagcloud .= "</div>\n"; return $tagcloud; } return ""; } private function OrderRowArrayAlphabetically(&$rows, $col) { $size = count($rows); for ($i=0; $i<$size; $i++) { #Finding the next row in alphabetical order (temperarorly stored as $alpha) $alpha = $i; for ($j=$i; $j<$size; $j++) { if ((strcasecmp($rows[$alpha][$col], $rows[$j][$col]))>0) {$alpha =$j; } } #Inserting the next row $alpha and moving the previous #entry at that position back into the sorting que if ($alpha!= $i) { $tmprow = $rows[$i]; $rows[$i] = $rows[$alpha]; $rows[$alpha] = $tmprow; } } } public function Setup() { #Checking for Script Specific DB Username and Password otherwise using the #mediawiki account /*if (!$this->dbuser || !$this->dbpassword) { $this->dbuser = $wgDBuser; $this->dbpassword = $wgDBpassword; }*/ #Checking if MySQL is installed and working properly # Test for missing mysql.so # First try to load it if (!@extension_loaded('mysql')) { @dl('mysql.so'); } # Fail now # Otherwise we get a suppressed fatal error, which is very hard to track down if ( !function_exists( 'mysql_connect' ) ) { echo ("ATS Error: SQL Not properly Installed."); exit; }; #Checking if the Tags table has been setup $query = "SELECT 1 FROM `".$this->dbprefix.$this->TagTableName."` LIMIT 0"; $result = $this->DBConnect($query); if ($result==false) { //If the table has not been setup attempt to make it $query=" CREATE TABLE `".$this->dbname."`.`".$this->dbprefix.$this->TagTableName."` ( id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, Page VARCHAR(100) NOT NULL, UserName VARCHAR(50) NOT NULL, Tag VARCHAR(50) NOT NULL, PRIMARY KEY (`id`) );"; //Returning an error if the table cannot be created //Yes I realize this is a shoddy error message, but its 2am and i'm sick //so bugger off. (please) if (!$this->DBConnect($query)) { echo("ATS Error: Tag Table cannot be created." ."Please Insert the Following in your Wiki's MySQL Database:" ."<pre>" .$query ."</pre>" ."<br/><b>or</b>" ."Uncomment \$dbuser and \$dbpassword and set them to those " ."corresponding to a MySQL account with CREATE privledges for " ."the media wiki database and reload this page."); //Initialization of the Extension is stopped due to an SQL error exit(); } } //Sets up the session table in the RAM to track tagcloud users $this->SetupSession(); //All is well so we allow the Magic Word/Hook to be initialized return true; } //I Realize all functions beyond this point are sql related and techincally //should be in their own object but i'm being lazy on this one. #Private function used to connect to the Tag Table public function DBConnect($query) { $link = mysql_connect ($this->dbserver, $this->dbuser, $this->dbpassword); mysql_select_db ($this->dbname, $link); $result = mysql_query ($query, $link); $link = null; return $result; } private function getSQLarray($queryresults) { if ($queryresults == false) return false; $resultsarray[] = null; $num_results = mysql_num_rows($queryresults); for ($i=0; $i < $num_results; $i ++) { $resultsarray[] = mysql_fetch_array($queryresults); } return $resultsarray; } private function getSQLcolumntext_CommaSeperated($queryresults, $column) { if ($queryresults == false) return false; $resultstext = ""; $num_results = mysql_num_rows($queryresults); for ($i=0; $i < $num_results; $i ++) { $resultstext .= mysql_result($queryresults,$i,$column) . ","; } return $resultstext; } private function validateuser($pagename, $user, $key) { #If User is logged in if ($user != "" and $this->SessionEntryExists($user)) { #If user's credentials check out if ( $this->GetSessionData('ATShash',$user) == sha1($key) and #Checking Encryption Key $this->GetSessionData('ATSpage',$user) == $pagename #Checking Page Name ) { return true; } } return false; } }